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

2587 lines
98 KiB

// -*- 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 <tqfont.h>
#include <tqfile.h>
#include <tqwidget.h>
#include <tqpicture.h>
#include <tqpainter.h>
#include <tqwmatrix.h>
#include <tqdom.h>
#include <tqapplication.h>
#include <tqfontdatabase.h>
#include <tqpopupmenu.h>
#include <tqclipboard.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 TQString &KPrTextObject::tagTEXTOBJ=KGlobal::staticQString("TEXTOBJ");
const TQString &KPrTextObject::attrLineSpacing=KGlobal::staticQString("lineSpacing");
const TQString &KPrTextObject::attrParagSpacing=KGlobal::staticQString("paragSpacing");
const TQString &KPrTextObject::attrMargin=KGlobal::staticQString("margin");
const TQString &KPrTextObject::attrBulletType1=KGlobal::staticQString("bulletType1");
const TQString &KPrTextObject::attrBulletType2=KGlobal::staticQString("bulletType2");
const TQString &KPrTextObject::attrBulletType3=KGlobal::staticQString("bulletType3");
const TQString &KPrTextObject::attrBulletType4=KGlobal::staticQString("bulletType4");
const TQString &KPrTextObject::attrBulletColor1=KGlobal::staticQString("bulletColor1");
const TQString &KPrTextObject::attrBulletColor2=KGlobal::staticQString("bulletColor2");
const TQString &KPrTextObject::attrBulletColor3=KGlobal::staticQString("bulletColor3");
const TQString &KPrTextObject::attrBulletColor4=KGlobal::staticQString("bulletColor4");
const TQString &KPrTextObject::tagP=KGlobal::staticQString("P");
const TQString &KPrTextObject::attrAlign=KGlobal::staticQString("align");
const TQString &KPrTextObject::attrType=KGlobal::staticQString("type");
const TQString &KPrTextObject::attrDepth=KGlobal::staticQString("depth");
const TQString &KPrTextObject::tagTEXT=KGlobal::staticQString("TEXT");
const TQString &KPrTextObject::attrFamily=KGlobal::staticQString("family");
const TQString &KPrTextObject::attrPointSize=KGlobal::staticQString("pointSize");
const TQString &KPrTextObject::attrBold=KGlobal::staticQString("bold");
const TQString &KPrTextObject::attrItalic=KGlobal::staticQString("italic");
const TQString &KPrTextObject::attrUnderline=KGlobal::staticQString("underline");
const TQString &KPrTextObject::attrStrikeOut=KGlobal::staticQString("strikeOut");
const TQString &KPrTextObject::attrColor=KGlobal::staticQString("color");
const TQString &KPrTextObject::attrWhitespace=KGlobal::staticQString("whitespace");
const TQString &KPrTextObject::attrTextBackColor=KGlobal::staticQString("textbackcolor");
const TQString &KPrTextObject::attrVertAlign=KGlobal::staticQString("VERTALIGN");
KPrTextObject::KPrTextObject( KPrDocument *doc )
: KPr2DObject()
{
m_doc=doc;
m_textVertAlign = KP_TOP;
// Default color should be TQColor() ... but kpresenter isn't fully color-scheme-aware yet
KoTextFormatCollection* fc = new KoTextFormatCollection( doc->defaultFont(), TQt::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, TQT_SIGNAL( newCommand( KCommand * ) ),
TQT_SLOT( slotNewCommand( KCommand * ) ) );
connect( m_textobj, TQT_SIGNAL( availableHeightNeeded() ),
TQT_SLOT( slotAvailableHeightNeeded() ) );
connect( m_textobj, TQT_SIGNAL( repaintChanged( KoTextObject* ) ),
TQT_SLOT( slotRepaintChanged() ) );
// Send our "repaintChanged" signals to the document.
connect( this, TQT_SIGNAL( repaintChanged( KPrTextObject * ) ),
m_doc, TQT_SLOT( slotRepaintChanged( KPrTextObject * ) ) );
connect(m_textobj, TQT_SIGNAL( showFormatObject(const KoTextFormat &) ),
TQT_SLOT( slotFormatChanged(const KoTextFormat &)) );
connect( m_textobj, TQT_SIGNAL( afterFormatting( int, KoTextParag*, bool* ) ),
TQT_SLOT( slotAfterFormatting( int, KoTextParag*, bool* ) ) );
connect( m_textobj, TQT_SIGNAL( paragraphDeleted( KoTextParag*) ),
TQT_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);
}
TQBrush KPrTextObject::getBrush() const
{
TQBrush tmpBrush( m_brush.getBrush() );
if(!tmpBrush.color().isValid())
tmpBrush.setColor(TQApplication::palette().color( TQPalette::Active, TQColorGroup::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
}
}
TQDomDocumentFragment KPrTextObject::save( TQDomDocument& doc, double offset )
{
TQDomDocumentFragment 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 tqalignment
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 TQDomElement &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 tqalignment
if ( styleStack.hasAttributeNS( KoXmlNS::draw, "textarea-vertical-align" ) )
{
TQString tqalignment = styleStack.attributeNS( KoXmlNS::draw, "textarea-vertical-align" );
if ( tqalignment == "top" )
m_textVertAlign= KP_TOP;
else if ( tqalignment == "middle" )
m_textVertAlign= KP_CENTER;
else if ( tqalignment == "bottom" )
m_textVertAlign= KP_BOTTOM;
}
kdDebug()<<" vertical Alignment :"<< ( ( m_textVertAlign== KP_TOP ) ? "top" : ( m_textVertAlign== KP_CENTER ) ? "center": "bottom" )<<endl;
TQDomElement 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 TQDomElement &element)
{
double offset=KPr2DObject::load(element);
TQDomElement 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"))
{
TQString 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 = TQt::gray;
}
// Standard paint method for KP2DObjects.
void KPrTextObject::paint( TQPainter *_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( TQPainter *_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( TQPainter *_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 ) {
TQPen pen3( TQt::black, 1, TQt::DotLine );
_painter->setPen( pen3 );
_painter->setRasterOp( TQt::NotXorROP );
_painter->drawRect( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw),
_zoomHandler->zoomItX(ow), _zoomHandler->zoomItY( oh) );
return;
}
_painter->save();
TQPen pen2 = pen.zoomedPen(_zoomHandler);
//TQRect clip=TQRect(_zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw), _zoomHandler->zoomItX( ow - 2 * pw),_zoomHandler->zoomItY( oh - 2 * pw));
//setupClipRegion( _painter, clip );
//for debug
//_painter->fillRect( clip, TQt::blue );
_painter->setPen( pen2 );
if ( editingTextObj && _painter->device() && _painter->device()->devType() != TQInternal::Printer) // editing text object
_painter->setBrush( TQBrush( m_doc->txtBackCol(), TQt::SolidPattern ) );
else {
// Handle the rotation, draw the background/border, then call drawText()
if ( getFillType() == FT_BRUSH || !gradient ) {
_painter->setBrush( getBrush() );
}
else {
TQSize 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() == TQt::NoPen )
{
_painter->save();
_painter->setPen( TQPen( TQt::gray, 1, TQt::DotLine ) );
_painter->setBrush( TQt::NoBrush );
_painter->setRasterOp( TQt::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( TQPainter* _painter, KoTextZoomHandler *zoomHandler, bool onlyChanged, KoTextCursor* cursor, bool resetChanged )
{
//kdDebug(33001) << "KPrTextObject::drawText onlyChanged=" << onlyChanged << " cursor=" << cursor << " resetChanged=" << resetChanged << endl;
recalcVerticalAlignment();
TQColorGroup cg = TQApplication::tqpalette().active();
_painter->save();
_painter->translate( m_doc->zoomHandler()->zoomItX( bLeft()), m_doc->zoomHandler()->zoomItY( bTop()+alignVertical));
if ( !editingTextObj || (_painter->device() && _painter->device()->devType() == TQInternal::Printer))
cg.setBrush( TQColorGroup::Base, Qt::NoBrush );
else
cg.setColor( TQColorGroup::Base, m_doc->txtBackCol() );
TQRect 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() != TQInternal::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;
}
TQDomElement KPrTextObject::saveKTextObject( TQDomDocument& doc )
{
#if 0
KTextEditParag *parag = ktextobject.document()->firstParag();
KTextEditDocument::TextSettings textSettings = ktextobject.document()->textSettings();
#endif
TQDomElement 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( TQDomElement & element, KoTextFormat*lastFormat )
{
TQString 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);
TQString 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);
TQString 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());
}
TQDomElement KPrTextObject::saveHelper(const TQString &tmpText,KoTextFormat*lastFormat , TQDomDocument &doc)
{
TQDomElement element=doc.createElement(tagTEXT);
saveFormat ( element, lastFormat );
if(tmpText.stripWhiteSpace().isEmpty())
// working around a bug in TQDom
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 TQDomElement &elem )
{
TQDomElement 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() ) {
TQValueList<TQDomElement> listVariable;
listVariable.clear();
if ( e.tagName() == tagP ) {
TQDomElement 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[TQStyleSheetItem::MarginLeft] = depth * MM_TO_POINT(10.0);
}
//kdDebug(33001) << k_funcinfo << "old bullet depth is: " << depth << endl;
// 1.1 compatibility (bullets)
TQString 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(TQString());
paragLayout.counter->setSuffix(TQString());
}
// 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[ TQStyleSheetItem::MarginTop ] == 0 )
paragLayout.margins[ TQStyleSheetItem::MarginTop ] = topBorder;
if ( paragLayout.margins[ TQStyleSheetItem::MarginBottom ] == 0 )
paragLayout.margins[ TQStyleSheetItem::MarginBottom ] = bottomBorder;
lastParag->setParagLayout( paragLayout );
//lastParag->setAlign(TQt::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(TQt::AlignLeft);
else if(tmpAlign==2)
lastParag->setAlign(TQt::AlignRight);
else if(tmpAlign==4)
lastParag->setAlign(TQt::AlignHCenter);
else if(tmpAlign==8)
lastParag->setAlign(TQt::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() );
TQString 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 ) {
//TQColor 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( TQValueList<TQDomElement> & listVariable,KoTextParag *lastParag, int offset )
{
TQValueList<TQDomElement>::Iterator it = listVariable.begin();
TQValueList<TQDomElement>::Iterator end = listVariable.end();
for ( ; it != end ; ++it )
{
TQDomElement elem = *it;
if ( !elem.hasAttribute("pos"))
continue;
int index = elem.attribute("pos").toInt();
index+=offset;
TQDomElement varElem = elem.namedItem( "VARIABLE" ).toElement();
if ( !varElem.isNull() )
{
TQDomElement typeElem = varElem.namedItem( "TYPE" ).toElement();
int type = typeElem.attribute( "type" ).toInt();
TQString 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( TQDomElement &n, KoTextFormat * refFormat, const TQFont & defaultFont,
const TQString & defaultLanguage, bool hyphen )
{
KoTextFormat format;
format.setHyphenation( hyphen );
TQFont fn;
if ( refFormat )
{
format = *refFormat;
format.setCollection( 0 ); // Out of collection copy
fn = format.font();
}
else
fn = defaultFont;
if ( !n.isNull() )
{
TQFontDatabase fdb;
TQStringList families = fdb.tqfamilies();
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 ))
{
TQString 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(TQColor(n.attribute("underlinecolor")));
if(n.hasAttribute(attrStrikeOut))
{
TQString 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"))
{
TQString strLineType = n.attribute("strikeoutstyleline");
format.setStrikeOutStyle( KoTextFormat::stringToStrikeOutStyle( strLineType ));
}
TQString color = n.attribute( attrColor );
fn.setPointSize( size );
fn.setBold( bold );
fn.setItalic( italic );
//kdDebug(33001) << "KPrTextObject::loadFormat: family=" << fn.family() << " size=" << fn.pointSize() << endl;
TQColor col( color );
format.setFont( fn );
format.setColor( col );
TQString textBackColor=n.attribute(attrTextBackColor);
if(!textBackColor.isEmpty())
{
TQColor tmpCol(textBackColor);
tmpCol=tmpCol.isValid() ? tmpCol : TQApplication::palette().color( TQPalette::Active, TQColorGroup::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( TQDomElement & parentElem, KPrDocument *doc, bool findStyle)
{
KoParagLayout tqlayout;
// 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!
TQDomElement element = parentElem.namedItem( "NAME" ).toElement();
if ( !element.isNull() )
{
TQString 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);
tqlayout.style = style;
}
TQDomElement element = parentElem.namedItem( "INDENTS" ).toElement();
if ( !element.isNull() )
{
double val=0.0;
if(element.hasAttribute("first"))
val=element.attribute("first").toDouble();
tqlayout.margins[TQStyleSheetItem::MarginFirstLine] = val;
val=0.0;
if(element.hasAttribute( "left"))
// The GUI prevents a negative indent, so let's fixup broken docs too
val=TQMAX(0, element.attribute( "left").toDouble());
tqlayout.margins[TQStyleSheetItem::MarginLeft] = val;
val=0.0;
if(element.hasAttribute("right"))
// The GUI prevents a negative indent, so let's fixup broken docs too
val=TQMAX(0, element.attribute("right").toDouble());
tqlayout.margins[TQStyleSheetItem::MarginRight] = val;
}
element = parentElem.namedItem( "LINESPACING" ).toElement();
if ( !element.isNull() )
{
//compatibility with koffice 1.1
if ( element.hasAttribute( "value" ))
{
TQString value = element.attribute( "value" );
if ( value == "oneandhalf" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_ONEANDHALF;
tqlayout.setLineSpacingValue(0);
}
else if ( value == "double" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_DOUBLE;
tqlayout.setLineSpacingValue(0);
}
else
{
tqlayout.lineSpacingType = KoParagLayout::LS_CUSTOM;
tqlayout.setLineSpacingValue(value.toDouble());
}
}
else
{
TQString type = element.attribute( "type" );
if ( type == "oneandhalf" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_ONEANDHALF;
tqlayout.setLineSpacingValue(0);
}
else if ( type == "double" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_DOUBLE;
tqlayout.setLineSpacingValue(0);
}
else if ( type == "custom" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_CUSTOM;
tqlayout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble());
}
else if ( type == "atleast" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_AT_LEAST;
tqlayout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble());
}
else if ( type == "multiple" )
{
tqlayout.lineSpacingType = KoParagLayout::LS_MULTIPLE;
tqlayout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble());
}
}
}
element = parentElem.namedItem( "OFFSETS" ).toElement();
if ( !element.isNull() )
{
double val =0.0;
if(element.hasAttribute("before"))
val=TQMAX(0, element.attribute("before").toDouble());
tqlayout.margins[TQStyleSheetItem::MarginTop] = val;
val = 0.0;
if(element.hasAttribute("after"))
val=TQMAX(0, element.attribute("after").toDouble());
tqlayout.margins[TQStyleSheetItem::MarginBottom] = val;
}
element = parentElem.namedItem( "LEFTBORDER" ).toElement();
if ( !element.isNull() )
tqlayout.leftBorder = KoBorder::loadBorder( element );
else
tqlayout.leftBorder.setPenWidth( 0);
element = parentElem.namedItem( "RIGHTBORDER" ).toElement();
if ( !element.isNull() )
tqlayout.rightBorder = KoBorder::loadBorder( element );
else
tqlayout.rightBorder.setPenWidth( 0);
element = parentElem.namedItem( "TOPBORDER" ).toElement();
if ( !element.isNull() )
tqlayout.topBorder = KoBorder::loadBorder( element );
else
tqlayout.topBorder.setPenWidth(0);
element = parentElem.namedItem( "BOTTOMBORDER" ).toElement();
if ( !element.isNull() )
tqlayout.bottomBorder = KoBorder::loadBorder( element );
else
tqlayout.bottomBorder.setPenWidth(0);
element = parentElem.namedItem( "COUNTER" ).toElement();
if ( !element.isNull() )
{
tqlayout.counter = new KoParagCounter;
tqlayout.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 );
}
}
tqlayout.setTabList( tabList );
return tqlayout;
}
void KPrTextObject::saveParagLayout( const KoParagLayout& tqlayout, TQDomElement & parentElem )
{
TQDomDocument doc = parentElem.ownerDocument();
TQDomElement element = doc.createElement( "NAME" );
parentElem.appendChild( element );
if ( tqlayout.style )
element.setAttribute( "value", tqlayout.style->name() );
else
kdWarning() << "KWTextParag::saveParagLayout: style==0L!" << endl;
if ( tqlayout.margins[TQStyleSheetItem::MarginFirstLine] != 0 ||
tqlayout.margins[TQStyleSheetItem::MarginLeft] != 0 ||
tqlayout.margins[TQStyleSheetItem::MarginRight] != 0 )
{
element = doc.createElement( "INDENTS" );
parentElem.appendChild( element );
if ( tqlayout.margins[TQStyleSheetItem::MarginFirstLine] != 0 )
element.setAttribute( "first", tqlayout.margins[TQStyleSheetItem::MarginFirstLine] );
if ( tqlayout.margins[TQStyleSheetItem::MarginLeft] != 0 )
element.setAttribute( "left", tqlayout.margins[TQStyleSheetItem::MarginLeft] );
if ( tqlayout.margins[TQStyleSheetItem::MarginRight] != 0 )
element.setAttribute( "right", tqlayout.margins[TQStyleSheetItem::MarginRight] );
}
if ( tqlayout.margins[TQStyleSheetItem::MarginTop] != 0 ||
tqlayout.margins[TQStyleSheetItem::MarginBottom] != 0 )
{
element = doc.createElement( "OFFSETS" );
parentElem.appendChild( element );
if ( tqlayout.margins[TQStyleSheetItem::MarginTop] != 0 )
element.setAttribute( "before", tqlayout.margins[TQStyleSheetItem::MarginTop] );
if ( tqlayout.margins[TQStyleSheetItem::MarginBottom] != 0 )
element.setAttribute( "after", tqlayout.margins[TQStyleSheetItem::MarginBottom] );
}
if ( tqlayout.lineSpacingType != KoParagLayout::LS_SINGLE )
{
element = doc.createElement( "LINESPACING" );
parentElem.appendChild( element );
if ( tqlayout.lineSpacingType == KoParagLayout::LS_ONEANDHALF )
element.setAttribute( "type", "oneandhalf" );
else if ( tqlayout.lineSpacingType == KoParagLayout::LS_DOUBLE )
element.setAttribute( "type", "double" );
else if ( tqlayout.lineSpacingType == KoParagLayout::LS_CUSTOM )
{
element.setAttribute( "type", "custom" );
element.setAttribute( "spacingvalue", tqlayout.lineSpacingValue());
}
else if ( tqlayout.lineSpacingType == KoParagLayout::LS_AT_LEAST )
{
element.setAttribute( "type", "atleast" );
element.setAttribute( "spacingvalue", tqlayout.lineSpacingValue());
}
else if ( tqlayout.lineSpacingType == KoParagLayout::LS_MULTIPLE )
{
element.setAttribute( "type", "multiple" );
element.setAttribute( "spacingvalue", tqlayout.lineSpacingValue());
}
else
kdDebug(33001) << " error in lineSpacing Type" << endl;
}
if ( tqlayout.leftBorder.penWidth() > 0 )
{
element = doc.createElement( "LEFTBORDER" );
parentElem.appendChild( element );
tqlayout.leftBorder.save( element );
}
if ( tqlayout.rightBorder.penWidth() > 0 )
{
element = doc.createElement( "RIGHTBORDER" );
parentElem.appendChild( element );
tqlayout.rightBorder.save( element );
}
if ( tqlayout.topBorder.penWidth() > 0 )
{
element = doc.createElement( "TOPBORDER" );
parentElem.appendChild( element );
tqlayout.topBorder.save( element );
}
if ( tqlayout.bottomBorder.penWidth() > 0 )
{
element = doc.createElement( "BOTTOMBORDER" );
parentElem.appendChild( element );
tqlayout.bottomBorder.save( element );
}
if ( tqlayout.counter && tqlayout.counter->numbering() != KoParagCounter::NUM_NONE )
{
element = doc.createElement( "COUNTER" );
parentElem.appendChild( element );
if (tqlayout.counter )
tqlayout.counter->save( element );
}
KoTabulatorList tabList = tqlayout.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;
TQPtrListIterator<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( TQMAX( pgnum -1 , 0) +
kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber());
break;
case KPrPgNumVariable::VST_PGNUM_NEXT:
var->setPgNum( TQMIN( (int)m_doc->getPageNums(), pgnum+1 ) +
kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber());
break;
default:
break;
}
var->resize();
var->paragraph()->tqinvalidate( 0 ); // size may have changed -> need reformatting !
var->paragraph()->setChanged( true );
}
}
}
void KPrTextObject::tqlayout()
{
tqinvalidate();
// Get the thing going though, repainting doesn't call formatMore
m_textobj->formatMore( 2 );
}
void KPrTextObject::tqinvalidate()
{
//kdDebug(33001) << "KWTextFrameSet::tqinvalidate " << getName() << endl;
m_textobj->setLastFormattedParag( textDocument()->firstParag() );
textDocument()->formatter()->setViewFormattingChars( m_doc->viewFormattingChars() );
textDocument()->tqinvalidate(); // lazy tqlayout, real update follows upon next tqrepaint
}
// For the "paragraph after paragraph" effect
void KPrTextObject::drawParags( TQPainter *painter, KoTextZoomHandler* zoomHandler, const TQColorGroup& 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();
TQRect 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( TQPainter *p, KoTextCursor *cursor, bool cursorVisible, KPrCanvas* canvas )
{
// The implementation is very related to KWord's KWTextFrameSet::drawCursor
KoTextZoomHandler *zh = m_doc->zoomHandler();
TQPoint 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();
TQPoint topLeft = parag->rect().topLeft(); // in TQRT coords
int lineY;
// Cursor height, in pixels
int cursorHeight = zh->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) );
TQPoint iPoint( topLeft.x() + cursor->x(),
topLeft.y() + lineY );
// from now on, iPoint will be in pixels
iPoint = zh->layoutUnitToPixel( iPoint );
TQPoint 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
TQRect clip( vPoint.x() - 5, vPoint.y() , 10, cursorHeight );
setupClipRegion( p, clip );
// for debug only!
//p->fillRect( clip, TQt::blue );
TQPixmap *pix = 0;
TQColorGroup cg = TQApplication::tqpalette().active();
cg.setColor( TQColorGroup::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,
TQMAX(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
TQPoint ximPoint = vPoint;
TQFont 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 /*tqrepaint*/ );
}
void KPrTextObject::highlightPortion( KoTextParag * parag, int index, int length, KPrCanvas* canvas, bool tqrepaint, KDialogBase* dialog )
{
m_textobj->highlightPortion( parag, index, length, tqrepaint );
if ( tqrepaint )
{
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
TQRect rect = m_doc->zoomHandler()->zoomRect( getRect() );
TQRect 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 ) {
TQRect globalRect( expose );
globalRect.moveTopLeft( canvas->mapToGlobal( globalRect.topLeft() ) );
KDialog::avoidArea( dialog, globalRect );
}
#endif
}
}
KCommand * KPrTextObject::pasteOasis( KoTextCursor * cursor, const TQByteArray & 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, */TQString() ) );
*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 TQColor &_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 tqlayout 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 = TQMIN( wantedPosition, pageBottom ); // don't grow bigger than the page
newBottom = TQMAX( 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->tqrepaint( 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 = TQMAX( 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( TQString(), 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;
}
}
TQPoint KPrTextObject::cursorPos(KPrCanvas *canvas, KoTextCursor *cursor) const
{
KoTextZoomHandler *zh = m_doc->zoomHandler();
TQPoint origPix = zh->zoomPoint( orig+KoPoint(bLeft(), bTop()+alignVertical) );
KoTextParag* parag = cursor->parag();
TQPoint topLeft = parag->rect().topLeft(); // in TQRT coords
int lineY = 0;
// Cursor height, in pixels
//int cursorHeight = zh->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) );
TQPoint 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(), TQT_SIGNAL( selectionChanged(bool) ),
m_canvas, TQT_SIGNAL( selectionChanged(bool) ) );
KoTextView::setReadWrite( txtObj->kPresenterDocument()->isReadWrite() );
connect( textView(), TQT_SIGNAL( cut() ), TQT_SLOT( cut() ) );
connect( textView(), TQT_SIGNAL( copy() ), TQT_SLOT( copy() ) );
connect( textView(), TQT_SIGNAL( paste() ), TQT_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(), TQT_SIGNAL( selectionChanged(bool) ),
m_canvas, TQT_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 ) ) {
TQDragObject *drag = newDrag( 0 );
TQApplication::tqclipboard()->setData( drag );
}
}
void KPrTextView::paste()
{
//kdDebug(33001) << "KPrTextView::paste()" << endl;
TQMimeSource *data = TQApplication::tqclipboard()->data();
TQCString returnedMimeType = KoTextObject::providesOasis( data );
if ( !returnedMimeType.isEmpty() )
{
TQByteArray arr = data->tqencodedData( returnedMimeType );
if ( arr.size() )
{
#if 0
TQFile 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: TQClipboard::text() seems to do a better job than tqencodedData( "text/plain" )
// In particular it handles charsets (in the mimetype).
TQString text = TQApplication::tqclipboard()->text();
if ( !text.isEmpty() )
textObject()->pasteText( cursor(), text, currentFormat(), true /*removeSelected*/ );
}
kpTextObject()->tqlayout();
}
void KPrTextView::updateUI( bool updateFormat, bool force )
{
KoTextView::updateUI( updateFormat, force );
// Paragraph settings
KoTextParag * parag = static_cast<KoTextParag*>( cursor()->parag());
if ( m_paragLayout.tqalignment != parag->resolveAlignment() || force ) {
m_paragLayout.tqalignment = parag->resolveAlignment();
m_canvas->getView()->alignChanged( m_paragLayout.tqalignment );
}
// 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[TQStyleSheetItem::MarginLeft] != parag->margin(TQStyleSheetItem::MarginLeft)
|| m_paragLayout.margins[TQStyleSheetItem::MarginFirstLine] != parag->margin(TQStyleSheetItem::MarginFirstLine)
|| m_paragLayout.margins[TQStyleSheetItem::MarginRight] != parag->margin(TQStyleSheetItem::MarginRight)
|| force )
{
m_paragLayout.margins[TQStyleSheetItem::MarginFirstLine] = parag->margin(TQStyleSheetItem::MarginFirstLine);
m_paragLayout.margins[TQStyleSheetItem::MarginLeft] = parag->margin(TQStyleSheetItem::MarginLeft);
m_paragLayout.margins[TQStyleSheetItem::MarginRight] = parag->margin(TQStyleSheetItem::MarginRight);
m_canvas->getView()->showRulerIndent( m_paragLayout.margins[TQStyleSheetItem::MarginLeft],
m_paragLayout.margins[TQStyleSheetItem::MarginFirstLine],
m_paragLayout.margins[TQStyleSheetItem::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() );
TQPoint 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, TQWidget *widget, const TQPoint &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[TQStyleSheetItem::MarginLeft]>0)
{
m_canvas->setTextDepthMinus();
return true;
}
else
return false;
}
void KPrTextView::doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, TQChar 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,TQChar 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();
TQDragObject *drag = newDrag( m_canvas );
if ( !kpTextObject()->kPresenterDocument()->isReadWrite() )
drag->dragCopy();
else
{
if ( drag->drag() && TQDragObject::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( TQKeyEvent *e )
{
//Calculate position of tooltip for autocompletion
const TQPoint pos = kpTextObject()->cursorPos(m_canvas, cursor());
textView()->handleKeyPressEvent( e, m_canvas, pos );
}
void KPrTextView::keyReleaseEvent( TQKeyEvent *e )
{
handleKeyReleaseEvent(e);
}
void KPrTextView::imStartEvent( TQIMEvent *e )
{
handleImStartEvent(e);
}
void KPrTextView::imComposeEvent( TQIMEvent *e )
{
handleImComposeEvent(e);
}
void KPrTextView::imEndEvent( TQIMEvent *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;
TQPainter 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 TQRT document position
TQPoint KPrTextView::viewToInternal( const TQPoint & pos ) const
{
#if 0
KoTextZoomHandler* zh = kpTextObject()->kPresenterDocument()->zoomHandler();
TQPoint tmp(pos);
TQWMatrix 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( TQMouseEvent *e, const TQPoint &/*_pos*/)
{
bool addParag = handleMousePressEvent( e, viewToInternal( e->pos() ),true /*bool canStartDrag*/,
kpTextObject()->kPresenterDocument()->insertDirectCursor() );
if ( addParag )
kpTextObject()->kPresenterDocument()->setModified( true );
}
void KPrTextView::mouseDoubleClickEvent( TQMouseEvent *e, const TQPoint &pos)
{
handleMouseDoubleClickEvent( e, pos );
}
void KPrTextView::mouseMoveEvent( TQMouseEvent *e, const TQPoint &_pos )
{
if ( textView()->maybeStartDrag( e ) )
return;
if ( _pos.y() > 0 )
textView()->handleMouseMoveEvent( e,viewToInternal( e->pos() ) );
}
bool KPrTextView::isLinkVariable( const TQPoint & pos )
{
const TQPoint 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( TQMouseEvent *, const TQPoint & )
{
handleMouseReleaseEvent();
}
void KPrTextView::showPopup( KPrView *view, const TQPoint &point, TQPtrList<KAction>& actionList )
{
TQString word = wordUnderCursor( *cursor() );
view->unplugActionList( "datatools" );
view->unplugActionList( "datatools_link" );
view->unplugActionList( "spell_result_action" );
view->unplugActionList( "variable_action" );
TQPtrList<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 );
TQPopupMenu * 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 );
TQPopupMenu * 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 )
{
TQPtrList<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 TQString &name)
{
KPrDocument * doc = kpTextObject()->kPresenterDocument();
KoVariable * var = new KoCustomVariable( textDocument(), name, doc->variableFormatCollection()->format( "STRING" ),
doc->getVariableCollection());
insertVariable( var );
}
void KPrTextView::insertLink(const TQString &_linkName, const TQString & hrefName)
{
KPrDocument * doc = kpTextObject()->kPresenterDocument();
KoVariable * var = new KoLinkVariable( textDocument(), _linkName, hrefName,
doc->variableFormatCollection()->format( "STRING" ),
doc->getVariableCollection());
insertVariable( var );
}
void KPrTextView::insertComment(const TQString &_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() == TQDialog::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()->tqrepaint( kpTextObject() );
}
}
bool KPrTextView::canDecode( TQMimeSource *e )
{
return kpTextObject()->kPresenterDocument()->isReadWrite() && ( !KoTextObject::providesOasis( e ).isNull() || TQTextDrag::canDecode( e ) );
}
TQDragObject * KPrTextView::newDrag( TQWidget * parent )
{
TQBuffer buffer;
const TQCString mimeType = "application/vnd.oasis.opendocument.text";
KoStore * store = KoStore::createStore( TQT_TQIODEVICE(&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( TQDateTime::tqcurrentDateTime() );
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 TQString 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 TQTextDrag( 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( TQDragEnterEvent *e )
{
if ( !canDecode( e ) )
{
e->ignore();
return;
}
e->acceptAction();
}
void KPrTextView::dragMoveEvent( TQDragMoveEvent *e, const TQPoint & )
{
if ( !canDecode( e ) )
{
e->ignore();
return;
}
TQPoint iPoint = viewToInternal( e->pos() );
textObject()->emitHideCursor();
placeCursor( iPoint );
textObject()->emitShowCursor();
e->acceptAction(); // here or out of the if ?
}
void KPrTextView::dropEvent( TQDropEvent * e )
{
if ( canDecode( e ) )
{
KPrDocument *doc = kpTextObject()->kPresenterDocument();
e->acceptAction();
KoTextCursor dropCursor( textDocument() );
TQPoint 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() == TQDropEvent::Move &&
// this is the indicator that the source and dest text objects are the same
textDocument()->hasSelection( KoTextDocument::Standard )
) {
//kdDebug(33001)<<"decodeFrameSetNumber( TQMimeSource *e ) :"<<numberFrameSet<<endl;
KCommand *cmd = textView()->prepareDropMove( dropCursor );
if(cmd)
{
kpTextObject()->tqlayout();
macroCmd->addCommand(cmd);
addMacroCmd = true;
}
else
{
delete macroCmd;
return;
}
}
else
{ // drop coming from outside -> forget about current selection
textDocument()->removeSelection( KoTextDocument::Standard );
textObject()->selectionChangedNotify();
}
TQCString returnedTypeMime = KoTextObject::providesOasis( e );
if ( !returnedTypeMime.isEmpty() )
{
TQByteArray arr = e->tqencodedData( returnedTypeMime );
if ( arr.size() )
{
KCommand *cmd = kpTextObject()->pasteOasis( cursor(), arr, false );
if ( cmd )
{
macroCmd->addCommand(cmd);
addMacroCmd = true;
}
}
}
else
{
TQString text;
if ( TQTextDrag::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( TQDomDocument& doc,KoTextParag * parag,TQDomElement &parentElem,
int from /* default 0 */,
int to /* default length()-2 */ )
{
if(!parag)
return;
TQDomElement paragraph=doc.createElement(tagP);
int tmpAlign=0;
switch(parag->resolveAlignment())
{
case TQt::AlignLeft:
tmpAlign=1;
break;
case TQt::AlignRight:
tmpAlign=2;
break;
case TQt::AlignHCenter:
tmpAlign=4;
break;
case TQt::AlignJustify:
tmpAlign=8;
}
if(tmpAlign!=1)
paragraph.setAttribute(attrAlign, tmpAlign);
saveParagLayout( parag->paragLayout(), paragraph );
KoTextFormat *lastFormat = 0;
TQString tmpText;
for ( int i = from; i <= to; ++i ) {
KoTextStringChar &c = parag->string()->at(i);
if ( c.isCustom() )
{
TQDomElement 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=TQString();
}
tmpText+=TQString(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( TQt::black, 1.0, Qt::NoPen );
}
TQPoint KPrTextObject::viewToInternal( const TQPoint & pos, KPrCanvas* canvas ) const
{
KoTextZoomHandler* zh = kPresenterDocument()->zoomHandler();
TQPoint iPoint = pos - zh->zoomPoint(
getOrig() + KoPoint( bLeft(),
bTop() + alignmentValue()) );
iPoint = zh->pixelToLayoutUnit(
TQPoint( iPoint.x() + canvas->diffx(), iPoint.y() + canvas->diffy() ) );
return iPoint;
}