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/KWTextFrameSet.h

550 lines
23 KiB

/* This file is part of the KDE project
Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@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 kwtextframeset_h
#define kwtextframeset_h
#include "KoRichText.h"
#include "KWFrameSet.h"
#include "KWFrameSetEdit.h"
#include <KoTextView.h>
#include <KoParagLayout.h>
#include <KoChangeCaseDia.h>
#include "KWVariable.h"
class KoGenStyles;
class KoParagStyle;
class KWDocument;
class DCOPObject;
#ifndef KWTextFormat
#define KWTextFormat KoTextFormat
#endif
class KWViewMode;
class KWTextDocument;
class KWordFrameSetIface;
class KWFrame;
class KWFrameViewManager;
class KoTextObject;
class KoDataToolInfo;
class KoVariable;
class KAction;
class KNamedCommand;
class KMacroCommand;
class TQDragObject;
class TQProgressDialog;
/**
* Class: KWTextFrameSet
* Contains text (KoTextObject) and frames to display that text.
*
* This class implements the KoTextFormatInterface methods for "apply to the
* whole text object". This is how "setBold", "setItalic" etc. can apply to
* a whole text frameset.
*/
class KWTextFrameSet : public KWFrameSet, public KoTextFlow, public KoTextFormatInterface
{
Q_OBJECT
public:
/// Cnstructor
KWTextFrameSet( KWDocument *_doc, const TQString & name );
/// Used for OASIS loading
KWTextFrameSet( KWDocument* doc, const TQDomElement& tag, KoOasisContext& context );
/// Destructor
~KWTextFrameSet();
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_TEXT; }
virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * canvas );
/** Return the contained text object */
KoTextObject * textObject() const { return m_textobj; }
KoTextDocument *textDocument() const;
KWTextDocument *kwTextDocument() const;
void setProtectContent ( bool _protect ) { textObject()->setProtectContent(_protect);}
bool protectContent() const { return textObject()->protectContent();}
void clearUndoRedoInfo();
/** Convert the @p dPoint in the normal coordinate system (and in pt)
* into a point (@p iPoint) in the internal qtextdoc coordinates (in layout units). */
KWFrame * documentToInternal( const KoPoint &dPoint, TQPoint &iPoint ) const;
/// used by documentToInternalMouseSelection()
enum RelativePosition { InsideFrame, LeftOfFrame, TopOfFrame, AtEnd };
KWFrame * documentToInternalMouseSelection( const KoPoint &dPoint, TQPoint &iPoint, RelativePosition& relPos, KWViewMode *viewMode ) const;
/** Convert the @p in the internal qtextdoc coordinates (in layout units)
* into a point in the document coordinate system (in pt).
* Also returns the frame in which this point is. */
KWFrame * internalToDocument( const KoPoint &relPoint, KoPoint &dPoint ) const;
// version taking a LU point as input
KWFrame * internalToDocument( const TQPoint &iPoint, KoPoint &dPoint ) const;
/** Same as internalToDocument, but goes directly to the normal coords (zoomed)
* since this method is used for view stuff only (mouse).
* @param hintDPoint hint, in case of copied frames. If specified, its y
* value will be used as a minimum on the returned result, to prefer a frame
* over any of its copies (e.g. in the header/footer case).
* @param iPoint internal document point
* @param dPoint the other point
*/
KWFrame * internalToDocumentWithHint( const TQPoint &iPoint, KoPoint &dPoint, const KoPoint &hintDPoint ) const;
/** A variant of internalToDocument, when the frame is already known.
* Both faster, and more correct for inline frames that spawn over multiple containing frames
*/
KoPoint internalToDocumentKnowingFrame( const KoPoint &relPoint, KWFrame* theFrame ) const;
// [deprecated?] version taking a LU point as input
KoPoint internalToDocumentKnowingFrame( const TQPoint &iPoint, KWFrame* theFrame ) const;
/** Implementation of Ctrl+PageUp/PageDown
* Returns a point in layout units (for placing the cursor) */
TQPoint moveToPage( int currentPgNum, short int direction ) const;
/** Return the available height in pixels (sum of all frames' height, with zoom applied)
* Used to know if we need to create more pages. */
virtual int availableHeight() const;
/** Return true if the last frame is empty */
bool isFrameEmpty( KWFrame * frame );
virtual bool canRemovePage( int num );
// reimp for internal reasons
virtual void deleteFrame( unsigned int num, bool remove = true, bool recalc = true );
void deleteFrame( KWFrame *frm, bool remove = true, bool recalc = true )
{ KWFrameSet::deleteFrame( frm, remove, recalc ); } // strange C++ feature ;)
/** reshuffle frames so text is always displayed from top-left down and then right.
* @param flags
*/
virtual void updateFrames( int flags = 0xff );
/** Views notify the KWTextFrameSet of which area of the text
* they're looking at, so that formatMore() ensures it's always formatted
* correctly.
* @param w the wigdet (usually kwcanvas) that identifies the view
* @param w the current viewmode (to make sure the frameset is visible)
* @param nPointBottom the max the view looks at, in normal coordinates
* @param viewMode the current viewMode
*/
void updateViewArea( TQWidget * w, KWViewMode* viewMode, const TQPoint & nPointBottom );
virtual TQDomElement save( TQDomElement &parentElem, bool saveFrames = true )
{ return saveInternal( parentElem, saveFrames, false ); }
/** save to XML - when copying to clipboard (includes floating framesets) */
virtual TQDomElement toXML( TQDomElement &parentElem, bool saveFrames = true )
{ return saveInternal( parentElem, saveFrames, true ); }
virtual void load( TQDomElement &attributes, bool loadFrames = true );
/// Load the contents of a frame (i.e. the text)
void loadOasisContent( const TQDomElement &bodyElem, KoOasisContext& context );
/// Load a complete textbox (frame and text)
KWFrame* loadOasis( const TQDomElement& frame, const TQDomElement &bodyElem, KoOasisContext& context );
/// Load a frame and add it to this frameset - called by KWOasisLoader
KWFrame* loadOasisTextFrame( const TQDomElement& frameTag, const TQDomElement &tag, KoOasisContext& context );
/// Save the contents of a frame (i.e. the text)
void saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const;
/// Save a complete textbox (frame and text)
virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const;
virtual TQString toPlainText() const;
virtual void finalize();
//virtual void preparePrinting( TQPainter *painter, TQProgressDialog *progress, int &processedParags );
/** return true if some text is selected */
bool hasSelection() const;
/** returns the selected text [without formatting] if hasSelection() */
TQString selectedText() const;
virtual void drawContents( TQPainter *painter, const TQRect &crect,
const TQColorGroup &cg, bool onlyChanged, bool resetChanged,
KWFrameSetEdit* edit, KWViewMode *viewMode,
KWFrameViewManager *frameViewManager );
virtual void drawFrame( KWFrame * frame, TQPainter *painter, const TQRect& fcrect, const TQRect& crect,
const TQPoint& translationOffset,
KWFrame *settingsFrame, const TQColorGroup &cg, bool onlyChanged, bool resetChanged,
KWFrameSetEdit * edit, KWViewMode *viewMode, bool drawUnderlyingFrames );
virtual void drawFrameContents( KWFrame * frame, TQPainter *painter, const TQRect & fcrect,
const TQColorGroup &cg, bool onlyChanged, bool resetChanged,
KWFrameSetEdit * edit, KWViewMode *viewMode );
void drawCursor( TQPainter *p, KoTextCursor *cursor, bool cursorVisible, KWCanvas *canvas, KWFrame *currentFrame );
TQPoint cursorPos( KoTextCursor *cursor, KWCanvas* canvas, KWFrame* currentFrame );
KCommand* pasteOasis( KoTextCursor * cursor, const TQByteArray & data, bool removeSelected );
void insertTOC( KoTextCursor * cursor );
KNamedCommand* insertFrameBreakCommand( KoTextCursor *cursor );
void insertFrameBreak( KoTextCursor * cursor );
KCommand * setPageBreakingCommand( KoTextCursor * cursor, int pageBreaking );
TQRect paragRect( KoTextParag * parag ) const; // in normal coords
KCommand *deleteAnchoredFrame( KWAnchor * anchor );
void findPosition( const KoPoint &dPoint, KoTextParag * & parag, int & index );
/** Highlighting support (for search/replace, spellchecking etc.) */
void highlightPortion( KoTextParag * parag, int index, int length, KWCanvas * canvas, bool repaint = true, KDialogBase* dialog = 0 );
void removeHighlight( bool repaint = true );
virtual void addTextFrameSets( TQPtrList<KWTextFrameSet> &lst, bool onlyReadWrite=false );
/** Update the paragraph that use the given style, after this style was changed.
* The flags tell which changes should be applied.
* @param changed the changed style map
*/
void applyStyleChange( KoStyleChangeDefMap changed );
/** set the visibility of the frameset. */
virtual void setVisible( bool v );
/** Show or hide all inline frames that are inside this frameset */
void setInlineFramesVisible(bool);
#ifndef NDEBUG
virtual void printDebug();
#endif
/** Invalidate all paragraphs and start re-formatting */
virtual void layout();
/** Invalidate all paragraphs (causes a re-flow of the text upon next redraw) */
virtual void invalidate();
virtual int paragraphs();
virtual int paragraphsSelected();
/** Calculate statistics for this frameset */
virtual bool statistics( TQProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace,
ulong & words, ulong& sentences, ulong & syllables, ulong & lines, bool selected );
/** reimplemented from KoTextFlow, implements flowing around frames etc. */
virtual void adjustMargins( int yp, int h, int reqMinWidth, int& leftMargin, int& rightMargin, int& pageWidth, KoTextParag* parag );
/** reimplemented from KoTextParag, adjusts y and returns the shift. */
virtual int adjustFlow( int y, int w, int h );
/** Called by KWTextFormatter. Implements page breaking, breaking around frames, etc. */
int formatVertically( KoTextParag *parag, const TQRect& rect );
/** Called by KWTextFormatter::postFormat() */
void fixParagWidth( KWTextParag* parag );
/** Make sure this paragraph is formatted
* If formatting happens, the afterFormatting signal will only be emitted if emitAfterFormatting is true.
* This prevents re-entrancy if ensureFormatting is called by canRemovePage (from another frameset's
* slotAfterFormatting) */
void ensureFormatted( KoTextParag * parag, bool emitAfterFormatting = true );
/** The viewmode that was passed to drawContents. Special hook for KWAnchor. Don't use. */
KWViewMode * currentViewMode() const { return m_currentViewMode; }
/** The frame that we are currently drawing in drawFrame. Stored here since we can't pass it
* through TQRT's drawing methods. Used by e.g. KWAnchor. */
KWFrame * currentDrawnFrame() const { return m_currentDrawnFrame; }
/** Let KoTextFormatInterface access the current format */
virtual KoTextFormat * currentFormat() const;
/** Let KoTextFormatInterface set the modified format */
virtual KCommand *setFormatCommand( const KoTextFormat * newFormat, int flags, bool zoomFont = false );
/** Let KoTextFormatInterface access the current parag layout */
virtual const KoParagLayout * currentParagLayoutFormat() const;
virtual bool rtl() const ;
/** Let KoTextFormatInterface set a modified current parag layout */
virtual KCommand *setParagLayoutFormatCommand( KoParagLayout *newLayout, int flags, int marginIndex=-1);
virtual KCommand *setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type);
/** (Assuming this==main frameset), recalc the foot note numbers */
void renumberFootNotes( bool repaint = true );
/**
* Iteration over text objects - used by KWBgSpellCheck
*/
virtual KWTextFrameSet* nextTextObject( KWFrameSet * ) { return this;}
/**
* Return the min and max LU coordinates for the text in the given page,
* if the frameset has any frames in this page.
* Used by e.g. KWDoc::sectionTitle and KWFrameLayout.
*/
bool minMaxInternalOnPage( int pageNum, int& topLU, int& bottomLU ) const;
/**
* Find the parag at the given Y position (in LU)
*/
KoTextParag* paragAtLUPos( int yLU ) const;
/**
* Insert a footnote (var and frameset). Shared code for loading and inserting from GUI.
*/
KWFootNoteFrameSet * insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const TQString &manualString );
KoTextDocCommand *deleteTextCommand( KoTextDocument *textdoc, int id, int index, const TQMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const TQValueList<KoParagLayout> & oldParagLayouts );
TQString copyTextParag( KoXmlWriter& writer, KoSavingContext& context, int selectionId );
/// Sort selected paragraphs
/// Return a complete OASIS store, ready for "pasting"
TQByteArray sortText(SortType type) const;
KoLinkVariable* linkVariableUnderMouse( const KoPoint& dPoint );
KoVariable* variableUnderMouse( const KoPoint& dPoint );
signals:
/** Tell the Edit object that this frame got deleted */
void frameDeleted( KWFrame* frame );
/** Tell the text viewmode that the height of the text might have changed */
void mainTextHeightChanged();
public slots:
// Connected to KoTextObject
void slotRepaintChanged();
protected slots:
// All those slots are connected to KoTextObject
void slotAvailableHeightNeeded();
void slotAfterFormatting( int bottom, KoTextParag *lastFormatted, bool* abort );
void slotNewCommand( KCommand *cmd );
void slotParagraphDeleted(KoTextParag*_parag);
void slotParagraphCreated(KoTextParag*_parag);
void slotParagraphModified(KoTextParag*_parag, int /*KoTextParag::ParagModifyType*/, int, int);
protected: // for testing purposes
KWTextFrameSet( const TQString & name );
private:
void init();
bool slotAfterFormattingNeedMoreSpace( int bottom, KoTextParag *lastFormatted );
void slotAfterFormattingTooMuchSpace( int bottom );
void getMargins( int yp, int h, int reqMinWidth, int* marginLeft, int* marginRight, int* pageWidth, int* validHeight,
int* breakBegin, int* breakEnd, KoTextParag* parag );
bool checkVerticalBreak( int & yp, int & h, KoTextParag * parag, bool linesTogether, int breakBegin, int breakEnd );
void frameResized( KWFrame *theFrame, bool invalidateLayout );
/**
* Return the list of frames containing the text that goes from @p y1 to @p y2
* (in internal coordinates).
*/
TQValueList<KWFrame*> framesFromTo( int y1, int y2 ) const;
double footerHeaderSizeMax( KWFrame *theFrame );
double footNoteSize( KWFrame *theFrame );
TQDomElement saveInternal( TQDomElement &parentElem, bool saveFrames, bool saveAnchorsFramesets );
bool createNewPageAndNewFrame( KoTextParag* lastFormatted, int difference );
private:
/** The contained text object */
KoTextObject * m_textobj;
/** The viewmode we currently used (while drawing). For internal purposes (KWAnchor). */
KWViewMode * m_currentViewMode;
/** The frame currently being drawn. */
KWFrame * m_currentDrawnFrame;
/** For the mainTextHeightChanged signal. */
int m_lastTextDocHeight;
};
/**
* Object that is created to edit a Text frame set (KWTextFrameSet).
* It handles all the events for it.
* In terms of doc/view design, this object is part of the _view_.
* There can be several KWFrameSetEdit objects for the same frameset,
* but there is only one KWFrameSetEdit object per view at a given moment.
*/
class KWTextFrameSetEdit : public KoTextView, public KWFrameSetEdit
{
Q_OBJECT
public:
KWTextFrameSetEdit( KWTextFrameSet * fs, KWCanvas * canvas );
virtual ~KWTextFrameSetEdit();
virtual KoTextViewIface* dcopObject();
virtual KWFrameSetEdit* currentTextEdit(){return this;}
virtual void terminate(bool removeselection=true);
KWTextFrameSet * textFrameSet() const
{
return static_cast<KWTextFrameSet*>(frameSet());
}
KoTextDocument * textDocument() const
{
return textFrameSet()->textDocument();
}
// Just in case we change to containing a textview instead
KoTextView * textView() { return this; }
// Events forwarded by the canvas (when being in "edit" mode)
virtual void keyPressEvent( TQKeyEvent * );
virtual void keyReleaseEvent( TQKeyEvent * );
virtual void imStartEvent( TQIMEvent * );
virtual void imComposeEvent( TQIMEvent * );
virtual void imEndEvent( TQIMEvent * );
virtual void mousePressEvent( TQMouseEvent *, const TQPoint &, const KoPoint & );
virtual void mouseMoveEvent( TQMouseEvent *, const TQPoint &, const KoPoint & ); // only called if button is pressed
virtual void mouseReleaseEvent( TQMouseEvent *, const TQPoint &, const KoPoint & );
virtual void mouseDoubleClickEvent( TQMouseEvent *, const TQPoint &, const KoPoint & );
virtual void dragEnterEvent( TQDragEnterEvent * );
virtual void dragMoveEvent( TQDragMoveEvent *, const TQPoint &, const KoPoint & );
virtual void dragLeaveEvent( TQDragLeaveEvent * );
virtual void dropEvent( TQDropEvent *, const TQPoint &, const KoPoint &, KWView* view );
virtual void focusInEvent();
virtual void focusOutEvent();
virtual void selectAll();
// Reimplemented from KoTextView
virtual void drawCursor( bool b );
virtual void showFormat( KoTextFormat *format );
virtual bool pgUpKeyPressed();
virtual bool pgDownKeyPressed();
virtual void ctrlPgUpKeyPressed();
virtual void ctrlPgDownKeyPressed();
void setCursor( KoTextParag* parag, int index );
void insertFrameBreak() { textFrameSet()->insertFrameBreak( cursor() ); }
void insertWPPage();
void insertVariable( int type, int subtype = 0 );
void insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const TQString& manualString );
void insertCustomVariable( const TQString &name);
void insertVariable( KoVariable *var,
KoTextFormat *format = 0 /*means currentFormat()*/,
bool refreshCustomMenu = false/*don't refresh all the time custom menu*/ );
void insertLink(const TQString &_linkName, const TQString & hrefName);
void insertComment(const TQString &_comment);
void insertExpression(const TQString &_c);
void insertFloatingFrameSet( KWFrameSet * fs, const TQString & commandName );
void insertTOC() { textFrameSet()->insertTOC( cursor() ); }
KCommand * setPageBreakingCommand( int pageBreaking )
{ return textFrameSet()->setPageBreakingCommand( cursor(), pageBreaking ); }
//const KoParagLayout & currentParagLayout() const { return m_paragLayout; }
double currentLeftMargin() const { return m_paragLayout.margins[TQStyleSheetItem::MarginLeft]; }
virtual void removeToolTipCompletion();
//bool isLinkVariable(const KoPoint &, bool setUrl=false);
/// Called by KoTextView when clicking on a link
bool openLink( KoLinkVariable* variable );
/// Called by KWView when using the action
void openLink();
void pasteData( TQMimeSource* data, int provides, bool drop );
KCommand* pasteOasisCommand( TQMimeSource* data );
/**
* Return the requested border of the paragraph that the cursor currently is in.
* @param type specifies which of the borders to return;
* @return the requested border of the current paragraph
*/
KoBorder border(KoBorder::BorderType type);
public slots:
// Reimplemented from KWFrameSet and connected to KoTextView's signals
virtual void cut();
virtual void copy();
virtual void paste();
// Reimplemented from KoTextView
virtual void updateUI( bool updateFormat, bool force = false );
virtual void ensureCursorVisible();
protected:
// Reimplemented from KoTextView
virtual void doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, TQChar ch );
virtual bool doIgnoreDoubleSpace(KoTextParag * parag, int index,TQChar ch );
virtual bool doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index );
virtual bool doToolTipCompletion( KoTextCursor* cursor, KoTextParag *parag, int index,int keyPress );
virtual void showToolTipBox(KoTextParag *parag, int index, TQWidget *widget, const TQPoint &pos);
virtual void textIncreaseIndent();
virtual bool textDecreaseIndent();
virtual void startDrag();
TQDragObject * newDrag( TQWidget * parent );
private slots:
void slotFrameDeleted(KWFrame *);
private:
bool enterCustomItem( KoTextCustomItem* customItem, bool fromRight );
KoParagLayout m_paragLayout;
bool m_rtl; // maybe make part of KoParagLayout later
};
class KWFootNoteVariable;
class KWFootNoteFrameSet : public KWTextFrameSet
{
public:
/** constructor */
KWFootNoteFrameSet( KWDocument *doc, const TQString & name )
: KWTextFrameSet( doc, name ), m_footNoteVar( 0L ) {}
virtual KWordFrameSetIface* dcopObject();
void setFootNoteVariable( KWFootNoteVariable* var );
KWFootNoteVariable* footNoteVariable() const { return m_footNoteVar; }
/** Create the first frame for this frameset.
* KWFrameLayout will reposition it at the correct place.
*/
void createInitialFrame( int pageNum );
/**
* Edit and ensure cursor is visible. Helper function which is useful because
* the caller is usually a KWFrameSetEdit, which gets deleted by the
* editFrameSet() call.
*/
void startEditing( KWCanvas* canvas );
/** Called by KWTextFrameSet::renumberFootNotes.
* Sets the text of the parag-counter in the footnote text.
*/
void setCounterText( const TQString& text );
virtual bool isFootNote() const;
virtual bool isEndNote() const;
private:
KWFootNoteVariable* m_footNoteVar;
};
#endif