You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kword/KWFrameSet.h

505 lines
23 KiB

/* This file is part of the KDE project
Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
Copyright (C) 2005 Thomas Zander <zander@kde.org>
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 frame_set_h
#define frame_set_h
#include "KWFrame.h"
#include <qptrvector.h>
#include <qptrlist.h>
#include "qdom.h"
class KWAnchor;
class KWFrame;
class KWFrameSetEdit;
class KWPageManager;
class KWTableFrameSet;
class KWTextFrameSet;
class KWTextFrameSetEdit;
class KWTextParag;
class KWView;
class KWordFrameSetIface;
class KWFrameViewManager;
class KoSavingContext;
class KoTextDocument;
class KoTextFormat;
class KoTextParag;
class KoXmlWriter;
class KCommand;
class QPoint;
class QProgressDialog;
/**
* Class: KWFrameSet
* Base type, a frameset holds content as well as frames to show that
* content.
* The different types of content are implemented in the different
* types of frameSet implementations (see below)
* @see KWTextFrameSet, KWPartFrameSet, KWPictureFrameSet,
* KWFormulaFrameSet, KWTableFrameSet
*/
class KWFrameSet : public QObject
{
Q_OBJECT
public:
/// constructor
KWFrameSet( KWDocument *doc );
/// destructor
virtual ~KWFrameSet();
virtual KWordFrameSetIface* dcopObject();
/** The type of frameset. Use this to differentiate between different instantiations of
* the framesets. Each implementation will return a different frameType.
*/
virtual FrameSetType type() const { return FT_BASE; }
virtual void addTextFrameSets( QPtrList<KWTextFrameSet> & /*lst*/, bool /*onlyReadWrite*/ = false ) {};
virtual bool ownLine() const { return FALSE;}
/** The different types of textFramesets (that TEXT is important here!)
* FI_BODY = normal text frames.<br>
* FI_FIRST_HEADER = Header on page 1<br>
* FI_EVEN_HEADER = header on any even page<br>
* FI_ODD_HEADER = header on any odd page (can be including page 1)<br>
* FI_FIRST_FOOTER = footer on page 1<br>
* FI_EVEN_FOOTER = footer on any even page<br>
* FI_ODD_FOOTER = footer on any odd page (can be including page 1)<br>
* FI_FOOTNOTE = a footnote frame.
*/
enum Info { FI_BODY = 0, FI_FIRST_HEADER = 1, FI_EVEN_HEADER = 2, FI_ODD_HEADER = 3,
FI_FIRST_FOOTER = 4, FI_EVEN_FOOTER = 5, FI_ODD_FOOTER = 6,
FI_FOOTNOTE = 7 };
/** Returns the type of TextFrameSet this is */
Info frameSetInfo()const { return m_info; }
/** Set the type of TextFrameSet this is */
void setFrameSetInfo( Info fi ) { m_info = fi; }
bool isAHeader() const;
bool isAFooter() const;
bool isHeaderOrFooter() const { return isAHeader() || isAFooter(); }
bool isFootEndNote() const;
const char* headerFooterTag() const; // for OASIS saving
virtual bool isFootNote() const { return false; }
virtual bool isEndNote() const { return false; }
bool isMainFrameset() const;
bool isMoveable() const;
// frame management
virtual void addFrame( KWFrame *_frame, bool recalc = true );
/** Delete a frame from the set of frames this frameSet has.
* @param num The frameNumber to be removed.
* @param remove passing true means that there can not be an undo of the action.
* @param recalc do an updateFrames()
*/
virtual void deleteFrame( unsigned int num, bool remove = true, bool recalc = true );
/** Delete a frame from the set of frames this frameSet has.
* @param frm The frame that should be deleted
* @param remove passing true means that there can not be an undo of the action.
* @param recalc do an updateFrames()
*/
void deleteFrame( KWFrame *frm, bool remove = true, bool recalc = true ); // calls the virtual one
/// Called by deleteFrame when it really deletes a frame (remove=true), to remove it from the table too
virtual void frameDeleted( KWFrame* /*frm*/, bool /*recalc*/ ) {}
void deleteAllFrames();
void deleteAllCopies(); /// \note for headers/footers only
/** retrieve frame from x and y coords (unzoomed coords) */
KWFrame *frameAtPos( double _x, double _y ) const;
/** Return if the point is on the frame.
* @param nPoint the point in normal coordinates.
* @param borderOfFrameOnly when true an additional check is done if the point
* is on the border.
* @param frame the frame to check inside of
*/
bool isFrameAtPos( const KWFrame* frame, const QPoint& nPoint, bool borderOfFrameOnly=false ) const;
/** get a frame by number */
KWFrame *frame( unsigned int _num ) const;
/**
* Returns the original frame that the param frame is a copy off, or the frame itself.
* For changing a frame that is a copy of another (as found in KWFrame::isCopy()) you
* need a so called settings frame, or original frame. This method can savely be called
* on any frame to make sure you are dealing with the original frame.
* @param frame the frame to find the settings frame for.
* @return the frame itself if its not a copy, or the original frame if it is one.
*/
static KWFrame * settingsFrame( const KWFrame* frame );
/** Iterator over the child frames */
const QPtrList<KWFrame> &frameIterator() const { return m_frames; }
/** Get frame number */
int frameFromPtr( KWFrame *frame );
/** Get number of child frames */
unsigned int frameCount() const { return m_frames.count(); }
/** True if the frameset was deleted (but not destroyed, since it's in the undo/redo) */
bool isDeleted() const { return m_frames.isEmpty(); }
/** Create a framesetedit object to edit this frameset in @p canvas */
virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * ) { return 0; }
/**
* Let the caller know which parts of @p emptyRegion we do not claim, and thus the caller is
* free to paint on without interfering with later paints from us.
* For painting all frames of all framesets the painter needs to find out what area we
* will fill with a background color and possibly paint over.
* What this method does is fill an QRegion with all the areas we are going to fill, which
* typically means we will paint the background of a frame there.
* @param emptyRegion The region is modified to subtract the areas painted, thus
* allowing the caller to determine which areas remain to be painted.
* Framesets that can be transparent should reimplement this and make it a no-op,
* so that the background is painted below the transparent frame.
* @param crect the cliprect; only parts inside this rect are of interrest to us
* @param viewMode For coordinate conversion, always set.
*/
virtual void createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode );
/**
* Paint this frameset
* @param painter The painter in which to draw the contents of the frameset
* @param crect The rectangle (in scrollview "contents coordinates", i.e. "view coords")
* to be painted
* @param cg The colorgroup from which to get the colors
* @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged)
* @param resetChanged If true, set the changed flag to false after drawing.
* @param edit If set, this frameset is being edited, so a cursor is needed.
* @param viewMode For coordinate conversion, always set.
* @param frameViewManager the frameViewManager;
*
* The way this "onlyChanged/resetChanged" works is: when something changes,
* all views are asked to redraw themselves with onlyChanged=true.
* But all views except the last one shouldn't reset the changed flag to false,
* otherwise the other views wouldn't repaint anything.
* So resetChanged is called with "false" for all views except the last one,
* and with "true" for the last one, so that it resets the flag.
*
* Framesets shouldn't reimplement this one in theory [but KWTableFrameSet has to].
*/
virtual void drawContents( QPainter *painter, const QRect &crect,
const QColorGroup &cg, bool onlyChanged, bool resetChanged,
KWFrameSetEdit *edit, KWViewMode *viewMode,
KWFrameViewManager *frameViewManager );
/**
* This one is called by drawContents for each frame.
* It sets up clip rect and painter translation, and calls drawFrame, drawFrameBorder and drawMargins
*
* @param drawUnderlyingFrames if the frame implements it, then it should draw underlying frames.
* This is set to false by the default drawFrame implementation, so that the frames under a
* transparent frame are simply drawn, without transparency handling (nor their own
* double-buffering).
* @param frame the frame to draw
* @param painter the painter to draw to
* @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour)
* @param cg The colorgroup from which to get the colors
* @param edit If set, this frameset is being edited, so a cursor is needed.
* @param viewMode For coordinate conversion, always set.
* @param crect rectangle to be repainted, in view coordinates. Includes padding.
*/
void drawFrameAndBorders( KWFrame *frame,
QPainter *painter, const QRect &crect,
const QColorGroup &cg, bool, bool,
KWFrameSetEdit *edit, KWViewMode *viewMode,
KWFrame *settingsFrame, bool drawUnderlyingFrames );
/**
* Paint the borders for one frame of this frameset.
* @param painter The painter in which to draw the contents of the frameset
* @param frame The frame to be drawn
* @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour)
* @param crect The rectangle (in "contents coordinates") to be painted
* @param viewMode For coordinate conversion, always set.
*/
void drawFrameBorder( QPainter *painter, KWFrame *frame, KWFrame *settingsFrame,
const QRect &crect, KWViewMode *viewMode );
/**
* Draw a particular frame of this frameset.
* This is called by drawContents and is what framesets must reimplement.
* @param fcrect rectangle to be repainted, in the _frame_'s coordinate system, in pixels.
* Doesn't include padding.
*
* @param crect rectangle to be repainted, in view coordinates. Includes padding.
* Default implementation does double-buffering and calls drawFrameContents.
* @param frame the frame to draw
* @param painter the painter to draw to
* @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour)
* @param cg The colorgroup from which to get the colors
* @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged)
* @param resetChanged If true, set the changed flag to false after drawing.
* @param edit If set, this frameset is being edited, so a cursor is needed.
* @param viewMode For coordinate conversion, always set.
* @param drawUnderlyingFrames if the frame implements it, then it should draw underlying frames.
* @param translationOffset offset this method will translate the paiter before doing its work.
*/
virtual void drawFrame( KWFrame *frame, QPainter *painter, const QRect &fcrect, const QRect &crect,
const QPoint& translationOffset,
KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
KWFrameSetEdit *edit, KWViewMode *viewMode, bool drawUnderlyingFrames );
/**
* Implement this one instead of drawFrame to benefit from double-buffering
* AND transparency handling (painting frames below this one) automatically.
* You MUST reimplement one or the other, or you'll get infinite recursion ;)
*
* In this method, the painter has been translated to the frame's coordinate system
* @param fcrect rectangle to be repainted, in the _frame_'s coordinate system, in pixels.
* Doesn't include padding.
* @param frame the frame to draw
* @param painter the painter to draw to
* @param cg The colorgroup from which to get the colors
* @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged)
* @param resetChanged If true, set the changed flag to false after drawing.
* @param edit If set, this frameset is being edited, so a cursor is needed.
* @param viewMode For coordinate conversion, always set.
*/
virtual void drawFrameContents( KWFrame * frame, QPainter *painter, const QRect& fcrect,
const QColorGroup &cg, bool onlyChanged, bool resetChanged,
KWFrameSetEdit * edit, KWViewMode *viewMode );
/**
* Draw the padding area inside of a specific frame of this frameSet
*/
virtual void drawPadding( KWFrame *frame, QPainter *p, const QRect &fcrect, const QColorGroup &cg, KWViewMode *viewMode);
enum UpdateFramesFlags {
UpdateFramesInPage = 1,
SortFrames = 2 ///< kwtextframeset only
// next one is 4, not 3 ;)
};
/**
* Called when our frames change, or when another frameset's frames change.
* Framesets can reimplement it, but should always call the parent method.
*/
virtual void updateFrames( int flags = 0xff );
/** Return list of frames in page @p pageNum.
* This is fast since it uses the m_framesInPage array.*/
const QPtrList<KWFrame> & framesInPage( int pageNum ) const;
/** Allows to detect that updateFrames() hasn't been called yet (e.g. on loading) */
bool hasFramesInPageArray() const { return !m_framesInPage.isEmpty(); }
/** relayout text in frames, so that it flows correctly around other frames */
virtual void layout() {}
virtual void invalidate() {}
/// save to XML - when saving
virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true ) = 0;
/// save to XML - when copying to clipboard
virtual QDomElement toXML( QDomElement &parentElem, bool saveFrames = true )
{ return save( parentElem, saveFrames ); }
/// Save to OASIS format
virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const = 0;
/// If the frameset is inline, is it ok to save it inside an oasis <text:p>?
/// If not, KWAnchor will create a textbox around it.
virtual bool canBeSavedAsInlineCharacter() const { return true; }
/// load from XML - when loading
virtual void load( QDomElement &framesetElem, bool loadFrames = true );
KWFrame* loadOasisFrame( const QDomElement& tag, KoOasisContext& context );
/// load from XML - when pasting from clipboard
virtual void fromXML( QDomElement &framesetElem, bool loadFrames = true, bool /*useNames*/ = true )
{ load( framesetElem, loadFrames ); }
virtual QString toPlainText() const { return QString::null; }
//virtual void preparePrinting( QPainter *, QProgressDialog *, int & ) { }
/** Called once the frameset has been completely loaded or constructed.
* The default implementation calls updateFrames() and zoom(). Call the parent :) */
virtual void finalize();
virtual int paragraphs() { return 0; }
virtual int paragraphsSelected() { return 0; }
virtual bool statistics( QProgressDialog * /*progress*/, ulong & /*charsWithSpace*/, ulong & /*charsWithoutSpace*/, ulong & /*words*/,
ulong & /*sentences*/, ulong & /*syllables*/, ulong & /*lines*/, bool /*process only selected */ ) { return true; }
KWDocument* kWordDocument() const { return m_doc; }
/// Return true if page @p num can be removed, as far as this frameset is concerned
virtual bool canRemovePage( int num );
//Note: none of those floating-frameset methods creates undo/redo
//They are _called_ by the undo/redo commands.
/// Make this frameset floating (anchored), as close to its current position as possible.
void setFloating();
/**
* Make this frameset anchored, with the anchor at @p paragId,@p index in the text frameset @p textfs.
* Also used during OASIS loading (placeHolderExists=true)
*/
void setAnchored( KWTextFrameSet* textfs, KoTextParag* parag, int index, bool placeHolderExists = false, bool repaint = true );
/** Make this frameset floating, with the anchor at @p paragId,@p index in the text frameset @p textfs.
* \deprecated
*/
void setAnchored( KWTextFrameSet* textfs, int paragId, int index, bool placeHolderExists = false, bool repaint = true );
/** Note that this frameset has been made floating already, and store anchor position */
void setAnchored( KWTextFrameSet* textfs );
/// Make this frameset fixed, i.e. not anchored
void setFixed();
/// Return true if this frameset is floating (inline), false if it's fixed
bool isFloating() const { return m_anchorTextFs; }
/// Return the frameset in which our anchor is - assuming isFloating()
KWTextFrameSet * anchorFrameset() const { return m_anchorTextFs; }
/// Sets the frameset in which we are about to become inline. Used for OASIS loading.
void setAnchorFrameset(KWTextFrameSet * textfs) { m_anchorTextFs = textfs; }
/// Return the anchor object for this frame number
KWAnchor * findAnchor( int frameNum );
/// Tell this frame the format of it's anchor
virtual void setAnchorFormat( KoTextFormat* /*format*/, int /*frameNum*/ ) {}
/// Create an anchor for the floating frame identified by frameNum
virtual KWAnchor * createAnchor( KoTextDocument *txt, int frameNum );
/** Move the frame frameNum to the given position - this is called when
the frame is anchored and the anchor moves (see KWAnchor). */
virtual void moveFloatingFrame( int frameNum, const KoPoint &position );
/** Get the size of the "floating frame" identified by frameNum.
By default a real frame but not for tables. */
virtual KoSize floatingFrameSize( int frameNum = 0 );
/** Get the rect of the "floating frame" identified by frameNum,
in coordinates RELATIVE TO THE PARENT FRAMESET.
This is especially important for multi-parent inline frames. */
KoRect floatingFrameRect( int frameNum = 0 );
/** Get the 'baseline' to use for the "floating frame" identified by frameNum.
-1 means same as the height (usual case) */
virtual int floatingFrameBaseline( int /*frameNum*/ ) { return -1; }
/// Store command for creating an anchored object
virtual KCommand * anchoredObjectCreateCommand( int frameNum );
/// Store command for deleting an anchored object
virtual KCommand * anchoredObjectDeleteCommand( int frameNum );
/** make this frameset part of a groupmanager
* @see KWTableFrameSet
*/
void setGroupManager( KWTableFrameSet *gm ) { m_groupmanager = gm; }
/** returns the groupManager this frameset belongs to. A Groupmanager is better known as a table */
KWTableFrameSet *groupmanager()const { return m_groupmanager; }
bool isProtectSize()const { return m_protectSize; }
void setProtectSize( bool _b);
/**
* Returns true if the frameset is visible.
* A frameset is visible if setVisible(false) wasn't called,
* but also, for a header frameset, if m_doc->isHeaderVisible is true, etc.
* For an "even pages header" frameset, the corresponding headerType setting
* must be selected (i.e. different headers for even and odd pages).
* @param viewMode pass the current viewmode when using this method for any visual
* stuff (drawing, handling input etc.). Frameset visibility depends on the viewmode.
*/
bool isVisible( KWViewMode* viewMode = 0L ) const;
/// set the visibility of the frameset.
virtual void setVisible( bool v );
/// get/set frameset name. For tables in particular, this _must_ be unique
QString name() const { return m_name; }
void setName( const QString &name );
/// set frameBehavior on all frames, see KWFrame for specifics
void setFrameBehavior( KWFrame::FrameBehavior fb );
/// set newFrameBehavior on all frames, see KWFrame for specifics
void setNewFrameBehavior( KWFrame::NewFrameBehavior nfb );
#ifndef NDEBUG
virtual void printDebug();
virtual void printDebug( KWFrame * );
#endif
virtual KWTextFrameSet* nextTextObject( KWFrameSet * ) { return 0L;}
bool isPaintedBy( KWFrameSet* fs ) const;
/// set z-order for all frames
virtual void setZOrder();
virtual void setProtectContent ( bool protect ) = 0;
virtual bool protectContent() const = 0;
void setPageManager(KWPageManager *pm) { m_pageManager = pm; }
KWPageManager* pageManager() const { return m_pageManager; }
signals:
/// Emitted when something has changed in this frameset,
/// so that all views repaint it. KWDocument connects to it,
/// and KWCanvas connects to KWDocument.
void repaintChanged( KWFrameSet * frameset );
void sigFrameAdded(KWFrame*);
void sigFrameRemoved(KWFrame*);
void sigNameChanged(KWFrameSet*);
protected:
/// save the common attributes for the frameset
void saveCommon( QDomElement &parentElem, bool saveFrames );
/**Determine the clipping rectangle for drawing the contents of @p frame with @p painter
* in the rectangle delimited by @p crect.
* This determines where to clip the painter to draw the contents of a given frame
*/
QRegion frameClipRegion( QPainter * painter, KWFrame *frame, const QRect & crect,
KWViewMode * viewMode );
void deleteAnchor( KWAnchor * anchor );
virtual void deleteAnchors();
virtual void createAnchors( KoTextParag * parag, int index, bool placeHolderExists = false, bool repaint = true );
KWDocument *m_doc; // Document
QPtrList<KWFrame> m_frames; // Our frames
// Cached info for optimization
/// This array provides a direct access to the frames on page N
QPtrVector< QPtrList<KWFrame> > m_framesInPage;
/// always equal to m_framesInPage[0].first()->pageNumber() :)
int m_firstPage;
/// always empty, for convenience in @ref framesInPage
QPtrList<KWFrame> m_emptyList; // ## make static pointer to save memory ?
Info m_info;
KWTableFrameSet *m_groupmanager;
bool m_visible;
bool m_protectSize;
QString m_name;
KWTextFrameSet * m_anchorTextFs;
KWordFrameSetIface *m_dcop;
KWPageManager *m_pageManager;
};
#endif