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