kspread

kspread_doc.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005-2006 Inge Wallin <inge@lysator.liu.se>
3 (C) 2004 Ariya Hidayat <ariya@kde.org>
4 (C) 2002-2003 Norbert Andres <nandres@web.de>
5 (C) 2000-2002 Laurent Montel <montel@kde.org>
6 (C) 2002 John Dailey <dailey@vt.edu>
7 (C) 2002 Phillip Mueller <philipp.mueller@gmx.de>
8 (C) 2000 Werner Trobin <trobin@kde.org>
9 (C) 1999-2000 Simon Hausmann <hausmann@kde.org>
10 (C) 1999 David Faure <faure@kde.org>
11 (C) 1998-2000 Torben Weis <weis@kde.org>
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Library General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Library General Public License for more details.
22
23 You should have received a copy of the GNU Library General Public License
24 along with this library; see the file COPYING.LIB. If not, write to
25 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
27*/
28
29#include <unistd.h>
30#include <assert.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <dirent.h>
34#include <pwd.h>
35
36#include <tqapplication.h>
37#include <tqfileinfo.h>
38#include <tqfont.h>
39#include <tqpair.h>
40
41#include <kstandarddirs.h>
42#include <kdebug.h>
43#include <tdeconfig.h>
44#include <tdemessagebox.h>
45#include <ksconfig.h>
46#include <tdetempfile.h>
47
48#include <KoApplication.h>
49#include <KoCommandHistory.h>
50#include <KoDocumentInfo.h>
51#include <KoDom.h>
52#include <KoMainWindow.h>
53#include <KoOasisSettings.h>
54#include <KoOasisStyles.h>
55#include <KoStoreDevice.h>
56#include <KoTemplateChooseDia.h>
57#include <KoVariable.h>
58#include <KoXmlNS.h>
59#include <KoXmlWriter.h>
60
61#include "kspread_canvas.h"
62#include "kspread_locale.h"
63#include "kspread_map.h"
64#include "kspread_sheet.h"
65#include "kspread_sheetprint.h"
66#include "kspread_style_manager.h"
67#include "kspread_undo.h"
68#include "kspread_util.h"
69#include "kspread_view.h"
70
71#include "commands.h"
72#include "damages.h"
73#include "formula.h"
74#include "functions.h"
75#include "ksploadinginfo.h"
76#include "selection.h"
77#include "valuecalc.h"
78#include "valueconverter.h"
79#include "valueformatter.h"
80#include "valueparser.h"
81
82#include "KSpreadDocIface.h"
83
84#include "kspread_doc.h"
85
86using namespace std;
87using namespace KSpread;
88
89static const int CURRENT_SYNTAX_VERSION = 1;
90// Make sure an appropriate DTD is available in www/koffice/DTD if changing this value
91static const char * CURRENT_DTD_VERSION = "1.2";
92
93class Doc::Private
94{
95public:
96
97 Map *map;
98 TDELocale *locale;
99 StyleManager *styleManager;
100 ValueParser *parser;
101 ValueFormatter *formatter;
102 ValueConverter *converter;
103 ValueCalc *calc;
104
105 Sheet *activeSheet;
106 KSPLoadingInfo *m_loadingInfo;
107 static TQValueList<Doc*> s_docs;
108 static int s_docId;
109
110 DCOPObject* dcop;
111
112 // URL of the this part. This variable is only set if the load() function
113 // had been called with an URL as argument.
114 TQString fileURL;
115
116 // for undo/redo
117 int undoLocked;
118 KoCommandHistory* commandHistory;
119
120 // true if loading is in process, otherwise false.
121 // This flag is used to avoid updates etc. during loading.
122 bool isLoading;
123
124 TQColor pageBorderColor;
125
126 TQPtrList<Plugin> plugins;
127
128 TQValueList<Reference> refs;
129 TDECompletion listCompletion;
130
131 int numOperations;
132
133 TQValueList<Damage*> damages;
134
135 // document properties
136 int syntaxVersion;
137 bool verticalScrollBar:1;
138 bool horizontalScrollBar:1;
139 bool columnHeader:1;
140 bool rowHeader:1;
141 TQColor gridColor;
142 double indentValue;
143 bool showStatusBar:1;
144 bool showTabBar:1;
145 bool showFormulaBar:1;
146 bool showError:1;
147 TDEGlobalSettings::Completion completionMode;
148 KSpread::MoveTo moveTo;
149 MethodOfCalc calcMethod;
150 bool delayCalculation:1;
151 KSpellConfig *spellConfig;
152 bool dontCheckUpperWord:1;
153 bool dontCheckTitleCase:1;
154 bool configLoadFromFile:1;
155 TQStringList spellListIgnoreAll;
157 TQPtrList<EmbeddedObject> m_embeddedObjects;
158 KoPictureCollection m_pictureCollection;
159 TQValueList<KoPictureKey> usedPictures;
160 bool m_savingWholeDocument;
161};
162
163/*****************************************************************************
164 *
165 * Doc
166 *
167 *****************************************************************************/
168
169TQValueList<Doc*> Doc::Private::s_docs;
170int Doc::Private::s_docId = 0;
171
172Doc::Doc( TQWidget *parentWidget, const char *widgetName, TQObject* parent, const char* name, bool singleViewMode )
173 : KoDocument( parentWidget, widgetName, parent, name, singleViewMode )
174{
175 d = new Private;
176 d->m_loadingInfo = 0L;
177
178 d->map = new Map( this, "Map" );
179 d->locale = new Locale;
180 d->styleManager = new StyleManager();
181
182 d->parser = new ValueParser( d->locale );
183 d->converter = new ValueConverter ( d->parser );
184 d->calc = new ValueCalc( d->converter );
185 d->calc->setDoc (this);
186 d->formatter = new ValueFormatter( d->converter );
187
188 d->activeSheet = 0;
189
190 d->pageBorderColor = TQt::red;
191 d->configLoadFromFile = false;
192
193 TQFont f( KoGlobal::defaultFont() );
194 Format::setGlobalRowHeight( f.pointSizeFloat() + 3 );
195 Format::setGlobalColWidth( ( f.pointSizeFloat() + 3 ) * 5 );
196
197 d->plugins.setAutoDelete( false );
198
199 d->delayCalculation = false;
200
201 documents().append( this );
202
203 setInstance( Factory::global(), false );
204 setTemplateType( "kspread_template" );
205
206 d->dcop = 0;
207 d->isLoading = false;
208 d->numOperations = 1; // don't start repainting before the GUI is done...
209
210 d->undoLocked = 0;
211 d->commandHistory = new KoCommandHistory( actionCollection() );
212 connect( d->commandHistory, TQ_SIGNAL( commandExecuted() ), TQ_SLOT( commandExecuted() ) );
213 connect( d->commandHistory, TQ_SIGNAL( documentRestored() ), TQ_SLOT( documentRestored() ) );
214
215
216 // Make us scripsheet if the document has a name
217 // Set a name if there is no name specified
218 if ( !name )
219 {
220 TQString tmp( "Document%1" );
221 tmp = tmp.arg( d->s_docId++ );
222 setName( tmp.local8Bit());//tmp.latin1() );
223 dcopObject();
224 }
225 else
226 dcopObject();
227
228 // default document properties
229 d->syntaxVersion = CURRENT_SYNTAX_VERSION;
230 d->verticalScrollBar = true;
231 d->horizontalScrollBar = true;
232 d->columnHeader = true;
233 d->rowHeader = true;
234 d->gridColor = TQt::lightGray;
235 d->indentValue = 10.0;
236 d->showStatusBar = true;
237 d->showFormulaBar = true;
238 d->showTabBar = true;
239 d->showError = false;
240 d->calcMethod = SumOfNumber;
241 d->moveTo = KSpread::Bottom;
242 d->completionMode = TDEGlobalSettings::CompletionAuto;
243 d->spellConfig = 0;
244 d->dontCheckUpperWord = false;
245 d->dontCheckTitleCase = false;
246}
247
249{
250 //don't save config when kword is embedded into konqueror
251 if(isReadWrite())
252 saveConfig();
253
254 delete d->dcop;
255 d->s_docs.remove( this );
256
257 kdDebug(36001) << "alive 1" << endl;
258
259 delete d->commandHistory;
260
261 delete d->spellConfig;
262
263 delete d->locale;
264 delete d->map;
265 delete d->styleManager;
266 delete d->parser;
267 delete d->formatter;
268 delete d->converter;
269 delete d->calc;
270
271 delete d;
272}
273
274TQValueList<Doc*> Doc::documents()
275{
276 return Private::s_docs;
277}
278
279bool Doc::initDoc(InitDocFlags flags, TQWidget* parentWidget)
280{
281 // ElapsedTime et( " initDoc " );
282
283 TQString f;
284
285 if (flags==KoDocument::InitDocEmpty)
286 {
287 TDEConfig *config = Factory::global()->config();
288 int _page=1;
289 if( config->hasGroup("Parameters" ))
290 {
291 config->setGroup( "Parameters" );
292 _page=config->readNumEntry( "NbPage",1 ) ;
293 }
294
295 for( int i=0; i<_page; i++ )
296 map()->addNewSheet();
297
298 resetURL();
299 setEmpty();
300 initConfig();
301 styleManager()->createBuiltinStyles();
302
303 return true;
304 }
305
306 KoTemplateChooseDia::ReturnType ret;
307 KoTemplateChooseDia::DialogType dlgtype;
308 if (flags != KoDocument::InitDocFileNew )
309 dlgtype = KoTemplateChooseDia::Everything;
310 else
311 dlgtype = KoTemplateChooseDia::OnlyTemplates;
312
313 ret = KoTemplateChooseDia::choose( Factory::global(), f,
314 dlgtype, "kspread_template", parentWidget );
315
316 if ( ret == KoTemplateChooseDia::File )
317 {
318 KURL url( f );
319
320 bool ok=openURL(url);
321
322 while (KoDocument::isLoading())
323 kapp->processEvents();
324
325 return ok;
326
327
328 }
329
330 if ( ret == KoTemplateChooseDia::Empty )
331 {
332 TDEConfig *config = Factory::global()->config();
333 int _page=1;
334 if( config->hasGroup("Parameters" ))
335 {
336 config->setGroup( "Parameters" );
337 _page=config->readNumEntry( "NbPage",1 ) ;
338 }
339
340 for( int i=0; i<_page; i++ )
341 map()->addNewSheet ();
342
343 resetURL();
344 setEmpty();
345 initConfig();
346 styleManager()->createBuiltinStyles();
347 return true;
348 }
349
350 if ( ret == KoTemplateChooseDia::Template )
351 {
352 resetURL();
353 d->m_loadingInfo = new KSPLoadingInfo;
354 d->m_loadingInfo->setLoadTemplate( true );
355 bool ok = loadNativeFormat( f );
356 if ( !ok )
357 {
358 showLoadingErrorDialog();
360 }
361 setEmpty();
362 initConfig();
363 return ok;
364 }
365
366 return false;
367}
368
369void Doc::openTemplate (const TQString& file)
370{
371 d->m_loadingInfo = new KSPLoadingInfo;
372 d->m_loadingInfo->setLoadTemplate( true );
373 KoDocument::openTemplate( file );
375 initConfig();
376}
377
378void Doc::initEmpty()
379{
380 TDEConfig *config = Factory::global()->config();
381 int _page=1;
382 if( config->hasGroup("Parameters" ))
383 {
384 config->setGroup( "Parameters" );
385 _page=config->readNumEntry( "NbPage",1 ) ;
386 }
387
388 for( int i=0; i<_page; i++ )
389 map()->addNewSheet();
390
391 resetURL();
392 initConfig();
393 styleManager()->createBuiltinStyles();
394
395 KoDocument::initEmpty();
396}
397
398TDELocale *Doc::locale () const
399{
400 return d->locale;
401}
402
403Map *Doc::map () const
404{
405 return d->map;
406}
407
408StyleManager *Doc::styleManager () const
409{
410 return d->styleManager;
411}
412
413ValueParser *Doc::parser () const
414{
415 return d->parser;
416}
417
418ValueFormatter *Doc::formatter () const
419{
420 return d->formatter;
421}
422
423ValueConverter *Doc::converter () const
424{
425 return d->converter;
426}
427
428ValueCalc *Doc::calc () const
429{
430 return d->calc;
431}
432
433void Doc::saveConfig()
434{
435 if ( isEmbedded() ||!isReadWrite())
436 return;
437 TDEConfig *config = Factory::global()->config();
438 config->setGroup( "Parameters" );
439 config->writeEntry( "Zoom", m_zoom );
440
441}
442
443void Doc::initConfig()
444{
445 TDEConfig *config = Factory::global()->config();
446
447 if( config->hasGroup("KSpread Page Layout" ))
448 {
449 config->setGroup( "KSpread Page Layout" );
450 setUnit( (KoUnit::Unit)config->readNumEntry( "Default unit page" ,0));
451 }
452 if( config->hasGroup("Parameters" ))
453 {
454 config->setGroup( "Parameters" );
455 m_zoom = config->readNumEntry( "Zoom", 100 );
456 }
457 else
458 m_zoom = 100;
459
460 int undo=30;
461 if(config->hasGroup("Misc" ) )
462 {
463 config->setGroup( "Misc" );
464 undo=config->readNumEntry("UndoRedo",-1);
465 }
466 if(undo!=-1)
467 setUndoRedoLimit(undo);
468
469 setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
470}
471
473{
474 return d->syntaxVersion;
475}
476
477bool Doc::isLoading() const
478{
479 return d->isLoading || KoDocument::isLoading();
480}
481
482void Doc::doNotPaint(bool status)
483{
484 d->isLoading = status;
485}
486
487
488TQColor Doc::pageBorderColor() const
489{
490 return d->pageBorderColor;
491}
492
493void Doc::changePageBorderColor( const TQColor & _color)
494{
495 d->pageBorderColor = _color;
496}
497
498const TQValueList<Reference> &Doc::listArea()
499{
500 return d->refs;
501}
502
503TDECompletion& Doc::completion()
504{
505 return d->listCompletion;
506}
507
508KoView* Doc::createViewInstance( TQWidget* parent, const char* name )
509{
510 if ( name == 0 )
511 name = "View";
512 return new View( parent, name, this );
513}
514
515bool Doc::saveChildren( KoStore* _store )
516{
517 return map()->saveChildren( _store );
518}
519
520int Doc::supportedSpecialFormats() const
521{
522 return KoDocument::supportedSpecialFormats();
523}
524
525bool Doc::completeSaving( KoStore* _store )
526{
527 d->m_pictureCollection.saveToStore( KoPictureCollection::CollectionPicture, _store, d->usedPictures );
528
529 return true;
530}
531
532
533TQDomDocument Doc::saveXML()
534{
535 //Terminate current cell edition, if any
536 TQPtrListIterator<KoView> it( views() );
537
538 /* don't pull focus away from the editor if this is just a background
539 autosave */
540 if (!isAutosaving())
541 {
542 for (; it.current(); ++it )
543 static_cast<View *>( it.current() )->deleteEditor( true );
544 }
545
546 TQDomDocument doc = createDomDocument( "spreadsheet", CURRENT_DTD_VERSION );
547 TQDomElement spread = doc.documentElement();
548 spread.setAttribute( "editor", "KSpread" );
549 spread.setAttribute( "mime", "application/x-kspread" );
550 spread.setAttribute( "syntaxVersion", CURRENT_SYNTAX_VERSION );
551
552 TQDomElement dlocale = ((Locale *)locale())->save( doc );
553 spread.appendChild( dlocale );
554
555 if (d->refs.count() != 0 )
556 {
557 TQDomElement areaname = saveAreaName( doc );
558 spread.appendChild( areaname );
559 }
560
561 if( !d->spellListIgnoreAll.isEmpty() )
562 {
563 TQDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" );
564 spread.appendChild( spellCheckIgnore );
565 for ( TQStringList::Iterator it = d->spellListIgnoreAll.begin(); it != d->spellListIgnoreAll.end(); ++it )
566 {
567 TQDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" );
568 spellCheckIgnore.appendChild( spellElem );
569 spellElem.setAttribute( "word", *it );
570 }
571 }
572
573 SavedDocParts::const_iterator iter = m_savedDocParts.begin();
574 SavedDocParts::const_iterator end = m_savedDocParts.end();
575 while ( iter != end )
576 {
577 // save data we loaded in the beginning and which has no owner back to file
578 spread.appendChild( iter.data() );
579 ++iter;
580 }
581
582 TQDomElement defaults = doc.createElement( "defaults" );
583 defaults.setAttribute( "row-height", Format::globalRowHeight() );
584 defaults.setAttribute( "col-width", Format::globalColWidth() );
585 spread.appendChild( defaults );
586
587 Plugin * plugin = d->plugins.first();
588 for ( ; plugin != 0; plugin = d->plugins.next() )
589 {
590 TQDomElement data( plugin->saveXML( doc ) );
591 if ( !data.isNull() )
592 spread.appendChild( data );
593 }
594
595 TQDomElement s = styleManager()->save( doc );
596 spread.appendChild( s );
597 TQDomElement e = map()->save( doc );
598 spread.appendChild( e );
599
600 setModified( false );
601
602 return doc;
603}
604
605bool Doc::loadChildren( KoStore* _store )
606{
607 return map()->loadChildren( _store );
608}
609
610bool Doc::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
611{
612 emitBeginOperation(true);
613 bool result=saveOasisHelper( store, manifestWriter, SaveAll );
615
616 return result;
617}
618
619bool Doc::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag,
620 TQString* /*plainText*/, KoPicture* /*picture*/ )
621{
622 d->m_pictureCollection.assignUniqueIds();
623 //Terminate current cell edition, if any
624 TQPtrListIterator<KoView> it2( views() );
625 d->m_savingWholeDocument = saveFlag == SaveAll ? true : false;
626
627 /* don't pull focus away from the editor if this is just a background
628 autosave */
629 if (!isAutosaving())
630 {
631 for (; it2.current(); ++it2 )
632 static_cast<View *>( it2.current() )->deleteEditor( true );
633 }
634 if ( !store->open( "content.xml" ) )
635 return false;
636
637 KoStoreDevice dev( store );
638 KoXmlWriter* contentWriter = createOasisXmlWriter( &dev, "office:document-content" );
639 KoGenStyles mainStyles;//for compile
640
641 KTempFile contentTmpFile;
642 //Check that temp file was successfully created
643 if (contentTmpFile.status() != 0)
644 {
645 tqWarning("Creation of temporary file to store document content failed.");
646 return false;
647 }
648
649 contentTmpFile.setAutoDelete( true );
650 TQFile* tmpFile = contentTmpFile.file();
651 KoXmlWriter contentTmpWriter( tmpFile, 1 );
652
653
654
655 //todo fixme just add a element for testing saving content.xml
656 contentTmpWriter.startElement( "office:body" );
657 contentTmpWriter.startElement( "office:spreadsheet" );
658
659 int indexObj = 1;
660 int partIndexObj = 0;
661
662 // Saving the custom cell styles including the default cell style.
663 styleManager()->saveOasis( mainStyles );
664
665 // Saving the default column style
666 KoGenStyle defaultColumnStyle( Doc::STYLE_COLUMN_USER, "table-column" );
667 defaultColumnStyle.addPropertyPt( "style:column-width", Format::globalColWidth() );
668 defaultColumnStyle.setDefaultStyle( true );
669 mainStyles.lookup( defaultColumnStyle, "Default", KoGenStyles::DontForceNumbering );
670
671 // Saving the default row style
672 KoGenStyle defaultRowStyle( Doc::STYLE_ROW_USER, "table-row" );
673 defaultRowStyle.addPropertyPt( "style:row-height", Format::globalRowHeight() );
674 defaultRowStyle.setDefaultStyle( true );
675 mainStyles.lookup( defaultRowStyle, "Default", KoGenStyles::DontForceNumbering );
676
677 // Saving the map.
678 map()->saveOasis( contentTmpWriter, mainStyles, store, manifestWriter, indexObj, partIndexObj );
679
680 saveOasisAreaName( contentTmpWriter );
681 contentTmpWriter.endElement();
682 contentTmpWriter.endElement();
683
684 // Done with writing out the contents to the tempfile, we can now write out the automatic styles
685 contentWriter->startElement( "office:automatic-styles" );
686
687 TQValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
688 TQValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
689 for ( ; it != styles.end() ; ++it ) {
690 (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
691 }
692
693 styles = mainStyles.styles( STYLE_PAGE );
694 it = styles.begin();
695 for ( ; it != styles.end() ; ++it ) {
696 (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-properties" );
697 }
698
699 styles = mainStyles.styles( STYLE_COLUMN_AUTO );
700 it = styles.begin();
701 for ( ; it != styles.end() ; ++it ) {
702 (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" );
703 }
704
705 styles = mainStyles.styles( STYLE_ROW_AUTO );
706 it = styles.begin();
707 for ( ; it != styles.end() ; ++it ) {
708 (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" );
709 }
710
711 styles = mainStyles.styles( STYLE_CELL_AUTO );
712 it = styles.begin();
713 for ( ; it != styles.end() ; ++it ) {
714 (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" );
715 }
716
717 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_NUMBER );
718 it = styles.begin();
719 for ( ; it != styles.end() ; ++it ) {
720 (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ );
721 }
722
723 //TODO FIXME !!!!
724 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE );
725 it = styles.begin();
726 for ( ; it != styles.end() ; ++it ) {
727 (*it).style->writeStyle( contentWriter, mainStyles, "number:date-style", (*it).name, 0 /*TODO ????*/ );
728 }
729
730 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_TIME );
731 it = styles.begin();
732 for ( ; it != styles.end() ; ++it ) {
733 (*it).style->writeStyle( contentWriter, mainStyles, "number:time-style", (*it).name, 0 /*TODO ????*/ );
734 }
735
736 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_FRACTION );
737 it = styles.begin();
738 for ( ; it != styles.end() ; ++it ) {
739 (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ );
740 }
741
742 //TODO FIME !!!!!
743 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_PERCENTAGE );
744 it = styles.begin();
745 for ( ; it != styles.end() ; ++it ) {
746 (*it).style->writeStyle( contentWriter, mainStyles, "number:percentage-style", (*it).name, 0 /*TODO ????*/ );
747 }
748
749 //TODO FIME !!!!!
750 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_CURRENCY );
751 it = styles.begin();
752 for ( ; it != styles.end() ; ++it ) {
753 (*it).style->writeStyle( contentWriter, mainStyles, "number:currency-style", (*it).name, 0 /*TODO ????*/ );
754 }
755
756 styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_SCIENTIFIC );
757 it = styles.begin();
758 for ( ; it != styles.end() ; ++it ) {
759 (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ );
760 }
761
762
763 contentWriter->endElement(); // office:automatic-styles
764
765
766 // And now we can copy over the contents from the tempfile to the real one
767 tmpFile->close();
768 contentWriter->addCompleteElement( tmpFile );
769 contentTmpFile.close();
770
771
772 contentWriter->endElement(); // root element
773 contentWriter->endDocument();
774 delete contentWriter;
775 if ( !store->close() )
776 return false;
777 //add manifest line for content.xml
778 manifestWriter->addManifestEntry( "content.xml", "text/xml" );
779
780 //todo add manifest line for style.xml
781 if ( !store->open( "styles.xml" ) )
782 return false;
783
784 manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
785 saveOasisDocumentStyles( store, mainStyles );
786
787 if ( !store->close() ) // done with styles.xml
788 return false;
789
790 makeUsedPixmapList();
791 d->m_pictureCollection.saveOasisToStore( store, d->usedPictures, manifestWriter);
792
793 if(!store->open("settings.xml"))
794 return false;
795
796 KoXmlWriter* settingsWriter = createOasisXmlWriter(&dev, "office:document-settings");
797 settingsWriter->startElement("office:settings");
798 settingsWriter->startElement("config:config-item-set");
799 settingsWriter->addAttribute("config:name", "view-settings");
800
801 KoUnit::saveOasis(settingsWriter, unit());
802
803 saveOasisSettings( *settingsWriter );
804
805 settingsWriter->endElement(); // config:config-item-set
806
807 settingsWriter->startElement("config:config-item-set");
808 settingsWriter->addAttribute("config:name", "configuration-settings");
809 settingsWriter->addConfigItem("SpellCheckerIgnoreList", d->spellListIgnoreAll.join( "," ) );
810 settingsWriter->endElement(); // config:config-item-set
811 settingsWriter->endElement(); // office:settings
812 settingsWriter->endElement(); // Root:element
813 settingsWriter->endDocument();
814 delete settingsWriter;
815
816 if(!store->close())
817 return false;
818
819 manifestWriter->addManifestEntry("settings.xml", "text/xml");
820
821
822 if ( saveFlag == SaveSelected )
823 {
824 TQPtrListIterator<EmbeddedObject> it(embeddedObjects() );
825 for( ; it.current(); ++it )
826 {
827 if ( it.current()->getType() != OBJECT_CHART && it.current()->getType() != OBJECT_KOFFICE_PART )
828 continue;
829 KoDocumentChild *embedded = dynamic_cast<EmbeddedKOfficeObject *>(it.current() )->embeddedObject();
830 //NOTE: If an application's .desktop file lies about opendocument support (ie. it indicates that it has
831 //a native OASIS mime type, when it doesn't, this causes a crash when trying to reload and paint
832 //the object, since it won't have an associated document.
833 if ( !embedded->saveOasis( store, manifestWriter ) )
834 continue;
835 }
836 }
837
838
839 setModified( false );
840
841 return true;
842}
843
844void Doc::loadOasisSettings( const TQDomDocument&settingsDoc )
845{
846 KoOasisSettings settings( settingsDoc );
847 KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
848 if ( !viewSettings.isNull() )
849 {
850 setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit")));
851 }
852 map()->loadOasisSettings( settings );
853 loadOasisIgnoreList( settings );
854}
855
856void Doc::saveOasisSettings( KoXmlWriter &settingsWriter )
857{
858 settingsWriter.startElement("config:config-item-map-indexed");
859 settingsWriter.addAttribute("config:name", "Views");
860 settingsWriter.startElement( "config:config-item-map-entry" );
861 map()->saveOasisSettings( settingsWriter );
862 settingsWriter.endElement();
863 settingsWriter.endElement();
864}
865
866
867void Doc::loadOasisIgnoreList( const KoOasisSettings& settings )
868{
869 KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" );
870 if ( !configurationSettings.isNull() )
871 {
872 const TQString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" );
873 //kdDebug()<<" ignorelist :"<<ignorelist<<endl;
874 d->spellListIgnoreAll = TQStringList::split( ',', ignorelist );
875 }
876}
877
878
879void Doc::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles ) const
880{
881 KoStoreDevice stylesDev( store );
882 KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" );
883
884 stylesWriter->startElement( "office:styles" );
885 TQValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_USER );
886 TQValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
887 for ( ; it != styles.end() ; ++it ) {
888 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
889 }
890
891 // Writing out the common column styles.
892 styles = mainStyles.styles( Doc::STYLE_COLUMN_USER );
893 it = styles.begin();
894 for ( ; it != styles.end() ; ++it ) {
895 if ( (*it).style->isDefaultStyle() ) {
896 (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-column-properties" );
897 }
898 else {
899 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" );
900 }
901 }
902
903 // Writing out the row column styles.
904 styles = mainStyles.styles( Doc::STYLE_ROW_USER );
905 it = styles.begin();
906 for ( ; it != styles.end() ; ++it ) {
907 if ( (*it).style->isDefaultStyle() ) {
908 (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-row-properties" );
909 }
910 else {
911 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" );
912 }
913 }
914
915 // Writing out the common cell styles.
916 styles = mainStyles.styles( Doc::STYLE_CELL_USER );
917 it = styles.begin();
918 for ( ; it != styles.end() ; ++it ) {
919 if ( (*it).style->isDefaultStyle() ) {
920 (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-cell-properties" );
921 }
922 else {
923 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" );
924 }
925 }
926
927 styles = mainStyles.styles( KoGenStyle::STYLE_HATCH );
928 it = styles.begin();
929 for ( ; it != styles.end() ; ++it ) {
930 (*it).style->writeStyle( stylesWriter, mainStyles, "draw:hatch", (*it).name, "style:graphic-properties" , true, true /*add draw:name*/);
931 }
932 styles = mainStyles.styles( KoGenStyle::STYLE_GRAPHICAUTO );
933 it = styles.begin();
934 for ( ; it != styles.end() ; ++it ) {
935 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" );
936 }
937
938 stylesWriter->endElement(); // office:styles
939
940 stylesWriter->startElement( "office:automatic-styles" );
941 styles = mainStyles.styles( KoGenStyle::STYLE_PAGELAYOUT );
942 it = styles.begin();
943 for ( ; it != styles.end() ; ++it ) {
944 (*it).style->writeStyle( stylesWriter, mainStyles, "style:page-layout", (*it).name, "style:page-layout-properties", false /*don't close*/ );
945 stylesWriter->endElement();
946 }
947
948 stylesWriter->endElement(); // office:automatic-styles
949 //code from kword
950 stylesWriter->startElement( "office:master-styles" );
951
952 styles = mainStyles.styles( Doc::STYLE_PAGEMASTER );
953 it = styles.begin();
954 for ( ; it != styles.end() ; ++it ) {
955 (*it).style->writeStyle( stylesWriter, mainStyles, "style:master-page", (*it).name, "" );
956 }
957
958 stylesWriter->endElement(); // office:master-style
959
960
961 stylesWriter->endElement(); // root element (office:document-styles)
962 stylesWriter->endDocument();
963 delete stylesWriter;;
964}
965
966bool Doc::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* store)
967{
968 if ( !d->m_loadingInfo )
969 d->m_loadingInfo = new KSPLoadingInfo;
970
971 TQTime dt;
972 dt.start();
973
974 emit sigProgress( 0 );
975 d->isLoading = true;
976 d->spellListIgnoreAll.clear();
977
978 d->refs.clear();
979
980 TQDomElement content = doc.documentElement();
981 TQDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
982 if ( realBody.isNull() )
983 {
984 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ));
986 return false;
987 }
988 TQDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "spreadsheet" );
989
990 if ( body.isNull() )
991 {
992 kdError(32001) << "No office:spreadsheet found!" << endl;
993 TQDomElement childElem;
994 TQString localName;
995 forEachElement( childElem, realBody ) {
996 localName = childElem.localName();
997 }
998 if ( localName.isEmpty() )
999 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
1000 else
1001 setErrorMessage( i18n( "This document is not a spreadsheet, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
1003 return false;
1004 }
1005
1006 KoOasisLoadingContext context( this, oasisStyles, store );
1007
1008 //load in first
1009 styleManager()->loadOasisStyleTemplate( oasisStyles );
1010
1011 // load default column style
1012 const TQDomElement* defaultColumnStyle = oasisStyles.defaultStyle( "table-column" );
1013 if ( defaultColumnStyle )
1014 {
1015// kDebug() << "style:default-style style:family=\"table-column\"" << endl;
1016 KoStyleStack styleStack;
1017 styleStack.push( *defaultColumnStyle );
1018 styleStack.setTypeProperties( "table-column" );
1019 if ( styleStack.hasAttributeNS( KoXmlNS::style, "column-width" ) )
1020 {
1021 const double width = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "column-width" ), -1.0 );
1022 if ( width != -1.0 )
1023 {
1024// kDebug() << "\tstyle:column-width: " << width << endl;
1025 Format::setGlobalColWidth( width );
1026 }
1027 }
1028 }
1029
1030 // load default row style
1031 const TQDomElement* defaultRowStyle = oasisStyles.defaultStyle( "table-row" );
1032 if ( defaultRowStyle )
1033 {
1034// kDebug() << "style:default-style style:family=\"table-row\"" << endl;
1035 KoStyleStack styleStack;
1036 styleStack.push( *defaultRowStyle );
1037 styleStack.setTypeProperties( "table-row" );
1038 if ( styleStack.hasAttributeNS( KoXmlNS::style, "row-height" ) )
1039 {
1040 const double height = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "row-height" ), -1.0 );
1041 if ( height != -1.0 )
1042 {
1043// kDebug() << "\tstyle:row-height: " << height << endl;
1044 Format::setGlobalRowHeight( height );
1045 }
1046 }
1047 }
1048
1049 // TODO check versions and mimetypes etc.
1050 loadOasisAreaName( body );
1051 loadOasisCellValidation( body );
1052
1053 // all <sheet:sheet> goes to workbook
1054 if ( !map()->loadOasis( body, context ) )
1055 {
1056 d->isLoading = false;
1058 return false;
1059 }
1060
1061
1062 if ( !settings.isNull() )
1063 {
1064 loadOasisSettings( settings );
1065 }
1066 emit sigProgress( 90 );
1067 initConfig();
1068 emit sigProgress(-1);
1069
1070 //display loading time
1071 kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl;
1072 return true;
1073}
1074
1075bool Doc::loadXML( TQIODevice *, const TQDomDocument& doc )
1076{
1077 TQTime dt;
1078 dt.start();
1079
1080 emit sigProgress( 0 );
1081 d->isLoading = true;
1082 d->spellListIgnoreAll.clear();
1083 // <spreadsheet>
1084 TQDomElement spread = doc.documentElement();
1085
1086 if ( spread.attribute( "mime" ) != "application/x-kspread" && spread.attribute( "mime" ) != "application/vnd.kde.kspread" )
1087 {
1088 d->isLoading = false;
1089 setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kspread or application/vnd.kde.kspread, got %1" ).arg( spread.attribute("mime") ) );
1090 return false;
1091 }
1092
1093 d->syntaxVersion = Doc::getAttribute( spread, "syntaxVersion", 0 );
1094 if ( d->syntaxVersion > CURRENT_SYNTAX_VERSION )
1095 {
1096 int ret = KMessageBox::warningContinueCancel(
1097 0, i18n("This document was created with a newer version of KSpread (syntax version: %1)\n"
1098 "When you open it with this version of KSpread, some information may be lost.").arg(d->syntaxVersion),
1099 i18n("File Format Mismatch"), KStdGuiItem::cont() );
1100 if ( ret == KMessageBox::Cancel )
1101 {
1102 setErrorMessage( "USER_CANCELED" );
1103 return false;
1104 }
1105 }
1106
1107 // <locale>
1108 TQDomElement loc = spread.namedItem( "locale" ).toElement();
1109 if ( !loc.isNull() )
1110 ((Locale *) locale())->load( loc );
1111
1112 emit sigProgress( 5 );
1113
1114 TQDomElement defaults = spread.namedItem( "defaults" ).toElement();
1115 if ( !defaults.isNull() )
1116 {
1117 bool ok = false;
1118 double d = defaults.attribute( "row-height" ).toDouble( &ok );
1119 if ( !ok )
1120 return false;
1121 Format::setGlobalRowHeight( d );
1122
1123 d = defaults.attribute( "col-width" ).toDouble( &ok );
1124
1125 if ( !ok )
1126 return false;
1127
1128 Format::setGlobalColWidth( d );
1129 }
1130
1131 d->refs.clear();
1132 //<areaname >
1133 TQDomElement areaname = spread.namedItem( "areaname" ).toElement();
1134 if ( !areaname.isNull())
1135 loadAreaName(areaname);
1136
1137 TQDomElement ignoreAll = spread.namedItem( "SPELLCHECKIGNORELIST").toElement();
1138 if ( !ignoreAll.isNull())
1139 {
1140 TQDomElement spellWord=spread.namedItem("SPELLCHECKIGNORELIST").toElement();
1141
1142 spellWord=spellWord.firstChild().toElement();
1143 while ( !spellWord.isNull() )
1144 {
1145 if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" )
1146 {
1147 d->spellListIgnoreAll.append(spellWord.attribute("word"));
1148 }
1149 spellWord=spellWord.nextSibling().toElement();
1150 }
1151 }
1152
1153 emit sigProgress( 40 );
1154 // In case of reload (e.g. from konqueror)
1155 map()->sheetList().clear(); // it's set to autoDelete
1156
1157 TQDomElement styles = spread.namedItem( "styles" ).toElement();
1158 if ( !styles.isNull() )
1159 {
1160 if ( !styleManager()->loadXML( styles ) )
1161 {
1162 setErrorMessage( i18n( "Styles cannot be loaded." ) );
1163 d->isLoading = false;
1164 return false;
1165 }
1166 }
1167
1168 // <map>
1169 TQDomElement mymap = spread.namedItem( "map" ).toElement();
1170 if ( mymap.isNull() )
1171 {
1172 setErrorMessage( i18n("Invalid document. No map tag.") );
1173 d->isLoading = false;
1174 return false;
1175 }
1176 if ( !map()->loadXML( mymap ) )
1177 {
1178 d->isLoading = false;
1179 return false;
1180 }
1181
1182 //Backwards compatibility with older versions for paper layout
1183 if ( d->syntaxVersion < 1 )
1184 {
1185 TQDomElement paper = spread.namedItem( "paper" ).toElement();
1186 if ( !paper.isNull() )
1187 {
1188 loadPaper( paper );
1189 }
1190 }
1191
1192 emit sigProgress( 85 );
1193
1194 TQDomElement element( spread.firstChild().toElement() );
1195 while ( !element.isNull() )
1196 {
1197 TQString tagName( element.tagName() );
1198
1199 if ( tagName != "locale" && tagName != "map" && tagName != "styles"
1200 && tagName != "SPELLCHECKIGNORELIST" && tagName != "areaname"
1201 && tagName != "paper" )
1202 {
1203 // belongs to a plugin, load it and save it for later use
1204 m_savedDocParts[ tagName ] = element;
1205 }
1206
1207 element = element.nextSibling().toElement();
1208 }
1209
1210 emit sigProgress( 90 );
1211 initConfig();
1212 emit sigProgress(-1);
1213
1214 kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl;
1215
1216 emit sig_refreshView();
1217
1218 return true;
1219}
1220
1221void Doc::loadPaper( TQDomElement const & paper )
1222{
1223 // <paper>
1224 TQString format = paper.attribute( "format" );
1225 TQString orientation = paper.attribute( "orientation" );
1226
1227 // <borders>
1228 TQDomElement borders = paper.namedItem( "borders" ).toElement();
1229 if ( !borders.isNull() )
1230 {
1231 float left = borders.attribute( "left" ).toFloat();
1232 float right = borders.attribute( "right" ).toFloat();
1233 float top = borders.attribute( "top" ).toFloat();
1234 float bottom = borders.attribute( "bottom" ).toFloat();
1235
1236 //apply to all sheet
1237 TQPtrListIterator<Sheet> it ( map()->sheetList() );
1238 for( ; it.current(); ++it )
1239 {
1240 it.current()->print()->setPaperLayout( left, top, right, bottom,
1241 format, orientation );
1242 }
1243 }
1244
1245 TQString hleft, hright, hcenter;
1246 TQString fleft, fright, fcenter;
1247 // <head>
1248 TQDomElement head = paper.namedItem( "head" ).toElement();
1249 if ( !head.isNull() )
1250 {
1251 TQDomElement left = head.namedItem( "left" ).toElement();
1252 if ( !left.isNull() )
1253 hleft = left.text();
1254 TQDomElement center = head.namedItem( "center" ).toElement();
1255 if ( !center.isNull() )
1256 hcenter = center.text();
1257 TQDomElement right = head.namedItem( "right" ).toElement();
1258 if ( !right.isNull() )
1259 hright = right.text();
1260 }
1261 // <foot>
1262 TQDomElement foot = paper.namedItem( "foot" ).toElement();
1263 if ( !foot.isNull() )
1264 {
1265 TQDomElement left = foot.namedItem( "left" ).toElement();
1266 if ( !left.isNull() )
1267 fleft = left.text();
1268 TQDomElement center = foot.namedItem( "center" ).toElement();
1269 if ( !center.isNull() )
1270 fcenter = center.text();
1271 TQDomElement right = foot.namedItem( "right" ).toElement();
1272 if ( !right.isNull() )
1273 fright = right.text();
1274 }
1275 //The macro "<sheet>" formerly was typed as "<table>"
1276 hleft = hleft.replace( "<table>", "<sheet>" );
1277 hcenter = hcenter.replace( "<table>", "<sheet>" );
1278 hright = hright.replace( "<table>", "<sheet>" );
1279 fleft = fleft.replace( "<table>", "<sheet>" );
1280 fcenter = fcenter.replace( "<table>", "<sheet>" );
1281 fright = fright.replace( "<table>", "<sheet>" );
1282
1283 TQPtrListIterator<Sheet> it ( map()->sheetList() );
1284 for( ; it.current(); ++it )
1285 {
1286 it.current()->print()->setHeadFootLine( hleft, hcenter, hright,
1287 fleft, fcenter, fright);
1288 }
1289}
1290
1291bool Doc::completeLoading( KoStore* /* _store */ )
1292{
1293 kdDebug(36001) << "------------------------ COMPLETING --------------------" << endl;
1294
1295 d->isLoading = false;
1296
1297 // map()->update();
1298
1299 TQPtrListIterator<KoView> it( views() );
1300 for (; it.current(); ++it )
1301 ((View*)it.current())->initialPosition();
1302
1303 kdDebug(36001) << "------------------------ COMPLETION DONE --------------------" << endl;
1304
1305 setModified( false );
1306 return true;
1307}
1308
1309
1310void Doc::registerPlugin( Plugin * plugin )
1311{
1312 d->plugins.append( plugin );
1313}
1314
1315void Doc::deregisterPlugin( Plugin * plugin )
1316{
1317 d->plugins.remove( plugin );
1318}
1319
1320bool Doc::docData( TQString const & xmlTag, TQDomElement & data )
1321{
1322 SavedDocParts::iterator iter = m_savedDocParts.find( xmlTag );
1323 if ( iter == m_savedDocParts.end() )
1324 return false;
1325
1326 data = iter.data();
1327 m_savedDocParts.erase( iter );
1328
1329 return true;
1330}
1331
1333{
1334 d->verticalScrollBar=_show;
1335}
1336
1338{
1339 return d->verticalScrollBar;
1340}
1341
1343{
1344 d->horizontalScrollBar=_show;
1345}
1346
1348{
1349 return d->horizontalScrollBar;
1350}
1351
1352TDEGlobalSettings::Completion Doc::completionMode( ) const
1353{
1354 return d->completionMode;
1355}
1356
1358{
1359 d->columnHeader=_show;
1360}
1361
1363{
1364 return d->columnHeader;
1365}
1366
1368{
1369 d->rowHeader=_show;
1370}
1371
1373{
1374 return d->rowHeader;
1375}
1376
1377void Doc::setGridColor( const TQColor& color )
1378{
1379 d->gridColor = color;
1380}
1381
1382TQColor Doc::gridColor() const
1383{
1384 return d->gridColor;
1385}
1386
1387void Doc::setCompletionMode( TDEGlobalSettings::Completion complMode)
1388{
1389 d->completionMode= complMode;
1390}
1391
1392double Doc::indentValue() const
1393{
1394 return d->indentValue;
1395}
1396
1397void Doc::setIndentValue( double val )
1398{
1399 d->indentValue = val;
1400}
1401
1402void Doc::setShowStatusBar(bool _statusBar)
1403{
1404 d->showStatusBar=_statusBar;
1405}
1406
1408{
1409 return d->showStatusBar;
1410}
1411
1412void Doc::setShowTabBar(bool _tabbar)
1413{
1414 d->showTabBar=_tabbar;
1415}
1416
1418{
1419 return d->showTabBar;
1420}
1421
1422void Doc::setShowFormulaBar(bool _formulaBar)
1423{
1424 d->showFormulaBar=_formulaBar;
1425}
1426
1428{
1429 return d->showFormulaBar;
1430}
1431
1433{
1434 d->showError=_show;
1435}
1436
1438{
1439 return d->showError;
1440}
1441
1442KSpread::MoveTo Doc::getMoveToValue() const
1443{
1444 return d->moveTo;
1445}
1446
1447void Doc::setMoveToValue(KSpread::MoveTo _moveTo)
1448{
1449 d->moveTo = _moveTo;
1450}
1451
1452void Doc::setTypeOfCalc( MethodOfCalc _calc)
1453{
1454 d->calcMethod=_calc;
1455}
1456
1457MethodOfCalc Doc::getTypeOfCalc() const
1458{
1459 return d->calcMethod;
1460}
1461
1462void Doc::setKSpellConfig(KSpellConfig _tdespell)
1463{
1464 if (d->spellConfig == 0 )
1465 d->spellConfig = new KSpellConfig();
1466
1467 d->spellConfig->setNoRootAffix(_tdespell.noRootAffix ());
1468 d->spellConfig->setRunTogether(_tdespell.runTogether ());
1469 d->spellConfig->setDictionary(_tdespell.dictionary ());
1470 d->spellConfig->setDictFromList(_tdespell.dictFromList());
1471 d->spellConfig->setEncoding(_tdespell.encoding());
1472 d->spellConfig->setClient(_tdespell.client());
1473}
1474
1475KSpellConfig * Doc::getKSpellConfig()
1476{
1477 if (!d->spellConfig)
1478 {
1479 KSpellConfig ksconfig;
1480
1481 TDEConfig *config = Factory::global()->config();
1482 if( config->hasGroup("KSpell kspread" ) )
1483 {
1484 config->setGroup( "KSpell kspread" );
1485 ksconfig.setNoRootAffix(config->readNumEntry ("KSpell_NoRootAffix", 0));
1486 ksconfig.setRunTogether(config->readNumEntry ("KSpell_RunTogether", 0));
1487 ksconfig.setDictionary(config->readEntry ("KSpell_Dictionary", ""));
1488 ksconfig.setDictFromList(config->readNumEntry ("KSpell_DictFromList", false));
1489 ksconfig.setEncoding(config->readNumEntry ("KSpell_Encoding", KS_E_ASCII));
1490 ksconfig.setClient(config->readNumEntry ("KSpell_Client", KS_CLIENT_ISPELL));
1491 setKSpellConfig(ksconfig);
1492
1493 setDontCheckUpperWord(config->readBoolEntry("KSpell_IgnoreUppercaseWords", false));
1494 setDontCheckTitleCase(config->readBoolEntry("KSpell_IgnoreTitleCaseWords", false));
1495 }
1496 }
1497 return d->spellConfig;
1498}
1499
1500bool Doc::dontCheckUpperWord() const
1501{
1502 return d->dontCheckUpperWord;
1503}
1504
1505void Doc::setDontCheckUpperWord( bool b )
1506{
1507 d->dontCheckUpperWord = b;
1508}
1509
1510bool Doc::dontCheckTitleCase() const
1511{
1512 return d->dontCheckTitleCase;
1513}
1514
1515void Doc::setDontCheckTitleCase( bool b )
1516{
1517 d->dontCheckTitleCase = b;
1518}
1519
1520TQString Doc::unitName() const
1521{
1522 return KoUnit::unitName( unit() );
1523}
1524
1525void Doc::increaseNumOperation()
1526{
1527 ++d->numOperations;
1528}
1529
1530void Doc::decreaseNumOperation()
1531{
1532 --d->numOperations;
1533}
1534
1535void Doc::addIgnoreWordAllList( const TQStringList & _lst)
1536{
1537 d->spellListIgnoreAll = _lst;
1538}
1539
1540TQStringList Doc::spellListIgnoreAll() const
1541{
1542 return d->spellListIgnoreAll;
1543}
1544
1545void Doc::setZoomAndResolution( int zoom, int dpiX, int dpiY )
1546{
1547 KoZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY );
1548}
1549
1550void Doc::newZoomAndResolution( bool updateViews, bool /*forPrint*/ )
1551{
1552/* layout();
1553 updateAllFrames();*/
1554 if ( updateViews )
1555 {
1556 emit sig_refreshView();
1557 }
1558}
1559
1560void Doc::addCommand( KCommand* command )
1561{
1562 if (undoLocked()) return;
1563 d->commandHistory->addCommand( command, false );
1564 setModified( true );
1565}
1566
1567void Doc::addCommand( UndoAction* undo )
1568{
1569 if (undoLocked()) return;
1570 UndoWrapperCommand* command = new UndoWrapperCommand( undo );
1571 addCommand( command );
1572 setModified( true );
1573}
1574
1576{
1577 undoLock ();
1578 d->commandHistory->undo();
1579 undoUnlock ();
1580}
1581
1583{
1584 undoLock ();
1585 d->commandHistory->redo();
1586 undoUnlock ();
1587}
1588
1589void Doc::commandExecuted()
1590{
1591 setModified( true );
1592}
1593
1594void Doc::documentRestored()
1595{
1596 setModified( false );
1597}
1598
1600{
1601 d->undoLocked++;
1602}
1603
1605{
1606 d->undoLocked--;
1607}
1608
1610{
1611 return (d->undoLocked > 0);
1612}
1613
1614KoCommandHistory* Doc::commandHistory()
1615{
1616 return d->commandHistory;
1617}
1618
1619void Doc::enableUndo( bool _b )
1620{
1621 TQPtrListIterator<KoView> it( views() );
1622 for (; it.current(); ++it )
1623 static_cast<View *>( it.current() )->enableUndo( _b );
1624}
1625
1626void Doc::enableRedo( bool _b )
1627{
1628 TQPtrListIterator<KoView> it( views() );
1629 for (; it.current(); ++it )
1630 static_cast<View *>( it.current() )->enableRedo( _b );
1631}
1632
1633void Doc::paintContent( TQPainter& painter, const TQRect& rect,
1634 bool transparent, double zoomX, double /*zoomY*/ )
1635{
1636 kdDebug(36001) << "paintContent() called on " << rect << endl;
1637
1638 // ElapsedTime et( "Doc::paintContent1" );
1639 //kdDebug(36001) << "Doc::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << endl;
1640
1641 // save current zoom
1642 int oldZoom = m_zoom;
1643
1644 // choose sheet: the first or the active
1645 Sheet* sheet = 0L;
1646 if ( !d->activeSheet )
1647 sheet = map()->firstSheet();
1648 else
1649 sheet = d->activeSheet;
1650 if ( !sheet )
1651 return;
1652
1653 // only one zoom is supported
1654 double d_zoom = 1.0;
1655 setZoomAndResolution( 100, KoGlobal::dpiX(), KoGlobal::dpiY() );
1656 if ( m_zoomedResolutionX != zoomX )
1657 d_zoom *= ( zoomX / m_zoomedResolutionX );
1658
1659 // KSpread support zoom, therefore no need to scale with worldMatrix
1660 TQWMatrix matrix = painter.worldMatrix();
1661 matrix.setMatrix( 1, 0, 0, 1, matrix.dx(), matrix.dy() );
1662 TQRect prect = rect;
1663 prect.setWidth( (int) (prect.width() * painter.worldMatrix().m11()) );
1664 prect.setHeight( (int) (prect.height() * painter.worldMatrix().m22()) );
1665 setZoomAndResolution( (int) ( d_zoom * 100 ), KoGlobal::dpiX(), KoGlobal::dpiY() );
1666 // paint the content, now zoom is correctly set
1667 kdDebug(36001)<<"paintContent-------------------------------------\n";
1668 painter.save();
1669 painter.setWorldMatrix( matrix );
1670 paintContent( painter, prect, transparent, sheet, false );
1671 painter.restore();
1672
1673 // restore zoom
1674 m_zoom = oldZoom;
1675 setZoomAndResolution( oldZoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
1676}
1677
1678void Doc::paintContent( TQPainter& painter, const TQRect& rect, bool /*transparent*/, Sheet* sheet, bool drawCursor )
1679{
1680 if ( isLoading() )
1681 return;
1682 // ElapsedTime et( "Doc::paintContent2" );
1683
1684 // if ( !transparent )
1685 // painter.eraseRect( rect );
1686
1687 double xpos;
1688 double ypos;
1689 int left_col = sheet->leftColumn( unzoomItX( rect.x() ), xpos );
1690 int right_col = sheet->rightColumn( unzoomItX( rect.right() ) );
1691 int top_row = sheet->topRow( unzoomItY( rect.y() ), ypos );
1692 int bottom_row = sheet->bottomRow( unzoomItY( rect.bottom() ) );
1693 TQPen pen;
1694 pen.setWidth( 1 );
1695 painter.setPen( pen );
1696
1697 /* Update the entire visible area. */
1698 TQValueList<TQRect> cellAreaList;
1699 cellAreaList.append( TQRect( left_col,
1700 top_row,
1701 right_col - left_col + 1,
1702 bottom_row - top_row + 1) );
1703
1704 paintCellRegions(painter, rect, NULL, cellAreaList, sheet, drawCursor);
1705}
1706
1707void Doc::paintUpdates()
1708{
1709 // ElapsedTime et( "Doc::paintUpdates" );
1710
1711 TQPtrListIterator<KoView> it( views() );
1712 View * view = NULL;
1713 Sheet * sheet = NULL;
1714
1715 for (; it.current(); ++it )
1716 {
1717 view = static_cast<View *>( it.current() );
1718 view->paintUpdates();
1719 }
1720
1721 for (sheet = map()->firstSheet(); sheet != NULL;
1722 sheet = map()->nextSheet())
1723 {
1724 sheet->clearPaintDirtyData();
1725 }
1726}
1727
1728void Doc::paintCellRegions(TQPainter& painter, const TQRect &viewRect,
1729 View* view,
1730 TQValueList<TQRect> cellRegions,
1731 const Sheet* sheet, bool /*drawCursor*/)
1732{
1733 //
1734 // Clip away children
1735 //
1736
1737 TQRegion rgn = painter.clipRegion();
1738 if ( rgn.isEmpty() )
1739 rgn = TQRegion( TQRect( 0, 0, viewRect.width(), viewRect.height() ) );
1740
1741 TQWMatrix matrix;
1742 if ( view ) {
1743 matrix.scale( zoomedResolutionX(),
1744 zoomedResolutionY() );
1745 matrix.translate( - view->canvasWidget()->xOffset(),
1746 - view->canvasWidget()->yOffset() );
1747 }
1748 else {
1749 matrix = painter.worldMatrix();
1750 }
1751
1752// TQPtrListIterator<KoDocumentChild> it( children() );
1753// for( ; it.current(); ++it ) {
1754// // if ( ((Child*)it.current())->sheet() == sheet &&
1755// // !m_pView->hasDocumentInWindow( it.current()->document() ) )
1756// if ( ((Child*)it.current())->sheet() == sheet)
1757// rgn -= it.current()->region( matrix );
1758// }
1759 painter.setClipRegion( rgn );
1760
1761 TQPen pen;
1762 pen.setWidth( 1 );
1763 painter.setPen( pen );
1764
1765 TQRect cellRegion;
1766 KoRect unzoomedViewRect = unzoomRect( viewRect );
1767
1768 for (unsigned int i=0; i < cellRegions.size(); i++) {
1769 cellRegion = cellRegions[i];
1770
1771 PaintRegion(painter, unzoomedViewRect, view, cellRegion, sheet);
1772 }
1773}
1774
1775
1776void Doc::PaintRegion(TQPainter &painter, const KoRect &viewRegion,
1777 View* view, const TQRect &paintRegion,
1778 const Sheet* sheet)
1779{
1780 // Paint region has cell coordinates (col,row) while viewRegion has
1781 // world coordinates. paintRegion is the cells to update and
1782 // viewRegion is the area actually onscreen.
1783
1784 if ( paintRegion.left() <= 0 || paintRegion.top() <= 0 )
1785 return;
1786
1787 // Get the world coordinates of the upper left corner of the
1788 // paintRegion The view is NULL, when paintRegion is called from
1789 // paintContent, which itself is only called, when we should paint
1790 // the output for INACTIVE embedded view. If inactive embedded,
1791 // then there is no view and we alwas start at top/left, so the
1792 // offset is 0.
1793 //
1794 KoPoint dblCorner;
1795 if ( view == 0L ) //Most propably we are embedded and inactive, so no offset
1796 dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ),
1797 sheet->dblRowPos( paintRegion.top() ) );
1798 else
1799 dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() )
1800 - view->canvasWidget()->xOffset(),
1801 sheet->dblRowPos( paintRegion.top() )
1802 - view->canvasWidget()->yOffset() );
1803 KoPoint dblCurrentCellPos( dblCorner );
1804
1805 int regionBottom = paintRegion.bottom();
1806 int regionRight = paintRegion.right();
1807 int regionLeft = paintRegion.left();
1808 int regionTop = paintRegion.top();
1809
1810 TQValueList<TQPoint> mergedCellsPainted;
1811 for ( int y = regionTop;
1812 y <= regionBottom && dblCurrentCellPos.y() <= viewRegion.bottom();
1813 ++y )
1814 {
1815 const RowFormat * row_lay = sheet->rowFormat( y );
1816 dblCurrentCellPos.setX( dblCorner.x() );
1817
1818 for ( int x = regionLeft;
1819 x <= regionRight && dblCurrentCellPos.x() <= viewRegion.right();
1820 ++x )
1821 {
1822 const ColumnFormat *col_lay = sheet->columnFormat( x );
1823 Cell* cell = sheet->cellAt( x, y );
1824
1825 TQPoint cellRef( x, y );
1826
1827#if 0
1828 bool paintBordersBottom = false;
1829 bool paintBordersRight = false;
1830 bool paintBordersLeft = false;
1831 bool paintBordersTop = false;
1832#endif
1833 int paintBorder = Cell::Border_None;
1834
1835 TQPen rightPen( cell->effRightBorderPen( x, y ) );
1836 TQPen leftPen( cell->effLeftBorderPen( x, y ) );
1837 TQPen topPen( cell->effTopBorderPen( x, y ) );
1838 TQPen bottomPen( cell->effBottomBorderPen( x, y ) );
1839
1840 // Paint border if outermost cell or if the pen is more "worth"
1841 // than the border pen of the cell on the other side of the
1842 // border or if the cell on the other side is not painted. In
1843 // the latter case get the pen that is of more "worth"
1844
1845 // right border:
1846 if ( x >= KS_colMax )
1847 //paintBordersRight = true;
1848 paintBorder |= Cell::Border_Right;
1849 else if ( x == regionRight ) {
1850 paintBorder |= Cell::Border_Right;
1851 if ( cell->effRightBorderValue( x, y )
1852 < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) )
1853 rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y );
1854 }
1855 else {
1856 paintBorder |= Cell::Border_Right;
1857 if ( cell->effRightBorderValue( x, y )
1858 < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) )
1859 rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y );
1860 }
1861
1862 // Similiar for other borders...
1863 // bottom border:
1864 if ( y >= KS_rowMax )
1865 paintBorder |= Cell::Border_Bottom;
1866 else if ( y == regionBottom ) {
1867 paintBorder |= Cell::Border_Bottom;
1868 if ( cell->effBottomBorderValue( x, y )
1869 < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) )
1870 bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 );
1871 }
1872 else {
1873 paintBorder |= Cell::Border_Bottom;
1874 if ( cell->effBottomBorderValue( x, y )
1875 < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) )
1876 bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 );
1877 }
1878
1879 // left border:
1880 if ( x == 1 )
1881 paintBorder |= Cell::Border_Left;
1882 else if ( x == regionLeft ) {
1883 paintBorder |= Cell::Border_Left;
1884 if ( cell->effLeftBorderValue( x, y )
1885 < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) )
1886 leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y );
1887 }
1888 else {
1889 paintBorder |= Cell::Border_Left;
1890 if ( cell->effLeftBorderValue( x, y )
1891 < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) )
1892 leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y );
1893 }
1894
1895 // top border:
1896 if ( y == 1 )
1897 paintBorder |= Cell::Border_Top;
1898 else if ( y == regionTop ) {
1899 paintBorder |= Cell::Border_Top;
1900 if ( cell->effTopBorderValue( x, y )
1901 < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) )
1902 topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 );
1903 }
1904 else {
1905 paintBorder |= Cell::Border_Top;
1906 if ( cell->effTopBorderValue( x, y )
1907 < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) )
1908 topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 );
1909 }
1910
1911#if 0
1912 cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef,
1913 paintBordersRight, paintBordersBottom,
1914 paintBordersLeft, paintBordersTop,
1915 rightPen, bottomPen, leftPen, topPen,
1916 mergedCellsPainted, false );
1917
1918 Cell::BorderSides highlightBorder=Cell::Border_None;
1919 TQPen highlightPen;
1920#endif
1921
1922 cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef,
1923 paintBorder,
1924 rightPen, bottomPen, leftPen, topPen,
1925 mergedCellsPainted, false );
1926
1927
1928 dblCurrentCellPos.setX( dblCurrentCellPos.x() + col_lay->dblWidth() );
1929 }
1930 dblCurrentCellPos.setY( dblCurrentCellPos.y() + row_lay->dblHeight() );
1931 }
1932}
1933
1934
1935DCOPObject* Doc::dcopObject()
1936{
1937 if ( !d->dcop )
1938 d->dcop = new DocIface( this );
1939
1940 return d->dcop;
1941}
1942
1943void Doc::addAreaName(const TQRect &_rect,const TQString & name,const TQString & sheetName)
1944{
1945 setModified( true );
1946 Reference tmp;
1947 tmp.rect = _rect;
1948 tmp.sheet_name = sheetName;
1949 tmp.ref_name = name;
1950 d->refs.append( tmp);
1951 emit sig_addAreaName( name );
1952}
1953
1954void Doc::removeArea( const TQString & name)
1955{
1956 TQValueList<Reference>::Iterator it2;
1957 for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
1958 {
1959 if((*it2).ref_name==name)
1960 {
1961 d->refs.remove(it2);
1962 emit sig_removeAreaName( name );
1963 return;
1964 }
1965 }
1966}
1967
1968void Doc::changeAreaSheetName(const TQString & oldName,const TQString & sheetName)
1969{
1970 TQValueList<Reference>::Iterator it2;
1971 for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
1972 {
1973 if((*it2).sheet_name==oldName)
1974 (*it2).sheet_name=sheetName;
1975 }
1976}
1977
1978TQRect Doc::getRectArea(const TQString &_sheetName)
1979{
1980 TQValueList<Reference>::Iterator it2;
1981 for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
1982 {
1983 if((*it2).ref_name==_sheetName)
1984 {
1985 return (*it2).rect;
1986 }
1987 }
1988 return TQRect(-1,-1,-1,-1);
1989}
1990
1991TQDomElement Doc::saveAreaName( TQDomDocument& doc )
1992{
1993 TQDomElement element = doc.createElement( "areaname" );
1994 TQValueList<Reference>::Iterator it2;
1995 for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
1996 {
1997 TQDomElement e = doc.createElement("reference");
1998 TQDomElement tabname = doc.createElement( "tabname" );
1999 tabname.appendChild( doc.createTextNode( (*it2).sheet_name ) );
2000 e.appendChild( tabname );
2001
2002 TQDomElement refname = doc.createElement( "refname" );
2003 refname.appendChild( doc.createTextNode( (*it2).ref_name ) );
2004 e.appendChild( refname );
2005
2006 TQDomElement rect = doc.createElement( "rect" );
2007 rect.setAttribute( "left-rect", ((*it2).rect).left() );
2008 rect.setAttribute( "right-rect",((*it2).rect).right() );
2009 rect.setAttribute( "top-rect", ((*it2).rect).top() );
2010 rect.setAttribute( "bottom-rect", ((*it2).rect).bottom() );
2011 e.appendChild( rect );
2012 element.appendChild(e);
2013 }
2014 return element;
2015}
2016
2017void Doc::loadOasisCellValidation( const TQDomElement&body )
2018{
2019 TQDomNode validation = KoDom::namedItemNS( body, KoXmlNS::table, "content-validations" );
2020 kdDebug()<<"void Doc::loadOasisCellValidation( const TQDomElement&body ) \n";
2021 kdDebug()<<"validation.isNull ? "<<validation.isNull()<<endl;
2022 if ( !validation.isNull() )
2023 {
2024 TQDomNode n = validation.firstChild();
2025 for( ; !n.isNull(); n = n.nextSibling() )
2026 {
2027 if ( n.isElement() )
2028 {
2029 TQDomElement element = n.toElement();
2030 //kdDebug()<<" loadOasisCellValidation element.tagName() :"<<element.tagName()<<endl;
2031 if ( element.tagName() == "content-validation" && element.namespaceURI() == KoXmlNS::table ) {
2032 d->m_loadingInfo->appendValidation(element.attributeNS( KoXmlNS::table, "name", TQString() ), element );
2033 kdDebug()<<" validation found :"<<element.attributeNS( KoXmlNS::table, "name", TQString() )<<endl;
2034 }
2035 else {
2036 kdDebug()<<" Tag not recognize :"<<element.tagName()<<endl;
2037 }
2038 }
2039 }
2040 }
2041}
2042
2043void Doc::saveOasisAreaName( KoXmlWriter & xmlWriter )
2044{
2045 if ( listArea().count()>0 )
2046 {
2047 xmlWriter.startElement( "table:named-expressions" );
2048 TQValueList<Reference>::Iterator it;
2049 for ( it = d->refs.begin(); it != d->refs.end(); ++it )
2050 {
2051 xmlWriter.startElement( "table:named-range" );
2052
2053 xmlWriter.addAttribute( "table:name", ( *it ).ref_name );
2054 xmlWriter.addAttribute( "table:base-cell-address", convertRefToBase( ( *it ).sheet_name, ( *it ).rect ) );
2055 xmlWriter.addAttribute( "table:cell-range-address", convertRefToRange( ( *it ).sheet_name, ( *it ).rect ) );
2056
2057 xmlWriter.endElement();
2058 }
2059 xmlWriter.endElement();
2060 }
2061}
2062
2063void Doc::loadOasisAreaName( const TQDomElement& body )
2064{
2065 kdDebug()<<"void Doc::loadOasisAreaName( const TQDomElement& body ) \n";
2066 TQDomNode namedAreas = KoDom::namedItemNS( body, KoXmlNS::table, "named-expressions" );
2067 if ( !namedAreas.isNull() )
2068 {
2069 kdDebug()<<" area name exist \n";
2070 TQDomNode area = namedAreas.firstChild();
2071 while ( !area.isNull() )
2072 {
2073 TQDomElement e = area.toElement();
2074
2075 if ( e.localName() == "named-range" )
2076 {
2077 if ( !e.hasAttributeNS( KoXmlNS::table, "name" ) || !e.hasAttributeNS( KoXmlNS::table, "cell-range-address" ) )
2078 {
2079 kdDebug() << "Reading in named area failed" << endl;
2080 area = area.nextSibling();
2081 continue;
2082 }
2083
2084 // TODO: what is: sheet:base-cell-address
2085 TQString name = e.attributeNS( KoXmlNS::table, "name", TQString() );
2086 TQString range = e.attributeNS( KoXmlNS::table, "cell-range-address", TQString() );
2087 kdDebug()<<"area name : "<<name<<" range :"<<range<<endl;
2088 d->m_loadingInfo->addWordInAreaList( name );
2089 kdDebug() << "Reading in named area, name: " << name << ", area: " << range << endl;
2090
2091 range = Oasis::decodeFormula( range );
2092
2093 if ( range.find( ':' ) == -1 )
2094 {
2095 Point p( range );
2096
2097 int n = range.find( '!' );
2098 if ( n > 0 )
2099 range = range + ":" + range.right( range.length() - n - 1);
2100
2101 kdDebug() << "=> Area: " << range << endl;
2102 }
2103
2104 if ( range.contains( '!' ) && range[0] == '$' )
2105 {
2106 // cut absolute sheet indicator
2107 range.remove( 0, 1 );
2108 }
2109
2110 Range p( range );
2111
2112 addAreaName( p.range(), name, p.sheetName() );
2113 kdDebug() << "Area range: " << p.toString() << endl;
2114 }
2115 else if ( e.localName() == "named-expression" )
2116 {
2117 kdDebug() << "Named expression found." << endl;
2118 // TODO
2119 }
2120
2121 area = area.nextSibling();
2122 }
2123 }
2124}
2125
2126void Doc::loadAreaName( const TQDomElement& element )
2127{
2128 TQDomElement tmp=element.firstChild().toElement();
2129 for( ; !tmp.isNull(); tmp=tmp.nextSibling().toElement() )
2130 {
2131 if ( tmp.tagName() == "reference" )
2132 {
2133 TQString tabname;
2134 TQString refname;
2135 int left=0;
2136 int right=0;
2137 int top=0;
2138 int bottom=0;
2139 TQDomElement sheetName = tmp.namedItem( "tabname" ).toElement();
2140 if ( !sheetName.isNull() )
2141 {
2142 tabname=sheetName.text();
2143 }
2144 TQDomElement referenceName = tmp.namedItem( "refname" ).toElement();
2145 if ( !referenceName.isNull() )
2146 {
2147 refname=referenceName.text();
2148 }
2149 TQDomElement rect =tmp.namedItem( "rect" ).toElement();
2150 if (!rect.isNull())
2151 {
2152 bool ok;
2153 if ( rect.hasAttribute( "left-rect" ) )
2154 left=rect.attribute("left-rect").toInt( &ok );
2155 if ( rect.hasAttribute( "right-rect" ) )
2156 right=rect.attribute("right-rect").toInt( &ok );
2157 if ( rect.hasAttribute( "top-rect" ) )
2158 top=rect.attribute("top-rect").toInt( &ok );
2159 if ( rect.hasAttribute( "bottom-rect" ) )
2160 bottom=rect.attribute("bottom-rect").toInt( &ok );
2161 }
2162 TQRect _rect;
2163 _rect.setCoords(left,top,right,bottom);
2164 addAreaName(_rect,refname,tabname);
2165 }
2166 }
2167}
2168
2169void Doc::addStringCompletion(const TQString &stringCompletion)
2170{
2171 if ( d->listCompletion.items().contains(stringCompletion) == 0 )
2172 d->listCompletion.addItem( stringCompletion );
2173}
2174
2175void Doc::refreshInterface()
2176{
2177 emit sig_refreshView();
2178}
2179
2180void Doc::refreshLocale()
2181{
2182 emit sig_refreshLocale();
2183}
2184
2185
2186void Doc::emitBeginOperation(bool waitCursor)
2187{
2188 //If an emitBeginOperation occurs with waitCursor enabled, then the waiting cursor is set
2189 //until all operations have been completed.
2190 //
2191 //The reason being that any operations started before the first one with waitCursor set
2192 //are expected to be completed in a short time anyway.
2193 TQCursor* activeOverride = static_cast<TQCursor*>(TQApplication::overrideCursor());
2194
2195 if (waitCursor && ( (!activeOverride) || (activeOverride->shape() != TQt::waitCursor.shape()) ) )
2196 {
2197 TQApplication::setOverrideCursor(TQt::waitCursor);
2198 }
2199
2200// /* just duplicate the current cursor on the stack, then */
2201// else if (TQApplication::overrideCursor() != NULL)
2202// {
2203// TQApplication::setOverrideCursor(TQApplication::overrideCursor()->shape());
2204// }
2205
2206 KoDocument::emitBeginOperation();
2207 d->delayCalculation = true;
2208 d->numOperations++;
2209}
2210
2212{
2213 emitBeginOperation(true);
2214}
2215
2216
2218{
2219 d->numOperations--;
2220
2221 if (d->numOperations <= 0)
2222 {
2223 d->numOperations = 0;
2224 d->delayCalculation = false;
2225 }
2226
2227 KoDocument::emitEndOperation();
2228
2229 if (d->numOperations == 0)
2230 {
2231 TQApplication::restoreOverrideCursor();
2232
2233 /* do this after the parent class emitEndOperation because that allows updates
2234 on the view again
2235 */
2236 paintUpdates();
2237 }
2238}
2239
2240void Doc::emitEndOperation( const Region& /*region*/ )
2241{
2242 d->numOperations--;
2243
2244 if ( d->numOperations > 0 || !d->activeSheet )
2245 {
2246 KoDocument::emitEndOperation();
2247 return;
2248 }
2249
2250 d->numOperations = 0;
2251 d->delayCalculation = false;
2252
2253 KoDocument::emitEndOperation();
2254
2255 TQApplication::restoreOverrideCursor();
2256
2257 /* do this after the parent class emitEndOperation because that allows updates
2258 on the view again
2259 */
2260 paintUpdates();
2261}
2262
2263bool Doc::delayCalculation() const
2264{
2265 return d->delayCalculation;
2266}
2267
2268void Doc::updateBorderButton()
2269{
2270 TQPtrListIterator<KoView> it( views() );
2271 for (; it.current(); ++it )
2272 static_cast<View *>( it.current() )->updateBorderButton();
2273}
2274
2275void Doc::insertSheet( Sheet * sheet )
2276{
2277 TQPtrListIterator<KoView> it( views() );
2278 for (; it.current(); ++it )
2279 ((View*)it.current())->insertSheet( sheet );
2280}
2281
2282void Doc::takeSheet( Sheet * sheet )
2283{
2284 TQPtrListIterator<KoView> it( views() );
2285 for (; it.current(); ++it )
2286 ((View*)it.current())->removeSheet( sheet );
2287}
2288
2289void Doc::addIgnoreWordAll( const TQString & word)
2290{
2291 if( d->spellListIgnoreAll.findIndex( word )==-1)
2292 d->spellListIgnoreAll.append( word );
2293}
2294
2295void Doc::clearIgnoreWordAll( )
2296{
2297 d->spellListIgnoreAll.clear();
2298}
2299
2300void Doc::setDisplaySheet(Sheet *_sheet )
2301{
2302 d->activeSheet = _sheet;
2303}
2304
2306{
2307 return d->m_loadingInfo;
2308}
2309
2311{
2312 delete d->m_loadingInfo;
2313 d->m_loadingInfo = 0;
2314}
2315
2316Sheet * Doc::displaySheet() const
2317{
2318 return d->activeSheet;
2319}
2320
2321void Doc::addView( KoView *_view )
2322{
2323 KoDocument::addView( _view );
2324 TQPtrListIterator<KoView> it( views() );
2325 for (; it.current(); ++it )
2326 ((View*)it.current())->closeEditor();
2327}
2328
2329void Doc::addDamage( Damage* damage )
2330{
2331 d->damages.append( damage );
2332
2333 if( d->damages.count() == 1 )
2334 TQTimer::singleShot( 0, this, TQ_SLOT( flushDamages() ) );
2335}
2336
2337void Doc::flushDamages()
2338{
2339 emit damagesFlushed( d->damages );
2340 TQValueList<Damage*>::Iterator it;
2341 for( it = d->damages.begin(); it != d->damages.end(); ++it )
2342 delete *it;
2343 d->damages.clear();
2344}
2345
2346void Doc::loadConfigFromFile()
2347{
2348 d->configLoadFromFile = true;
2349}
2350
2351bool Doc::configLoadFromFile() const
2352{
2353 return d->configLoadFromFile;
2354}
2355
2356
2358{
2359 switch ( obj->getType() )
2360 {
2361 case OBJECT_KOFFICE_PART: case OBJECT_CHART:
2362 {
2363 KoDocument::insertChild( dynamic_cast<EmbeddedKOfficeObject*>(obj)->embeddedObject() );
2364 break;
2365 }
2366 default:
2367 ;
2368 }
2369 d->m_embeddedObjects.append( obj );
2370}
2371
2372TQPtrList<EmbeddedObject>& Doc::embeddedObjects()
2373{
2374 return d->m_embeddedObjects;
2375}
2376
2377KoPictureCollection *Doc::pictureCollection()
2378{
2379 return &d->m_pictureCollection;
2380}
2381
2382void Doc::repaint( const TQRect& rect )
2383{
2384 TQRect r;
2385 TQPtrListIterator<KoView> it( views() );
2386 for( ; it.current(); ++it )
2387 {
2388 r = rect;
2389 Canvas* canvas = ((View*)it.current())->canvasWidget();
2390 r.moveTopLeft( TQPoint( r.x() - (int) canvas->xOffset(),
2391 r.y() - (int) canvas->yOffset() ) );
2392 canvas->update( r );
2393 }
2394}
2395
2396void Doc::repaint( EmbeddedObject *obj )
2397{
2398 TQPtrListIterator<KoView> it( views() );
2399 for( ; it.current(); ++it )
2400 {
2401 Canvas* canvas = ((View*)it.current())->canvasWidget();
2402 if ( obj->sheet() == canvas->activeSheet() )
2403 canvas->repaintObject( obj );
2404 }
2405}
2406
2407void Doc::repaint( const KoRect& rect )
2408{
2409 TQRect r;
2410 TQPtrListIterator<KoView> it( views() );
2411 for( ; it.current(); ++it )
2412 {
2413 Canvas* canvas = ((View*)it.current())->canvasWidget();
2414
2415 r = zoomRect( rect );
2416 r.moveBy( (int)( -canvas->xOffset()*zoomedResolutionX() ) ,
2417 (int)( -canvas->yOffset() *zoomedResolutionY()) );
2418 canvas->update( r );
2419 }
2420}
2421
2422void Doc::addShell( KoMainWindow *shell )
2423{
2424 connect( shell, TQ_SIGNAL( documentSaved() ), d->commandHistory, TQ_SLOT( documentSaved() ) );
2425 KoDocument::addShell( shell );
2426}
2427
2428int Doc::undoRedoLimit() const
2429{
2430 return d->commandHistory->undoLimit();
2431}
2432
2433void Doc::setUndoRedoLimit(int val)
2434{
2435 d->commandHistory->setUndoLimit(val);
2436 d->commandHistory->setRedoLimit(val);
2437}
2438
2439void Doc::insertPixmapKey( KoPictureKey key )
2440{
2441 if ( !d->usedPictures.contains( key ) )
2442 d->usedPictures.append( key );
2443}
2444
2445void Doc::makeUsedPixmapList()
2446{
2447 d->usedPictures.clear();
2448 TQPtrListIterator<EmbeddedObject> it( d->m_embeddedObjects );
2449 for ( ; it.current() ; ++it )
2450 {
2451 if( it.current()->getType() == OBJECT_PICTURE && ( d->m_savingWholeDocument || it.current()->isSelected() ) )
2452 insertPixmapKey( static_cast<EmbeddedPictureObject*>( it.current() )->getKey() );
2453 }
2454}
2455
2456bool Doc::savingWholeDocument()
2457{
2458 return d->m_savingWholeDocument;
2459}
2460
2461#include "kspread_doc.moc"
2462
The canvas builds a part of the GUI of KSpread.
double yOffset() const
Sheet * activeSheet() const
double xOffset() const
For every cell in the spread sheet there is a Cell object.
const TQPen & effBottomBorderPen(int col, int row) const
void paintCell(const KoRect &rect, TQPainter &painter, View *view, const KoPoint &coordinate, const TQPoint &cellRef, int paintBorder, TQPen &rightPen, TQPen &bottomPen, TQPen &leftPen, TQPen &topPen, TQValueList< TQPoint > &mergedCellsPainted, bool drawCursor=true)
Paints the cell.
uint effRightBorderValue(int col, int row) const
const TQPen & effTopBorderPen(int col, int row) const
const TQPen & effRightBorderPen(int col, int row) const
uint effLeftBorderValue(int col, int row) const
uint effTopBorderValue(int col, int row) const
uint effBottomBorderValue(int col, int row) const
bool showMessageError() const
Returns true if error message should pop up whenever error occurs.
void setShowTabBar(bool b)
If b is true, tab bar is visible, otherwise it will be hidden.
void setShowVerticalScrollBar(bool b)
If b is true, vertical scrollbar is visible, otherwise it will be hidden.
void setShowStatusBar(bool b)
If b is true, status bar is visible, otherwise it will be hidden.
bool showStatusBar() const
Returns true if status bar is visible.
int syntaxVersion() const
Returns the syntax version of the currently opened file.
virtual void setZoomAndResolution(int zoom, int dpiX, int dpiY)
Change the zoom factor to z (e.g.
bool showColumnHeader() const
Returns true if column header is visible.
void setIndentValue(double val)
Sets the indentation value.
void redo()
Redoes the last undo.
void setShowColumnHeader(bool b)
If b is true, column header is visible, otherwise it will be hidden.
void sig_refreshLocale()
Emitted if we update to locale system.
void setTypeOfCalc(MethodOfCalc _calc)
Method of calc.
bool isLoading() const
KoCommandHistory * commandHistory()
Returns the command history for the document.
void sig_refreshView()
Emitted if all interfaces have to be updated.
bool undoLocked() const
Returns true if undo buffer is locked.
bool saveOasisHelper(KoStore *store, KoXmlWriter *manifestWriter, SaveFlag saveFlag, TQString *plainText=0, KoPicture *picture=0)
Save the whole document, or just the selection, into OASIS format When saving the selection,...
void doNotPaint(bool status)
Prevents painting.
virtual bool completeLoading(KoStore *)
Overloaded function of KoDocument.
~Doc()
Destroys the document.
void setGridColor(const TQColor &color)
Sets the color of the grid.
void setShowMessageError(bool b)
If b is true, an error message will pop up whenever error occurs.
void setShowHorizontalScrollBar(bool b)
If b is true, horizontal scrollbar is visible, otherwise it will be hidden.
Doc(TQWidget *parentWidget=0, const char *widgetName=0, TQObject *parent=0, const char *name=0, bool singleViewMode=false)
Creates a new document.
bool showVerticalScrollBar() const
Returns true if vertical scroll bar is visible.
bool showRowHeader() const
Returns true if row header is visible.
void newZoomAndResolution(bool updateViews, bool forPrint)
updates all properties after zoom changed
virtual bool saveChildren(KoStore *_store)
Overloaded function of KoDocument.
void addCommand(KCommand *command)
Adds a command to the command history.
void setShowFormulaBar(bool b)
If b is true, formula bar is visible, otherwise it will be hidden.
bool showFormulaBar() const
Returns true if formula bar is visible.
virtual void emitBeginOperation()
default override of koDocument version.
TDEGlobalSettings::Completion completionMode() const
completion mode
KSPLoadingInfo * loadingInfo() const
void undoUnlock()
Releases lock of undo buffer.
TQString unitName() const
Returns the name of the unit used to display margins.
void insertObject(EmbeddedObject *obj)
Inserts an object to the object list.
void setKSpellConfig(KSpellConfig _tdespell)
get custom tdespell config
bool showHorizontalScrollBar() const
Returns true if horizontal scroll bar is visible.
bool showTabBar() const
Returns true if tab bar is visible.
void deleteLoadingInfo()
deletes the loading info after loading is complete
void undoLock()
Locks the undo buffer.
TQColor gridColor() const
Returns the color of the grid.
@ STYLE_COLUMN_AUTO
auto column styles
@ STYLE_COLUMN_USER
commmon column styles
@ STYLE_ROW_AUTO
auto row styles
@ STYLE_ROW_USER
common row styles
virtual void emitEndOperation()
Mark the end of an operation and triggers a repaint of any cells or regions of cells which have been ...
void paintCellRegions(TQPainter &painter, const TQRect &viewRect, View *view, TQValueList< TQRect > cellRegions, const Sheet *sheet, bool drawCursor)
Primary entry point for painting.
double indentValue() const
Returns the indentation value.
static TQValueList< Doc * > documents()
Returns list of all documents.
void undo()
Undoes the last operation.
TQPtrList< EmbeddedObject > & embeddedObjects()
void setShowRowHeader(bool b)
If b is true, row header is visible, otherwise it will be hidden.
Holds an embedded koffice object.
Contains basic information for every object.
Temporary information used only during loading.
A map is a simple container for all sheets.
Definition kspread_map.h:59
Sheet * addNewSheet()
add a new sheet to the map, returning a pointer to it
The one for all class for points and ranges.
Definition region.h:44
Abstract base class.
Class UndoWrapperCommand is used to help migration from custom UndoAction to KCommand-based system.
Definition commands.h:90
The ValueCalc class is used to perform all sorts of calculations.
Definition valuecalc.h:69
The ValueConverter class can convert Value between various different formats.
The ValueFormatter class generates a textual representation of data stored in a Value,...
The ValueParser parses a text input from the user, generating Value in the desired format.
Definition valueparser.h:40
The View class displays a KSpread document.
void deleteEditor(bool saveChanges=true)
Called before saving, to finish the current edition (if any).
Canvas * canvasWidget() const
Returns the canvas of the view.
void paintUpdates()
Repaint any cell with the paintDirty flag that is visible in this view.
The KSpread namespace.
Definition commands.h:39