/* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer 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 #include #include #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 TDEAction; 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 { TQ_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 &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 & str, const CustomItemsMap & customItemsMap, const TQValueList & 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 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 { TQ_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(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