diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
| commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
| tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kpresenter/KPrTextObject.cpp | |
| download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip | |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kpresenter/KPrTextObject.cpp')
| -rw-r--r-- | kpresenter/KPrTextObject.cpp | 2586 |
1 files changed, 2586 insertions, 0 deletions
diff --git a/kpresenter/KPrTextObject.cpp b/kpresenter/KPrTextObject.cpp new file mode 100644 index 000000000..74d3ee7e8 --- /dev/null +++ b/kpresenter/KPrTextObject.cpp @@ -0,0 +1,2586 @@ +// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org> + Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@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. +*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "KPrTextObject.h" +#include "KPrTextObject.moc" +#include "KPrGradient.h" +#include "KPrCommand.h" +#include "KPrCanvas.h" +#include "KPrPage.h" +#include "KPrView.h" +#include "KPrDocument.h" +#include "KPrBgSpellCheck.h" +#include "KPrVariableCollection.h" + +#include <KoAutoFormat.h> +#include <KoTextParag.h> +#include <KoTextObject.h> +#include <KoStyleCollection.h> +#include <KoTextFormatter.h> +#include <KoTextZoomHandler.h> +#include "KPrTextViewIface.h" +#include "KPrTextObjectIface.h" +#include <KoOasisContext.h> +#include <KoStyleStack.h> +#include <ktempfile.h> +#include <klocale.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kmultipledrag.h> + +#include <qfont.h> +#include <qfile.h> +#include <qwidget.h> +#include <qpicture.h> +#include <qpainter.h> +#include <qwmatrix.h> +#include <qdom.h> +#include <qapplication.h> +#include <qfontdatabase.h> +#include <qpopupmenu.h> +#include <qclipboard.h> + +#include <KoParagCounter.h> +#include <kaction.h> +#include <KoVariable.h> +#include <KoCustomVariablesDia.h> +#include <KoRuler.h> +#include <KoSize.h> +#include <KoXmlNS.h> +#include <KoDom.h> +#include <KoStore.h> +#include <KoStoreDrag.h> +#include <KoOasisStore.h> + +#include <float.h> +using namespace std; + +#undef S_NONE // Solaris defines it in sys/signal.h + +const QString &KPrTextObject::tagTEXTOBJ=KGlobal::staticQString("TEXTOBJ"); +const QString &KPrTextObject::attrLineSpacing=KGlobal::staticQString("lineSpacing"); +const QString &KPrTextObject::attrParagSpacing=KGlobal::staticQString("paragSpacing"); +const QString &KPrTextObject::attrMargin=KGlobal::staticQString("margin"); +const QString &KPrTextObject::attrBulletType1=KGlobal::staticQString("bulletType1"); +const QString &KPrTextObject::attrBulletType2=KGlobal::staticQString("bulletType2"); +const QString &KPrTextObject::attrBulletType3=KGlobal::staticQString("bulletType3"); +const QString &KPrTextObject::attrBulletType4=KGlobal::staticQString("bulletType4"); +const QString &KPrTextObject::attrBulletColor1=KGlobal::staticQString("bulletColor1"); +const QString &KPrTextObject::attrBulletColor2=KGlobal::staticQString("bulletColor2"); +const QString &KPrTextObject::attrBulletColor3=KGlobal::staticQString("bulletColor3"); +const QString &KPrTextObject::attrBulletColor4=KGlobal::staticQString("bulletColor4"); +const QString &KPrTextObject::tagP=KGlobal::staticQString("P"); +const QString &KPrTextObject::attrAlign=KGlobal::staticQString("align"); +const QString &KPrTextObject::attrType=KGlobal::staticQString("type"); +const QString &KPrTextObject::attrDepth=KGlobal::staticQString("depth"); +const QString &KPrTextObject::tagTEXT=KGlobal::staticQString("TEXT"); +const QString &KPrTextObject::attrFamily=KGlobal::staticQString("family"); +const QString &KPrTextObject::attrPointSize=KGlobal::staticQString("pointSize"); +const QString &KPrTextObject::attrBold=KGlobal::staticQString("bold"); +const QString &KPrTextObject::attrItalic=KGlobal::staticQString("italic"); +const QString &KPrTextObject::attrUnderline=KGlobal::staticQString("underline"); +const QString &KPrTextObject::attrStrikeOut=KGlobal::staticQString("strikeOut"); +const QString &KPrTextObject::attrColor=KGlobal::staticQString("color"); +const QString &KPrTextObject::attrWhitespace=KGlobal::staticQString("whitespace"); +const QString &KPrTextObject::attrTextBackColor=KGlobal::staticQString("textbackcolor"); +const QString &KPrTextObject::attrVertAlign=KGlobal::staticQString("VERTALIGN"); + + +KPrTextObject::KPrTextObject( KPrDocument *doc ) + : KPr2DObject() +{ + m_doc=doc; + m_textVertAlign = KP_TOP; + // Default color should be QColor() ... but kpresenter isn't fully color-scheme-aware yet + KoTextFormatCollection* fc = new KoTextFormatCollection( doc->defaultFont(), Qt::black, doc->globalLanguage(), doc->globalHyphenation() ); + KPrTextDocument * textdoc = new KPrTextDocument( this, fc ); + if ( m_doc->tabStopValue() != -1 ) + textdoc->setTabStops( m_doc->zoomHandler()->ptToLayoutUnitPixX( m_doc->tabStopValue() )); + + m_textobj = new KoTextObject( textdoc, m_doc->styleCollection()->findStyle( "Standard" ), this ); + textdoc->setFlow( this ); + + m_doc->backSpeller()->registerNewTextObject( m_textobj ); + pen = defaultPen(); + drawEditRect = true; + drawEmpty = true; + editingTextObj = false; + + bleft = 0.0; + btop = 0.0; + bright = 0.0; + bbottom = 0.0; + alignVertical = 0.0; + + connect( m_textobj, SIGNAL( newCommand( KCommand * ) ), + SLOT( slotNewCommand( KCommand * ) ) ); + connect( m_textobj, SIGNAL( availableHeightNeeded() ), + SLOT( slotAvailableHeightNeeded() ) ); + connect( m_textobj, SIGNAL( repaintChanged( KoTextObject* ) ), + SLOT( slotRepaintChanged() ) ); + + // Send our "repaintChanged" signals to the document. + connect( this, SIGNAL( repaintChanged( KPrTextObject * ) ), + m_doc, SLOT( slotRepaintChanged( KPrTextObject * ) ) ); + connect(m_textobj, SIGNAL( showFormatObject(const KoTextFormat &) ), + SLOT( slotFormatChanged(const KoTextFormat &)) ); + connect( m_textobj, SIGNAL( afterFormatting( int, KoTextParag*, bool* ) ), + SLOT( slotAfterFormatting( int, KoTextParag*, bool* ) ) ); + connect( m_textobj, SIGNAL( paragraphDeleted( KoTextParag*) ), + SLOT( slotParagraphDeleted(KoTextParag*) )); + +} + +KPrTextObject::~KPrTextObject() +{ + textDocument()->takeFlow(); + m_doc = 0L; +} + +DCOPObject* KPrTextObject::dcopObject() +{ + if ( !dcop ) + dcop = new KPrTextObjectIface( this ); + return dcop; +} + +void KPrTextObject::slotParagraphDeleted(KoTextParag*_parag) +{ + m_doc->spellCheckParagraphDeleted( _parag, this); +} + +QBrush KPrTextObject::getBrush() const +{ + QBrush tmpBrush( m_brush.getBrush() ); + if(!tmpBrush.color().isValid()) + tmpBrush.setColor(QApplication::palette().color( QPalette::Active, QColorGroup::Base )); + return tmpBrush; +} + +void KPrTextObject::resizeTextDocument( bool widthChanged, bool heightChanged ) +{ + if ( heightChanged ) + { + // Recalc available height + slotAvailableHeightNeeded(); + // Recalc the vertical centering, if enabled + recalcVerticalAlignment(); + } + if ( widthChanged ) + { + // not when simply changing the height, otherwise the auto-resize code + // prevents making a textobject less high than it currently is. + textDocument()->setWidth( m_doc->zoomHandler()->ptToLayoutUnitPixX( innerWidth() ) ); + m_textobj->setLastFormattedParag( textDocument()->firstParag() ); + m_textobj->formatMore( 2 ); + } +} + +void KPrTextObject::setSize( double _width, double _height ) +{ + bool widthModified = KABS( _width - ext.width() ) > DBL_EPSILON ; // floating-point equality test + bool heightModified = KABS( _height - ext.height() ) > DBL_EPSILON; + if ( widthModified || heightModified ) + { + KPrObject::setSize( _width, _height ); + resizeTextDocument( widthModified, heightModified ); // will call formatMore() if widthModified + } +} + +QDomDocumentFragment KPrTextObject::save( QDomDocument& doc, double offset ) +{ + QDomDocumentFragment fragment=KPr2DObject::save(doc, offset); + fragment.appendChild(saveKTextObject( doc )); + return fragment; +} + +bool KPrTextObject::saveOasisObjectAttributes( KPOasisSaveContext &sc ) const +{ + sc.xmlWriter.startElement( "draw:text-box" ); + m_textobj->saveOasisContent( sc.xmlWriter, sc.context ); + sc.xmlWriter.endElement(); + return true; +} + +const char * KPrTextObject::getOasisElementName() const +{ + return "draw:frame"; +} + +void KPrTextObject::saveOasisMarginElement( KoGenStyle &styleobjectauto ) const +{ + kdDebug()<<"void KPrTextObject::saveOasisMarginElement( KoGenStyle &styleobjectauto )\n"; + if ( btop != 0.0 ) + styleobjectauto.addPropertyPt("fo:padding-top", btop ); + if ( bbottom != 0.0 ) + styleobjectauto.addPropertyPt("fo:padding-bottom", bbottom ); + if ( bleft != 0.0 ) + styleobjectauto.addPropertyPt("fo:padding-left", bleft ); + if ( bright != 0.0 ) + styleobjectauto.addPropertyPt("fo:padding-right", bright ); + + //add vertical alignment + switch( m_textVertAlign ) + { + case KP_TOP: + styleobjectauto.addProperty("draw:textarea-vertical-align", "top" ); + break; + case KP_CENTER: + styleobjectauto.addProperty("draw:textarea-vertical-align", "middle" ); + break; + case KP_BOTTOM: + styleobjectauto.addProperty("draw:textarea-vertical-align", "bottom" ); + break; + } + + // fo:padding-top="1.372cm" fo:padding-bottom="0.711cm" fo:padding-left="1.118cm" fo:padding-right="1.27cm" +} + +void KPrTextObject::loadOasis(const QDomElement &element, KoOasisContext& context, + KPrLoadingInfo *info ) +{ + KPr2DObject::loadOasis(element, context, info); + //todo other attribute + KoStyleStack &styleStack = context.styleStack(); + styleStack.setTypeProperties( "graphic" ); + if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-top" ) ) + btop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-top" ) ); + if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-bottom" ) ) + bbottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-bottom" ) ); + if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-left") ) + bleft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-left" ) ); + if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-right" ) ) + bright = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-right" ) ); + kdDebug()<<" KPrTextObject::loadOasis : btp :"<<btop<<" bbottom :"<<bbottom<<" bleft :"<<bleft<<" bright :"<<bright<<endl; + // vertical alignment + if ( styleStack.hasAttributeNS( KoXmlNS::draw, "textarea-vertical-align" ) ) + { + QString alignment = styleStack.attributeNS( KoXmlNS::draw, "textarea-vertical-align" ); + if ( alignment == "top" ) + m_textVertAlign= KP_TOP; + else if ( alignment == "middle" ) + m_textVertAlign= KP_CENTER; + else if ( alignment == "bottom" ) + m_textVertAlign= KP_BOTTOM; + } + kdDebug()<<" vertical Alignment :"<< ( ( m_textVertAlign== KP_TOP ) ? "top" : ( m_textVertAlign== KP_CENTER ) ? "center": "bottom" )<<endl; + QDomElement tmp = KoDom::namedItemNS( element, KoXmlNS::draw, "text-box"); + m_textobj->loadOasisContent( tmp, context, m_doc->styleCollection() ); + resizeTextDocument(); // this will to formatMore() +} + + +double KPrTextObject::load(const QDomElement &element) +{ + double offset=KPr2DObject::load(element); + QDomElement e=element.namedItem(tagTEXTOBJ).toElement(); + if(!e.isNull()) { + if ( e.hasAttribute( "protectcontent")) + setProtectContent((bool)e.attribute( "protectcontent" ).toInt()); + if (e.hasAttribute( "bleftpt")) + bleft = e.attribute( "bleftpt").toDouble(); + if (e.hasAttribute( "brightpt")) + bright = e.attribute( "brightpt").toDouble(); + if (e.hasAttribute( "btoppt")) + btop = e.attribute( "btoppt").toDouble(); + if (e.hasAttribute( "bbottompt")) + bbottom = e.attribute( "bbottompt").toDouble(); + if ( e.hasAttribute("verticalAlign")) + { + QString str =e.attribute("verticalAlign"); + if ( str == "bottom" ) + m_textVertAlign= KP_BOTTOM; + else if ( str == "center" ) + m_textVertAlign= KP_CENTER; + else if ( str == "top" )//never + m_textVertAlign= KP_TOP; + } + if ( e.hasAttribute( "verticalValue" )) + alignVertical = e.attribute( "verticalValue" ).toDouble(); + + loadKTextObject( e ); + } + + shadowCompatibility(); + + resizeTextDocument(); // this will to formatMore() + return offset; +} + +void KPrTextObject::shadowCompatibility() +{ + if ( shadowDistance != 0) + { + int sx = 0; + int sy = 0; + switch ( shadowDirection ) + { + case SD_LEFT_BOTTOM: + case SD_LEFT: + case SD_LEFT_UP: + sx = - shadowDistance; + case SD_RIGHT_UP: + case SD_RIGHT: + case SD_RIGHT_BOTTOM: + sx = shadowDistance; + default: + break; + } + switch ( shadowDirection ) + { + case SD_LEFT_UP: + case SD_UP: + case SD_RIGHT_UP: + sy = - shadowDistance; + case SD_LEFT_BOTTOM: + case SD_BOTTOM: + case SD_RIGHT_BOTTOM: + sy = shadowDistance; + default: + break; + } + KoTextFormat tmpFormat; + tmpFormat.setShadow( sx, sy, shadowColor ); + KCommand* cmd = m_textobj->setFormatCommand( &tmpFormat, KoTextFormat::ShadowText ); + delete cmd; + } + //force to reset shadow compatibility between koffice 1.1 and 1.2 + shadowDirection = SD_RIGHT_BOTTOM; + shadowDistance = 0; + shadowColor = Qt::gray; +} + + +// Standard paint method for KP2DObjects. +void KPrTextObject::paint( QPainter *_painter, KoTextZoomHandler*_zoomHandler, + int pageNum, bool drawingShadow, bool drawContour ) +{ + // Never draw shadow (in text objects, it's a character property, not an object property) + KPrPage *p = m_doc->pageList().at( pageNum ); + // neccessary when on masterpage + if ( p ) + recalcPageNum( p ); + if ( drawingShadow ) return; + paint( _painter, _zoomHandler, false, 0L, true, drawContour ); +} + +// Special method for drawing a text object that is being edited +void KPrTextObject::paintEdited( QPainter *_painter, KoTextZoomHandler*_zoomHandler, + bool onlyChanged, KoTextCursor* cursor, bool resetChanged ) +{ + _painter->save(); + _painter->translate( _zoomHandler->zoomItX(orig.x()), _zoomHandler->zoomItY(orig.y()) ); + + if ( angle != 0 ) + rotateObject(_painter,_zoomHandler); + paint( _painter, _zoomHandler, onlyChanged, cursor, resetChanged, false /*not drawContour*/ ); + _painter->restore(); +} + +// Common functionality for the above 2 methods +void KPrTextObject::paint( QPainter *_painter, KoTextZoomHandler*_zoomHandler, + bool onlyChanged, KoTextCursor* cursor, bool resetChanged, + bool drawContour ) +{ + double ow = ext.width(); + double oh = ext.height(); + double pw = pen.pointWidth() / 2; + if ( drawContour ) { + QPen pen3( Qt::black, 1, Qt::DotLine ); + _painter->setPen( pen3 ); + _painter->setRasterOp( Qt::NotXorROP ); + _painter->drawRect( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw), + _zoomHandler->zoomItX(ow), _zoomHandler->zoomItY( oh) ); + + return; + } + + _painter->save(); + QPen pen2 = pen.zoomedPen(_zoomHandler); + //QRect clip=QRect(_zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw), _zoomHandler->zoomItX( ow - 2 * pw),_zoomHandler->zoomItY( oh - 2 * pw)); + //setupClipRegion( _painter, clip ); + //for debug + //_painter->fillRect( clip, Qt::blue ); + _painter->setPen( pen2 ); + + if ( editingTextObj && _painter->device() && _painter->device()->devType() != QInternal::Printer) // editing text object + _painter->setBrush( QBrush( m_doc->txtBackCol(), Qt::SolidPattern ) ); + else { + // Handle the rotation, draw the background/border, then call drawText() + if ( getFillType() == FT_BRUSH || !gradient ) { + _painter->setBrush( getBrush() ); + } + else { + QSize size( _zoomHandler->zoomSize( ext ) ); + gradient->setSize( size ); + _painter->drawPixmap( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItX(pw), gradient->pixmap(), 0, 0, + _zoomHandler->zoomItX( ow - 2 * pw ), + _zoomHandler->zoomItY( oh - 2 * pw ) ); + } + } + if ( !editingTextObj || !onlyChanged ) + { + /// #### Port this to KoBorder, see e.g. kword/kwframe.cc:590 + // (so that the border gets drawn OUTSIDE of the object area) + _painter->drawRect( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItX(pw), _zoomHandler->zoomItX( ow - 2 * pw), + _zoomHandler->zoomItY( oh - 2 * pw) ); + } + + drawText( _painter, _zoomHandler, onlyChanged, cursor, resetChanged ); + _painter->restore(); + + + // And now draw the border for text objects. + // When they are drawn outside of the object, this can be moved to the standard paint() method, + // so that we don't have to do it while editing the object, maybe. + if ( m_doc->firstView() && m_doc->firstView()->getCanvas()->getEditMode() && + getDrawEditRect() && getPen().style() == Qt::NoPen ) + { + _painter->save(); + + _painter->setPen( QPen( Qt::gray, 1, Qt::DotLine ) ); + _painter->setBrush( Qt::NoBrush ); + _painter->setRasterOp( Qt::NotXorROP ); + _painter->drawRect( 0, 0, _zoomHandler->zoomItX(ow), _zoomHandler->zoomItY( oh) ); + + _painter->restore(); + } +} + +// This method simply draws the paragraphs in the given painter +// Assumes the painter is already set up correctly. +void KPrTextObject::drawText( QPainter* _painter, KoTextZoomHandler *zoomHandler, bool onlyChanged, KoTextCursor* cursor, bool resetChanged ) +{ + //kdDebug(33001) << "KPrTextObject::drawText onlyChanged=" << onlyChanged << " cursor=" << cursor << " resetChanged=" << resetChanged << endl; + recalcVerticalAlignment(); + QColorGroup cg = QApplication::palette().active(); + _painter->save(); + _painter->translate( m_doc->zoomHandler()->zoomItX( bLeft()), m_doc->zoomHandler()->zoomItY( bTop()+alignVertical)); + if ( !editingTextObj || (_painter->device() && _painter->device()->devType() == QInternal::Printer)) + cg.setBrush( QColorGroup::Base, NoBrush ); + else + cg.setColor( QColorGroup::Base, m_doc->txtBackCol() ); + + QRect r = zoomHandler->zoomRect( KoRect( 0, 0, innerWidth(), innerHeight() ) ); + bool editMode = false; + if( m_doc->firstView() && m_doc->firstView()->getCanvas()) + editMode = m_doc->firstView()->getCanvas()->getEditMode(); + + uint drawingFlags = 0; + if ( _painter->device() && _painter->device()->devType() != QInternal::Printer ) + drawingFlags |= KoTextDocument::DrawSelections; + if ( m_doc->backgroundSpellCheckEnabled() && editMode ) + drawingFlags |= KoTextDocument::DrawMisspelledLine; + if ( !editMode ) + drawingFlags |= KoTextDocument::DontDrawNoteVariable; + if ( m_doc->viewFormattingChars() && editMode ) + drawingFlags |= KoTextDocument::DrawFormattingChars; + + if ( specEffects ) + { + switch ( effect2 ) + { + case EF2T_PARA: + //kdDebug(33001) << "KPrTextObject::draw onlyCurrStep=" << onlyCurrStep << " subPresStep=" << subPresStep << endl; + drawParags( _painter, zoomHandler, cg, ( onlyCurrStep ? subPresStep : 0 ), subPresStep ); + break; + default: + /*KoTextParag * lastFormatted =*/ textDocument()->drawWYSIWYG( + _painter, r.x(), r.y(), r.width(), r.height(), + cg, zoomHandler, + onlyChanged, cursor != 0, cursor, resetChanged, drawingFlags ); + } + } + else + { + + //kdDebug(33001) << "KPrTextObject::drawText r=" << DEBUGRECT(r) << endl; + /*KoTextParag * lastFormatted = */ textDocument()->drawWYSIWYG( + _painter, r.x(), r.y(), r.width(), r.height(), + cg, zoomHandler, + onlyChanged, cursor != 0, cursor, resetChanged, drawingFlags ); + } + _painter->restore(); +} + +int KPrTextObject::getSubPresSteps() const +{ + int paragraphs = 0; + KoTextParag * parag = textDocument()->firstParag(); + for ( ; parag ; parag = parag->next() ) + paragraphs++; + return paragraphs; +} + + +QDomElement KPrTextObject::saveKTextObject( QDomDocument& doc ) +{ +#if 0 + KTextEditParag *parag = ktextobject.document()->firstParag(); + KTextEditDocument::TextSettings textSettings = ktextobject.document()->textSettings(); +#endif + + QDomElement textobj=doc.createElement(tagTEXTOBJ); + if ( isProtectContent() ) + textobj.setAttribute( "protectcontent", (int)isProtectContent()); + if (bleft !=0.0) + textobj.setAttribute( "bleftpt", bleft ); + if (bright !=0.0) + textobj.setAttribute( "brightpt", bright ); + if (btop !=0.0) + textobj.setAttribute( "btoppt", btop ); + if (bbottom !=0.0) + textobj.setAttribute( "bbottompt", bbottom ); + if ( m_textVertAlign != KP_TOP ) + { + if ( m_textVertAlign == KP_BOTTOM ) + textobj.setAttribute( "verticalAlign", "bottom" ); + else if ( m_textVertAlign == KP_CENTER ) + textobj.setAttribute( "verticalAlign", "center" ); + else if ( m_textVertAlign == KP_TOP )//never + textobj.setAttribute( "verticalAlign", "top" ); + textobj.setAttribute( "verticalValue",alignVertical ); + } +#if 0 + textobj.setAttribute(attrLineSpacing, ktextobject.document()->lineSpacing()); + textobj.setAttribute(attrParagSpacing, ktextobject.document()->paragSpacing()); + textobj.setAttribute(attrMargin, ktextobject.document()->margin()); + textobj.setAttribute(attrBulletType1, (int)textSettings.bulletType[0]); + textobj.setAttribute(attrBulletType2, (int)textSettings.bulletType[1]); + textobj.setAttribute(attrBulletType3, (int)textSettings.bulletType[2]); + textobj.setAttribute(attrBulletType4, (int)textSettings.bulletType[3]); + textobj.setAttribute(attrBulletColor1, textSettings.bulletColor[0].name()); + textobj.setAttribute(attrBulletColor2, textSettings.bulletColor[1].name()); + textobj.setAttribute(attrBulletColor3, textSettings.bulletColor[2].name()); + textobj.setAttribute(attrBulletColor4, textSettings.bulletColor[3].name()); +#endif + KoTextParag *parag = static_cast<KoTextParag*> (textDocument()->firstParag()); + // ### fix this loop (Werner) + while ( parag ) { + saveParagraph( doc, parag, textobj, 0, parag->length()-2 ); + parag = static_cast<KoTextParag*>( parag->next()); + } + return textobj; +} + +void KPrTextObject::saveFormat( QDomElement & element, KoTextFormat*lastFormat ) +{ + QString tmpFamily, tmpColor, tmpTextBackColor; + unsigned int tmpBold=false, tmpItalic=false, tmpUnderline=false,tmpStrikeOut=false; + int tmpVerticalAlign=-1; + + tmpFamily=lastFormat->font().family(); + tmpBold=static_cast<unsigned int>(lastFormat->font().bold()); + tmpItalic=static_cast<unsigned int>(lastFormat->font().italic()); + tmpUnderline=static_cast<unsigned int>(lastFormat->underline()); + tmpStrikeOut=static_cast<unsigned int>(lastFormat->strikeOut()); + tmpColor=lastFormat->color().name(); + tmpVerticalAlign=static_cast<unsigned int>(lastFormat->vAlign()); + if(lastFormat->textBackgroundColor().isValid()) + tmpTextBackColor=lastFormat->textBackgroundColor().name(); + + element.setAttribute(attrFamily, tmpFamily); + element.setAttribute(attrPointSize, lastFormat->pointSize()); + + if(tmpBold) + element.setAttribute(attrBold, tmpBold); + if(tmpItalic) + element.setAttribute(attrItalic, tmpItalic); + if ( lastFormat->underlineType()!= KoTextFormat::U_NONE ) + { + if(lastFormat->doubleUnderline()) + element.setAttribute(attrUnderline, "double"); + if(lastFormat->underlineType()==KoTextFormat::U_SIMPLE_BOLD) + element.setAttribute(attrUnderline, "single-bold"); + else if( lastFormat->underlineType()==KoTextFormat::U_WAVE) + element.setAttribute(attrUnderline, "wave"); + else if(tmpUnderline) + element.setAttribute(attrUnderline, tmpUnderline); + QString strLineType=KoTextFormat::underlineStyleToString( lastFormat->underlineStyle() ); + element.setAttribute( "underlinestyleline", strLineType ); + if ( lastFormat->textUnderlineColor().isValid() ) + element.setAttribute( "underlinecolor", lastFormat->textUnderlineColor().name() ); + } + if ( lastFormat->strikeOutType()!= KoTextFormat::S_NONE ) + { + if ( lastFormat->doubleStrikeOut() ) + element.setAttribute(attrStrikeOut, "double"); + else if ( lastFormat->strikeOutType()== KoTextFormat::S_SIMPLE_BOLD) + element.setAttribute(attrStrikeOut, "single-bold"); + else if(tmpStrikeOut) + element.setAttribute(attrStrikeOut, tmpStrikeOut); + QString strLineType=KoTextFormat::strikeOutStyleToString( lastFormat->strikeOutStyle() ); + element.setAttribute( "strikeoutstyleline", strLineType ); + + } + element.setAttribute(attrColor, tmpColor); + + if(!tmpTextBackColor.isEmpty()) + element.setAttribute(attrTextBackColor, tmpTextBackColor); + if(tmpVerticalAlign!=-1) + { + element.setAttribute(attrVertAlign,tmpVerticalAlign); + if(lastFormat->relativeTextSize()!=0.66) + element.setAttribute("relativetextsize",lastFormat->relativeTextSize()); + } + + if ( lastFormat->shadowDistanceX() != 0 + || lastFormat->shadowDistanceY() != 0) + element.setAttribute("text-shadow", lastFormat->shadowAsCss()); + if ( lastFormat->offsetFromBaseLine()!=0 ) + element.setAttribute( "offsetfrombaseline" , lastFormat->offsetFromBaseLine()); + if ( lastFormat->wordByWord() ) + element.setAttribute("wordbyword", true); + if ( lastFormat->attributeFont()!= KoTextFormat::ATT_NONE ) + element.setAttribute("fontattribute", KoTextFormat::attributeFontToString(lastFormat->attributeFont() )); + if ( !lastFormat->language().isEmpty()) + element.setAttribute("language", lastFormat->language()); +} + +QDomElement KPrTextObject::saveHelper(const QString &tmpText,KoTextFormat*lastFormat , QDomDocument &doc) +{ + QDomElement element=doc.createElement(tagTEXT); + + saveFormat ( element, lastFormat ); + + if(tmpText.stripWhiteSpace().isEmpty()) + // working around a bug in QDom + element.setAttribute(attrWhitespace, tmpText.length()); + element.appendChild(doc.createTextNode(tmpText)); + return element; +} + +void KPrTextObject::fillStyle( KoGenStyle& styleObjectAuto, KoGenStyles& mainStyles ) const +{ + KPr2DObject::fillStyle( styleObjectAuto, mainStyles ); + saveOasisMarginElement( styleObjectAuto ); +} + +void KPrTextObject::loadKTextObject( const QDomElement &elem ) +{ + QDomElement e = elem.firstChild().toElement(); + KoTextParag *lastParag = static_cast<KoTextParag *>(textDocument()->firstParag()); + int i = 0; + int listNum = 0; + // Initialize lineSpacing and paragSpacing with the values of the object-level attributes + // (KOffice-1.1 file format) + int lineSpacing = elem.attribute( attrLineSpacing ).toInt(); + int bottomBorder = elem.attribute( attrParagSpacing ).toInt(); + int topBorder = 0; + + while ( !e.isNull() ) { + QValueList<QDomElement> listVariable; + listVariable.clear(); + + if ( e.tagName() == tagP ) { + QDomElement n = e.firstChild().toElement(); + + //skip the whitespace if it's a bullet/number + if( e.hasAttribute( attrType ) && n.hasAttribute( attrWhitespace ) ) + if ( e.attribute( attrType )!="0" && n.attribute( attrWhitespace )=="1" ) { + e = e.nextSibling().toElement(); + continue; + } + + KoParagLayout paragLayout = loadParagLayout(e, m_doc, true); + + // compatibility (bullet/numbering depth); only a simulation thru the margins, this is how it _looked_ before + double depth = 0.0; + if( e.hasAttribute(attrDepth) ) { + depth = e.attribute( attrDepth ).toDouble(); + paragLayout.margins[QStyleSheetItem::MarginLeft] = depth * MM_TO_POINT(10.0); + } + + //kdDebug(33001) << k_funcinfo << "old bullet depth is: " << depth << endl; + + // 1.1 compatibility (bullets) + QString type; + if( e.hasAttribute(attrType) ) + type = e.attribute( attrType ); + + //kdDebug(33001) << k_funcinfo << "old PARAG type is: " << type << endl; + + // Do not import type="2" (enum list). The enum was there in 1.1, but not the code! + if(type == "1") + { + if(!paragLayout.counter) + paragLayout.counter = new KoParagCounter; + paragLayout.counter->setStyle(KoParagCounter::STYLE_DISCBULLET); + paragLayout.counter->setNumbering(KoParagCounter::NUM_LIST); + paragLayout.counter->setPrefix(QString::null); + paragLayout.counter->setSuffix(QString::null); + } + + // This is for very old (KOffice-1.0) documents. + if ( e.hasAttribute( attrLineSpacing ) ) + lineSpacing = e.attribute( attrLineSpacing ).toInt(); + if ( e.hasAttribute( "distBefore" ) ) + topBorder = e.attribute( "distBefore" ).toInt(); + if ( e.hasAttribute( "distAfter" ) ) + bottomBorder = e.attribute( "distAfter" ).toInt(); + + // Apply values coming from 1.0 or 1.1 documents + if ( paragLayout.lineSpacingValue() == 0 ) + paragLayout.setLineSpacingValue(lineSpacing); + if ( paragLayout.margins[ QStyleSheetItem::MarginTop ] == 0 ) + paragLayout.margins[ QStyleSheetItem::MarginTop ] = topBorder; + if ( paragLayout.margins[ QStyleSheetItem::MarginBottom ] == 0 ) + paragLayout.margins[ QStyleSheetItem::MarginBottom ] = bottomBorder; + lastParag->setParagLayout( paragLayout ); + //lastParag->setAlign(Qt::AlignAuto); + + if(e.hasAttribute(attrAlign)) + { + int tmpAlign=e.attribute( attrAlign ).toInt(); + if(tmpAlign==1 || tmpAlign==0 /* a kpresenter version I think a cvs version saved leftAlign = 0 for header/footer */) + lastParag->setAlign(Qt::AlignLeft); + else if(tmpAlign==2) + lastParag->setAlign(Qt::AlignRight); + else if(tmpAlign==4) + lastParag->setAlign(Qt::AlignHCenter); + else if(tmpAlign==8) + lastParag->setAlign(Qt::AlignJustify); + else + kdDebug(33001) << "Error in e.attribute( attrAlign ).toInt()" << endl; + } + // ######## TODO paragraph direction (LTR or RTL) + + // TODO check/convert values + bool firstTextTag = true; + while ( !n.isNull() ) { + if ( n.tagName() == tagTEXT ) { + + if ( firstTextTag ) { + lastParag->remove( 0, 1 ); // Remove current trailing space + firstTextTag = false; + } + KoTextFormat fm = loadFormat( n, lastParag->paragraphFormat(), m_doc->defaultFont(), m_doc->globalLanguage(), + m_doc->globalHyphenation() ); + + QString txt = n.firstChild().toText().data(); + + if(n.hasAttribute(attrWhitespace)) { + int ws=n.attribute(attrWhitespace).toInt(); + txt.fill(' ', ws); + } + n=n.nextSibling().toElement(); + if ( n.isNull() ) + txt += ' '; // trailing space at end of paragraph + lastParag->append( txt, true ); + lastParag->setFormat( i, txt.length(), textDocument()->formatCollection()->format( &fm ) ); + //kdDebug(33001)<<"setFormat :"<<txt<<" i :"<<i<<" txt.length() "<<txt.length()<<endl; + i += txt.length(); + } + else if ( n.tagName() == "CUSTOM" ) + { + listVariable.append( n ); + n = n.nextSibling().toElement(); + } + else + n = n.nextSibling().toElement(); + } + } else if ( e.tagName() == "UNSORTEDLISTTYPE" ) { + if ( listNum < 4 ) { + //QColor c( e.attribute( "red" ).toInt(), e.attribute( "green" ).toInt(), e.attribute( "blue" ).toInt() ); + // ## settings.bulletColor[ listNum++ ] = c; + } + } + e = e.nextSibling().toElement(); + loadVariable( listVariable,lastParag ); + if ( e.isNull() ) + break; + i = 0; + if ( !lastParag->length() == 0 ) + lastParag = new KoTextParag( textDocument(), lastParag, 0 ); + } +} + +void KPrTextObject::loadVariable( QValueList<QDomElement> & listVariable,KoTextParag *lastParag, int offset ) +{ + QValueList<QDomElement>::Iterator it = listVariable.begin(); + QValueList<QDomElement>::Iterator end = listVariable.end(); + for ( ; it != end ; ++it ) + { + QDomElement elem = *it; + if ( !elem.hasAttribute("pos")) + continue; + int index = elem.attribute("pos").toInt(); + index+=offset; + QDomElement varElem = elem.namedItem( "VARIABLE" ).toElement(); + if ( !varElem.isNull() ) + { + QDomElement typeElem = varElem.namedItem( "TYPE" ).toElement(); + int type = typeElem.attribute( "type" ).toInt(); + QString key = typeElem.attribute( "key" ); + int correct = 0; + if (typeElem.hasAttribute( "correct" )) + correct = typeElem.attribute("correct").toInt(); + kdDebug(33001) << "loadKTextObject variable type=" << type << " key=" << key << endl; + KoVariableFormat * varFormat = key.isEmpty() ? 0 : m_doc->variableFormatCollection()->format( key.latin1() ); + // If varFormat is 0 (no key specified), the default format will be used. + KoVariable * var =m_doc->getVariableCollection()->createVariable( type, -1, m_doc->variableFormatCollection(), + varFormat, lastParag->textDocument(), + m_doc, correct, true/* force default format for date/time*/ ); + if ( var ) + { + var->load( varElem ); + KoTextFormat format = loadFormat( *it, lastParag->paragraphFormat(), m_doc->defaultFont(), m_doc->globalLanguage(), + m_doc->globalHyphenation() ); + lastParag->setCustomItem( index, var, lastParag->document()->formatCollection()->format( &format )); + var->recalc(); + } + } + } +} + +KoTextFormat KPrTextObject::loadFormat( QDomElement &n, KoTextFormat * refFormat, const QFont & defaultFont, + const QString & defaultLanguage, bool hyphen ) +{ + KoTextFormat format; + format.setHyphenation( hyphen ); + QFont fn; + if ( refFormat ) + { + format = *refFormat; + format.setCollection( 0 ); // Out of collection copy + fn = format.font(); + } + else + fn = defaultFont; + + if ( !n.isNull() ) + { + QFontDatabase fdb; + QStringList families = fdb.families(); + if ( families.findIndex( n.attribute( attrFamily ) ) != -1 ) + fn.setFamily( n.attribute( attrFamily ) ); + else + fn = defaultFont; + } + else if ( !refFormat ) + { // No reference format and no FONT tag -> use default font + fn = defaultFont; + } + + + int size = n.attribute( attrPointSize ).toInt(); + bool bold=false; + if(n.hasAttribute(attrBold)) + bold = (bool)n.attribute( attrBold ).toInt(); + bool italic = false; + if(n.hasAttribute(attrItalic)) + italic=(bool)n.attribute( attrItalic ).toInt(); + + if(n.hasAttribute( attrUnderline )) + { + QString value = n.attribute( attrUnderline ); + if ( value == "double" ) + format.setUnderlineType ( KoTextFormat::U_DOUBLE); + else if ( value == "single" ) + format.setUnderlineType ( KoTextFormat::U_SIMPLE); + else if ( value == "single-bold" ) + format.setUnderlineType ( KoTextFormat::U_SIMPLE_BOLD); + else if( value =="wave" ) + format.setUnderlineType( KoTextFormat::U_WAVE); + else + format.setUnderlineType ( (bool)value.toInt() ? KoTextFormat::U_SIMPLE :KoTextFormat::U_NONE); + } + if (n.hasAttribute("underlinestyleline") ) + format.setUnderlineStyle( KoTextFormat::stringToUnderlineStyle( n.attribute("underlinestyleline") )); + + if (n.hasAttribute("underlinecolor")) + format.setTextUnderlineColor(QColor(n.attribute("underlinecolor"))); + + if(n.hasAttribute(attrStrikeOut)) + { + QString value = n.attribute( attrStrikeOut ); + if ( value == "double" ) + format.setStrikeOutType ( KoTextFormat::S_DOUBLE); + else if ( value == "single" ) + format.setStrikeOutType ( KoTextFormat::S_SIMPLE); + else if ( value == "single-bold" ) + format.setStrikeOutType ( KoTextFormat::S_SIMPLE_BOLD); + else + format.setStrikeOutType ( (bool)value.toInt() ? KoTextFormat::S_SIMPLE :KoTextFormat::S_NONE); + } + + if (n.hasAttribute("strikeoutstyleline")) + { + QString strLineType = n.attribute("strikeoutstyleline"); + format.setStrikeOutStyle( KoTextFormat::stringToStrikeOutStyle( strLineType )); + } + + QString color = n.attribute( attrColor ); + fn.setPointSize( size ); + fn.setBold( bold ); + fn.setItalic( italic ); + //kdDebug(33001) << "KPrTextObject::loadFormat: family=" << fn.family() << " size=" << fn.pointSize() << endl; + QColor col( color ); + + format.setFont( fn ); + format.setColor( col ); + QString textBackColor=n.attribute(attrTextBackColor); + if(!textBackColor.isEmpty()) + { + QColor tmpCol(textBackColor); + tmpCol=tmpCol.isValid() ? tmpCol : QApplication::palette().color( QPalette::Active, QColorGroup::Base ); + format.setTextBackgroundColor(tmpCol); + } + if(n.hasAttribute(attrVertAlign)) + format.setVAlign( static_cast<KoTextFormat::VerticalAlignment>(n.attribute(attrVertAlign).toInt() ) ); + if ( n.hasAttribute("text-shadow") ) + format.parseShadowFromCss( n.attribute("text-shadow") ); + if ( n.hasAttribute("relativetextsize") ) + format.setRelativeTextSize( n.attribute("relativetextsize").toDouble() ) ; + if ( n.hasAttribute("offsetfrombaseline") ) + format.setOffsetFromBaseLine( static_cast<int>(n.attribute("offsetfrombaseline").toInt() ) ); + if ( n.hasAttribute("wordbyword") ) + format.setWordByWord( static_cast<int>(n.attribute("wordbyword").toInt() ) ); + + if ( n.hasAttribute("fontattribute") ) + format.setAttributeFont( KoTextFormat::stringToAttributeFont(n.attribute("fontattribute") ) ); + if ( n.hasAttribute("language")) + format.setLanguage( n.attribute("language")); + else + { // No reference format and no language tag -> use default font + format.setLanguage( defaultLanguage); + } + + //kdDebug(33001)<<"loadFormat :"<<format.key()<<endl; + return format; +} + +KoParagLayout KPrTextObject::loadParagLayout( QDomElement & parentElem, KPrDocument *doc, bool findStyle) +{ + KoParagLayout layout; + + // Only when loading paragraphs, not when loading styles + if ( findStyle ) + { + KoParagStyle *style; + // Name of the style. If there is no style, then we do not supply + // any default! + QDomElement element = parentElem.namedItem( "NAME" ).toElement(); + if ( !element.isNull() ) + { + QString styleName = element.attribute( "value" ); + style = doc->styleCollection()->findStyle( styleName ); + if (!style) + { + kdError(33001) << "Cannot find style \"" << styleName << "\" specified in paragraph LAYOUT - using Standard" << endl; + style = doc->styleCollection()->findStyle( "Standard" ); + } + //else kdDebug(33001) << "KoParagLayout::KoParagLayout setting style to " << style << " " << style->name() << endl; + } + else + { + kdError(33001) << "Missing NAME tag in paragraph LAYOUT - using Standard" << endl; + style = doc->styleCollection()->findStyle( "Standard" ); + } + Q_ASSERT(style); + layout.style = style; + } + + QDomElement element = parentElem.namedItem( "INDENTS" ).toElement(); + if ( !element.isNull() ) + { + double val=0.0; + if(element.hasAttribute("first")) + val=element.attribute("first").toDouble(); + layout.margins[QStyleSheetItem::MarginFirstLine] = val; + val=0.0; + if(element.hasAttribute( "left")) + // The GUI prevents a negative indent, so let's fixup broken docs too + val=QMAX(0, element.attribute( "left").toDouble()); + layout.margins[QStyleSheetItem::MarginLeft] = val; + val=0.0; + if(element.hasAttribute("right")) + // The GUI prevents a negative indent, so let's fixup broken docs too + val=QMAX(0, element.attribute("right").toDouble()); + layout.margins[QStyleSheetItem::MarginRight] = val; + } + element = parentElem.namedItem( "LINESPACING" ).toElement(); + if ( !element.isNull() ) + { + //compatibility with koffice 1.1 + if ( element.hasAttribute( "value" )) + { + QString value = element.attribute( "value" ); + if ( value == "oneandhalf" ) + { + layout.lineSpacingType = KoParagLayout::LS_ONEANDHALF; + layout.setLineSpacingValue(0); + } + else if ( value == "double" ) + { + layout.lineSpacingType = KoParagLayout::LS_DOUBLE; + layout.setLineSpacingValue(0); + } + else + { + layout.lineSpacingType = KoParagLayout::LS_CUSTOM; + layout.setLineSpacingValue(value.toDouble()); + } + } + else + { + QString type = element.attribute( "type" ); + if ( type == "oneandhalf" ) + { + layout.lineSpacingType = KoParagLayout::LS_ONEANDHALF; + layout.setLineSpacingValue(0); + } + else if ( type == "double" ) + { + layout.lineSpacingType = KoParagLayout::LS_DOUBLE; + layout.setLineSpacingValue(0); + } + else if ( type == "custom" ) + { + layout.lineSpacingType = KoParagLayout::LS_CUSTOM; + layout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble()); + } + else if ( type == "atleast" ) + { + layout.lineSpacingType = KoParagLayout::LS_AT_LEAST; + layout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble()); + } + else if ( type == "multiple" ) + { + layout.lineSpacingType = KoParagLayout::LS_MULTIPLE; + layout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble()); + } + } + } + + element = parentElem.namedItem( "OFFSETS" ).toElement(); + if ( !element.isNull() ) + { + double val =0.0; + if(element.hasAttribute("before")) + val=QMAX(0, element.attribute("before").toDouble()); + layout.margins[QStyleSheetItem::MarginTop] = val; + val = 0.0; + if(element.hasAttribute("after")) + val=QMAX(0, element.attribute("after").toDouble()); + layout.margins[QStyleSheetItem::MarginBottom] = val; + } + + + element = parentElem.namedItem( "LEFTBORDER" ).toElement(); + if ( !element.isNull() ) + layout.leftBorder = KoBorder::loadBorder( element ); + else + layout.leftBorder.setPenWidth( 0); + + element = parentElem.namedItem( "RIGHTBORDER" ).toElement(); + if ( !element.isNull() ) + layout.rightBorder = KoBorder::loadBorder( element ); + else + layout.rightBorder.setPenWidth( 0); + + element = parentElem.namedItem( "TOPBORDER" ).toElement(); + if ( !element.isNull() ) + layout.topBorder = KoBorder::loadBorder( element ); + else + layout.topBorder.setPenWidth(0); + + element = parentElem.namedItem( "BOTTOMBORDER" ).toElement(); + if ( !element.isNull() ) + layout.bottomBorder = KoBorder::loadBorder( element ); + else + layout.bottomBorder.setPenWidth(0); + + element = parentElem.namedItem( "COUNTER" ).toElement(); + if ( !element.isNull() ) + { + layout.counter = new KoParagCounter; + layout.counter->load( element ); + } + + KoTabulatorList tabList; + element = parentElem.firstChild().toElement(); + for ( ; !element.isNull() ; element = element.nextSibling().toElement() ) + { + if ( element.tagName() == "TABULATOR" ) + { + KoTabulator tab; + tab.type=T_LEFT; + if(element.hasAttribute("type")) + tab.type = static_cast<KoTabulators>( element.attribute("type").toInt()); + tab.ptPos=0.0; + if(element.hasAttribute("ptpos")) + tab.ptPos=element.attribute("ptpos").toDouble(); + tab.filling=TF_BLANK; + if(element.hasAttribute("filling")) + tab.filling = static_cast<KoTabulatorFilling>( element.attribute("filling").toInt()); + tab.ptWidth=0.5; + if(element.hasAttribute("width")) + tab.ptWidth=element.attribute("width").toDouble(); + tabList.append( tab ); + } + } + layout.setTabList( tabList ); + + + return layout; +} + +void KPrTextObject::saveParagLayout( const KoParagLayout& layout, QDomElement & parentElem ) +{ + QDomDocument doc = parentElem.ownerDocument(); + QDomElement element = doc.createElement( "NAME" ); + parentElem.appendChild( element ); + if ( layout.style ) + element.setAttribute( "value", layout.style->name() ); + else + kdWarning() << "KWTextParag::saveParagLayout: style==0L!" << endl; + + + if ( layout.margins[QStyleSheetItem::MarginFirstLine] != 0 || + layout.margins[QStyleSheetItem::MarginLeft] != 0 || + layout.margins[QStyleSheetItem::MarginRight] != 0 ) + { + element = doc.createElement( "INDENTS" ); + parentElem.appendChild( element ); + if ( layout.margins[QStyleSheetItem::MarginFirstLine] != 0 ) + element.setAttribute( "first", layout.margins[QStyleSheetItem::MarginFirstLine] ); + if ( layout.margins[QStyleSheetItem::MarginLeft] != 0 ) + element.setAttribute( "left", layout.margins[QStyleSheetItem::MarginLeft] ); + if ( layout.margins[QStyleSheetItem::MarginRight] != 0 ) + element.setAttribute( "right", layout.margins[QStyleSheetItem::MarginRight] ); + } + + + if ( layout.margins[QStyleSheetItem::MarginTop] != 0 || + layout.margins[QStyleSheetItem::MarginBottom] != 0 ) + { + element = doc.createElement( "OFFSETS" ); + parentElem.appendChild( element ); + if ( layout.margins[QStyleSheetItem::MarginTop] != 0 ) + element.setAttribute( "before", layout.margins[QStyleSheetItem::MarginTop] ); + if ( layout.margins[QStyleSheetItem::MarginBottom] != 0 ) + element.setAttribute( "after", layout.margins[QStyleSheetItem::MarginBottom] ); + } + + if ( layout.lineSpacingType != KoParagLayout::LS_SINGLE ) + { + element = doc.createElement( "LINESPACING" ); + parentElem.appendChild( element ); + if ( layout.lineSpacingType == KoParagLayout::LS_ONEANDHALF ) + element.setAttribute( "type", "oneandhalf" ); + else if ( layout.lineSpacingType == KoParagLayout::LS_DOUBLE ) + element.setAttribute( "type", "double" ); + else if ( layout.lineSpacingType == KoParagLayout::LS_CUSTOM ) + { + element.setAttribute( "type", "custom" ); + element.setAttribute( "spacingvalue", layout.lineSpacingValue()); + } + else if ( layout.lineSpacingType == KoParagLayout::LS_AT_LEAST ) + { + element.setAttribute( "type", "atleast" ); + element.setAttribute( "spacingvalue", layout.lineSpacingValue()); + } + else if ( layout.lineSpacingType == KoParagLayout::LS_MULTIPLE ) + { + element.setAttribute( "type", "multiple" ); + element.setAttribute( "spacingvalue", layout.lineSpacingValue()); + } + else + kdDebug(33001) << " error in lineSpacing Type" << endl; + } + + if ( layout.leftBorder.penWidth() > 0 ) + { + element = doc.createElement( "LEFTBORDER" ); + parentElem.appendChild( element ); + layout.leftBorder.save( element ); + } + if ( layout.rightBorder.penWidth() > 0 ) + { + element = doc.createElement( "RIGHTBORDER" ); + parentElem.appendChild( element ); + layout.rightBorder.save( element ); + } + if ( layout.topBorder.penWidth() > 0 ) + { + element = doc.createElement( "TOPBORDER" ); + parentElem.appendChild( element ); + layout.topBorder.save( element ); + } + if ( layout.bottomBorder.penWidth() > 0 ) + { + element = doc.createElement( "BOTTOMBORDER" ); + parentElem.appendChild( element ); + layout.bottomBorder.save( element ); + } + + if ( layout.counter && layout.counter->numbering() != KoParagCounter::NUM_NONE ) + { + element = doc.createElement( "COUNTER" ); + parentElem.appendChild( element ); + if (layout.counter ) + layout.counter->save( element ); + } + + KoTabulatorList tabList = layout.tabList(); + KoTabulatorList::ConstIterator it = tabList.begin(); + for ( ; it != tabList.end() ; it++ ) + { + element = doc.createElement( "TABULATOR" ); + parentElem.appendChild( element ); + element.setAttribute( "type", (*it).type ); + element.setAttribute( "ptpos", (*it).ptPos ); + element.setAttribute( "filling", (*it).filling ); + element.setAttribute( "width", (*it).ptWidth ); + } +} + +void KPrTextObject::recalcPageNum( KPrPage *page ) +{ + int pgnum=m_doc->pageList().findRef(page); + + pgnum+=1; + QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() ); + for ( ; cit.current() ; ++cit ) + { + KPrPgNumVariable * var = dynamic_cast<KPrPgNumVariable *>( cit.current() ); + if ( var && !var->isDeleted() ) + { + switch ( var->subType() ) { + case KPrPgNumVariable::VST_PGNUM_CURRENT: + var->setPgNum( pgnum + kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber()-1); + break; + case KPrPgNumVariable::VST_CURRENT_SECTION: + var->setSectionTitle( page->pageTitle() ); + break; + case KPrPgNumVariable::VST_PGNUM_PREVIOUS: + var->setPgNum( QMAX( pgnum -1 , 0) + + kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber()); + break; + case KPrPgNumVariable::VST_PGNUM_NEXT: + var->setPgNum( QMIN( (int)m_doc->getPageNums(), pgnum+1 ) + + kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber()); + break; + default: + break; + } + + var->resize(); + var->paragraph()->invalidate( 0 ); // size may have changed -> need reformatting ! + var->paragraph()->setChanged( true ); + } + } +} + +void KPrTextObject::layout() +{ + invalidate(); + // Get the thing going though, repainting doesn't call formatMore + m_textobj->formatMore( 2 ); +} + +void KPrTextObject::invalidate() +{ + //kdDebug(33001) << "KWTextFrameSet::invalidate " << getName() << endl; + m_textobj->setLastFormattedParag( textDocument()->firstParag() ); + textDocument()->formatter()->setViewFormattingChars( m_doc->viewFormattingChars() ); + textDocument()->invalidate(); // lazy layout, real update follows upon next repaint +} + +// For the "paragraph after paragraph" effect +void KPrTextObject::drawParags( QPainter *painter, KoTextZoomHandler* zoomHandler, const QColorGroup& cg, int from, int to ) +{ + // The fast and difficult way would be to call drawParagWYSIWYG + // only on the paragraphs to be drawn. Then we have duplicate quite some code + // (or lose double-buffering). + // Easy (and not so slow) way: + // we call KoTextDocument::drawWYSIWYG with a cliprect. + Q_ASSERT( from <= to ); + int i = 0; + bool editMode=false; + if( m_doc->firstView() && m_doc->firstView()->getCanvas()) + editMode = m_doc->firstView()->getCanvas()->getEditMode(); + + QRect r = zoomHandler->zoomRect( KoRect( 0, 0, innerWidth(), innerHeight() ) ); + KoTextParag *parag = textDocument()->firstParag(); + while ( parag ) { + if ( !parag->isValid() ) + parag->format(); + if ( i == from ) + r.setTop( m_doc->zoomHandler()->layoutUnitToPixelY( parag->rect().top() ) ); + if ( i == to ) { + r.setBottom( m_doc->zoomHandler()->layoutUnitToPixelY( parag->rect().bottom() ) ); + break; + } + ++i; + parag = parag->next(); + } + + uint drawingFlags = 0; // don't draw selections + if ( m_doc->backgroundSpellCheckEnabled() && editMode ) + drawingFlags |= KoTextDocument::DrawMisspelledLine; + textDocument()->drawWYSIWYG( + painter, r.x(), r.y(), r.width(), r.height(), + cg, m_doc->zoomHandler(), // TODO (long term) the view's zoomHandler + false /*onlyChanged*/, false /*cursor != 0*/, 0 /*cursor*/, + true /*resetChanged*/, drawingFlags ); +} + +void KPrTextObject::drawCursor( QPainter *p, KoTextCursor *cursor, bool cursorVisible, KPrCanvas* canvas ) +{ + // The implementation is very related to KWord's KWTextFrameSet::drawCursor + KoTextZoomHandler *zh = m_doc->zoomHandler(); + QPoint origPix = zh->zoomPoint( orig+KoPoint(bLeft(), bTop()+alignVertical) ); + // Painter is already translated for diffx/diffy, but not for the object yet + p->translate( origPix.x(), origPix.y() ); + if ( angle != 0 ) + rotateObject( p, zh ); + + KoTextParag* parag = cursor->parag(); + QPoint topLeft = parag->rect().topLeft(); // in QRT coords + int lineY; + // Cursor height, in pixels + int cursorHeight = zh->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) ); + QPoint iPoint( topLeft.x() + cursor->x(), + topLeft.y() + lineY ); + // from now on, iPoint will be in pixels + iPoint = zh->layoutUnitToPixel( iPoint ); + + QPoint vPoint = iPoint; // vPoint and iPoint are the same currently + // do not simplify this, will be useful with viewmodes. + //int xadj = parag->at( cursor->index() )->pixelxadj; + //iPoint.rx() += xadj; + //vPoint.rx() += xadj; + // very small clipping around the cursor + QRect clip( vPoint.x() - 5, vPoint.y() , 10, cursorHeight ); + setupClipRegion( p, clip ); + + // for debug only! + //p->fillRect( clip, Qt::blue ); + + QPixmap *pix = 0; + QColorGroup cg = QApplication::palette().active(); + cg.setColor( QColorGroup::Base, m_doc->txtBackCol() ); + + uint drawingFlags = KoTextDocument::DrawSelections; + if ( m_doc->backgroundSpellCheckEnabled() ) + drawingFlags |= KoTextDocument::DrawMisspelledLine; + if ( m_doc->viewFormattingChars() ) + drawingFlags |= KoTextDocument::DrawFormattingChars; + + // To force the drawing to happen: + bool wasChanged = parag->hasChanged(); + int oldLineChanged = parag->lineChanged(); + int line; // line number + parag->lineStartOfChar( cursor->index(), 0, &line ); + parag->setChanged( false ); // not all changed, only from a given line + parag->setLineChanged( line ); + //kdDebug(33001) << "KPrTextObject::drawCursor cursorVisible=" << cursorVisible << " line=" << line << endl; + + textDocument()->drawParagWYSIWYG( + p, parag, + QMAX(0, iPoint.x() - 5), // negative values create problems + iPoint.y(), clip.width(), clip.height(), + pix, cg, m_doc->zoomHandler(), + cursorVisible, cursor, FALSE /*resetChanged*/, drawingFlags ); + + if ( wasChanged ) // Maybe we have more changes to draw, than those in the small cliprect + cursor->parag()->setLineChanged( oldLineChanged ); // -1 = all + else + cursor->parag()->setChanged( false ); + + // XIM Position + QPoint ximPoint = vPoint; + QFont f = parag->at( cursor->index() )->format()->font(); + canvas->setXimPosition( ximPoint.x() + origPix.x(), ximPoint.y() + origPix.y(), + 0, cursorHeight - parag->lineSpacing( line ), &f ); +} + +KPrTextDocument * KPrTextObject::textDocument() const +{ + return static_cast<KPrTextDocument*>(m_textobj->textDocument()); +} + +void KPrTextObject::slotNewCommand( KCommand * cmd) +{ + m_doc->addCommand(cmd); +} + +int KPrTextObject::availableHeight() const +{ + return m_textobj->availableHeight(); +} + +void KPrTextObject::slotAvailableHeightNeeded() +{ + int ah = m_doc->zoomHandler()->ptToLayoutUnitPixY( innerHeight() ); + m_textobj->setAvailableHeight( ah ); + //kdDebug(33001)<<"slotAvailableHeightNeeded: height=:"<<ah<<endl; +} + +void KPrTextObject::slotRepaintChanged() +{ + emit repaintChanged( this ); +} + +KPrTextView * KPrTextObject::createKPTextView( KPrCanvas * _canvas, bool temp ) +{ + return new KPrTextView( this, _canvas, temp ); +} + +void KPrTextObject::removeHighlight () +{ + m_textobj->removeHighlight( true /*repaint*/ ); +} + +void KPrTextObject::highlightPortion( KoTextParag * parag, int index, int length, KPrCanvas* canvas, bool repaint, KDialogBase* dialog ) +{ + m_textobj->highlightPortion( parag, index, length, repaint ); + if ( repaint ) + { + KPrDocument* doc = canvas->getView()->kPresenterDoc(); + + // Is this object in the current active page? + if ( canvas->activePage()->findTextObject( this ) ) + { + kdDebug(33001) << k_funcinfo << "object in current page" << endl; + } + else + { + // No -> find the right page and activate it + // ** slow method ** + KPrPage* page = doc->findPage( this ); + if ( page ) { + int pageNum = doc->pageList().findRef( page ); + // if the pageNum is -1 the object is located on the master slide + if ( pageNum > -1 ) + { + canvas->getView()->skipToPage( pageNum ); + } + } else + kdWarning(33001) << "object " << this << " not found in any page!?" << endl; + } + // Now ensure text is fully visible + QRect rect = m_doc->zoomHandler()->zoomRect( getRect() ); + QRect expose = m_doc->zoomHandler()->layoutUnitToPixel( parag->rect() ); + expose.moveBy( rect.x(), rect.y() ); + canvas->ensureVisible( (expose.left()+expose.right()) / 2, // point = center of the rect + (expose.top()+expose.bottom()) / 2, + (expose.right()-expose.left()) / 2, // margin = half-width of the rect + (expose.bottom()-expose.top()) / 2); +#if KDE_IS_VERSION(3,1,90) + if ( dialog ) { + QRect globalRect( expose ); + globalRect.moveTopLeft( canvas->mapToGlobal( globalRect.topLeft() ) ); + KDialog::avoidArea( dialog, globalRect ); + } +#endif + } +} + +KCommand * KPrTextObject::pasteOasis( KoTextCursor * cursor, const QByteArray & data, bool removeSelected ) +{ + //kdDebug(33001) << "KPrTextObject::pasteOasis" << endl; + KMacroCommand * macroCmd = new KMacroCommand( i18n("Paste Text") ); + if ( removeSelected && textDocument()->hasSelection( KoTextDocument::Standard ) ) + macroCmd->addCommand( m_textobj->removeSelectedTextCommand( cursor, KoTextDocument::Standard ) ); + m_textobj->emitHideCursor(); + m_textobj->setLastFormattedParag( cursor->parag()->prev() ? + cursor->parag()->prev() : cursor->parag() ); + + // We have our own command for this. + // Using insert() wouldn't help storing the parag stuff for redo + KPrOasisPasteTextCommand * cmd = new KPrOasisPasteTextCommand( textDocument(), cursor->parag()->paragId(), cursor->index(), data ); + textDocument()->addCommand( cmd ); + + macroCmd->addCommand( new KoTextCommand( m_textobj, /*cmd, */QString::null ) ); + *cursor = *( cmd->execute( cursor ) ); + + m_textobj->formatMore( 2 ); + emit repaintChanged( this ); + m_textobj->emitEnsureCursorVisible(); + m_textobj->emitUpdateUI( true ); + m_textobj->emitShowCursor(); + m_textobj->selectionChangedNotify(); + return macroCmd; +} + + +void KPrTextObject::setShadowParameter(int _distance,ShadowDirection _direction,const QColor &_color) +{ + int sx = 0; + int sy = 0; + switch ( _direction ) + { + case SD_LEFT_BOTTOM: + case SD_LEFT: + case SD_LEFT_UP: + sx = - _distance; + case SD_RIGHT_UP: + case SD_RIGHT: + case SD_RIGHT_BOTTOM: + sx = _distance; + default: + break; + } + switch ( _direction ) + { + case SD_LEFT_UP: + case SD_UP: + case SD_RIGHT_UP: + sy = - _distance; + case SD_LEFT_BOTTOM: + case SD_BOTTOM: + case SD_RIGHT_BOTTOM: + sy = _distance; + default: + break; + } + KoTextFormat tmpFormat; + tmpFormat.setShadow( sx, sy, _color ); + KCommand* cmd = m_textobj->setFormatCommand( &tmpFormat, KoTextFormat::ShadowText ); + if ( cmd ) + m_doc->addCommand(cmd); +} + +void KPrTextObject::slotFormatChanged(const KoTextFormat &_format) +{ + if(m_doc && m_doc->firstView()) + m_doc->firstView()->showFormat( _format ); +} + +void KPrTextObject::applyStyleChange( KoStyleChangeDefMap changed ) +{ + m_textobj->applyStyleChange( changed ); +} + +void KPrTextObject::slotAfterFormatting( int bottom, KoTextParag* lastFormatted, bool* abort) +{ + recalcVerticalAlignment(); + int availHeight = availableHeight() - m_doc->zoomHandler()->ptToLayoutUnitPixY(alignmentValue()); + if ( ( bottom > availHeight ) || // this parag is already below the avail height + ( lastFormatted && (bottom + lastFormatted->rect().height() > availHeight) ) ) // or next parag will be below it + { + int difference = ( bottom + 2 ) - availHeight; // in layout unit pixels + if( lastFormatted && bottom + lastFormatted->rect().height() > availHeight ) + { + difference += lastFormatted->rect().height(); + } +#if 0 + if(lastFormatted) + kdDebug(33001) << "slotAfterFormatting We need more space in " << this + << " bottom=" << bottom + lastFormatted->rect().height() + << " availHeight=" << availHeight + << " ->difference=" << difference << endl; + else + kdDebug(33001) << "slotAfterFormatting We need more space in " << this + << " bottom2=" << bottom << " availHeight=" << availHeight + << " ->difference=" << difference << endl; +#endif + // We only auto-grow. We don't auto-shrink. + if(difference > 0 && !isProtect()) + { + double wantedPosition = m_doc->zoomHandler()->layoutUnitPtToPt( m_doc->zoomHandler()->pixelYToPt( difference ) ) + + getRect().bottom(); + const KoPageLayout& p = m_doc->pageLayout(); + double pageBottom = p.ptHeight - p.ptBottom; + double newBottom = QMIN( wantedPosition, pageBottom ); // don't grow bigger than the page + newBottom = QMAX( newBottom, getOrig().y() ); // avoid negative heights + //kdDebug(33001) << k_funcinfo << " current bottom=" << getRect().bottom() << " newBottom=" << newBottom << endl; + if ( getRect().bottom() != newBottom ) + { + // We resize the text object, but skipping the KPrTextObject::setSize code + // (which invalidates everything etc.) + KPrObject::setSize( getSize().width(), newBottom - getOrig().y() ); + // Do recalculate the new available height though + slotAvailableHeightNeeded(); + m_doc->updateRuler(); + m_doc->repaint( true ); + *abort = false; + } + } + else if ( isProtect() ) + m_textobj->setLastFormattedParag( 0 ); + } +} + +// "Extend Contents to Object Height" +KCommand * KPrTextObject::textContentsToHeight() +{ + if (isProtect() ) + return 0L; + + // Count total number of lines and sum up their height (linespacing excluded) + KoTextParag * parag = textDocument()->firstParag(); + int numLines = 0; + int textHeightLU = 0; + bool lineSpacingEqual = false; + int oldLineSpacing = 0; + for ( ; parag ; parag = parag->next() ) + { + int lines = parag->lines(); + numLines += lines; + for ( int line = 0 ; line < lines ; ++line ) + { + int y, h, baseLine; + parag->lineInfo( line, y, h, baseLine ); + int ls = parag->lineSpacing( line ); + lineSpacingEqual = (oldLineSpacing == ls); + oldLineSpacing = ls; + textHeightLU += h - ls; + } + } + + double textHeight = m_doc->zoomHandler()->layoutUnitPtToPt( textHeightLU ); + double lineSpacing = ( innerHeight() - textHeight ) / numLines; // this gives the linespacing diff to apply, in pt + //kdDebug(33001) << k_funcinfo << "lineSpacing=" << lineSpacing << endl; + + if ( KABS( innerHeight() - textHeight ) < DBL_EPSILON ) // floating-point equality test + return 0L; // nothing to do + bool oneLine =(textDocument()->firstParag() == textDocument()->lastParag() && numLines == 1); + if ( lineSpacing < 0 || oneLine) // text object is too small + lineSpacing = 0; // we can't do smaller linespacing than that, but we do need to apply it + // (in case there's some bigger linespacing in use) + if ( (oneLine || lineSpacingEqual) && (textDocument()->firstParag()->kwLineSpacing() == lineSpacing)) + return 0L; + // Apply the new linespacing to the whole object + textDocument()->selectAll( KoTextDocument::Temp ); + KCommand* cmd = m_textobj->setLineSpacingCommand( 0L, lineSpacing, KoParagLayout::LS_CUSTOM, KoTextDocument::Temp ); + textDocument()->removeSelection( KoTextDocument::Temp ); + return cmd; +} + +// "Resize Object to fit Contents" +KCommand * KPrTextObject::textObjectToContents() +{ + if ( isProtect() ) + return 0L; + // Calculate max parag width (in case all parags are short, otherwise - with wrapping - + // the width is more or less the current object's width anyway). + KoTextParag * parag = textDocument()->firstParag(); + double txtWidth = 10; + for ( ; parag ; parag = parag->next() ) + txtWidth = QMAX( txtWidth, m_doc->zoomHandler()->layoutUnitPtToPt( parag->widthUsed() )); + + // Calculate text height + int heightLU = textDocument()->height(); + double txtHeight = m_doc->zoomHandler()->layoutUnitPtToPt( heightLU ); + + // Compare with current object's size + KoSize sizeDiff = KoSize( txtWidth, txtHeight ) - innerRect().size(); + if( !sizeDiff.isNull() ) + { + // The command isn't named since it's always put into a macro command. + return new KPrResizeCmd( QString::null, KoPoint( 0, 0 ), sizeDiff, this, m_doc); + } + return 0L; +} + +void KPrTextObject::setTextMargins( double _left, double _top, double _right, double _bottom) +{ + bleft = _left; + btop = _top; + bright = _right; + bbottom = _bottom; +} + +KoRect KPrTextObject::innerRect() const +{ + KoRect inner( getRect()); + inner.moveBy( bLeft(), bTop()); + inner.setWidth( inner.width() - bLeft() - bRight() ); + inner.setHeight( inner.height() - bTop() - bBottom() ); + return inner; +} + +double KPrTextObject::innerWidth() const +{ + return getSize().width() - bLeft() - bRight(); +} + +double KPrTextObject::innerHeight() const +{ + return getSize().height() - bTop() - bBottom(); +} + +void KPrTextObject::setVerticalAligment( VerticalAlignmentType _type) +{ + m_textVertAlign = _type; + recalcVerticalAlignment(); +} + +void KPrTextObject::recalcVerticalAlignment() +{ + double txtHeight = m_doc->zoomHandler()->layoutUnitPtToPt( m_doc->zoomHandler()->pixelYToPt( textDocument()->height() ) ) + btop + bbottom; + double diffy = getSize().height() - txtHeight; + + //kdDebug(33001) << k_funcinfo << "txtHeight: " << txtHeight << " rectHeight:" << getSize().height() << " -> diffy=" << diffy << endl; + + if ( diffy <= 0.0 ) { + alignVertical = 0.0; + return; + } + switch( m_textVertAlign ) + { + case KP_CENTER: + alignVertical = diffy/2.0; + break; + case KP_TOP: + alignVertical = 0.0; + break; + case KP_BOTTOM: + alignVertical = diffy; + break; + } +} + +QPoint KPrTextObject::cursorPos(KPrCanvas *canvas, KoTextCursor *cursor) const +{ + KoTextZoomHandler *zh = m_doc->zoomHandler(); + QPoint origPix = zh->zoomPoint( orig+KoPoint(bLeft(), bTop()+alignVertical) ); + KoTextParag* parag = cursor->parag(); + QPoint topLeft = parag->rect().topLeft(); // in QRT coords + int lineY = 0; + // Cursor height, in pixels + //int cursorHeight = zh->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) ); + QPoint iPoint( topLeft.x() + cursor->x(), topLeft.y() + lineY ); + iPoint = zh->layoutUnitToPixel( iPoint ); + iPoint.rx() -= canvas->diffx(); + iPoint.ry() -= canvas->diffy(); + return origPix+iPoint; +} + +KPrTextView::KPrTextView( KPrTextObject * txtObj, KPrCanvas *_canvas, bool temp ) + : KoTextView( txtObj->textObject() ) +{ + setBackSpeller( txtObj->kPresenterDocument()->backSpeller() ); + m_canvas=_canvas; + m_kptextobj=txtObj; + if (temp) + return; + connect( txtObj->textObject(), SIGNAL( selectionChanged(bool) ), + m_canvas, SIGNAL( selectionChanged(bool) ) ); + KoTextView::setReadWrite( txtObj->kPresenterDocument()->isReadWrite() ); + connect( textView(), SIGNAL( cut() ), SLOT( cut() ) ); + connect( textView(), SIGNAL( copy() ), SLOT( copy() ) ); + connect( textView(), SIGNAL( paste() ), SLOT( paste() ) ); + updateUI( true, true ); + + txtObj->setEditingTextObj( true ); +} + +KPrTextView::~KPrTextView() +{ +} + +KoTextViewIface* KPrTextView::dcopObject() +{ + if ( !dcop ) + dcop = new KPrTextViewIface( this ); + + return dcop; +} + +void KPrTextView::terminate(bool removeSelection) +{ + disconnect( textView()->textObject(), SIGNAL( selectionChanged(bool) ), + m_canvas, SIGNAL( selectionChanged(bool) ) ); + textView()->terminate(removeSelection); +} + +void KPrTextView::cut() +{ + if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) { + copy(); + textObject()->removeSelectedText( cursor() ); + } +} + +void KPrTextView::copy() +{ + //kdDebug(33001)<<"void KPrTextView::copy() "<<endl; + if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) { + QDragObject *drag = newDrag( 0 ); + QApplication::clipboard()->setData( drag ); + } +} + +void KPrTextView::paste() +{ + //kdDebug(33001) << "KPrTextView::paste()" << endl; + + QMimeSource *data = QApplication::clipboard()->data(); + QCString returnedMimeType = KoTextObject::providesOasis( data ); + if ( !returnedMimeType.isEmpty() ) + { + QByteArray arr = data->encodedData( returnedMimeType ); + if ( arr.size() ) + { +#if 0 + QFile paste( "/tmp/oasis.tmp" ); + paste.open( IO_WriteOnly ); + paste.writeBlock( arr ); + paste.close(); +#endif + KCommand *cmd = kpTextObject()->pasteOasis( cursor(), arr, true ); + if ( cmd ) + kpTextObject()->kPresenterDocument()->addCommand(cmd); + } + } + else + { + // Note: QClipboard::text() seems to do a better job than encodedData( "text/plain" ) + // In particular it handles charsets (in the mimetype). + QString text = QApplication::clipboard()->text(); + if ( !text.isEmpty() ) + textObject()->pasteText( cursor(), text, currentFormat(), true /*removeSelected*/ ); + } + kpTextObject()->layout(); +} + +void KPrTextView::updateUI( bool updateFormat, bool force ) +{ + KoTextView::updateUI( updateFormat, force ); + // Paragraph settings + KoTextParag * parag = static_cast<KoTextParag*>( cursor()->parag()); + if ( m_paragLayout.alignment != parag->resolveAlignment() || force ) { + m_paragLayout.alignment = parag->resolveAlignment(); + m_canvas->getView()->alignChanged( m_paragLayout.alignment ); + } + + // Counter + if ( !m_paragLayout.counter ) + m_paragLayout.counter = new KoParagCounter; // we can afford to always have one here + KoParagCounter::Style cstyle = m_paragLayout.counter->style(); + if ( parag->counter() ) + *m_paragLayout.counter = *parag->counter(); + else + { + m_paragLayout.counter->setNumbering( KoParagCounter::NUM_NONE ); + m_paragLayout.counter->setStyle( KoParagCounter::STYLE_NONE ); + } + + if ( m_paragLayout.counter->style() != cstyle || force ) + m_canvas->getView()->showCounter( * m_paragLayout.counter ); + + if(m_paragLayout.leftBorder!=parag->leftBorder() || + m_paragLayout.rightBorder!=parag->rightBorder() || + m_paragLayout.topBorder!=parag->topBorder() || + m_paragLayout.bottomBorder!=parag->bottomBorder() || force ) + { + m_paragLayout.leftBorder = parag->leftBorder(); + m_paragLayout.rightBorder = parag->rightBorder(); + m_paragLayout.topBorder = parag->topBorder(); + m_paragLayout.bottomBorder = parag->bottomBorder(); + //todo + //m_canvas->gui()->getView()->showParagBorders( m_paragLayout.leftBorder, m_paragLayout.rightBorder, m_paragLayout.topBorder, m_paragLayout.bottomBorder ); + } + + if ( !parag->style() ) + kdWarning(33001) << "Paragraph " << parag->paragId() << " has no style" << endl; + else if ( m_paragLayout.style != parag->style() || force ) + { + m_paragLayout.style = parag->style(); + m_canvas->getView()->showStyle( m_paragLayout.style->name() ); + } + + if( m_paragLayout.margins[QStyleSheetItem::MarginLeft] != parag->margin(QStyleSheetItem::MarginLeft) + || m_paragLayout.margins[QStyleSheetItem::MarginFirstLine] != parag->margin(QStyleSheetItem::MarginFirstLine) + || m_paragLayout.margins[QStyleSheetItem::MarginRight] != parag->margin(QStyleSheetItem::MarginRight) + || force ) + { + m_paragLayout.margins[QStyleSheetItem::MarginFirstLine] = parag->margin(QStyleSheetItem::MarginFirstLine); + m_paragLayout.margins[QStyleSheetItem::MarginLeft] = parag->margin(QStyleSheetItem::MarginLeft); + m_paragLayout.margins[QStyleSheetItem::MarginRight] = parag->margin(QStyleSheetItem::MarginRight); + m_canvas->getView()->showRulerIndent( m_paragLayout.margins[QStyleSheetItem::MarginLeft], + m_paragLayout.margins[QStyleSheetItem::MarginFirstLine], + m_paragLayout.margins[QStyleSheetItem::MarginRight], + parag->string()->isRightToLeft() ); + } + + if( m_paragLayout.tabList() != parag->tabList() || force ) + { + m_paragLayout.setTabList( parag->tabList() ); + KoRuler * hr = m_canvas->getView()->getHRuler(); + if ( hr ) + hr->setTabList( parag->tabList() ); + } +} + +void KPrTextView::ensureCursorVisible() +{ + //kdDebug(33001) << "KWTextFrameSetEdit::ensureCursorVisible paragId=" << cursor()->parag()->paragId() << endl; + KoTextParag * parag = cursor()->parag(); + kpTextObject()->textObject()->ensureFormatted( parag ); + KoTextStringChar *chr = parag->at( cursor()->index() ); + int h = parag->lineHeightOfChar( cursor()->index() ); + int x = parag->rect().x() + chr->x; + int y = 0; int dummy; + + parag->lineHeightOfChar( cursor()->index(), &dummy, &y ); + y += parag->rect().y(); + int w = 1; + KPrDocument *doc= m_kptextobj->kPresenterDocument(); + KoPoint pt= kpTextObject()->getOrig(); + pt.setX( doc->zoomHandler()->layoutUnitPtToPt( doc->zoomHandler()->pixelXToPt( x) ) +pt.x()); + pt.setY( doc->zoomHandler()->layoutUnitPtToPt( doc->zoomHandler()->pixelYToPt( y ))+pt.y() ); + + QPoint p = m_kptextobj->kPresenterDocument()->zoomHandler()->zoomPoint( pt ); + w = m_kptextobj->kPresenterDocument()->zoomHandler()->layoutUnitToPixelX( w ); + h = m_kptextobj->kPresenterDocument()->zoomHandler()->layoutUnitToPixelY( h ); + m_canvas->ensureVisible( p.x(), p.y() + h / 2, w, h / 2 + 2 ); +} + +bool KPrTextView::doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index ) +{ + if( m_kptextobj->kPresenterDocument()->allowAutoFormat() ) + { + KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat(); + if( autoFormat ) + return autoFormat->doCompletion( cursor, parag, index, textObject()); + } + return false; +} + +bool KPrTextView::doToolTipCompletion( KoTextCursor* cursor, KoTextParag *parag, int index,int keyPress ) +{ + if( m_kptextobj->kPresenterDocument()->allowAutoFormat() ) + { + KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat(); + if( autoFormat ) + return autoFormat->doToolTipCompletion( cursor, parag, index, textObject(), keyPress); + } + return false; +} +void KPrTextView::showToolTipBox(KoTextParag *parag, int index, QWidget *widget, const QPoint &pos) +{ + if( m_kptextobj->kPresenterDocument()->allowAutoFormat() ) + { + KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat(); + if( autoFormat ) + autoFormat->showToolTipBox(parag, index, widget, pos); + } +} + +void KPrTextView::removeToolTipCompletion() +{ + if( m_kptextobj->kPresenterDocument()->allowAutoFormat() ) + { + KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat(); + if( autoFormat ) + autoFormat->removeToolTipCompletion(); + } +} +void KPrTextView::textIncreaseIndent() +{ + m_canvas->setTextDepthPlus(); +} + +bool KPrTextView::textDecreaseIndent() +{ + if (m_paragLayout.margins[QStyleSheetItem::MarginLeft]>0) + { + m_canvas->setTextDepthMinus(); + return true; + } + else + return false; +} + +void KPrTextView::doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, QChar ch ) +{ + if( m_kptextobj->kPresenterDocument()->allowAutoFormat()) + { + KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat(); + if ( autoFormat ) + autoFormat->doAutoFormat( cursor, parag, index, ch, textObject()); + } +} + +bool KPrTextView::doIgnoreDoubleSpace(KoTextParag * parag, int index,QChar ch ) +{ + if( m_kptextobj->kPresenterDocument()->allowAutoFormat()) + { + + KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat(); + if( autoFormat ) + return autoFormat->doIgnoreDoubleSpace( parag, index,ch ); + } + return false; +} + +void KPrTextView::startDrag() +{ + textView()->dragStarted(); + m_canvas->dragStarted(); + QDragObject *drag = newDrag( m_canvas ); + if ( !kpTextObject()->kPresenterDocument()->isReadWrite() ) + drag->dragCopy(); + else + { + if ( drag->drag() && QDragObject::target() != m_canvas ) + textObject()->removeSelectedText( cursor() ); + } +} + +void KPrTextView::showFormat( KoTextFormat *format ) +{ + m_canvas->getView()->showFormat( *format ); +} + +bool KPrTextView::pgUpKeyPressed() +{ + KoTextCursor *cursor = textView()->cursor(); + KoTextParag *s = cursor->parag(); + s = textDocument()->firstParag(); + + textView()->cursor()->setParag( s ); + textView()->cursor()->setIndex( 0 ); + return true; +} + +bool KPrTextView::pgDownKeyPressed() +{ + KoTextCursor *cursor = textView()->cursor(); + KoTextParag *s = cursor->parag(); + s = textDocument()->lastParag(); + cursor->setParag( s ); + cursor->setIndex( s->length() - 1 ); + return true; +} + +void KPrTextView::keyPressEvent( QKeyEvent *e ) +{ + //Calculate position of tooltip for autocompletion + const QPoint pos = kpTextObject()->cursorPos(m_canvas, cursor()); + textView()->handleKeyPressEvent( e, m_canvas, pos ); +} + +void KPrTextView::keyReleaseEvent( QKeyEvent *e ) +{ + handleKeyReleaseEvent(e); +} + +void KPrTextView::imStartEvent( QIMEvent *e ) +{ + handleImStartEvent(e); +} + +void KPrTextView::imComposeEvent( QIMEvent *e ) +{ + handleImComposeEvent(e); +} + +void KPrTextView::imEndEvent( QIMEvent *e ) +{ + handleImEndEvent(e); +} + +void KPrTextView::clearSelection() +{ + if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) + textDocument()->removeSelection(KoTextDocument::Standard ); +} + +void KPrTextView::selectAll(bool select) +{ + textObject()->selectAll( select ); +} + +void KPrTextView::drawCursor( bool b ) +{ + KoTextView::drawCursor( b ); + if ( !cursor()->parag() ) + return; + if ( !kpTextObject()->kPresenterDocument()->isReadWrite() ) + return; + + QPainter painter( m_canvas ); + painter.translate( -m_canvas->diffx(), -m_canvas->diffy() ); + painter.setBrushOrigin( -m_canvas->diffx(), -m_canvas->diffy() ); + + kpTextObject()->drawCursor( &painter, cursor(), b, m_canvas ); +} + +// Convert a mouse position into a QRT document position +QPoint KPrTextView::viewToInternal( const QPoint & pos ) const +{ +#if 0 + KoTextZoomHandler* zh = kpTextObject()->kPresenterDocument()->zoomHandler(); + QPoint tmp(pos); + QWMatrix m; + m.translate( zh->zoomItX(kpTextObject()->getSize().width() / 2.0), + zh->zoomItY(kpTextObject()->getSize().height() / 2.0) ); + m.rotate( kpTextObject()->getAngle() ); + + + + m.translate( zh->zoomItX(kpTextObject()->getOrig().x()), + zh->zoomItY(kpTextObject()->getOrig().y()) ); + //m = m.invert(); + tmp = m * pos; + + kdDebug(33001)<<" tmp.x() :"<<tmp.x()<<" tmp.y() "<<tmp.y()<<endl; + + KoRect br = KoRect( 0, 0, kpTextObject()->getSize().width(), kpTextObject()->getSize().height() ); + double pw = br.width(); + double ph = br.height(); + KoRect rr = br; + double yPos = -rr.y(); + double xPos = -rr.x(); + rr.moveTopLeft( KoPoint( -rr.width() / 2.0, -rr.height() / 2.0 ) ); + + m.translate( zh->zoomItX(pw / 2.0), + zh->zoomItY(ph / 2.0 )); + m.rotate( kpTextObject()->getAngle() ); + m.translate( zh->zoomItX(rr.left() + xPos), + zh->zoomItY(rr.top() + yPos) ); + + m = m.invert(); + + tmp = m * pos; + + kdDebug(33001)<<" tmp.x() :"<<tmp.x()<<" tmp.y() "<<tmp.y()<<endl; +#endif + + return kpTextObject()->viewToInternal( pos, m_canvas ); +} + +void KPrTextView::mousePressEvent( QMouseEvent *e, const QPoint &/*_pos*/) +{ + bool addParag = handleMousePressEvent( e, viewToInternal( e->pos() ),true /*bool canStartDrag*/, + kpTextObject()->kPresenterDocument()->insertDirectCursor() ); + + if ( addParag ) + kpTextObject()->kPresenterDocument()->setModified( true ); +} + +void KPrTextView::mouseDoubleClickEvent( QMouseEvent *e, const QPoint &pos) +{ + handleMouseDoubleClickEvent( e, pos ); +} + +void KPrTextView::mouseMoveEvent( QMouseEvent *e, const QPoint &_pos ) +{ + if ( textView()->maybeStartDrag( e ) ) + return; + if ( _pos.y() > 0 ) + textView()->handleMouseMoveEvent( e,viewToInternal( e->pos() ) ); +} + +bool KPrTextView::isLinkVariable( const QPoint & pos ) +{ + const QPoint iPoint = viewToInternal( pos ); + KoLinkVariable* linkVariable = dynamic_cast<KoLinkVariable *>( textObject()->variableAtPoint( iPoint ) ); + return linkVariable != 0; +} + +void KPrTextView::openLink() +{ + KPrDocument * doc = kpTextObject()->kPresenterDocument(); + if ( doc->getVariableCollection()->variableSetting()->displayLink() ) { + KoLinkVariable* v = linkVariable(); + if ( v ) + KoTextView::openLink( v ); + } +} + +void KPrTextView::mouseReleaseEvent( QMouseEvent *, const QPoint & ) +{ + handleMouseReleaseEvent(); +} + +void KPrTextView::showPopup( KPrView *view, const QPoint &point, QPtrList<KAction>& actionList ) +{ + QString word = wordUnderCursor( *cursor() ); + view->unplugActionList( "datatools" ); + view->unplugActionList( "datatools_link" ); + view->unplugActionList( "spell_result_action" ); + view->unplugActionList( "variable_action" ); + QPtrList<KAction> &variableList = view->variableActionList(); + variableList.clear(); + actionList.clear(); + + view->kPresenterDoc()->getVariableCollection()->setVariableSelected(variable()); + KoVariable* var = variable(); + if ( var ) + { + variableList = view->kPresenterDoc()->getVariableCollection()->popupActionList(); + } + + if( variableList.count()>0) + { + view->plugActionList( "variable_action", variableList ); + QPopupMenu * popup = view->popupMenu("variable_popup"); + Q_ASSERT(popup); + if (popup) + popup->popup( point ); // using exec() here breaks the spellcheck tool (event loop pb) + + } + else + { + bool singleWord= false; + actionList = dataToolActionList(view->kPresenterDoc()->instance(), word, singleWord); + //kdDebug(33001) << "KWView::openPopupMenuInsideFrame plugging actionlist with " << actionList.count() << " actions" << endl; + KoLinkVariable* linkVar = dynamic_cast<KoLinkVariable *>( var ); + QPopupMenu * popup; + if ( !linkVar ) + { + view->plugActionList( "datatools", actionList ); + + KoNoteVariable * noteVar = dynamic_cast<KoNoteVariable *>( var ); + KoCustomVariable * customVar = dynamic_cast<KoCustomVariable *>( var ); + if( noteVar ) + popup = view->popupMenu("note_popup"); + else if( customVar ) + popup = view->popupMenu("custom_var_popup"); + else + { + if ( singleWord ) + { + QPtrList<KAction> actionCheckSpellList =view->listOfResultOfCheckWord( word ); + if ( actionCheckSpellList.count()>0) + { + view->plugActionList( "spell_result_action", actionCheckSpellList ); + popup = view->popupMenu("text_popup_spell_with_result"); + } + else + popup = view->popupMenu("text_popup_spell"); + } + else + popup = view->popupMenu("text_popup"); + } + } + else + { + view->plugActionList( "datatools_link", actionList ); + popup = view->popupMenu("text_popup_link"); + } + Q_ASSERT(popup); + if (popup) + popup->popup( point ); // using exec() here breaks the spellcheck tool (event loop pb) + } +} + +void KPrTextView::insertCustomVariable( const QString &name) +{ + KPrDocument * doc = kpTextObject()->kPresenterDocument(); + KoVariable * var = new KoCustomVariable( textDocument(), name, doc->variableFormatCollection()->format( "STRING" ), + doc->getVariableCollection()); + insertVariable( var ); +} + +void KPrTextView::insertLink(const QString &_linkName, const QString & hrefName) +{ + KPrDocument * doc = kpTextObject()->kPresenterDocument(); + KoVariable * var = new KoLinkVariable( textDocument(), _linkName, hrefName, + doc->variableFormatCollection()->format( "STRING" ), + doc->getVariableCollection()); + insertVariable( var ); +} + +void KPrTextView::insertComment(const QString &_comment) +{ + KPrDocument * doc = kpTextObject()->kPresenterDocument(); + + KoVariable * var = new KoNoteVariable( textDocument(), _comment, + doc->variableFormatCollection()->format( "STRING" ), + doc->getVariableCollection()); + insertVariable( var ); +} + +void KPrTextView::insertVariable( int type, int subtype ) +{ + KPrDocument * doc = kpTextObject()->kPresenterDocument(); + bool refreshCustomMenu = false; + KoVariable * var = 0L; + if ( type == VT_CUSTOM ) + { + KoCustomVarDialog dia( m_canvas ); + if ( dia.exec() == QDialog::Accepted ) + { + KoCustomVariable *v = new KoCustomVariable( textDocument(), dia.name(), + doc->variableFormatCollection()->format( "STRING" ), + doc->getVariableCollection() ); + v->setValue( dia.value() ); + var = v; + refreshCustomMenu = true; + } + } + else + var = doc->getVariableCollection()->createVariable( type, subtype, doc->variableFormatCollection(), 0L, textDocument(),doc, 0); + if ( var ) + { + insertVariable( var, 0, refreshCustomMenu); + doc->recalcPageNum(); + } +} + +void KPrTextView::insertVariable( KoVariable *var, KoTextFormat *format, bool refreshCustomMenu ) +{ + if ( var ) + { + CustomItemsMap customItemsMap; + customItemsMap.insert( 0, var ); + if (!format) + format = currentFormat(); + //kdDebug(33001) << "KPrTextView::insertVariable inserting into paragraph" << endl; +#ifdef DEBUG_FORMATS + kdDebug(33001) << "KPrTextView::insertVariable currentFormat=" << currentFormat() << endl; +#endif + textObject()->insert( cursor(), format, KoTextObject::customItemChar(), + i18n("Insert Variable"), + KoTextDocument::Standard, + KoTextObject::DoNotRemoveSelected, + customItemsMap ); + if ( refreshCustomMenu && var->type() == VT_CUSTOM ) + kpTextObject()->kPresenterDocument()->refreshMenuCustomVariable(); + kpTextObject()->kPresenterDocument()->repaint( kpTextObject() ); + } +} + +bool KPrTextView::canDecode( QMimeSource *e ) +{ + return kpTextObject()->kPresenterDocument()->isReadWrite() && ( KoTextObject::providesOasis( e ) || QTextDrag::canDecode( e ) ); +} + +QDragObject * KPrTextView::newDrag( QWidget * parent ) +{ + QBuffer buffer; + const QCString mimeType = "application/vnd.oasis.opendocument.text"; + KoStore * store = KoStore::createStore( &buffer, KoStore::Write, mimeType ); + Q_ASSERT( store ); + Q_ASSERT( !store->bad() ); + + KoOasisStore oasisStore( store ); + + //KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType ); + + KPrDocument * doc = kpTextObject()->kPresenterDocument(); + + doc->getVariableCollection()->variableSetting()->setModificationDate( QDateTime::currentDateTime() ); + doc->recalcVariables( VT_DATE ); + doc->recalcVariables( VT_TIME ); + doc->recalcVariables( VT_STATISTIC ); + + KoGenStyles mainStyles; + KoSavingContext savingContext( mainStyles, 0, false, KoSavingContext::Store ); + + doc->styleCollection()->saveOasis( mainStyles, KoGenStyle::STYLE_USER, savingContext ); + + KoXmlWriter* bodyWriter = oasisStore.bodyWriter(); + bodyWriter->startElement( "office:body" ); + bodyWriter->startElement( "office:text" ); + + const QString plainText = textDocument()->copySelection( *bodyWriter, savingContext, KoTextDocument::Standard ); + + bodyWriter->endElement(); // office:text + bodyWriter->endElement(); // office:body + + KoXmlWriter* contentWriter = oasisStore.contentWriter(); + Q_ASSERT( contentWriter ); + + //KPrDocument * doc = kpTextObject()->kPresenterDocument(); + doc->writeAutomaticStyles( *contentWriter, mainStyles, savingContext, false ); + + oasisStore.closeContentWriter(); + + if ( !store->open( "styles.xml" ) ) + return false; + //manifestWriter->addManifestEntry( "styles.xml", "text/xml" ); + doc->saveOasisDocumentStyles( store, mainStyles, 0, savingContext, KPrDocument::SaveSelected /* simply means not SaveAll */ ); + if ( !store->close() ) // done with styles.xml + return false; + + delete store; + + KMultipleDrag* multiDrag = new KMultipleDrag( parent ); + if ( !plainText.isEmpty() ) + multiDrag->addDragObject( new QTextDrag( plainText, 0 ) ); + KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 ); + kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl; + storeDrag->setEncodedData( buffer.buffer() ); + multiDrag->addDragObject( storeDrag ); + return multiDrag; +} + +void KPrTextView::dragEnterEvent( QDragEnterEvent *e ) +{ + if ( !canDecode( e ) ) + { + e->ignore(); + return; + } + e->acceptAction(); +} + +void KPrTextView::dragMoveEvent( QDragMoveEvent *e, const QPoint & ) +{ + if ( !canDecode( e ) ) + { + e->ignore(); + return; + } + QPoint iPoint = viewToInternal( e->pos() ); + + textObject()->emitHideCursor(); + placeCursor( iPoint ); + textObject()->emitShowCursor(); + e->acceptAction(); // here or out of the if ? +} + +void KPrTextView::dropEvent( QDropEvent * e ) +{ + if ( canDecode( e ) ) + { + KPrDocument *doc = kpTextObject()->kPresenterDocument(); + e->acceptAction(); + KoTextCursor dropCursor( textDocument() ); + QPoint dropPoint = viewToInternal( e->pos() ); + KMacroCommand *macroCmd=new KMacroCommand(i18n("Paste Text")); + bool addMacroCmd = false; + dropCursor.place( dropPoint, textDocument()->firstParag() ); + kdDebug(33001) << "KPrTextView::dropEvent dropCursor at parag=" << dropCursor.parag()->paragId() << " index=" << dropCursor.index() << endl; + + if ( ( e->source() == m_canvas ) && + e->action() == QDropEvent::Move && + // this is the indicator that the source and dest text objects are the same + textDocument()->hasSelection( KoTextDocument::Standard ) + ) { + //kdDebug(33001)<<"decodeFrameSetNumber( QMimeSource *e ) :"<<numberFrameSet<<endl; + KCommand *cmd = textView()->prepareDropMove( dropCursor ); + if(cmd) + { + kpTextObject()->layout(); + macroCmd->addCommand(cmd); + addMacroCmd = true; + } + else + { + delete macroCmd; + return; + } + } + else + { // drop coming from outside -> forget about current selection + textDocument()->removeSelection( KoTextDocument::Standard ); + textObject()->selectionChangedNotify(); + } + QCString returnedTypeMime = KoTextObject::providesOasis( e ); + if ( !returnedTypeMime.isEmpty() ) + { + QByteArray arr = e->encodedData( returnedTypeMime ); + if ( arr.size() ) + { + KCommand *cmd = kpTextObject()->pasteOasis( cursor(), arr, false ); + if ( cmd ) + { + macroCmd->addCommand(cmd); + addMacroCmd = true; + } + } + } + else + { + QString text; + if ( QTextDrag::decode( e, text ) ) + textObject()->pasteText( cursor(), text, currentFormat(), + false /*do not remove selected text*/ ); + } + if ( addMacroCmd ) + doc->addCommand(macroCmd); + else + delete macroCmd; + } +} + +void KPrTextObject::saveParagraph( QDomDocument& doc,KoTextParag * parag,QDomElement &parentElem, + int from /* default 0 */, + int to /* default length()-2 */ ) +{ + if(!parag) + return; + QDomElement paragraph=doc.createElement(tagP); + int tmpAlign=0; + switch(parag->resolveAlignment()) + { + case Qt::AlignLeft: + tmpAlign=1; + break; + case Qt::AlignRight: + tmpAlign=2; + break; + case Qt::AlignHCenter: + tmpAlign=4; + break; + case Qt::AlignJustify: + tmpAlign=8; + } + if(tmpAlign!=1) + paragraph.setAttribute(attrAlign, tmpAlign); + + saveParagLayout( parag->paragLayout(), paragraph ); + KoTextFormat *lastFormat = 0; + QString tmpText; + for ( int i = from; i <= to; ++i ) { + KoTextStringChar &c = parag->string()->at(i); + if ( c.isCustom() ) + { + QDomElement variable = doc.createElement("CUSTOM"); + variable.setAttribute("pos", (i-from)); + saveFormat( variable, c.format() ); + paragraph.appendChild( variable ); + static_cast<KoTextCustomItem *>( c.customItem() )->save(variable ); + } + if ( !lastFormat || c.format()->key() != lastFormat->key() ) { + if ( lastFormat ) + paragraph.appendChild(saveHelper(tmpText, lastFormat, doc)); + lastFormat = static_cast<KoTextFormat*> (c.format()); + tmpText=QString::null; + } + tmpText+=QString(c.c); + } + if ( lastFormat ) + paragraph.appendChild(saveHelper(tmpText, lastFormat, doc)); + else + paragraph.appendChild(saveHelper(tmpText, parag->string()->at(0).format(), doc)); + + parentElem.appendChild(paragraph); +} + +KoPen KPrTextObject::defaultPen() const +{ + return KoPen( Qt::black, 1.0, Qt::NoPen ); +} + +QPoint KPrTextObject::viewToInternal( const QPoint & pos, KPrCanvas* canvas ) const +{ + KoTextZoomHandler* zh = kPresenterDocument()->zoomHandler(); + QPoint iPoint = pos - zh->zoomPoint( + getOrig() + KoPoint( bLeft(), + bTop() + alignmentValue()) ); + iPoint = zh->pixelToLayoutUnit( + QPoint( iPoint.x() + canvas->diffx(), iPoint.y() + canvas->diffy() ) ); + return iPoint; +} |
