kpresenter

KPrTextObject.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23#include "KPrTextObject.h"
24#include "KPrTextObject.moc"
25#include "KPrGradient.h"
26#include "KPrCommand.h"
27#include "KPrCanvas.h"
28#include "KPrPage.h"
29#include "KPrView.h"
30#include "KPrDocument.h"
31#include "KPrBgSpellCheck.h"
32#include "KPrVariableCollection.h"
33
34#include <KoAutoFormat.h>
35#include <KoTextParag.h>
36#include <KoTextObject.h>
37#include <KoStyleCollection.h>
38#include <KoTextFormatter.h>
39#include <KoTextZoomHandler.h>
40#include "KPrTextViewIface.h"
41#include "KPrTextObjectIface.h"
42#include <KoOasisContext.h>
43#include <KoStyleStack.h>
44#include <tdetempfile.h>
45#include <tdelocale.h>
46#include <kdebug.h>
47#include <tdemultipledrag.h>
48
49#include <tqfont.h>
50#include <tqfile.h>
51#include <tqwidget.h>
52#include <tqpicture.h>
53#include <tqpainter.h>
54#include <tqwmatrix.h>
55#include <tqdom.h>
56#include <tqapplication.h>
57#include <tqfontdatabase.h>
58#include <tqpopupmenu.h>
59#include <tqclipboard.h>
60
61#include <KoParagCounter.h>
62#include <tdeaction.h>
63#include <KoVariable.h>
64#include <KoCustomVariablesDia.h>
65#include <KoRuler.h>
66#include <KoSize.h>
67#include <KoXmlNS.h>
68#include <KoDom.h>
69#include <KoStore.h>
70#include <KoStoreDrag.h>
71#include <KoOasisStore.h>
72
73#include <float.h>
74using namespace std;
75
76#undef S_NONE // Solaris defines it in sys/signal.h
77
78const TQString &KPrTextObject::tagTEXTOBJ=TDEGlobal::staticQString("TEXTOBJ");
79const TQString &KPrTextObject::attrLineSpacing=TDEGlobal::staticQString("lineSpacing");
80const TQString &KPrTextObject::attrParagSpacing=TDEGlobal::staticQString("paragSpacing");
81const TQString &KPrTextObject::attrMargin=TDEGlobal::staticQString("margin");
82const TQString &KPrTextObject::attrBulletType1=TDEGlobal::staticQString("bulletType1");
83const TQString &KPrTextObject::attrBulletType2=TDEGlobal::staticQString("bulletType2");
84const TQString &KPrTextObject::attrBulletType3=TDEGlobal::staticQString("bulletType3");
85const TQString &KPrTextObject::attrBulletType4=TDEGlobal::staticQString("bulletType4");
86const TQString &KPrTextObject::attrBulletColor1=TDEGlobal::staticQString("bulletColor1");
87const TQString &KPrTextObject::attrBulletColor2=TDEGlobal::staticQString("bulletColor2");
88const TQString &KPrTextObject::attrBulletColor3=TDEGlobal::staticQString("bulletColor3");
89const TQString &KPrTextObject::attrBulletColor4=TDEGlobal::staticQString("bulletColor4");
90const TQString &KPrTextObject::tagP=TDEGlobal::staticQString("P");
91const TQString &KPrTextObject::attrAlign=TDEGlobal::staticQString("align");
92const TQString &KPrTextObject::attrType=TDEGlobal::staticQString("type");
93const TQString &KPrTextObject::attrDepth=TDEGlobal::staticQString("depth");
94const TQString &KPrTextObject::tagTEXT=TDEGlobal::staticQString("TEXT");
95const TQString &KPrTextObject::attrFamily=TDEGlobal::staticQString("family");
96const TQString &KPrTextObject::attrPointSize=TDEGlobal::staticQString("pointSize");
97const TQString &KPrTextObject::attrBold=TDEGlobal::staticQString("bold");
98const TQString &KPrTextObject::attrItalic=TDEGlobal::staticQString("italic");
99const TQString &KPrTextObject::attrUnderline=TDEGlobal::staticQString("underline");
100const TQString &KPrTextObject::attrStrikeOut=TDEGlobal::staticQString("strikeOut");
101const TQString &KPrTextObject::attrColor=TDEGlobal::staticQString("color");
102const TQString &KPrTextObject::attrWhitespace=TDEGlobal::staticQString("whitespace");
103const TQString &KPrTextObject::attrTextBackColor=TDEGlobal::staticQString("textbackcolor");
104const TQString &KPrTextObject::attrVertAlign=TDEGlobal::staticQString("VERTALIGN");
105
106
107KPrTextObject::KPrTextObject( KPrDocument *doc )
108 : KPr2DObject()
109{
110 m_doc=doc;
111 m_textVertAlign = KP_TOP;
112 // Default color should be TQColor() ... but kpresenter isn't fully color-scheme-aware yet
113 KoTextFormatCollection* fc = new KoTextFormatCollection( doc->defaultFont(), TQt::black, doc->globalLanguage(), doc->globalHyphenation() );
114 KPrTextDocument * textdoc = new KPrTextDocument( this, fc );
115 if ( m_doc->tabStopValue() != -1 )
116 textdoc->setTabStops( m_doc->zoomHandler()->ptToLayoutUnitPixX( m_doc->tabStopValue() ));
117
118 m_textobj = new KoTextObject( textdoc, m_doc->styleCollection()->findStyle( "Standard" ), this );
119 textdoc->setFlow( this );
120
121 m_doc->backSpeller()->registerNewTextObject( m_textobj );
122 pen = defaultPen();
123 drawEditRect = true;
124 drawEmpty = true;
125 editingTextObj = false;
126
127 bleft = 0.0;
128 btop = 0.0;
129 bright = 0.0;
130 bbottom = 0.0;
131 alignVertical = 0.0;
132
133 connect( m_textobj, TQ_SIGNAL( newCommand( KCommand * ) ),
134 TQ_SLOT( slotNewCommand( KCommand * ) ) );
135 connect( m_textobj, TQ_SIGNAL( availableHeightNeeded() ),
136 TQ_SLOT( slotAvailableHeightNeeded() ) );
137 connect( m_textobj, TQ_SIGNAL( repaintChanged( KoTextObject* ) ),
138 TQ_SLOT( slotRepaintChanged() ) );
139
140 // Send our "repaintChanged" signals to the document.
141 connect( this, TQ_SIGNAL( repaintChanged( KPrTextObject * ) ),
142 m_doc, TQ_SLOT( slotRepaintChanged( KPrTextObject * ) ) );
143 connect(m_textobj, TQ_SIGNAL( showFormatObject(const KoTextFormat &) ),
144 TQ_SLOT( slotFormatChanged(const KoTextFormat &)) );
145 connect( m_textobj, TQ_SIGNAL( afterFormatting( int, KoTextParag*, bool* ) ),
146 TQ_SLOT( slotAfterFormatting( int, KoTextParag*, bool* ) ) );
147 connect( m_textobj, TQ_SIGNAL( paragraphDeleted( KoTextParag*) ),
148 TQ_SLOT( slotParagraphDeleted(KoTextParag*) ));
149
150}
151
152KPrTextObject::~KPrTextObject()
153{
154 textDocument()->takeFlow();
155 m_doc = 0L;
156}
157
158DCOPObject* KPrTextObject::dcopObject()
159{
160 if ( !dcop )
161 dcop = new KPrTextObjectIface( this );
162 return dcop;
163}
164
165void KPrTextObject::slotParagraphDeleted(KoTextParag*_parag)
166{
167 m_doc->spellCheckParagraphDeleted( _parag, this);
168}
169
170TQBrush KPrTextObject::getBrush() const
171{
172 TQBrush tmpBrush( m_brush.getBrush() );
173 if(!tmpBrush.color().isValid())
174 tmpBrush.setColor(TQApplication::palette().color( TQPalette::Active, TQColorGroup::Base ));
175 return tmpBrush;
176}
177
178void KPrTextObject::resizeTextDocument( bool widthChanged, bool heightChanged )
179{
180 if ( heightChanged )
181 {
182 // Recalc available height
183 slotAvailableHeightNeeded();
184 // Recalc the vertical centering, if enabled
185 recalcVerticalAlignment();
186 }
187 if ( widthChanged )
188 {
189 // not when simply changing the height, otherwise the auto-resize code
190 // prevents making a textobject less high than it currently is.
191 textDocument()->setWidth( m_doc->zoomHandler()->ptToLayoutUnitPixX( innerWidth() ) );
192 m_textobj->setLastFormattedParag( textDocument()->firstParag() );
193 m_textobj->formatMore( 2 );
194 }
195}
196
197void KPrTextObject::setSize( double _width, double _height )
198{
199 bool widthModified = KABS( _width - ext.width() ) > DBL_EPSILON ; // floating-point equality test
200 bool heightModified = KABS( _height - ext.height() ) > DBL_EPSILON;
201 if ( widthModified || heightModified )
202 {
203 KPrObject::setSize( _width, _height );
204 resizeTextDocument( widthModified, heightModified ); // will call formatMore() if widthModified
205 }
206}
207
208TQDomDocumentFragment KPrTextObject::save( TQDomDocument& doc, double offset )
209{
210 TQDomDocumentFragment fragment=KPr2DObject::save(doc, offset);
211 fragment.appendChild(saveKTextObject( doc ));
212 return fragment;
213}
214
215bool KPrTextObject::saveOasisObjectAttributes( KPOasisSaveContext &sc ) const
216{
217 sc.xmlWriter.startElement( "draw:text-box" );
218 m_textobj->saveOasisContent( sc.xmlWriter, sc.context );
219 sc.xmlWriter.endElement();
220 return true;
221}
222
223const char * KPrTextObject::getOasisElementName() const
224{
225 return "draw:frame";
226}
227
228void KPrTextObject::saveOasisMarginElement( KoGenStyle &styleobjectauto ) const
229{
230 kdDebug()<<"void KPrTextObject::saveOasisMarginElement( KoGenStyle &styleobjectauto )\n";
231 if ( btop != 0.0 )
232 styleobjectauto.addPropertyPt("fo:padding-top", btop );
233 if ( bbottom != 0.0 )
234 styleobjectauto.addPropertyPt("fo:padding-bottom", bbottom );
235 if ( bleft != 0.0 )
236 styleobjectauto.addPropertyPt("fo:padding-left", bleft );
237 if ( bright != 0.0 )
238 styleobjectauto.addPropertyPt("fo:padding-right", bright );
239
240 //add vertical alignment
241 switch( m_textVertAlign )
242 {
243 case KP_TOP:
244 styleobjectauto.addProperty("draw:textarea-vertical-align", "top" );
245 break;
246 case KP_CENTER:
247 styleobjectauto.addProperty("draw:textarea-vertical-align", "middle" );
248 break;
249 case KP_BOTTOM:
250 styleobjectauto.addProperty("draw:textarea-vertical-align", "bottom" );
251 break;
252 }
253
254 // fo:padding-top="1.372cm" fo:padding-bottom="0.711cm" fo:padding-left="1.118cm" fo:padding-right="1.27cm"
255}
256
257void KPrTextObject::loadOasis(const TQDomElement &element, KoOasisContext& context,
258 KPrLoadingInfo *info )
259{
260 KPr2DObject::loadOasis(element, context, info);
261 //todo other attribute
262 KoStyleStack &styleStack = context.styleStack();
263 styleStack.setTypeProperties( "graphic" );
264 if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-top" ) )
265 btop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-top" ) );
266 if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-bottom" ) )
267 bbottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-bottom" ) );
268 if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-left") )
269 bleft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-left" ) );
270 if( styleStack.hasAttributeNS( KoXmlNS::fo, "padding-right" ) )
271 bright = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding-right" ) );
272 kdDebug()<<" KPrTextObject::loadOasis : btp :"<<btop<<" bbottom :"<<bbottom<<" bleft :"<<bleft<<" bright :"<<bright<<endl;
273 // vertical alignment
274 if ( styleStack.hasAttributeNS( KoXmlNS::draw, "textarea-vertical-align" ) )
275 {
276 TQString alignment = styleStack.attributeNS( KoXmlNS::draw, "textarea-vertical-align" );
277 if ( alignment == "top" )
278 m_textVertAlign= KP_TOP;
279 else if ( alignment == "middle" )
280 m_textVertAlign= KP_CENTER;
281 else if ( alignment == "bottom" )
282 m_textVertAlign= KP_BOTTOM;
283 }
284 kdDebug()<<" vertical Alignment :"<< ( ( m_textVertAlign== KP_TOP ) ? "top" : ( m_textVertAlign== KP_CENTER ) ? "center": "bottom" )<<endl;
285 TQDomElement tmp = KoDom::namedItemNS( element, KoXmlNS::draw, "text-box");
286 m_textobj->loadOasisContent( tmp, context, m_doc->styleCollection() );
287 resizeTextDocument(); // this will to formatMore()
288}
289
290
291double KPrTextObject::load(const TQDomElement &element)
292{
293 double offset=KPr2DObject::load(element);
294 TQDomElement e=element.namedItem(tagTEXTOBJ).toElement();
295 if(!e.isNull()) {
296 if ( e.hasAttribute( "protectcontent"))
297 setProtectContent((bool)e.attribute( "protectcontent" ).toInt());
298 if (e.hasAttribute( "bleftpt"))
299 bleft = e.attribute( "bleftpt").toDouble();
300 if (e.hasAttribute( "brightpt"))
301 bright = e.attribute( "brightpt").toDouble();
302 if (e.hasAttribute( "btoppt"))
303 btop = e.attribute( "btoppt").toDouble();
304 if (e.hasAttribute( "bbottompt"))
305 bbottom = e.attribute( "bbottompt").toDouble();
306 if ( e.hasAttribute("verticalAlign"))
307 {
308 TQString str =e.attribute("verticalAlign");
309 if ( str == "bottom" )
310 m_textVertAlign= KP_BOTTOM;
311 else if ( str == "center" )
312 m_textVertAlign= KP_CENTER;
313 else if ( str == "top" )//never
314 m_textVertAlign= KP_TOP;
315 }
316 if ( e.hasAttribute( "verticalValue" ))
317 alignVertical = e.attribute( "verticalValue" ).toDouble();
318
319 loadKTextObject( e );
320 }
321
322 shadowCompatibility();
323
324 resizeTextDocument(); // this will to formatMore()
325 return offset;
326}
327
328void KPrTextObject::shadowCompatibility()
329{
330 if ( shadowDistance != 0)
331 {
332 int sx = 0;
333 int sy = 0;
334 switch ( shadowDirection )
335 {
336 case SD_LEFT_BOTTOM:
337 case SD_LEFT:
338 case SD_LEFT_UP:
339 sx = - shadowDistance;
340 case SD_RIGHT_UP:
341 case SD_RIGHT:
342 case SD_RIGHT_BOTTOM:
343 sx = shadowDistance;
344 default:
345 break;
346 }
347 switch ( shadowDirection )
348 {
349 case SD_LEFT_UP:
350 case SD_UP:
351 case SD_RIGHT_UP:
352 sy = - shadowDistance;
353 case SD_LEFT_BOTTOM:
354 case SD_BOTTOM:
355 case SD_RIGHT_BOTTOM:
356 sy = shadowDistance;
357 default:
358 break;
359 }
360 KoTextFormat tmpFormat;
361 tmpFormat.setShadow( sx, sy, shadowColor );
362 KCommand* cmd = m_textobj->setFormatCommand( &tmpFormat, KoTextFormat::ShadowText );
363 delete cmd;
364 }
365 //force to reset shadow compatibility between koffice 1.1 and 1.2
366 shadowDirection = SD_RIGHT_BOTTOM;
367 shadowDistance = 0;
368 shadowColor = TQt::gray;
369}
370
371
372// Standard paint method for KP2DObjects.
373void KPrTextObject::paint( TQPainter *_painter, KoTextZoomHandler*_zoomHandler,
374 int pageNum, bool drawingShadow, bool drawContour )
375{
376 // Never draw shadow (in text objects, it's a character property, not an object property)
377 KPrPage *p = m_doc->pageList().at( pageNum );
378 // neccessary when on masterpage
379 if ( p )
380 recalcPageNum( p );
381 if ( drawingShadow ) return;
382 paint( _painter, _zoomHandler, false, 0L, true, drawContour );
383}
384
385// Special method for drawing a text object that is being edited
386void KPrTextObject::paintEdited( TQPainter *_painter, KoTextZoomHandler*_zoomHandler,
387 bool onlyChanged, KoTextCursor* cursor, bool resetChanged )
388{
389 _painter->save();
390 _painter->translate( _zoomHandler->zoomItX(orig.x()), _zoomHandler->zoomItY(orig.y()) );
391
392 if ( angle != 0 )
393 rotateObject(_painter,_zoomHandler);
394 paint( _painter, _zoomHandler, onlyChanged, cursor, resetChanged, false /*not drawContour*/ );
395 _painter->restore();
396}
397
398// Common functionality for the above 2 methods
399void KPrTextObject::paint( TQPainter *_painter, KoTextZoomHandler*_zoomHandler,
400 bool onlyChanged, KoTextCursor* cursor, bool resetChanged,
401 bool drawContour )
402{
403 double ow = ext.width();
404 double oh = ext.height();
405 double pw = pen.pointWidth() / 2;
406 if ( drawContour ) {
407 TQPen pen3( TQt::black, 1, TQt::DotLine );
408 _painter->setPen( pen3 );
409 _painter->setRasterOp( TQt::NotXorROP );
410 _painter->drawRect( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw),
411 _zoomHandler->zoomItX(ow), _zoomHandler->zoomItY( oh) );
412
413 return;
414 }
415
416 _painter->save();
417 TQPen pen2 = pen.zoomedPen(_zoomHandler);
418 //TQRect clip=TQRect(_zoomHandler->zoomItX(pw), _zoomHandler->zoomItY(pw), _zoomHandler->zoomItX( ow - 2 * pw),_zoomHandler->zoomItY( oh - 2 * pw));
419 //setupClipRegion( _painter, clip );
420 //for debug
421 //_painter->fillRect( clip, TQt::blue );
422 _painter->setPen( pen2 );
423
424 if ( editingTextObj && _painter->device() && _painter->device()->devType() != TQInternal::Printer) // editing text object
425 _painter->setBrush( TQBrush( m_doc->txtBackCol(), TQt::SolidPattern ) );
426 else {
427 // Handle the rotation, draw the background/border, then call drawText()
428 if ( getFillType() == FT_BRUSH || !gradient ) {
429 _painter->setBrush( getBrush() );
430 }
431 else {
432 TQSize size( _zoomHandler->zoomSize( ext ) );
433 gradient->setSize( size );
434 _painter->drawPixmap( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItX(pw), gradient->pixmap(), 0, 0,
435 _zoomHandler->zoomItX( ow - 2 * pw ),
436 _zoomHandler->zoomItY( oh - 2 * pw ) );
437 }
438 }
439 if ( !editingTextObj || !onlyChanged )
440 {
442 // (so that the border gets drawn OUTSIDE of the object area)
443 _painter->drawRect( _zoomHandler->zoomItX(pw), _zoomHandler->zoomItX(pw), _zoomHandler->zoomItX( ow - 2 * pw),
444 _zoomHandler->zoomItY( oh - 2 * pw) );
445 }
446
447 drawText( _painter, _zoomHandler, onlyChanged, cursor, resetChanged );
448 _painter->restore();
449
450
451 // And now draw the border for text objects.
452 // When they are drawn outside of the object, this can be moved to the standard paint() method,
453 // so that we don't have to do it while editing the object, maybe.
454 if ( m_doc->firstView() && m_doc->firstView()->getCanvas()->getEditMode() &&
455 getDrawEditRect() && getPen().style() == TQt::NoPen )
456 {
457 _painter->save();
458
459 _painter->setPen( TQPen( TQt::gray, 1, TQt::DotLine ) );
460 _painter->setBrush( TQt::NoBrush );
461 _painter->setRasterOp( TQt::NotXorROP );
462 _painter->drawRect( 0, 0, _zoomHandler->zoomItX(ow), _zoomHandler->zoomItY( oh) );
463
464 _painter->restore();
465 }
466}
467
468// This method simply draws the paragraphs in the given painter
469// Assumes the painter is already set up correctly.
470void KPrTextObject::drawText( TQPainter* _painter, KoTextZoomHandler *zoomHandler, bool onlyChanged, KoTextCursor* cursor, bool resetChanged )
471{
472 //kdDebug(33001) << "KPrTextObject::drawText onlyChanged=" << onlyChanged << " cursor=" << cursor << " resetChanged=" << resetChanged << endl;
473 recalcVerticalAlignment();
474 TQColorGroup cg = TQApplication::palette().active();
475 _painter->save();
476 _painter->translate( m_doc->zoomHandler()->zoomItX( bLeft()), m_doc->zoomHandler()->zoomItY( bTop()+alignVertical));
477 if ( !editingTextObj || (_painter->device() && _painter->device()->devType() == TQInternal::Printer))
478 cg.setBrush( TQColorGroup::Base, TQt::NoBrush );
479 else
480 cg.setColor( TQColorGroup::Base, m_doc->txtBackCol() );
481
482 TQRect r = zoomHandler->zoomRect( KoRect( 0, 0, innerWidth(), innerHeight() ) );
483 bool editMode = false;
484 if( m_doc->firstView() && m_doc->firstView()->getCanvas())
485 editMode = m_doc->firstView()->getCanvas()->getEditMode();
486
487 uint drawingFlags = 0;
488 if ( _painter->device() && _painter->device()->devType() != TQInternal::Printer )
489 drawingFlags |= KoTextDocument::DrawSelections;
490 if ( m_doc->backgroundSpellCheckEnabled() && editMode )
491 drawingFlags |= KoTextDocument::DrawMisspelledLine;
492 if ( !editMode )
493 drawingFlags |= KoTextDocument::DontDrawNoteVariable;
494 if ( m_doc->viewFormattingChars() && editMode )
495 drawingFlags |= KoTextDocument::DrawFormattingChars;
496
497 if ( specEffects )
498 {
499 switch ( effect2 )
500 {
501 case EF2T_PARA:
502 //kdDebug(33001) << "KPrTextObject::draw onlyCurrStep=" << onlyCurrStep << " subPresStep=" << subPresStep << endl;
503 drawParags( _painter, zoomHandler, cg, ( onlyCurrStep ? subPresStep : 0 ), subPresStep );
504 break;
505 default:
506 /*KoTextParag * lastFormatted =*/ textDocument()->drawWYSIWYG(
507 _painter, r.x(), r.y(), r.width(), r.height(),
508 cg, zoomHandler,
509 onlyChanged, cursor != 0, cursor, resetChanged, drawingFlags );
510 }
511 }
512 else
513 {
514
515 //kdDebug(33001) << "KPrTextObject::drawText r=" << DEBUGRECT(r) << endl;
516 /*KoTextParag * lastFormatted = */ textDocument()->drawWYSIWYG(
517 _painter, r.x(), r.y(), r.width(), r.height(),
518 cg, zoomHandler,
519 onlyChanged, cursor != 0, cursor, resetChanged, drawingFlags );
520 }
521 _painter->restore();
522}
523
524int KPrTextObject::getSubPresSteps() const
525{
526 int paragraphs = 0;
527 KoTextParag * parag = textDocument()->firstParag();
528 for ( ; parag ; parag = parag->next() )
529 paragraphs++;
530 return paragraphs;
531}
532
533
534TQDomElement KPrTextObject::saveKTextObject( TQDomDocument& doc )
535{
536#if 0
537 KTextEditParag *parag = ktextobject.document()->firstParag();
538 KTextEditDocument::TextSettings textSettings = ktextobject.document()->textSettings();
539#endif
540
541 TQDomElement textobj=doc.createElement(tagTEXTOBJ);
542 if ( isProtectContent() )
543 textobj.setAttribute( "protectcontent", (int)isProtectContent());
544 if (bleft !=0.0)
545 textobj.setAttribute( "bleftpt", bleft );
546 if (bright !=0.0)
547 textobj.setAttribute( "brightpt", bright );
548 if (btop !=0.0)
549 textobj.setAttribute( "btoppt", btop );
550 if (bbottom !=0.0)
551 textobj.setAttribute( "bbottompt", bbottom );
552 if ( m_textVertAlign != KP_TOP )
553 {
554 if ( m_textVertAlign == KP_BOTTOM )
555 textobj.setAttribute( "verticalAlign", "bottom" );
556 else if ( m_textVertAlign == KP_CENTER )
557 textobj.setAttribute( "verticalAlign", "center" );
558 else if ( m_textVertAlign == KP_TOP )//never
559 textobj.setAttribute( "verticalAlign", "top" );
560 textobj.setAttribute( "verticalValue",alignVertical );
561 }
562#if 0
563 textobj.setAttribute(attrLineSpacing, ktextobject.document()->lineSpacing());
564 textobj.setAttribute(attrParagSpacing, ktextobject.document()->paragSpacing());
565 textobj.setAttribute(attrMargin, ktextobject.document()->margin());
566 textobj.setAttribute(attrBulletType1, (int)textSettings.bulletType[0]);
567 textobj.setAttribute(attrBulletType2, (int)textSettings.bulletType[1]);
568 textobj.setAttribute(attrBulletType3, (int)textSettings.bulletType[2]);
569 textobj.setAttribute(attrBulletType4, (int)textSettings.bulletType[3]);
570 textobj.setAttribute(attrBulletColor1, textSettings.bulletColor[0].name());
571 textobj.setAttribute(attrBulletColor2, textSettings.bulletColor[1].name());
572 textobj.setAttribute(attrBulletColor3, textSettings.bulletColor[2].name());
573 textobj.setAttribute(attrBulletColor4, textSettings.bulletColor[3].name());
574#endif
575 KoTextParag *parag = static_cast<KoTextParag*> (textDocument()->firstParag());
576 // ### fix this loop (Werner)
577 while ( parag ) {
578 saveParagraph( doc, parag, textobj, 0, parag->length()-2 );
579 parag = static_cast<KoTextParag*>( parag->next());
580 }
581 return textobj;
582}
583
584void KPrTextObject::saveFormat( TQDomElement & element, KoTextFormat*lastFormat )
585{
586 TQString tmpFamily, tmpColor, tmpTextBackColor;
587 unsigned int tmpBold=false, tmpItalic=false, tmpUnderline=false,tmpStrikeOut=false;
588 int tmpVerticalAlign=-1;
589
590 tmpFamily=lastFormat->font().family();
591 tmpBold=static_cast<unsigned int>(lastFormat->font().bold());
592 tmpItalic=static_cast<unsigned int>(lastFormat->font().italic());
593 tmpUnderline=static_cast<unsigned int>(lastFormat->underline());
594 tmpStrikeOut=static_cast<unsigned int>(lastFormat->strikeOut());
595 tmpColor=lastFormat->color().name();
596 tmpVerticalAlign=static_cast<unsigned int>(lastFormat->vAlign());
597 if(lastFormat->textBackgroundColor().isValid())
598 tmpTextBackColor=lastFormat->textBackgroundColor().name();
599
600 element.setAttribute(attrFamily, tmpFamily);
601 element.setAttribute(attrPointSize, lastFormat->pointSize());
602
603 if(tmpBold)
604 element.setAttribute(attrBold, tmpBold);
605 if(tmpItalic)
606 element.setAttribute(attrItalic, tmpItalic);
607 if ( lastFormat->underlineType()!= KoTextFormat::U_NONE )
608 {
609 if(lastFormat->doubleUnderline())
610 element.setAttribute(attrUnderline, "double");
611 if(lastFormat->underlineType()==KoTextFormat::U_SIMPLE_BOLD)
612 element.setAttribute(attrUnderline, "single-bold");
613 else if( lastFormat->underlineType()==KoTextFormat::U_WAVE)
614 element.setAttribute(attrUnderline, "wave");
615 else if(tmpUnderline)
616 element.setAttribute(attrUnderline, tmpUnderline);
617 TQString strLineType=KoTextFormat::underlineStyleToString( lastFormat->underlineStyle() );
618 element.setAttribute( "underlinestyleline", strLineType );
619 if ( lastFormat->textUnderlineColor().isValid() )
620 element.setAttribute( "underlinecolor", lastFormat->textUnderlineColor().name() );
621 }
622 if ( lastFormat->strikeOutType()!= KoTextFormat::S_NONE )
623 {
624 if ( lastFormat->doubleStrikeOut() )
625 element.setAttribute(attrStrikeOut, "double");
626 else if ( lastFormat->strikeOutType()== KoTextFormat::S_SIMPLE_BOLD)
627 element.setAttribute(attrStrikeOut, "single-bold");
628 else if(tmpStrikeOut)
629 element.setAttribute(attrStrikeOut, tmpStrikeOut);
630 TQString strLineType=KoTextFormat::strikeOutStyleToString( lastFormat->strikeOutStyle() );
631 element.setAttribute( "strikeoutstyleline", strLineType );
632
633 }
634 element.setAttribute(attrColor, tmpColor);
635
636 if(!tmpTextBackColor.isEmpty())
637 element.setAttribute(attrTextBackColor, tmpTextBackColor);
638 if(tmpVerticalAlign!=-1)
639 {
640 element.setAttribute(attrVertAlign,tmpVerticalAlign);
641 if(lastFormat->relativeTextSize()!=0.66)
642 element.setAttribute("relativetextsize",lastFormat->relativeTextSize());
643 }
644
645 if ( lastFormat->shadowDistanceX() != 0
646 || lastFormat->shadowDistanceY() != 0)
647 element.setAttribute("text-shadow", lastFormat->shadowAsCss());
648 if ( lastFormat->offsetFromBaseLine()!=0 )
649 element.setAttribute( "offsetfrombaseline" , lastFormat->offsetFromBaseLine());
650 if ( lastFormat->wordByWord() )
651 element.setAttribute("wordbyword", true);
652 if ( lastFormat->attributeFont()!= KoTextFormat::ATT_NONE )
653 element.setAttribute("fontattribute", KoTextFormat::attributeFontToString(lastFormat->attributeFont() ));
654 if ( !lastFormat->language().isEmpty())
655 element.setAttribute("language", lastFormat->language());
656}
657
658TQDomElement KPrTextObject::saveHelper(const TQString &tmpText,KoTextFormat*lastFormat , TQDomDocument &doc)
659{
660 TQDomElement element=doc.createElement(tagTEXT);
661
662 saveFormat ( element, lastFormat );
663
664 if(tmpText.stripWhiteSpace().isEmpty())
665 // working around a bug in TQDom
666 element.setAttribute(attrWhitespace, tmpText.length());
667 element.appendChild(doc.createTextNode(tmpText));
668 return element;
669}
670
671void KPrTextObject::fillStyle( KoGenStyle& styleObjectAuto, KoGenStyles& mainStyles ) const
672{
673 KPr2DObject::fillStyle( styleObjectAuto, mainStyles );
674 saveOasisMarginElement( styleObjectAuto );
675}
676
677void KPrTextObject::loadKTextObject( const TQDomElement &elem )
678{
679 TQDomElement e = elem.firstChild().toElement();
680 KoTextParag *lastParag = static_cast<KoTextParag *>(textDocument()->firstParag());
681 int i = 0;
682 int listNum = 0;
683 // Initialize lineSpacing and paragSpacing with the values of the object-level attributes
684 // (KOffice-1.1 file format)
685 int lineSpacing = elem.attribute( attrLineSpacing ).toInt();
686 int bottomBorder = elem.attribute( attrParagSpacing ).toInt();
687 int topBorder = 0;
688
689 while ( !e.isNull() ) {
690 TQValueList<TQDomElement> listVariable;
691 listVariable.clear();
692
693 if ( e.tagName() == tagP ) {
694 TQDomElement n = e.firstChild().toElement();
695
696 //skip the whitespace if it's a bullet/number
697 if( e.hasAttribute( attrType ) && n.hasAttribute( attrWhitespace ) )
698 if ( e.attribute( attrType )!="0" && n.attribute( attrWhitespace )=="1" ) {
699 e = e.nextSibling().toElement();
700 continue;
701 }
702
703 KoParagLayout paragLayout = loadParagLayout(e, m_doc, true);
704
705 // compatibility (bullet/numbering depth); only a simulation thru the margins, this is how it _looked_ before
706 double depth = 0.0;
707 if( e.hasAttribute(attrDepth) ) {
708 depth = e.attribute( attrDepth ).toDouble();
709 paragLayout.margins[TQStyleSheetItem::MarginLeft] = depth * MM_TO_POINT(10.0);
710 }
711
712 //kdDebug(33001) << k_funcinfo << "old bullet depth is: " << depth << endl;
713
714 // 1.1 compatibility (bullets)
715 TQString type;
716 if( e.hasAttribute(attrType) )
717 type = e.attribute( attrType );
718
719 //kdDebug(33001) << k_funcinfo << "old PARAG type is: " << type << endl;
720
721 // Do not import type="2" (enum list). The enum was there in 1.1, but not the code!
722 if(type == "1")
723 {
724 if(!paragLayout.counter)
725 paragLayout.counter = new KoParagCounter;
726 paragLayout.counter->setStyle(KoParagCounter::STYLE_DISCBULLET);
727 paragLayout.counter->setNumbering(KoParagCounter::NUM_LIST);
728 paragLayout.counter->setPrefix(TQString());
729 paragLayout.counter->setSuffix(TQString());
730 }
731
732 // This is for very old (KOffice-1.0) documents.
733 if ( e.hasAttribute( attrLineSpacing ) )
734 lineSpacing = e.attribute( attrLineSpacing ).toInt();
735 if ( e.hasAttribute( "distBefore" ) )
736 topBorder = e.attribute( "distBefore" ).toInt();
737 if ( e.hasAttribute( "distAfter" ) )
738 bottomBorder = e.attribute( "distAfter" ).toInt();
739
740 // Apply values coming from 1.0 or 1.1 documents
741 if ( paragLayout.lineSpacingValue() == 0 )
742 paragLayout.setLineSpacingValue(lineSpacing);
743 if ( paragLayout.margins[ TQStyleSheetItem::MarginTop ] == 0 )
744 paragLayout.margins[ TQStyleSheetItem::MarginTop ] = topBorder;
745 if ( paragLayout.margins[ TQStyleSheetItem::MarginBottom ] == 0 )
746 paragLayout.margins[ TQStyleSheetItem::MarginBottom ] = bottomBorder;
747 lastParag->setParagLayout( paragLayout );
748 //lastParag->setAlign(TQt::AlignAuto);
749
750 if(e.hasAttribute(attrAlign))
751 {
752 int tmpAlign=e.attribute( attrAlign ).toInt();
753 if(tmpAlign==1 || tmpAlign==0 /* a kpresenter version I think a cvs version saved leftAlign = 0 for header/footer */)
754 lastParag->setAlign(TQt::AlignLeft);
755 else if(tmpAlign==2)
756 lastParag->setAlign(TQt::AlignRight);
757 else if(tmpAlign==4)
758 lastParag->setAlign(TQt::AlignHCenter);
759 else if(tmpAlign==8)
760 lastParag->setAlign(TQt::AlignJustify);
761 else
762 kdDebug(33001) << "Error in e.attribute( attrAlign ).toInt()" << endl;
763 }
764 // ######## TODO paragraph direction (LTR or RTL)
765
766 // TODO check/convert values
767 bool firstTextTag = true;
768 while ( !n.isNull() ) {
769 if ( n.tagName() == tagTEXT ) {
770
771 if ( firstTextTag ) {
772 lastParag->remove( 0, 1 ); // Remove current trailing space
773 firstTextTag = false;
774 }
775 KoTextFormat fm = loadFormat( n, lastParag->paragraphFormat(), m_doc->defaultFont(), m_doc->globalLanguage(),
776 m_doc->globalHyphenation() );
777
778 TQString txt = n.firstChild().toText().data();
779
780 if(n.hasAttribute(attrWhitespace)) {
781 int ws=n.attribute(attrWhitespace).toInt();
782 txt.fill(' ', ws);
783 }
784 n=n.nextSibling().toElement();
785 if ( n.isNull() )
786 txt += ' '; // trailing space at end of paragraph
787 lastParag->append( txt, true );
788 lastParag->setFormat( i, txt.length(), textDocument()->formatCollection()->format( &fm ) );
789 //kdDebug(33001)<<"setFormat :"<<txt<<" i :"<<i<<" txt.length() "<<txt.length()<<endl;
790 i += txt.length();
791 }
792 else if ( n.tagName() == "CUSTOM" )
793 {
794 listVariable.append( n );
795 n = n.nextSibling().toElement();
796 }
797 else
798 n = n.nextSibling().toElement();
799 }
800 } else if ( e.tagName() == "UNSORTEDLISTTYPE" ) {
801 if ( listNum < 4 ) {
802 //TQColor c( e.attribute( "red" ).toInt(), e.attribute( "green" ).toInt(), e.attribute( "blue" ).toInt() );
803 // ## settings.bulletColor[ listNum++ ] = c;
804 }
805 }
806 e = e.nextSibling().toElement();
807 loadVariable( listVariable,lastParag );
808 if ( e.isNull() )
809 break;
810 i = 0;
811 if ( !lastParag->length() == 0 )
812 lastParag = new KoTextParag( textDocument(), lastParag, 0 );
813 }
814}
815
816void KPrTextObject::loadVariable( TQValueList<TQDomElement> & listVariable,KoTextParag *lastParag, int offset )
817{
818 TQValueList<TQDomElement>::Iterator it = listVariable.begin();
819 TQValueList<TQDomElement>::Iterator end = listVariable.end();
820 for ( ; it != end ; ++it )
821 {
822 TQDomElement elem = *it;
823 if ( !elem.hasAttribute("pos"))
824 continue;
825 int index = elem.attribute("pos").toInt();
826 index+=offset;
827 TQDomElement varElem = elem.namedItem( "VARIABLE" ).toElement();
828 if ( !varElem.isNull() )
829 {
830 TQDomElement typeElem = varElem.namedItem( "TYPE" ).toElement();
831 int type = typeElem.attribute( "type" ).toInt();
832 TQString key = typeElem.attribute( "key" );
833 int correct = 0;
834 if (typeElem.hasAttribute( "correct" ))
835 correct = typeElem.attribute("correct").toInt();
836 kdDebug(33001) << "loadKTextObject variable type=" << type << " key=" << key << endl;
837 KoVariableFormat * varFormat = key.isEmpty() ? 0 : m_doc->variableFormatCollection()->format( key.latin1() );
838 // If varFormat is 0 (no key specified), the default format will be used.
839 KoVariable * var =m_doc->getVariableCollection()->createVariable( type, -1, m_doc->variableFormatCollection(),
840 varFormat, lastParag->textDocument(),
841 m_doc, correct, true/* force default format for date/time*/ );
842 if ( var )
843 {
844 var->load( varElem );
845 KoTextFormat format = loadFormat( *it, lastParag->paragraphFormat(), m_doc->defaultFont(), m_doc->globalLanguage(),
846 m_doc->globalHyphenation() );
847 lastParag->setCustomItem( index, var, lastParag->document()->formatCollection()->format( &format ));
848 var->recalc();
849 }
850 }
851 }
852}
853
854KoTextFormat KPrTextObject::loadFormat( TQDomElement &n, KoTextFormat * refFormat, const TQFont & defaultFont,
855 const TQString & defaultLanguage, bool hyphen )
856{
857 KoTextFormat format;
858 format.setHyphenation( hyphen );
859 TQFont fn;
860 if ( refFormat )
861 {
862 format = *refFormat;
863 format.setCollection( 0 ); // Out of collection copy
864 fn = format.font();
865 }
866 else
867 fn = defaultFont;
868
869 if ( !n.isNull() )
870 {
871 TQFontDatabase fdb;
872 TQStringList families = fdb.families();
873 if ( families.findIndex( n.attribute( attrFamily ) ) != -1 )
874 fn.setFamily( n.attribute( attrFamily ) );
875 else
876 fn = defaultFont;
877 }
878 else if ( !refFormat )
879 { // No reference format and no FONT tag -> use default font
880 fn = defaultFont;
881 }
882
883
884 int size = n.attribute( attrPointSize ).toInt();
885 bool bold=false;
886 if(n.hasAttribute(attrBold))
887 bold = (bool)n.attribute( attrBold ).toInt();
888 bool italic = false;
889 if(n.hasAttribute(attrItalic))
890 italic=(bool)n.attribute( attrItalic ).toInt();
891
892 if(n.hasAttribute( attrUnderline ))
893 {
894 TQString value = n.attribute( attrUnderline );
895 if ( value == "double" )
896 format.setUnderlineType ( KoTextFormat::U_DOUBLE);
897 else if ( value == "single" )
898 format.setUnderlineType ( KoTextFormat::U_SIMPLE);
899 else if ( value == "single-bold" )
900 format.setUnderlineType ( KoTextFormat::U_SIMPLE_BOLD);
901 else if( value =="wave" )
902 format.setUnderlineType( KoTextFormat::U_WAVE);
903 else
904 format.setUnderlineType ( (bool)value.toInt() ? KoTextFormat::U_SIMPLE :KoTextFormat::U_NONE);
905 }
906 if (n.hasAttribute("underlinestyleline") )
907 format.setUnderlineStyle( KoTextFormat::stringToUnderlineStyle( n.attribute("underlinestyleline") ));
908
909 if (n.hasAttribute("underlinecolor"))
910 format.setTextUnderlineColor(TQColor(n.attribute("underlinecolor")));
911
912 if(n.hasAttribute(attrStrikeOut))
913 {
914 TQString value = n.attribute( attrStrikeOut );
915 if ( value == "double" )
916 format.setStrikeOutType ( KoTextFormat::S_DOUBLE);
917 else if ( value == "single" )
918 format.setStrikeOutType ( KoTextFormat::S_SIMPLE);
919 else if ( value == "single-bold" )
920 format.setStrikeOutType ( KoTextFormat::S_SIMPLE_BOLD);
921 else
922 format.setStrikeOutType ( (bool)value.toInt() ? KoTextFormat::S_SIMPLE :KoTextFormat::S_NONE);
923 }
924
925 if (n.hasAttribute("strikeoutstyleline"))
926 {
927 TQString strLineType = n.attribute("strikeoutstyleline");
928 format.setStrikeOutStyle( KoTextFormat::stringToStrikeOutStyle( strLineType ));
929 }
930
931 TQString color = n.attribute( attrColor );
932 fn.setPointSize( size );
933 fn.setBold( bold );
934 fn.setItalic( italic );
935 //kdDebug(33001) << "KPrTextObject::loadFormat: family=" << fn.family() << " size=" << fn.pointSize() << endl;
936 TQColor col( color );
937
938 format.setFont( fn );
939 format.setColor( col );
940 TQString textBackColor=n.attribute(attrTextBackColor);
941 if(!textBackColor.isEmpty())
942 {
943 TQColor tmpCol(textBackColor);
944 tmpCol=tmpCol.isValid() ? tmpCol : TQApplication::palette().color( TQPalette::Active, TQColorGroup::Base );
945 format.setTextBackgroundColor(tmpCol);
946 }
947 if(n.hasAttribute(attrVertAlign))
948 format.setVAlign( static_cast<KoTextFormat::VerticalAlignment>(n.attribute(attrVertAlign).toInt() ) );
949 if ( n.hasAttribute("text-shadow") )
950 format.parseShadowFromCss( n.attribute("text-shadow") );
951 if ( n.hasAttribute("relativetextsize") )
952 format.setRelativeTextSize( n.attribute("relativetextsize").toDouble() ) ;
953 if ( n.hasAttribute("offsetfrombaseline") )
954 format.setOffsetFromBaseLine( static_cast<int>(n.attribute("offsetfrombaseline").toInt() ) );
955 if ( n.hasAttribute("wordbyword") )
956 format.setWordByWord( static_cast<int>(n.attribute("wordbyword").toInt() ) );
957
958 if ( n.hasAttribute("fontattribute") )
959 format.setAttributeFont( KoTextFormat::stringToAttributeFont(n.attribute("fontattribute") ) );
960 if ( n.hasAttribute("language"))
961 format.setLanguage( n.attribute("language"));
962 else
963 { // No reference format and no language tag -> use default font
964 format.setLanguage( defaultLanguage);
965 }
966
967 //kdDebug(33001)<<"loadFormat :"<<format.key()<<endl;
968 return format;
969}
970
971KoParagLayout KPrTextObject::loadParagLayout( TQDomElement & parentElem, KPrDocument *doc, bool findStyle)
972{
973 KoParagLayout layout;
974
975 // Only when loading paragraphs, not when loading styles
976 if ( findStyle )
977 {
978 KoParagStyle *style;
979 // Name of the style. If there is no style, then we do not supply
980 // any default!
981 TQDomElement element = parentElem.namedItem( "NAME" ).toElement();
982 if ( !element.isNull() )
983 {
984 TQString styleName = element.attribute( "value" );
985 style = doc->styleCollection()->findStyle( styleName );
986 if (!style)
987 {
988 kdError(33001) << "Cannot find style \"" << styleName << "\" specified in paragraph LAYOUT - using Standard" << endl;
989 style = doc->styleCollection()->findStyle( "Standard" );
990 }
991 //else kdDebug(33001) << "KoParagLayout::KoParagLayout setting style to " << style << " " << style->name() << endl;
992 }
993 else
994 {
995 kdError(33001) << "Missing NAME tag in paragraph LAYOUT - using Standard" << endl;
996 style = doc->styleCollection()->findStyle( "Standard" );
997 }
998 Q_ASSERT(style);
999 layout.style = style;
1000 }
1001
1002 TQDomElement element = parentElem.namedItem( "INDENTS" ).toElement();
1003 if ( !element.isNull() )
1004 {
1005 double val=0.0;
1006 if(element.hasAttribute("first"))
1007 val=element.attribute("first").toDouble();
1008 layout.margins[TQStyleSheetItem::MarginFirstLine] = val;
1009 val=0.0;
1010 if(element.hasAttribute( "left"))
1011 // The GUI prevents a negative indent, so let's fixup broken docs too
1012 val=TQMAX(0, element.attribute( "left").toDouble());
1013 layout.margins[TQStyleSheetItem::MarginLeft] = val;
1014 val=0.0;
1015 if(element.hasAttribute("right"))
1016 // The GUI prevents a negative indent, so let's fixup broken docs too
1017 val=TQMAX(0, element.attribute("right").toDouble());
1018 layout.margins[TQStyleSheetItem::MarginRight] = val;
1019 }
1020 element = parentElem.namedItem( "LINESPACING" ).toElement();
1021 if ( !element.isNull() )
1022 {
1023 //compatibility with koffice 1.1
1024 if ( element.hasAttribute( "value" ))
1025 {
1026 TQString value = element.attribute( "value" );
1027 if ( value == "oneandhalf" )
1028 {
1029 layout.lineSpacingType = KoParagLayout::LS_ONEANDHALF;
1030 layout.setLineSpacingValue(0);
1031 }
1032 else if ( value == "double" )
1033 {
1034 layout.lineSpacingType = KoParagLayout::LS_DOUBLE;
1035 layout.setLineSpacingValue(0);
1036 }
1037 else
1038 {
1039 layout.lineSpacingType = KoParagLayout::LS_CUSTOM;
1040 layout.setLineSpacingValue(value.toDouble());
1041 }
1042 }
1043 else
1044 {
1045 TQString type = element.attribute( "type" );
1046 if ( type == "oneandhalf" )
1047 {
1048 layout.lineSpacingType = KoParagLayout::LS_ONEANDHALF;
1049 layout.setLineSpacingValue(0);
1050 }
1051 else if ( type == "double" )
1052 {
1053 layout.lineSpacingType = KoParagLayout::LS_DOUBLE;
1054 layout.setLineSpacingValue(0);
1055 }
1056 else if ( type == "custom" )
1057 {
1058 layout.lineSpacingType = KoParagLayout::LS_CUSTOM;
1059 layout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble());
1060 }
1061 else if ( type == "atleast" )
1062 {
1063 layout.lineSpacingType = KoParagLayout::LS_AT_LEAST;
1064 layout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble());
1065 }
1066 else if ( type == "multiple" )
1067 {
1068 layout.lineSpacingType = KoParagLayout::LS_MULTIPLE;
1069 layout.setLineSpacingValue(element.attribute( "spacingvalue" ).toDouble());
1070 }
1071 }
1072 }
1073
1074 element = parentElem.namedItem( "OFFSETS" ).toElement();
1075 if ( !element.isNull() )
1076 {
1077 double val =0.0;
1078 if(element.hasAttribute("before"))
1079 val=TQMAX(0, element.attribute("before").toDouble());
1080 layout.margins[TQStyleSheetItem::MarginTop] = val;
1081 val = 0.0;
1082 if(element.hasAttribute("after"))
1083 val=TQMAX(0, element.attribute("after").toDouble());
1084 layout.margins[TQStyleSheetItem::MarginBottom] = val;
1085 }
1086
1087
1088 element = parentElem.namedItem( "LEFTBORDER" ).toElement();
1089 if ( !element.isNull() )
1090 layout.leftBorder = KoBorder::loadBorder( element );
1091 else
1092 layout.leftBorder.setPenWidth( 0);
1093
1094 element = parentElem.namedItem( "RIGHTBORDER" ).toElement();
1095 if ( !element.isNull() )
1096 layout.rightBorder = KoBorder::loadBorder( element );
1097 else
1098 layout.rightBorder.setPenWidth( 0);
1099
1100 element = parentElem.namedItem( "TOPBORDER" ).toElement();
1101 if ( !element.isNull() )
1102 layout.topBorder = KoBorder::loadBorder( element );
1103 else
1104 layout.topBorder.setPenWidth(0);
1105
1106 element = parentElem.namedItem( "BOTTOMBORDER" ).toElement();
1107 if ( !element.isNull() )
1108 layout.bottomBorder = KoBorder::loadBorder( element );
1109 else
1110 layout.bottomBorder.setPenWidth(0);
1111
1112 element = parentElem.namedItem( "COUNTER" ).toElement();
1113 if ( !element.isNull() )
1114 {
1115 layout.counter = new KoParagCounter;
1116 layout.counter->load( element );
1117 }
1118
1119 KoTabulatorList tabList;
1120 element = parentElem.firstChild().toElement();
1121 for ( ; !element.isNull() ; element = element.nextSibling().toElement() )
1122 {
1123 if ( element.tagName() == "TABULATOR" )
1124 {
1125 KoTabulator tab;
1126 tab.type=T_LEFT;
1127 if(element.hasAttribute("type"))
1128 tab.type = static_cast<KoTabulators>( element.attribute("type").toInt());
1129 tab.ptPos=0.0;
1130 if(element.hasAttribute("ptpos"))
1131 tab.ptPos=element.attribute("ptpos").toDouble();
1132 tab.filling=TF_BLANK;
1133 if(element.hasAttribute("filling"))
1134 tab.filling = static_cast<KoTabulatorFilling>( element.attribute("filling").toInt());
1135 tab.ptWidth=0.5;
1136 if(element.hasAttribute("width"))
1137 tab.ptWidth=element.attribute("width").toDouble();
1138 tabList.append( tab );
1139 }
1140 }
1141 layout.setTabList( tabList );
1142
1143
1144 return layout;
1145}
1146
1147void KPrTextObject::saveParagLayout( const KoParagLayout& layout, TQDomElement & parentElem )
1148{
1149 TQDomDocument doc = parentElem.ownerDocument();
1150 TQDomElement element = doc.createElement( "NAME" );
1151 parentElem.appendChild( element );
1152 if ( layout.style )
1153 element.setAttribute( "value", layout.style->name() );
1154 else
1155 kdWarning() << "KWTextParag::saveParagLayout: style==0L!" << endl;
1156
1157
1158 if ( layout.margins[TQStyleSheetItem::MarginFirstLine] != 0 ||
1159 layout.margins[TQStyleSheetItem::MarginLeft] != 0 ||
1160 layout.margins[TQStyleSheetItem::MarginRight] != 0 )
1161 {
1162 element = doc.createElement( "INDENTS" );
1163 parentElem.appendChild( element );
1164 if ( layout.margins[TQStyleSheetItem::MarginFirstLine] != 0 )
1165 element.setAttribute( "first", layout.margins[TQStyleSheetItem::MarginFirstLine] );
1166 if ( layout.margins[TQStyleSheetItem::MarginLeft] != 0 )
1167 element.setAttribute( "left", layout.margins[TQStyleSheetItem::MarginLeft] );
1168 if ( layout.margins[TQStyleSheetItem::MarginRight] != 0 )
1169 element.setAttribute( "right", layout.margins[TQStyleSheetItem::MarginRight] );
1170 }
1171
1172
1173 if ( layout.margins[TQStyleSheetItem::MarginTop] != 0 ||
1174 layout.margins[TQStyleSheetItem::MarginBottom] != 0 )
1175 {
1176 element = doc.createElement( "OFFSETS" );
1177 parentElem.appendChild( element );
1178 if ( layout.margins[TQStyleSheetItem::MarginTop] != 0 )
1179 element.setAttribute( "before", layout.margins[TQStyleSheetItem::MarginTop] );
1180 if ( layout.margins[TQStyleSheetItem::MarginBottom] != 0 )
1181 element.setAttribute( "after", layout.margins[TQStyleSheetItem::MarginBottom] );
1182 }
1183
1184 if ( layout.lineSpacingType != KoParagLayout::LS_SINGLE )
1185 {
1186 element = doc.createElement( "LINESPACING" );
1187 parentElem.appendChild( element );
1188 if ( layout.lineSpacingType == KoParagLayout::LS_ONEANDHALF )
1189 element.setAttribute( "type", "oneandhalf" );
1190 else if ( layout.lineSpacingType == KoParagLayout::LS_DOUBLE )
1191 element.setAttribute( "type", "double" );
1192 else if ( layout.lineSpacingType == KoParagLayout::LS_CUSTOM )
1193 {
1194 element.setAttribute( "type", "custom" );
1195 element.setAttribute( "spacingvalue", layout.lineSpacingValue());
1196 }
1197 else if ( layout.lineSpacingType == KoParagLayout::LS_AT_LEAST )
1198 {
1199 element.setAttribute( "type", "atleast" );
1200 element.setAttribute( "spacingvalue", layout.lineSpacingValue());
1201 }
1202 else if ( layout.lineSpacingType == KoParagLayout::LS_MULTIPLE )
1203 {
1204 element.setAttribute( "type", "multiple" );
1205 element.setAttribute( "spacingvalue", layout.lineSpacingValue());
1206 }
1207 else
1208 kdDebug(33001) << " error in lineSpacing Type" << endl;
1209 }
1210
1211 if ( layout.leftBorder.penWidth() > 0 )
1212 {
1213 element = doc.createElement( "LEFTBORDER" );
1214 parentElem.appendChild( element );
1215 layout.leftBorder.save( element );
1216 }
1217 if ( layout.rightBorder.penWidth() > 0 )
1218 {
1219 element = doc.createElement( "RIGHTBORDER" );
1220 parentElem.appendChild( element );
1221 layout.rightBorder.save( element );
1222 }
1223 if ( layout.topBorder.penWidth() > 0 )
1224 {
1225 element = doc.createElement( "TOPBORDER" );
1226 parentElem.appendChild( element );
1227 layout.topBorder.save( element );
1228 }
1229 if ( layout.bottomBorder.penWidth() > 0 )
1230 {
1231 element = doc.createElement( "BOTTOMBORDER" );
1232 parentElem.appendChild( element );
1233 layout.bottomBorder.save( element );
1234 }
1235
1236 if ( layout.counter && layout.counter->numbering() != KoParagCounter::NUM_NONE )
1237 {
1238 element = doc.createElement( "COUNTER" );
1239 parentElem.appendChild( element );
1240 if (layout.counter )
1241 layout.counter->save( element );
1242 }
1243
1244 KoTabulatorList tabList = layout.tabList();
1245 KoTabulatorList::ConstIterator it = tabList.begin();
1246 for ( ; it != tabList.end() ; it++ )
1247 {
1248 element = doc.createElement( "TABULATOR" );
1249 parentElem.appendChild( element );
1250 element.setAttribute( "type", (*it).type );
1251 element.setAttribute( "ptpos", (*it).ptPos );
1252 element.setAttribute( "filling", (*it).filling );
1253 element.setAttribute( "width", (*it).ptWidth );
1254 }
1255}
1256
1257void KPrTextObject::recalcPageNum( KPrPage *page )
1258{
1259 int pgnum=m_doc->pageList().findRef(page);
1260
1261 pgnum+=1;
1262 TQPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
1263 for ( ; cit.current() ; ++cit )
1264 {
1265 KPrPgNumVariable * var = dynamic_cast<KPrPgNumVariable *>( cit.current() );
1266 if ( var && !var->isDeleted() )
1267 {
1268 switch ( var->subType() ) {
1269 case KPrPgNumVariable::VST_PGNUM_CURRENT:
1270 var->setPgNum( pgnum + kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber()-1);
1271 break;
1272 case KPrPgNumVariable::VST_CURRENT_SECTION:
1273 var->setSectionTitle( page->pageTitle() );
1274 break;
1275 case KPrPgNumVariable::VST_PGNUM_PREVIOUS:
1276 var->setPgNum( TQMAX( pgnum -1 , 0) +
1277 kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber());
1278 break;
1279 case KPrPgNumVariable::VST_PGNUM_NEXT:
1280 var->setPgNum( TQMIN( (int)m_doc->getPageNums(), pgnum+1 ) +
1281 kPresenterDocument()->getVariableCollection()->variableSetting()->startingPageNumber());
1282 break;
1283 default:
1284 break;
1285 }
1286
1287 var->resize();
1288 var->paragraph()->invalidate( 0 ); // size may have changed -> need reformatting !
1289 var->paragraph()->setChanged( true );
1290 }
1291 }
1292}
1293
1294void KPrTextObject::layout()
1295{
1296 invalidate();
1297 // Get the thing going though, repainting doesn't call formatMore
1298 m_textobj->formatMore( 2 );
1299}
1300
1301void KPrTextObject::invalidate()
1302{
1303 //kdDebug(33001) << "KWTextFrameSet::invalidate " << getName() << endl;
1304 m_textobj->setLastFormattedParag( textDocument()->firstParag() );
1305 textDocument()->formatter()->setViewFormattingChars( m_doc->viewFormattingChars() );
1306 textDocument()->invalidate(); // lazy layout, real update follows upon next repaint
1307}
1308
1309// For the "paragraph after paragraph" effect
1310void KPrTextObject::drawParags( TQPainter *painter, KoTextZoomHandler* zoomHandler, const TQColorGroup& cg, int from, int to )
1311{
1312 // The fast and difficult way would be to call drawParagWYSIWYG
1313 // only on the paragraphs to be drawn. Then we have duplicate quite some code
1314 // (or lose double-buffering).
1315 // Easy (and not so slow) way:
1316 // we call KoTextDocument::drawWYSIWYG with a cliprect.
1317 Q_ASSERT( from <= to );
1318 int i = 0;
1319 bool editMode=false;
1320 if( m_doc->firstView() && m_doc->firstView()->getCanvas())
1321 editMode = m_doc->firstView()->getCanvas()->getEditMode();
1322
1323 TQRect r = zoomHandler->zoomRect( KoRect( 0, 0, innerWidth(), innerHeight() ) );
1324 KoTextParag *parag = textDocument()->firstParag();
1325 while ( parag ) {
1326 if ( !parag->isValid() )
1327 parag->format();
1328 if ( i == from )
1329 r.setTop( m_doc->zoomHandler()->layoutUnitToPixelY( parag->rect().top() ) );
1330 if ( i == to ) {
1331 r.setBottom( m_doc->zoomHandler()->layoutUnitToPixelY( parag->rect().bottom() ) );
1332 break;
1333 }
1334 ++i;
1335 parag = parag->next();
1336 }
1337
1338 uint drawingFlags = 0; // don't draw selections
1339 if ( m_doc->backgroundSpellCheckEnabled() && editMode )
1340 drawingFlags |= KoTextDocument::DrawMisspelledLine;
1341 textDocument()->drawWYSIWYG(
1342 painter, r.x(), r.y(), r.width(), r.height(),
1343 cg, m_doc->zoomHandler(), // TODO (long term) the view's zoomHandler
1344 false /*onlyChanged*/, false /*cursor != 0*/, 0 /*cursor*/,
1345 true /*resetChanged*/, drawingFlags );
1346}
1347
1348void KPrTextObject::drawCursor( TQPainter *p, KoTextCursor *cursor, bool cursorVisible, KPrCanvas* canvas )
1349{
1350 // The implementation is very related to KWord's KWTextFrameSet::drawCursor
1351 KoTextZoomHandler *zh = m_doc->zoomHandler();
1352 TQPoint origPix = zh->zoomPoint( orig+KoPoint(bLeft(), bTop()+alignVertical) );
1353 // Painter is already translated for diffx/diffy, but not for the object yet
1354 p->translate( origPix.x(), origPix.y() );
1355 if ( angle != 0 )
1356 rotateObject( p, zh );
1357
1358 KoTextParag* parag = cursor->parag();
1359 TQPoint topLeft = parag->rect().topLeft(); // in TQRT coords
1360 int lineY;
1361 // Cursor height, in pixels
1362 int cursorHeight = zh->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) );
1363 TQPoint iPoint( topLeft.x() + cursor->x(),
1364 topLeft.y() + lineY );
1365 // from now on, iPoint will be in pixels
1366 iPoint = zh->layoutUnitToPixel( iPoint );
1367
1368 TQPoint vPoint = iPoint; // vPoint and iPoint are the same currently
1369 // do not simplify this, will be useful with viewmodes.
1370 //int xadj = parag->at( cursor->index() )->pixelxadj;
1371 //iPoint.rx() += xadj;
1372 //vPoint.rx() += xadj;
1373 // very small clipping around the cursor
1374 TQRect clip( vPoint.x() - 5, vPoint.y() , 10, cursorHeight );
1375 setupClipRegion( p, clip );
1376
1377 // for debug only!
1378 //p->fillRect( clip, TQt::blue );
1379
1380 TQPixmap *pix = 0;
1381 TQColorGroup cg = TQApplication::palette().active();
1382 cg.setColor( TQColorGroup::Base, m_doc->txtBackCol() );
1383
1384 uint drawingFlags = KoTextDocument::DrawSelections;
1385 if ( m_doc->backgroundSpellCheckEnabled() )
1386 drawingFlags |= KoTextDocument::DrawMisspelledLine;
1387 if ( m_doc->viewFormattingChars() )
1388 drawingFlags |= KoTextDocument::DrawFormattingChars;
1389
1390 // To force the drawing to happen:
1391 bool wasChanged = parag->hasChanged();
1392 int oldLineChanged = parag->lineChanged();
1393 int line; // line number
1394 parag->lineStartOfChar( cursor->index(), 0, &line );
1395 parag->setChanged( false ); // not all changed, only from a given line
1396 parag->setLineChanged( line );
1397 //kdDebug(33001) << "KPrTextObject::drawCursor cursorVisible=" << cursorVisible << " line=" << line << endl;
1398
1399 textDocument()->drawParagWYSIWYG(
1400 p, parag,
1401 TQMAX(0, iPoint.x() - 5), // negative values create problems
1402 iPoint.y(), clip.width(), clip.height(),
1403 pix, cg, m_doc->zoomHandler(),
1404 cursorVisible, cursor, false /*resetChanged*/, drawingFlags );
1405
1406 if ( wasChanged ) // Maybe we have more changes to draw, than those in the small cliprect
1407 cursor->parag()->setLineChanged( oldLineChanged ); // -1 = all
1408 else
1409 cursor->parag()->setChanged( false );
1410
1411 // XIM Position
1412 TQPoint ximPoint = vPoint;
1413 TQFont f = parag->at( cursor->index() )->format()->font();
1414 canvas->setXimPosition( ximPoint.x() + origPix.x(), ximPoint.y() + origPix.y(),
1415 0, cursorHeight - parag->lineSpacing( line ), &f );
1416}
1417
1418KPrTextDocument * KPrTextObject::textDocument() const
1419{
1420 return static_cast<KPrTextDocument*>(m_textobj->textDocument());
1421}
1422
1423void KPrTextObject::slotNewCommand( KCommand * cmd)
1424{
1425 m_doc->addCommand(cmd);
1426}
1427
1428int KPrTextObject::availableHeight() const
1429{
1430 return m_textobj->availableHeight();
1431}
1432
1433void KPrTextObject::slotAvailableHeightNeeded()
1434{
1435 int ah = m_doc->zoomHandler()->ptToLayoutUnitPixY( innerHeight() );
1436 m_textobj->setAvailableHeight( ah );
1437 //kdDebug(33001)<<"slotAvailableHeightNeeded: height=:"<<ah<<endl;
1438}
1439
1440void KPrTextObject::slotRepaintChanged()
1441{
1442 emit repaintChanged( this );
1443}
1444
1445KPrTextView * KPrTextObject::createKPTextView( KPrCanvas * _canvas, bool temp )
1446{
1447 return new KPrTextView( this, _canvas, temp );
1448}
1449
1450void KPrTextObject::removeHighlight ()
1451{
1452 m_textobj->removeHighlight( true /*repaint*/ );
1453}
1454
1455void KPrTextObject::highlightPortion( KoTextParag * parag, int index, int length, KPrCanvas* canvas, bool repaint, KDialogBase* dialog )
1456{
1457 m_textobj->highlightPortion( parag, index, length, repaint );
1458 if ( repaint )
1459 {
1460 KPrDocument* doc = canvas->getView()->kPresenterDoc();
1461
1462 // Is this object in the current active page?
1463 if ( canvas->activePage()->findTextObject( this ) )
1464 {
1465 kdDebug(33001) << k_funcinfo << "object in current page" << endl;
1466 }
1467 else
1468 {
1469 // No -> find the right page and activate it
1470 // ** slow method **
1471 KPrPage* page = doc->findPage( this );
1472 if ( page ) {
1473 int pageNum = doc->pageList().findRef( page );
1474 // if the pageNum is -1 the object is located on the master slide
1475 if ( pageNum > -1 )
1476 {
1477 canvas->getView()->skipToPage( pageNum );
1478 }
1479 } else
1480 kdWarning(33001) << "object " << this << " not found in any page!?" << endl;
1481 }
1482 // Now ensure text is fully visible
1483 TQRect rect = m_doc->zoomHandler()->zoomRect( getRect() );
1484 TQRect expose = m_doc->zoomHandler()->layoutUnitToPixel( parag->rect() );
1485 expose.moveBy( rect.x(), rect.y() );
1486 canvas->ensureVisible( (expose.left()+expose.right()) / 2, // point = center of the rect
1487 (expose.top()+expose.bottom()) / 2,
1488 (expose.right()-expose.left()) / 2, // margin = half-width of the rect
1489 (expose.bottom()-expose.top()) / 2);
1490 if ( dialog ) {
1491 TQRect globalRect( expose );
1492 globalRect.moveTopLeft( canvas->mapToGlobal( globalRect.topLeft() ) );
1493 KDialog::avoidArea( dialog, globalRect );
1494 }
1495 }
1496}
1497
1498KCommand * KPrTextObject::pasteOasis( KoTextCursor * cursor, const TQByteArray & data, bool removeSelected )
1499{
1500 //kdDebug(33001) << "KPrTextObject::pasteOasis" << endl;
1501 KMacroCommand * macroCmd = new KMacroCommand( i18n("Paste Text") );
1502 if ( removeSelected && textDocument()->hasSelection( KoTextDocument::Standard ) )
1503 macroCmd->addCommand( m_textobj->removeSelectedTextCommand( cursor, KoTextDocument::Standard ) );
1504 m_textobj->emitHideCursor();
1505 m_textobj->setLastFormattedParag( cursor->parag()->prev() ?
1506 cursor->parag()->prev() : cursor->parag() );
1507
1508 // We have our own command for this.
1509 // Using insert() wouldn't help storing the parag stuff for redo
1510 KPrOasisPasteTextCommand * cmd = new KPrOasisPasteTextCommand( textDocument(), cursor->parag()->paragId(), cursor->index(), data );
1511 textDocument()->addCommand( cmd );
1512
1513 macroCmd->addCommand( new KoTextCommand( m_textobj, /*cmd, */TQString() ) );
1514 *cursor = *( cmd->execute( cursor ) );
1515
1516 m_textobj->formatMore( 2 );
1517 emit repaintChanged( this );
1518 m_textobj->emitEnsureCursorVisible();
1519 m_textobj->emitUpdateUI( true );
1520 m_textobj->emitShowCursor();
1521 m_textobj->selectionChangedNotify();
1522 return macroCmd;
1523}
1524
1525
1526void KPrTextObject::setShadowParameter(int _distance,ShadowDirection _direction,const TQColor &_color)
1527{
1528 int sx = 0;
1529 int sy = 0;
1530 switch ( _direction )
1531 {
1532 case SD_LEFT_BOTTOM:
1533 case SD_LEFT:
1534 case SD_LEFT_UP:
1535 sx = - _distance;
1536 case SD_RIGHT_UP:
1537 case SD_RIGHT:
1538 case SD_RIGHT_BOTTOM:
1539 sx = _distance;
1540 default:
1541 break;
1542 }
1543 switch ( _direction )
1544 {
1545 case SD_LEFT_UP:
1546 case SD_UP:
1547 case SD_RIGHT_UP:
1548 sy = - _distance;
1549 case SD_LEFT_BOTTOM:
1550 case SD_BOTTOM:
1551 case SD_RIGHT_BOTTOM:
1552 sy = _distance;
1553 default:
1554 break;
1555 }
1556 KoTextFormat tmpFormat;
1557 tmpFormat.setShadow( sx, sy, _color );
1558 KCommand* cmd = m_textobj->setFormatCommand( &tmpFormat, KoTextFormat::ShadowText );
1559 if ( cmd )
1560 m_doc->addCommand(cmd);
1561}
1562
1563void KPrTextObject::slotFormatChanged(const KoTextFormat &_format)
1564{
1565 if(m_doc && m_doc->firstView())
1566 m_doc->firstView()->showFormat( _format );
1567}
1568
1569void KPrTextObject::applyStyleChange( KoStyleChangeDefMap changed )
1570{
1571 m_textobj->applyStyleChange( changed );
1572}
1573
1574void KPrTextObject::slotAfterFormatting( int bottom, KoTextParag* lastFormatted, bool* abort)
1575{
1576 recalcVerticalAlignment();
1577 int availHeight = availableHeight() - m_doc->zoomHandler()->ptToLayoutUnitPixY(alignmentValue());
1578 if ( ( bottom > availHeight ) || // this parag is already below the avail height
1579 ( lastFormatted && (bottom + lastFormatted->rect().height() > availHeight) ) ) // or next parag will be below it
1580 {
1581 int difference = ( bottom + 2 ) - availHeight; // in layout unit pixels
1582 if( lastFormatted && bottom + lastFormatted->rect().height() > availHeight )
1583 {
1584 difference += lastFormatted->rect().height();
1585 }
1586#if 0
1587 if(lastFormatted)
1588 kdDebug(33001) << "slotAfterFormatting We need more space in " << this
1589 << " bottom=" << bottom + lastFormatted->rect().height()
1590 << " availHeight=" << availHeight
1591 << " ->difference=" << difference << endl;
1592 else
1593 kdDebug(33001) << "slotAfterFormatting We need more space in " << this
1594 << " bottom2=" << bottom << " availHeight=" << availHeight
1595 << " ->difference=" << difference << endl;
1596#endif
1597 // We only auto-grow. We don't auto-shrink.
1598 if(difference > 0 && !isProtect())
1599 {
1600 double wantedPosition = m_doc->zoomHandler()->layoutUnitPtToPt( m_doc->zoomHandler()->pixelYToPt( difference ) )
1601 + getRect().bottom();
1602 const KoPageLayout& p = m_doc->pageLayout();
1603 double pageBottom = p.ptHeight - p.ptBottom;
1604 double newBottom = TQMIN( wantedPosition, pageBottom ); // don't grow bigger than the page
1605 newBottom = TQMAX( newBottom, getOrig().y() ); // avoid negative heights
1606 //kdDebug(33001) << k_funcinfo << " current bottom=" << getRect().bottom() << " newBottom=" << newBottom << endl;
1607 if ( getRect().bottom() != newBottom )
1608 {
1609 // We resize the text object, but skipping the KPrTextObject::setSize code
1610 // (which invalidates everything etc.)
1611 KPrObject::setSize( getSize().width(), newBottom - getOrig().y() );
1612 // Do recalculate the new available height though
1613 slotAvailableHeightNeeded();
1614 m_doc->updateRuler();
1615 m_doc->repaint( true );
1616 *abort = false;
1617 }
1618 }
1619 else if ( isProtect() )
1620 m_textobj->setLastFormattedParag( 0 );
1621 }
1622}
1623
1624// "Extend Contents to Object Height"
1625KCommand * KPrTextObject::textContentsToHeight()
1626{
1627 if (isProtect() )
1628 return 0L;
1629
1630 // Count total number of lines and sum up their height (linespacing excluded)
1631 KoTextParag * parag = textDocument()->firstParag();
1632 int numLines = 0;
1633 int textHeightLU = 0;
1634 bool lineSpacingEqual = false;
1635 int oldLineSpacing = 0;
1636 for ( ; parag ; parag = parag->next() )
1637 {
1638 int lines = parag->lines();
1639 numLines += lines;
1640 for ( int line = 0 ; line < lines ; ++line )
1641 {
1642 int y, h, baseLine;
1643 parag->lineInfo( line, y, h, baseLine );
1644 int ls = parag->lineSpacing( line );
1645 lineSpacingEqual = (oldLineSpacing == ls);
1646 oldLineSpacing = ls;
1647 textHeightLU += h - ls;
1648 }
1649 }
1650
1651 double textHeight = m_doc->zoomHandler()->layoutUnitPtToPt( textHeightLU );
1652 double lineSpacing = ( innerHeight() - textHeight ) / numLines; // this gives the linespacing diff to apply, in pt
1653 //kdDebug(33001) << k_funcinfo << "lineSpacing=" << lineSpacing << endl;
1654
1655 if ( KABS( innerHeight() - textHeight ) < DBL_EPSILON ) // floating-point equality test
1656 return 0L; // nothing to do
1657 bool oneLine =(textDocument()->firstParag() == textDocument()->lastParag() && numLines == 1);
1658 if ( lineSpacing < 0 || oneLine) // text object is too small
1659 lineSpacing = 0; // we can't do smaller linespacing than that, but we do need to apply it
1660 // (in case there's some bigger linespacing in use)
1661 if ( (oneLine || lineSpacingEqual) && (textDocument()->firstParag()->kwLineSpacing() == lineSpacing))
1662 return 0L;
1663 // Apply the new linespacing to the whole object
1664 textDocument()->selectAll( KoTextDocument::Temp );
1665 KCommand* cmd = m_textobj->setLineSpacingCommand( 0L, lineSpacing, KoParagLayout::LS_CUSTOM, KoTextDocument::Temp );
1666 textDocument()->removeSelection( KoTextDocument::Temp );
1667 return cmd;
1668}
1669
1670// "Resize Object to fit Contents"
1671KCommand * KPrTextObject::textObjectToContents()
1672{
1673 if ( isProtect() )
1674 return 0L;
1675 // Calculate max parag width (in case all parags are short, otherwise - with wrapping -
1676 // the width is more or less the current object's width anyway).
1677 KoTextParag * parag = textDocument()->firstParag();
1678 double txtWidth = 10;
1679 for ( ; parag ; parag = parag->next() )
1680 txtWidth = TQMAX( txtWidth, m_doc->zoomHandler()->layoutUnitPtToPt( parag->widthUsed() ));
1681
1682 // Calculate text height
1683 int heightLU = textDocument()->height();
1684 double txtHeight = m_doc->zoomHandler()->layoutUnitPtToPt( heightLU );
1685
1686 // Compare with current object's size
1687 KoSize sizeDiff = KoSize( txtWidth, txtHeight ) - innerRect().size();
1688 if( !sizeDiff.isNull() )
1689 {
1690 // The command isn't named since it's always put into a macro command.
1691 return new KPrResizeCmd( TQString(), KoPoint( 0, 0 ), sizeDiff, this, m_doc);
1692 }
1693 return 0L;
1694}
1695
1696void KPrTextObject::setTextMargins( double _left, double _top, double _right, double _bottom)
1697{
1698 bleft = _left;
1699 btop = _top;
1700 bright = _right;
1701 bbottom = _bottom;
1702}
1703
1704KoRect KPrTextObject::innerRect() const
1705{
1706 KoRect inner( getRect());
1707 inner.moveBy( bLeft(), bTop());
1708 inner.setWidth( inner.width() - bLeft() - bRight() );
1709 inner.setHeight( inner.height() - bTop() - bBottom() );
1710 return inner;
1711}
1712
1713double KPrTextObject::innerWidth() const
1714{
1715 return getSize().width() - bLeft() - bRight();
1716}
1717
1718double KPrTextObject::innerHeight() const
1719{
1720 return getSize().height() - bTop() - bBottom();
1721}
1722
1723void KPrTextObject::setVerticalAligment( VerticalAlignmentType _type)
1724{
1725 m_textVertAlign = _type;
1726 recalcVerticalAlignment();
1727}
1728
1729void KPrTextObject::recalcVerticalAlignment()
1730{
1731 double txtHeight = m_doc->zoomHandler()->layoutUnitPtToPt( m_doc->zoomHandler()->pixelYToPt( textDocument()->height() ) ) + btop + bbottom;
1732 double diffy = getSize().height() - txtHeight;
1733
1734 //kdDebug(33001) << k_funcinfo << "txtHeight: " << txtHeight << " rectHeight:" << getSize().height() << " -> diffy=" << diffy << endl;
1735
1736 if ( diffy <= 0.0 ) {
1737 alignVertical = 0.0;
1738 return;
1739 }
1740 switch( m_textVertAlign )
1741 {
1742 case KP_CENTER:
1743 alignVertical = diffy/2.0;
1744 break;
1745 case KP_TOP:
1746 alignVertical = 0.0;
1747 break;
1748 case KP_BOTTOM:
1749 alignVertical = diffy;
1750 break;
1751 }
1752}
1753
1754TQPoint KPrTextObject::cursorPos(KPrCanvas *canvas, KoTextCursor *cursor) const
1755{
1756 KoTextZoomHandler *zh = m_doc->zoomHandler();
1757 TQPoint origPix = zh->zoomPoint( orig+KoPoint(bLeft(), bTop()+alignVertical) );
1758 KoTextParag* parag = cursor->parag();
1759 TQPoint topLeft = parag->rect().topLeft(); // in TQRT coords
1760 int lineY = 0;
1761 // Cursor height, in pixels
1762 //int cursorHeight = zh->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) );
1763 TQPoint iPoint( topLeft.x() + cursor->x(), topLeft.y() + lineY );
1764 iPoint = zh->layoutUnitToPixel( iPoint );
1765 iPoint.rx() -= canvas->diffx();
1766 iPoint.ry() -= canvas->diffy();
1767 return origPix+iPoint;
1768}
1769
1770KPrTextView::KPrTextView( KPrTextObject * txtObj, KPrCanvas *_canvas, bool temp )
1771 : KoTextView( txtObj->textObject() )
1772{
1773 setBackSpeller( txtObj->kPresenterDocument()->backSpeller() );
1774 m_canvas=_canvas;
1775 m_kptextobj=txtObj;
1776 if (temp)
1777 return;
1778 connect( txtObj->textObject(), TQ_SIGNAL( selectionChanged(bool) ),
1779 m_canvas, TQ_SIGNAL( selectionChanged(bool) ) );
1780 KoTextView::setReadWrite( txtObj->kPresenterDocument()->isReadWrite() );
1781 connect( textView(), TQ_SIGNAL( cut() ), TQ_SLOT( cut() ) );
1782 connect( textView(), TQ_SIGNAL( copy() ), TQ_SLOT( copy() ) );
1783 connect( textView(), TQ_SIGNAL( paste() ), TQ_SLOT( paste() ) );
1784 updateUI( true, true );
1785
1786 txtObj->setEditingTextObj( true );
1787}
1788
1789KPrTextView::~KPrTextView()
1790{
1791}
1792
1793KoTextViewIface* KPrTextView::dcopObject()
1794{
1795 if ( !dcop )
1796 dcop = new KPrTextViewIface( this );
1797
1798 return dcop;
1799}
1800
1801void KPrTextView::terminate(bool removeSelection)
1802{
1803 disconnect( textView()->textObject(), TQ_SIGNAL( selectionChanged(bool) ),
1804 m_canvas, TQ_SIGNAL( selectionChanged(bool) ) );
1805 textView()->terminate(removeSelection);
1806}
1807
1808void KPrTextView::cut()
1809{
1810 if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) {
1811 copy();
1812 textObject()->removeSelectedText( cursor() );
1813 }
1814}
1815
1816void KPrTextView::copy()
1817{
1818 //kdDebug(33001)<<"void KPrTextView::copy() "<<endl;
1819 if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) {
1820 TQDragObject *drag = newDrag( 0 );
1821 TQApplication::clipboard()->setData( drag );
1822 }
1823}
1824
1825void KPrTextView::paste()
1826{
1827 //kdDebug(33001) << "KPrTextView::paste()" << endl;
1828
1829 TQMimeSource *data = TQApplication::clipboard()->data();
1830 TQCString returnedMimeType = KoTextObject::providesOasis( data );
1831 if ( !returnedMimeType.isEmpty() )
1832 {
1833 TQByteArray arr = data->encodedData( returnedMimeType );
1834 if ( arr.size() )
1835 {
1836#if 0
1837 TQFile paste( "/tmp/oasis.tmp" );
1838 paste.open( IO_WriteOnly );
1839 paste.writeBlock( arr );
1840 paste.close();
1841#endif
1842 KCommand *cmd = kpTextObject()->pasteOasis( cursor(), arr, true );
1843 if ( cmd )
1844 kpTextObject()->kPresenterDocument()->addCommand(cmd);
1845 }
1846 }
1847 else
1848 {
1849 // Note: TQClipboard::text() seems to do a better job than encodedData( "text/plain" )
1850 // In particular it handles charsets (in the mimetype).
1851 TQString text = TQApplication::clipboard()->text();
1852 if ( !text.isEmpty() )
1853 textObject()->pasteText( cursor(), text, currentFormat(), true /*removeSelected*/ );
1854 }
1855 kpTextObject()->layout();
1856}
1857
1858void KPrTextView::updateUI( bool updateFormat, bool force )
1859{
1860 KoTextView::updateUI( updateFormat, force );
1861 // Paragraph settings
1862 KoTextParag * parag = static_cast<KoTextParag*>( cursor()->parag());
1863 if ( m_paragLayout.alignment != parag->resolveAlignment() || force ) {
1864 m_paragLayout.alignment = parag->resolveAlignment();
1865 m_canvas->getView()->alignChanged( m_paragLayout.alignment );
1866 }
1867
1868 // Counter
1869 if ( !m_paragLayout.counter )
1870 m_paragLayout.counter = new KoParagCounter; // we can afford to always have one here
1871 KoParagCounter::Style cstyle = m_paragLayout.counter->style();
1872 if ( parag->counter() )
1873 *m_paragLayout.counter = *parag->counter();
1874 else
1875 {
1876 m_paragLayout.counter->setNumbering( KoParagCounter::NUM_NONE );
1877 m_paragLayout.counter->setStyle( KoParagCounter::STYLE_NONE );
1878 }
1879
1880 if ( m_paragLayout.counter->style() != cstyle || force )
1881 m_canvas->getView()->showCounter( * m_paragLayout.counter );
1882
1883 if(m_paragLayout.leftBorder!=parag->leftBorder() ||
1884 m_paragLayout.rightBorder!=parag->rightBorder() ||
1885 m_paragLayout.topBorder!=parag->topBorder() ||
1886 m_paragLayout.bottomBorder!=parag->bottomBorder() || force )
1887 {
1888 m_paragLayout.leftBorder = parag->leftBorder();
1889 m_paragLayout.rightBorder = parag->rightBorder();
1890 m_paragLayout.topBorder = parag->topBorder();
1891 m_paragLayout.bottomBorder = parag->bottomBorder();
1892 //todo
1893 //m_canvas->gui()->getView()->showParagBorders( m_paragLayout.leftBorder, m_paragLayout.rightBorder, m_paragLayout.topBorder, m_paragLayout.bottomBorder );
1894 }
1895
1896 if ( !parag->style() )
1897 kdWarning(33001) << "Paragraph " << parag->paragId() << " has no style" << endl;
1898 else if ( m_paragLayout.style != parag->style() || force )
1899 {
1900 m_paragLayout.style = parag->style();
1901 m_canvas->getView()->showStyle( m_paragLayout.style->name() );
1902 }
1903
1904 if( m_paragLayout.margins[TQStyleSheetItem::MarginLeft] != parag->margin(TQStyleSheetItem::MarginLeft)
1905 || m_paragLayout.margins[TQStyleSheetItem::MarginFirstLine] != parag->margin(TQStyleSheetItem::MarginFirstLine)
1906 || m_paragLayout.margins[TQStyleSheetItem::MarginRight] != parag->margin(TQStyleSheetItem::MarginRight)
1907 || force )
1908 {
1909 m_paragLayout.margins[TQStyleSheetItem::MarginFirstLine] = parag->margin(TQStyleSheetItem::MarginFirstLine);
1910 m_paragLayout.margins[TQStyleSheetItem::MarginLeft] = parag->margin(TQStyleSheetItem::MarginLeft);
1911 m_paragLayout.margins[TQStyleSheetItem::MarginRight] = parag->margin(TQStyleSheetItem::MarginRight);
1912 m_canvas->getView()->showRulerIndent( m_paragLayout.margins[TQStyleSheetItem::MarginLeft],
1913 m_paragLayout.margins[TQStyleSheetItem::MarginFirstLine],
1914 m_paragLayout.margins[TQStyleSheetItem::MarginRight],
1915 parag->string()->isRightToLeft() );
1916 }
1917
1918 if( m_paragLayout.tabList() != parag->tabList() || force )
1919 {
1920 m_paragLayout.setTabList( parag->tabList() );
1921 KoRuler * hr = m_canvas->getView()->getHRuler();
1922 if ( hr )
1923 hr->setTabList( parag->tabList() );
1924 }
1925}
1926
1927void KPrTextView::ensureCursorVisible()
1928{
1929 //kdDebug(33001) << "KWTextFrameSetEdit::ensureCursorVisible paragId=" << cursor()->parag()->paragId() << endl;
1930 KoTextParag * parag = cursor()->parag();
1931 kpTextObject()->textObject()->ensureFormatted( parag );
1932 KoTextStringChar *chr = parag->at( cursor()->index() );
1933 int h = parag->lineHeightOfChar( cursor()->index() );
1934 int x = parag->rect().x() + chr->x;
1935 int y = 0; int dummy;
1936
1937 parag->lineHeightOfChar( cursor()->index(), &dummy, &y );
1938 y += parag->rect().y();
1939 int w = 1;
1940 KPrDocument *doc= m_kptextobj->kPresenterDocument();
1941 KoPoint pt= kpTextObject()->getOrig();
1942 pt.setX( doc->zoomHandler()->layoutUnitPtToPt( doc->zoomHandler()->pixelXToPt( x) ) +pt.x());
1943 pt.setY( doc->zoomHandler()->layoutUnitPtToPt( doc->zoomHandler()->pixelYToPt( y ))+pt.y() );
1944
1945 TQPoint p = m_kptextobj->kPresenterDocument()->zoomHandler()->zoomPoint( pt );
1946 w = m_kptextobj->kPresenterDocument()->zoomHandler()->layoutUnitToPixelX( w );
1947 h = m_kptextobj->kPresenterDocument()->zoomHandler()->layoutUnitToPixelY( h );
1948 m_canvas->ensureVisible( p.x(), p.y() + h / 2, w, h / 2 + 2 );
1949}
1950
1951bool KPrTextView::doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index )
1952{
1953 if( m_kptextobj->kPresenterDocument()->allowAutoFormat() )
1954 {
1955 KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat();
1956 if( autoFormat )
1957 return autoFormat->doCompletion( cursor, parag, index, textObject());
1958 }
1959 return false;
1960}
1961
1962bool KPrTextView::doToolTipCompletion( KoTextCursor* cursor, KoTextParag *parag, int index,int keyPress )
1963{
1964 if( m_kptextobj->kPresenterDocument()->allowAutoFormat() )
1965 {
1966 KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat();
1967 if( autoFormat )
1968 return autoFormat->doToolTipCompletion( cursor, parag, index, textObject(), keyPress);
1969 }
1970 return false;
1971}
1972void KPrTextView::showToolTipBox(KoTextParag *parag, int index, TQWidget *widget, const TQPoint &pos)
1973{
1974 if( m_kptextobj->kPresenterDocument()->allowAutoFormat() )
1975 {
1976 KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat();
1977 if( autoFormat )
1978 autoFormat->showToolTipBox(parag, index, widget, pos);
1979 }
1980}
1981
1982void KPrTextView::removeToolTipCompletion()
1983{
1984 if( m_kptextobj->kPresenterDocument()->allowAutoFormat() )
1985 {
1986 KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat();
1987 if( autoFormat )
1988 autoFormat->removeToolTipCompletion();
1989 }
1990}
1991void KPrTextView::textIncreaseIndent()
1992{
1993 m_canvas->setTextDepthPlus();
1994}
1995
1996bool KPrTextView::textDecreaseIndent()
1997{
1998 if (m_paragLayout.margins[TQStyleSheetItem::MarginLeft]>0)
1999 {
2000 m_canvas->setTextDepthMinus();
2001 return true;
2002 }
2003 else
2004 return false;
2005}
2006
2007void KPrTextView::doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, TQChar ch )
2008{
2009 if( m_kptextobj->kPresenterDocument()->allowAutoFormat())
2010 {
2011 KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat();
2012 if ( autoFormat )
2013 autoFormat->doAutoFormat( cursor, parag, index, ch, textObject());
2014 }
2015}
2016
2017bool KPrTextView::doIgnoreDoubleSpace(KoTextParag * parag, int index,TQChar ch )
2018{
2019 if( m_kptextobj->kPresenterDocument()->allowAutoFormat())
2020 {
2021
2022 KoAutoFormat * autoFormat = m_kptextobj->kPresenterDocument()->getAutoFormat();
2023 if( autoFormat )
2024 return autoFormat->doIgnoreDoubleSpace( parag, index,ch );
2025 }
2026 return false;
2027}
2028
2029void KPrTextView::startDrag()
2030{
2031 textView()->dragStarted();
2032 m_canvas->dragStarted();
2033 TQDragObject *drag = newDrag( m_canvas );
2034 if ( !kpTextObject()->kPresenterDocument()->isReadWrite() )
2035 drag->dragCopy();
2036 else
2037 {
2038 if ( drag->drag() && TQDragObject::target() != m_canvas )
2039 textObject()->removeSelectedText( cursor() );
2040 }
2041}
2042
2043void KPrTextView::showFormat( KoTextFormat *format )
2044{
2045 m_canvas->getView()->showFormat( *format );
2046}
2047
2048bool KPrTextView::pgUpKeyPressed()
2049{
2050 KoTextCursor *cursor = textView()->cursor();
2051 KoTextParag *s = cursor->parag();
2052 s = textDocument()->firstParag();
2053
2054 textView()->cursor()->setParag( s );
2055 textView()->cursor()->setIndex( 0 );
2056 return true;
2057}
2058
2059bool KPrTextView::pgDownKeyPressed()
2060{
2061 KoTextCursor *cursor = textView()->cursor();
2062 KoTextParag *s = cursor->parag();
2063 s = textDocument()->lastParag();
2064 cursor->setParag( s );
2065 cursor->setIndex( s->length() - 1 );
2066 return true;
2067}
2068
2069void KPrTextView::keyPressEvent( TQKeyEvent *e )
2070{
2071 //Calculate position of tooltip for autocompletion
2072 const TQPoint pos = kpTextObject()->cursorPos(m_canvas, cursor());
2073 textView()->handleKeyPressEvent( e, m_canvas, pos );
2074}
2075
2076void KPrTextView::keyReleaseEvent( TQKeyEvent *e )
2077{
2078 handleKeyReleaseEvent(e);
2079}
2080
2081void KPrTextView::imStartEvent( TQIMEvent *e )
2082{
2083 handleImStartEvent(e);
2084}
2085
2086void KPrTextView::imComposeEvent( TQIMEvent *e )
2087{
2088 handleImComposeEvent(e);
2089}
2090
2091void KPrTextView::imEndEvent( TQIMEvent *e )
2092{
2093 handleImEndEvent(e);
2094}
2095
2096void KPrTextView::clearSelection()
2097{
2098 if ( textDocument()->hasSelection( KoTextDocument::Standard ) )
2099 textDocument()->removeSelection(KoTextDocument::Standard );
2100}
2101
2102void KPrTextView::selectAll(bool select)
2103{
2104 textObject()->selectAll( select );
2105}
2106
2107void KPrTextView::drawCursor( bool b )
2108{
2109 KoTextView::drawCursor( b );
2110 if ( !cursor()->parag() )
2111 return;
2112 if ( !kpTextObject()->kPresenterDocument()->isReadWrite() )
2113 return;
2114
2115 TQPainter painter( m_canvas );
2116 painter.translate( -m_canvas->diffx(), -m_canvas->diffy() );
2117 painter.setBrushOrigin( -m_canvas->diffx(), -m_canvas->diffy() );
2118
2119 kpTextObject()->drawCursor( &painter, cursor(), b, m_canvas );
2120}
2121
2122// Convert a mouse position into a TQRT document position
2123TQPoint KPrTextView::viewToInternal( const TQPoint & pos ) const
2124{
2125#if 0
2126 KoTextZoomHandler* zh = kpTextObject()->kPresenterDocument()->zoomHandler();
2127 TQPoint tmp(pos);
2128 TQWMatrix m;
2129 m.translate( zh->zoomItX(kpTextObject()->getSize().width() / 2.0),
2130 zh->zoomItY(kpTextObject()->getSize().height() / 2.0) );
2131 m.rotate( kpTextObject()->getAngle() );
2132
2133
2134
2135 m.translate( zh->zoomItX(kpTextObject()->getOrig().x()),
2136 zh->zoomItY(kpTextObject()->getOrig().y()) );
2137 //m = m.invert();
2138 tmp = m * pos;
2139
2140 kdDebug(33001)<<" tmp.x() :"<<tmp.x()<<" tmp.y() "<<tmp.y()<<endl;
2141
2142 KoRect br = KoRect( 0, 0, kpTextObject()->getSize().width(), kpTextObject()->getSize().height() );
2143 double pw = br.width();
2144 double ph = br.height();
2145 KoRect rr = br;
2146 double yPos = -rr.y();
2147 double xPos = -rr.x();
2148 rr.moveTopLeft( KoPoint( -rr.width() / 2.0, -rr.height() / 2.0 ) );
2149
2150 m.translate( zh->zoomItX(pw / 2.0),
2151 zh->zoomItY(ph / 2.0 ));
2152 m.rotate( kpTextObject()->getAngle() );
2153 m.translate( zh->zoomItX(rr.left() + xPos),
2154 zh->zoomItY(rr.top() + yPos) );
2155
2156 m = m.invert();
2157
2158 tmp = m * pos;
2159
2160 kdDebug(33001)<<" tmp.x() :"<<tmp.x()<<" tmp.y() "<<tmp.y()<<endl;
2161#endif
2162
2163 return kpTextObject()->viewToInternal( pos, m_canvas );
2164}
2165
2166void KPrTextView::mousePressEvent( TQMouseEvent *e, const TQPoint &/*_pos*/)
2167{
2168 bool addParag = handleMousePressEvent( e, viewToInternal( e->pos() ),true /*bool canStartDrag*/,
2169 kpTextObject()->kPresenterDocument()->insertDirectCursor() );
2170
2171 if ( addParag )
2172 kpTextObject()->kPresenterDocument()->setModified( true );
2173}
2174
2175void KPrTextView::mouseDoubleClickEvent( TQMouseEvent *e, const TQPoint &pos)
2176{
2177 handleMouseDoubleClickEvent( e, pos );
2178}
2179
2180void KPrTextView::mouseMoveEvent( TQMouseEvent *e, const TQPoint &_pos )
2181{
2182 if ( textView()->maybeStartDrag( e ) )
2183 return;
2184 if ( _pos.y() > 0 )
2185 textView()->handleMouseMoveEvent( e,viewToInternal( e->pos() ) );
2186}
2187
2188bool KPrTextView::isLinkVariable( const TQPoint & pos )
2189{
2190 const TQPoint iPoint = viewToInternal( pos );
2191 KoLinkVariable* linkVariable = dynamic_cast<KoLinkVariable *>( textObject()->variableAtPoint( iPoint ) );
2192 return linkVariable != 0;
2193}
2194
2195void KPrTextView::openLink()
2196{
2197 KPrDocument * doc = kpTextObject()->kPresenterDocument();
2198 if ( doc->getVariableCollection()->variableSetting()->displayLink() ) {
2199 KoLinkVariable* v = linkVariable();
2200 if ( v )
2201 KoTextView::openLink( v );
2202 }
2203}
2204
2205void KPrTextView::mouseReleaseEvent( TQMouseEvent *, const TQPoint & )
2206{
2207 handleMouseReleaseEvent();
2208}
2209
2210void KPrTextView::showPopup( KPrView *view, const TQPoint &point, TQPtrList<TDEAction>& actionList )
2211{
2212 TQString word = wordUnderCursor( *cursor() );
2213 view->unplugActionList( "datatools" );
2214 view->unplugActionList( "datatools_link" );
2215 view->unplugActionList( "spell_result_action" );
2216 view->unplugActionList( "variable_action" );
2217 TQPtrList<TDEAction> &variableList = view->variableActionList();
2218 variableList.clear();
2219 actionList.clear();
2220
2221 view->kPresenterDoc()->getVariableCollection()->setVariableSelected(variable());
2222 KoVariable* var = variable();
2223 if ( var )
2224 {
2225 variableList = view->kPresenterDoc()->getVariableCollection()->popupActionList();
2226 }
2227
2228 if( variableList.count()>0)
2229 {
2230 view->plugActionList( "variable_action", variableList );
2231 TQPopupMenu * popup = view->popupMenu("variable_popup");
2232 Q_ASSERT(popup);
2233 if (popup)
2234 popup->popup( point ); // using exec() here breaks the spellcheck tool (event loop pb)
2235
2236 }
2237 else
2238 {
2239 bool singleWord= false;
2240 actionList = dataToolActionList(view->kPresenterDoc()->instance(), word, singleWord);
2241 //kdDebug(33001) << "KWView::openPopupMenuInsideFrame plugging actionlist with " << actionList.count() << " actions" << endl;
2242 KoLinkVariable* linkVar = dynamic_cast<KoLinkVariable *>( var );
2243 TQPopupMenu * popup;
2244 if ( !linkVar )
2245 {
2246 view->plugActionList( "datatools", actionList );
2247
2248 KoNoteVariable * noteVar = dynamic_cast<KoNoteVariable *>( var );
2249 KoCustomVariable * customVar = dynamic_cast<KoCustomVariable *>( var );
2250 if( noteVar )
2251 popup = view->popupMenu("note_popup");
2252 else if( customVar )
2253 popup = view->popupMenu("custom_var_popup");
2254 else
2255 {
2256 if ( singleWord )
2257 {
2258 TQPtrList<TDEAction> actionCheckSpellList =view->listOfResultOfCheckWord( word );
2259 if ( actionCheckSpellList.count()>0)
2260 {
2261 view->plugActionList( "spell_result_action", actionCheckSpellList );
2262 popup = view->popupMenu("text_popup_spell_with_result");
2263 }
2264 else
2265 popup = view->popupMenu("text_popup_spell");
2266 }
2267 else
2268 popup = view->popupMenu("text_popup");
2269 }
2270 }
2271 else
2272 {
2273 view->plugActionList( "datatools_link", actionList );
2274 popup = view->popupMenu("text_popup_link");
2275 }
2276 Q_ASSERT(popup);
2277 if (popup)
2278 popup->popup( point ); // using exec() here breaks the spellcheck tool (event loop pb)
2279 }
2280}
2281
2282void KPrTextView::insertCustomVariable( const TQString &name)
2283{
2284 KPrDocument * doc = kpTextObject()->kPresenterDocument();
2285 KoVariable * var = new KoCustomVariable( textDocument(), name, doc->variableFormatCollection()->format( "STRING" ),
2286 doc->getVariableCollection());
2287 insertVariable( var );
2288}
2289
2290void KPrTextView::insertLink(const TQString &_linkName, const TQString & hrefName)
2291{
2292 KPrDocument * doc = kpTextObject()->kPresenterDocument();
2293 KoVariable * var = new KoLinkVariable( textDocument(), _linkName, hrefName,
2294 doc->variableFormatCollection()->format( "STRING" ),
2295 doc->getVariableCollection());
2296 insertVariable( var );
2297}
2298
2299void KPrTextView::insertComment(const TQString &_comment)
2300{
2301 KPrDocument * doc = kpTextObject()->kPresenterDocument();
2302
2303 KoVariable * var = new KoNoteVariable( textDocument(), _comment,
2304 doc->variableFormatCollection()->format( "STRING" ),
2305 doc->getVariableCollection());
2306 insertVariable( var );
2307}
2308
2309void KPrTextView::insertVariable( int type, int subtype )
2310{
2311 KPrDocument * doc = kpTextObject()->kPresenterDocument();
2312 bool refreshCustomMenu = false;
2313 KoVariable * var = 0L;
2314 if ( type == VT_CUSTOM )
2315 {
2316 KoCustomVarDialog dia( m_canvas );
2317 if ( dia.exec() == TQDialog::Accepted )
2318 {
2319 KoCustomVariable *v = new KoCustomVariable( textDocument(), dia.name(),
2320 doc->variableFormatCollection()->format( "STRING" ),
2321 doc->getVariableCollection() );
2322 v->setValue( dia.value() );
2323 var = v;
2324 refreshCustomMenu = true;
2325 }
2326 }
2327 else
2328 var = doc->getVariableCollection()->createVariable( type, subtype, doc->variableFormatCollection(), 0L, textDocument(),doc, 0);
2329 if ( var )
2330 {
2331 insertVariable( var, 0, refreshCustomMenu);
2332 doc->recalcPageNum();
2333 }
2334}
2335
2336void KPrTextView::insertVariable( KoVariable *var, KoTextFormat *format, bool refreshCustomMenu )
2337{
2338 if ( var )
2339 {
2340 CustomItemsMap customItemsMap;
2341 customItemsMap.insert( 0, var );
2342 if (!format)
2343 format = currentFormat();
2344 //kdDebug(33001) << "KPrTextView::insertVariable inserting into paragraph" << endl;
2345#ifdef DEBUG_FORMATS
2346 kdDebug(33001) << "KPrTextView::insertVariable currentFormat=" << currentFormat() << endl;
2347#endif
2348 textObject()->insert( cursor(), format, KoTextObject::customItemChar(),
2349 i18n("Insert Variable"),
2350 KoTextDocument::Standard,
2351 KoTextObject::DoNotRemoveSelected,
2352 customItemsMap );
2353 if ( refreshCustomMenu && var->type() == VT_CUSTOM )
2354 kpTextObject()->kPresenterDocument()->refreshMenuCustomVariable();
2355 kpTextObject()->kPresenterDocument()->repaint( kpTextObject() );
2356 }
2357}
2358
2359bool KPrTextView::canDecode( TQMimeSource *e )
2360{
2361 return kpTextObject()->kPresenterDocument()->isReadWrite() && ( !KoTextObject::providesOasis( e ).isNull() || TQTextDrag::canDecode( e ) );
2362}
2363
2364TQDragObject * KPrTextView::newDrag( TQWidget * parent )
2365{
2366 TQBuffer buffer;
2367 const TQCString mimeType = "application/vnd.oasis.opendocument.text";
2368 KoStore * store = KoStore::createStore( &buffer, KoStore::Write, mimeType );
2369 Q_ASSERT( store );
2370 Q_ASSERT( !store->bad() );
2371
2372 KoOasisStore oasisStore( store );
2373
2374 //KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
2375
2376 KPrDocument * doc = kpTextObject()->kPresenterDocument();
2377
2378 doc->getVariableCollection()->variableSetting()->setModificationDate( TQDateTime::currentDateTime() );
2379 doc->recalcVariables( VT_DATE );
2380 doc->recalcVariables( VT_TIME );
2381 doc->recalcVariables( VT_STATISTIC );
2382
2383 KoGenStyles mainStyles;
2384 KoSavingContext savingContext( mainStyles, 0, false, KoSavingContext::Store );
2385
2386 doc->styleCollection()->saveOasis( mainStyles, KoGenStyle::STYLE_USER, savingContext );
2387
2388 KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
2389 bodyWriter->startElement( "office:body" );
2390 bodyWriter->startElement( "office:text" );
2391
2392 const TQString plainText = textDocument()->copySelection( *bodyWriter, savingContext, KoTextDocument::Standard );
2393
2394 bodyWriter->endElement(); // office:text
2395 bodyWriter->endElement(); // office:body
2396
2397 KoXmlWriter* contentWriter = oasisStore.contentWriter();
2398 Q_ASSERT( contentWriter );
2399
2400 //KPrDocument * doc = kpTextObject()->kPresenterDocument();
2401 doc->writeAutomaticStyles( *contentWriter, mainStyles, savingContext, false );
2402
2403 oasisStore.closeContentWriter();
2404
2405 if ( !store->open( "styles.xml" ) )
2406 return 0;
2407 //manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
2408 doc->saveOasisDocumentStyles( store, mainStyles, 0, savingContext, KPrDocument::SaveSelected /* simply means not SaveAll */ );
2409 if ( !store->close() ) // done with styles.xml
2410 return 0;
2411
2412 delete store;
2413
2414 KMultipleDrag* multiDrag = new KMultipleDrag( parent );
2415 if ( !plainText.isEmpty() )
2416 multiDrag->addDragObject( new TQTextDrag( plainText, 0 ) );
2417 KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 );
2418 kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
2419 storeDrag->setEncodedData( buffer.buffer() );
2420 multiDrag->addDragObject( storeDrag );
2421 return multiDrag;
2422}
2423
2424void KPrTextView::dragEnterEvent( TQDragEnterEvent *e )
2425{
2426 if ( !canDecode( e ) )
2427 {
2428 e->ignore();
2429 return;
2430 }
2431 e->acceptAction();
2432}
2433
2434void KPrTextView::dragMoveEvent( TQDragMoveEvent *e, const TQPoint & )
2435{
2436 if ( !canDecode( e ) )
2437 {
2438 e->ignore();
2439 return;
2440 }
2441 TQPoint iPoint = viewToInternal( e->pos() );
2442
2443 textObject()->emitHideCursor();
2444 placeCursor( iPoint );
2445 textObject()->emitShowCursor();
2446 e->acceptAction(); // here or out of the if ?
2447}
2448
2449void KPrTextView::dropEvent( TQDropEvent * e )
2450{
2451 if ( canDecode( e ) )
2452 {
2453 KPrDocument *doc = kpTextObject()->kPresenterDocument();
2454 e->acceptAction();
2455 KoTextCursor dropCursor( textDocument() );
2456 TQPoint dropPoint = viewToInternal( e->pos() );
2457 KMacroCommand *macroCmd=new KMacroCommand(i18n("Paste Text"));
2458 bool addMacroCmd = false;
2459 dropCursor.place( dropPoint, textDocument()->firstParag() );
2460 kdDebug(33001) << "KPrTextView::dropEvent dropCursor at parag=" << dropCursor.parag()->paragId() << " index=" << dropCursor.index() << endl;
2461
2462 if ( ( e->source() == m_canvas ) &&
2463 e->action() == TQDropEvent::Move &&
2464 // this is the indicator that the source and dest text objects are the same
2465 textDocument()->hasSelection( KoTextDocument::Standard )
2466 ) {
2467 //kdDebug(33001)<<"decodeFrameSetNumber( TQMimeSource *e ) :"<<numberFrameSet<<endl;
2468 KCommand *cmd = textView()->prepareDropMove( dropCursor );
2469 if(cmd)
2470 {
2471 kpTextObject()->layout();
2472 macroCmd->addCommand(cmd);
2473 addMacroCmd = true;
2474 }
2475 else
2476 {
2477 delete macroCmd;
2478 return;
2479 }
2480 }
2481 else
2482 { // drop coming from outside -> forget about current selection
2483 textDocument()->removeSelection( KoTextDocument::Standard );
2484 textObject()->selectionChangedNotify();
2485 }
2486 TQCString returnedTypeMime = KoTextObject::providesOasis( e );
2487 if ( !returnedTypeMime.isEmpty() )
2488 {
2489 TQByteArray arr = e->encodedData( returnedTypeMime );
2490 if ( arr.size() )
2491 {
2492 KCommand *cmd = kpTextObject()->pasteOasis( cursor(), arr, false );
2493 if ( cmd )
2494 {
2495 macroCmd->addCommand(cmd);
2496 addMacroCmd = true;
2497 }
2498 }
2499 }
2500 else
2501 {
2502 TQString text;
2503 if ( TQTextDrag::decode( e, text ) )
2504 textObject()->pasteText( cursor(), text, currentFormat(),
2505 false /*do not remove selected text*/ );
2506 }
2507 if ( addMacroCmd )
2508 doc->addCommand(macroCmd);
2509 else
2510 delete macroCmd;
2511 }
2512}
2513
2514void KPrTextObject::saveParagraph( TQDomDocument& doc,KoTextParag * parag,TQDomElement &parentElem,
2515 int from /* default 0 */,
2516 int to /* default length()-2 */ )
2517{
2518 if(!parag)
2519 return;
2520 TQDomElement paragraph=doc.createElement(tagP);
2521 int tmpAlign=0;
2522 switch(parag->resolveAlignment())
2523 {
2524 case TQt::AlignLeft:
2525 tmpAlign=1;
2526 break;
2527 case TQt::AlignRight:
2528 tmpAlign=2;
2529 break;
2530 case TQt::AlignHCenter:
2531 tmpAlign=4;
2532 break;
2533 case TQt::AlignJustify:
2534 tmpAlign=8;
2535 }
2536 if(tmpAlign!=1)
2537 paragraph.setAttribute(attrAlign, tmpAlign);
2538
2539 saveParagLayout( parag->paragLayout(), paragraph );
2540 KoTextFormat *lastFormat = 0;
2541 TQString tmpText;
2542 for ( int i = from; i <= to; ++i ) {
2543 KoTextStringChar &c = parag->string()->at(i);
2544 if ( c.isCustom() )
2545 {
2546 TQDomElement variable = doc.createElement("CUSTOM");
2547 variable.setAttribute("pos", (i-from));
2548 saveFormat( variable, c.format() );
2549 paragraph.appendChild( variable );
2550 static_cast<KoTextCustomItem *>( c.customItem() )->save(variable );
2551 }
2552 if ( !lastFormat || c.format()->key() != lastFormat->key() ) {
2553 if ( lastFormat )
2554 paragraph.appendChild(saveHelper(tmpText, lastFormat, doc));
2555 lastFormat = static_cast<KoTextFormat*> (c.format());
2556 tmpText=TQString();
2557 }
2558 tmpText+=TQString(c.c);
2559 }
2560 if ( lastFormat )
2561 paragraph.appendChild(saveHelper(tmpText, lastFormat, doc));
2562 else
2563 paragraph.appendChild(saveHelper(tmpText, parag->string()->at(0).format(), doc));
2564
2565 parentElem.appendChild(paragraph);
2566}
2567
2568KoPen KPrTextObject::defaultPen() const
2569{
2570 return KoPen( TQt::black, 1.0, TQt::NoPen );
2571}
2572
2573TQPoint KPrTextObject::viewToInternal( const TQPoint & pos, KPrCanvas* canvas ) const
2574{
2575 KoTextZoomHandler* zh = kPresenterDocument()->zoomHandler();
2576 TQPoint iPoint = pos - zh->zoomPoint(
2577 getOrig() + KoPoint( bLeft(),
2578 bTop() + alignmentValue()) );
2579 iPoint = zh->pixelToLayoutUnit(
2580 TQPoint( iPoint.x() + canvas->diffx(), iPoint.y() + canvas->diffy() ) );
2581 return iPoint;
2582}
Class KPCanvas - There is a single instance of this class for a given view.
Definition KPrCanvas.h:82
Temporary information used only during loading.
virtual KoPen defaultPen() const
save() only saves if the pen is different from the default pen.
This is our KoTextDocument reimplementation, to relate it to the textobject it's in.