kspread

kspread_doc.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005-2006 Inge Wallin <inge@lysator.liu.se>
00003              (C) 2004 Ariya Hidayat <ariya@kde.org>
00004              (C) 2002-2003 Norbert Andres <nandres@web.de>
00005              (C) 2000-2002 Laurent Montel <montel@kde.org>
00006              (C) 2002 John Dailey <dailey@vt.edu>
00007              (C) 2002 Phillip Mueller <philipp.mueller@gmx.de>
00008              (C) 2000 Werner Trobin <trobin@kde.org>
00009              (C) 1999-2000 Simon Hausmann <hausmann@kde.org>
00010              (C) 1999 David Faure <faure@kde.org>
00011              (C) 1998-2000 Torben Weis <weis@kde.org>
00012 
00013    This library is free software; you can redistribute it and/or
00014    modify it under the terms of the GNU Library General Public
00015    License as published by the Free Software Foundation; either
00016    version 2 of the License, or (at your option) any later version.
00017 
00018    This library is distributed in the hope that it will be useful,
00019    but WITHOUT ANY WARRANTY; without even the implied warranty of
00020    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021    Library General Public License for more details.
00022 
00023    You should have received a copy of the GNU Library General Public License
00024    along with this library; see the file COPYING.LIB.  If not, write to
00025    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00026  * Boston, MA 02110-1301, USA.
00027 */
00028 
00029 #include <unistd.h>
00030 #include <assert.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <dirent.h>
00034 #include <pwd.h>
00035 
00036 #include <qapplication.h>
00037 #include <qfileinfo.h>
00038 #include <qfont.h>
00039 #include <qpair.h>
00040 
00041 #include <kstandarddirs.h>
00042 #include <kdebug.h>
00043 #include <kconfig.h>
00044 #include <kmessagebox.h>
00045 #include <ksconfig.h>
00046 #include <ktempfile.h>
00047 
00048 #include <KoApplication.h>
00049 #include <KoCommandHistory.h>
00050 #include <KoDocumentInfo.h>
00051 #include <KoDom.h>
00052 #include <KoMainWindow.h>
00053 #include <KoOasisSettings.h>
00054 #include <KoOasisStyles.h>
00055 #include <KoStoreDevice.h>
00056 #include <KoTemplateChooseDia.h>
00057 #include <KoVariable.h>
00058 #include <KoXmlNS.h>
00059 #include <KoXmlWriter.h>
00060 
00061 #include "kspread_canvas.h"
00062 #include "kspread_locale.h"
00063 #include "kspread_map.h"
00064 #include "kspread_sheet.h"
00065 #include "kspread_sheetprint.h"
00066 #include "kspread_style.h"
00067 #include "kspread_style_manager.h"
00068 #include "kspread_undo.h"
00069 #include "kspread_util.h"
00070 #include "kspread_view.h"
00071 
00072 #include "commands.h"
00073 #include "damages.h"
00074 #include "formula.h"
00075 #include "functions.h"
00076 #include "ksploadinginfo.h"
00077 #include "selection.h"
00078 #include "valuecalc.h"
00079 #include "valueconverter.h"
00080 #include "valueformatter.h"
00081 #include "valueparser.h"
00082 
00083 #include "KSpreadDocIface.h"
00084 
00085 #include "kspread_doc.h"
00086 
00087 using namespace std;
00088 using namespace KSpread;
00089 
00090 static const int CURRENT_SYNTAX_VERSION = 1;
00091 // Make sure an appropriate DTD is available in www/koffice/DTD if changing this value
00092 static const char * CURRENT_DTD_VERSION = "1.2";
00093 
00094 class Doc::Private
00095 {
00096 public:
00097 
00098   Map *map;
00099   KLocale *locale;
00100   StyleManager *styleManager;
00101   ValueParser *parser;
00102   ValueFormatter *formatter;
00103   ValueConverter *converter;
00104   ValueCalc *calc;
00105 
00106   Sheet *activeSheet;
00107     KSPLoadingInfo *m_loadingInfo;
00108   static QValueList<Doc*> s_docs;
00109   static int s_docId;
00110 
00111   DCOPObject* dcop;
00112 
00113   // URL of the this part. This variable is only set if the load() function
00114   // had been called with an URL as argument.
00115   QString fileURL;
00116 
00117   // for undo/redo
00118   int undoLocked;
00119   KoCommandHistory* commandHistory;
00120 
00121   // true if loading is in process, otherwise false.
00122   // This flag is used to avoid updates etc. during loading.
00123   bool isLoading;
00124 
00125   QColor pageBorderColor;
00126 
00127   QPtrList<Plugin> plugins;
00128 
00129   QValueList<Reference> refs;
00130   KCompletion listCompletion;
00131 
00132   int numOperations;
00133 
00134   QValueList<Damage*> damages;
00135 
00136   // document properties
00137   int syntaxVersion;
00138   bool verticalScrollBar:1;
00139   bool horizontalScrollBar:1;
00140   bool columnHeader:1;
00141   bool rowHeader:1;
00142   QColor gridColor;
00143   double indentValue;
00144   bool showStatusBar:1;
00145   bool showTabBar:1;
00146   bool showFormulaBar:1;
00147   bool showError:1;
00148   KGlobalSettings::Completion completionMode;
00149   KSpread::MoveTo moveTo;
00150   MethodOfCalc calcMethod;
00151   bool delayCalculation:1;
00152   KSpellConfig *spellConfig;
00153   bool dontCheckUpperWord:1;
00154   bool dontCheckTitleCase:1;
00155     bool configLoadFromFile:1;
00156   QStringList spellListIgnoreAll;
00158   QPtrList<EmbeddedObject> m_embeddedObjects;
00159   KoPictureCollection m_pictureCollection;
00160   QValueList<KoPictureKey> usedPictures;
00161   bool m_savingWholeDocument;
00162 };
00163 
00164 /*****************************************************************************
00165  *
00166  * Doc
00167  *
00168  *****************************************************************************/
00169 
00170 QValueList<Doc*> Doc::Private::s_docs;
00171 int Doc::Private::s_docId = 0;
00172 
00173 #define deleteLoadingInfo() { \
00174         delete d->m_loadingInfo; \
00175         d->m_loadingInfo = 0L; \
00176 }
00177 
00178 Doc::Doc( QWidget *parentWidget, const char *widgetName, QObject* parent, const char* name, bool singleViewMode )
00179   : KoDocument( parentWidget, widgetName, parent, name, singleViewMode )
00180 {
00181   d = new Private;
00182   d->m_loadingInfo = 0L;
00183 
00184   d->map = new Map( this, "Map" );
00185   d->locale = new Locale;
00186   d->styleManager = new StyleManager();
00187 
00188   d->parser = new ValueParser( d->locale );
00189   d->converter = new ValueConverter ( d->parser );
00190   d->calc = new ValueCalc( d->converter );
00191   d->calc->setDoc (this);
00192   d->formatter = new ValueFormatter( d->converter );
00193 
00194   d->activeSheet = 0;
00195 
00196   d->pageBorderColor = Qt::red;
00197   d->configLoadFromFile = false;
00198 
00199   QFont f( KoGlobal::defaultFont() );
00200   Format::setGlobalRowHeight( f.pointSizeFloat() + 3 );
00201   Format::setGlobalColWidth( ( f.pointSizeFloat() + 3 ) * 5 );
00202 
00203   d->plugins.setAutoDelete( false );
00204 
00205   d->delayCalculation = false;
00206 
00207   documents().append( this );
00208 
00209   setInstance( Factory::global(), false );
00210   setTemplateType( "kspread_template" );
00211 
00212   d->dcop = 0;
00213   d->isLoading = false;
00214   d->numOperations = 1; // don't start repainting before the GUI is done...
00215 
00216   d->undoLocked = 0;
00217   d->commandHistory = new KoCommandHistory( actionCollection() );
00218   connect( d->commandHistory, SIGNAL( commandExecuted() ), SLOT( commandExecuted() ) );
00219   connect( d->commandHistory, SIGNAL( documentRestored() ), SLOT( documentRestored() ) );
00220 
00221 
00222   // Make us scripsheet if the document has a name
00223   // Set a name if there is no name specified
00224   if ( !name )
00225   {
00226       QString tmp( "Document%1" );
00227       tmp = tmp.arg( d->s_docId++ );
00228       setName( tmp.local8Bit());//tmp.latin1() );
00229       dcopObject();
00230   }
00231   else
00232       dcopObject();
00233 
00234   // default document properties
00235   d->syntaxVersion = CURRENT_SYNTAX_VERSION;
00236   d->verticalScrollBar = true;
00237   d->horizontalScrollBar = true;
00238   d->columnHeader = true;
00239   d->rowHeader = true;
00240   d->gridColor = Qt::lightGray;
00241   d->indentValue = 10.0;
00242   d->showStatusBar = true;
00243   d->showFormulaBar = true;
00244   d->showTabBar = true;
00245   d->showError = false;
00246   d->calcMethod = SumOfNumber;
00247   d->moveTo = Bottom;
00248   d->completionMode = KGlobalSettings::CompletionAuto;
00249   d->spellConfig = 0;
00250   d->dontCheckUpperWord = false;
00251   d->dontCheckTitleCase = false;
00252 }
00253 
00254 Doc::~Doc()
00255 {
00256   //don't save config when kword is embedded into konqueror
00257   if(isReadWrite())
00258     saveConfig();
00259 
00260   delete d->dcop;
00261   d->s_docs.remove( this );
00262 
00263   kdDebug(36001) << "alive 1" << endl;
00264 
00265   delete d->commandHistory;
00266 
00267   delete d->spellConfig;
00268 
00269   delete d->locale;
00270   delete d->map;
00271   delete d->styleManager;
00272   delete d->parser;
00273   delete d->formatter;
00274   delete d->converter;
00275   delete d->calc;
00276 
00277   delete d;
00278 }
00279 
00280 QValueList<Doc*> Doc::documents()
00281 {
00282   return Private::s_docs;
00283 }
00284 
00285 bool Doc::initDoc(InitDocFlags flags, QWidget* parentWidget)
00286 {
00287   //  ElapsedTime et( "      initDoc        " );
00288 
00289     QString f;
00290 
00291     if (flags==KoDocument::InitDocEmpty)
00292     {
00293         KConfig *config = Factory::global()->config();
00294         int _page=1;
00295         if( config->hasGroup("Parameters" ))
00296         {
00297                 config->setGroup( "Parameters" );
00298                 _page=config->readNumEntry( "NbPage",1 ) ;
00299         }
00300 
00301         for( int i=0; i<_page; i++ )
00302           map()->addNewSheet();
00303 
00304         resetURL();
00305         setEmpty();
00306         initConfig();
00307         styleManager()->createBuiltinStyles();
00308 
00309         return true;
00310     }
00311 
00312     KoTemplateChooseDia::ReturnType ret;
00313     KoTemplateChooseDia::DialogType dlgtype;
00314     if (flags != KoDocument::InitDocFileNew )
00315             dlgtype = KoTemplateChooseDia::Everything;
00316     else
00317             dlgtype = KoTemplateChooseDia::OnlyTemplates;
00318 
00319     ret = KoTemplateChooseDia::choose( Factory::global(), f,
00320                                        dlgtype, "kspread_template", parentWidget );
00321 
00322     if ( ret == KoTemplateChooseDia::File )
00323     {
00324   KURL url( f );
00325 
00326   bool ok=openURL(url);
00327 
00328   while (KoDocument::isLoading())
00329     kapp->processEvents();
00330 
00331   return ok;
00332 
00333 
00334     }
00335 
00336     if ( ret == KoTemplateChooseDia::Empty )
00337     {
00338   KConfig *config = Factory::global()->config();
00339   int _page=1;
00340   if( config->hasGroup("Parameters" ))
00341   {
00342     config->setGroup( "Parameters" );
00343     _page=config->readNumEntry( "NbPage",1 ) ;
00344   }
00345 
00346   for( int i=0; i<_page; i++ )
00347     map()->addNewSheet ();
00348 
00349   resetURL();
00350   setEmpty();
00351   initConfig();
00352         styleManager()->createBuiltinStyles();
00353   return true;
00354     }
00355 
00356     if ( ret == KoTemplateChooseDia::Template )
00357     {
00358         resetURL();
00359         d->m_loadingInfo = new KSPLoadingInfo;
00360         d->m_loadingInfo->setLoadTemplate( true );
00361         bool ok = loadNativeFormat( f );
00362         deleteLoadingInfo();
00363         if ( !ok )
00364             showLoadingErrorDialog();
00365         setEmpty();
00366         initConfig();
00367         return ok;
00368     }
00369 
00370     return false;
00371 }
00372 
00373 void Doc::openTemplate (const QString& file)
00374 {
00375     d->m_loadingInfo = new KSPLoadingInfo;
00376     d->m_loadingInfo->setLoadTemplate( true );
00377     KoDocument::openTemplate( file );
00378     deleteLoadingInfo();
00379     initConfig();
00380 }
00381 
00382 void Doc::initEmpty()
00383 {
00384     KConfig *config = Factory::global()->config();
00385     int _page=1;
00386     if( config->hasGroup("Parameters" ))
00387     {
00388         config->setGroup( "Parameters" );
00389         _page=config->readNumEntry( "NbPage",1 ) ;
00390     }
00391 
00392     for( int i=0; i<_page; i++ )
00393         map()->addNewSheet();
00394 
00395     resetURL();
00396     initConfig();
00397     styleManager()->createBuiltinStyles();
00398 
00399     KoDocument::initEmpty();
00400 }
00401 
00402 KLocale *Doc::locale () const
00403 {
00404   return d->locale;
00405 }
00406 
00407 Map *Doc::map () const
00408 {
00409   return d->map;
00410 }
00411 
00412 StyleManager *Doc::styleManager () const
00413 {
00414   return d->styleManager;
00415 }
00416 
00417 ValueParser *Doc::parser () const
00418 {
00419   return d->parser;
00420 }
00421 
00422 ValueFormatter *Doc::formatter () const
00423 {
00424   return d->formatter;
00425 }
00426 
00427 ValueConverter *Doc::converter () const
00428 {
00429   return d->converter;
00430 }
00431 
00432 ValueCalc *Doc::calc () const
00433 {
00434   return d->calc;
00435 }
00436 
00437 void Doc::saveConfig()
00438 {
00439     if ( isEmbedded() ||!isReadWrite())
00440         return;
00441     KConfig *config = Factory::global()->config();
00442     config->setGroup( "Parameters" );
00443     config->writeEntry( "Zoom", m_zoom );
00444 
00445 }
00446 
00447 void Doc::initConfig()
00448 {
00449     KConfig *config = Factory::global()->config();
00450 
00451     if( config->hasGroup("KSpread Page Layout" ))
00452     {
00453       config->setGroup( "KSpread Page Layout" );
00454       setUnit( (KoUnit::Unit)config->readNumEntry( "Default unit page" ,0));
00455     }
00456     if( config->hasGroup("Parameters" ))
00457     {
00458         config->setGroup( "Parameters" );
00459         m_zoom = config->readNumEntry( "Zoom", 100 );
00460     }
00461     else
00462       m_zoom = 100;
00463 
00464     int undo=30;
00465     if(config->hasGroup("Misc" ) )
00466     {
00467         config->setGroup( "Misc" );
00468         undo=config->readNumEntry("UndoRedo",-1);
00469     }
00470     if(undo!=-1)
00471         setUndoRedoLimit(undo);
00472 
00473     setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
00474 }
00475 
00476 int Doc::syntaxVersion() const
00477 {
00478   return d->syntaxVersion;
00479 }
00480 
00481 bool Doc::isLoading() const
00482 {
00483   return d->isLoading;
00484 }
00485 
00486 QColor Doc::pageBorderColor() const
00487 {
00488   return d->pageBorderColor;
00489 }
00490 
00491 void Doc::changePageBorderColor( const QColor  & _color)
00492 {
00493   d->pageBorderColor = _color;
00494 }
00495 
00496 const QValueList<Reference>  &Doc::listArea()
00497 {
00498   return d->refs;
00499 }
00500 
00501 KCompletion& Doc::completion()
00502 {
00503   return d->listCompletion;
00504 }
00505 
00506 KoView* Doc::createViewInstance( QWidget* parent, const char* name )
00507 {
00508     if ( name == 0 )
00509         name = "View";
00510     return new View( parent, name, this );
00511 }
00512 
00513 bool Doc::saveChildren( KoStore* _store )
00514 {
00515   return map()->saveChildren( _store );
00516 }
00517 
00518 int Doc::supportedSpecialFormats() const
00519 {
00520     return KoDocument::supportedSpecialFormats();
00521 }
00522 
00523 bool Doc::completeSaving( KoStore* _store )
00524 {
00525     d->m_pictureCollection.saveToStore( KoPictureCollection::CollectionPicture, _store, d->usedPictures );
00526 
00527     return true;
00528 }
00529 
00530 
00531 QDomDocument Doc::saveXML()
00532 {
00533     //Terminate current cell edition, if any
00534     QPtrListIterator<KoView> it( views() );
00535 
00536     /* don't pull focus away from the editor if this is just a background
00537        autosave */
00538     if (!isAutosaving())
00539     {
00540         for (; it.current(); ++it )
00541             static_cast<View *>( it.current() )->deleteEditor( true );
00542     }
00543 
00544     QDomDocument doc = createDomDocument( "spreadsheet", CURRENT_DTD_VERSION );
00545     QDomElement spread = doc.documentElement();
00546     spread.setAttribute( "editor", "KSpread" );
00547     spread.setAttribute( "mime", "application/x-kspread" );
00548     spread.setAttribute( "syntaxVersion", CURRENT_SYNTAX_VERSION );
00549 
00550     QDomElement dlocale = ((Locale *)locale())->save( doc );
00551     spread.appendChild( dlocale );
00552 
00553     if (d->refs.count() != 0 )
00554     {
00555         QDomElement areaname = saveAreaName( doc );
00556         spread.appendChild( areaname );
00557     }
00558 
00559     if( !d->spellListIgnoreAll.isEmpty() )
00560     {
00561         QDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" );
00562         spread.appendChild( spellCheckIgnore );
00563         for ( QStringList::Iterator it = d->spellListIgnoreAll.begin(); it != d->spellListIgnoreAll.end(); ++it )
00564         {
00565             QDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" );
00566             spellCheckIgnore.appendChild( spellElem );
00567             spellElem.setAttribute( "word", *it );
00568         }
00569     }
00570 
00571     SavedDocParts::const_iterator iter = m_savedDocParts.begin();
00572     SavedDocParts::const_iterator end  = m_savedDocParts.end();
00573     while ( iter != end )
00574     {
00575       // save data we loaded in the beginning and which has no owner back to file
00576       spread.appendChild( iter.data() );
00577       ++iter;
00578     }
00579 
00580     QDomElement defaults = doc.createElement( "defaults" );
00581     defaults.setAttribute( "row-height", Format::globalRowHeight() );
00582     defaults.setAttribute( "col-width", Format::globalColWidth() );
00583     spread.appendChild( defaults );
00584 
00585     Plugin * plugin = d->plugins.first();
00586     for ( ; plugin != 0; plugin = d->plugins.next() )
00587     {
00588       QDomElement data( plugin->saveXML( doc ) );
00589       if ( !data.isNull() )
00590         spread.appendChild( data );
00591     }
00592 
00593     QDomElement s = styleManager()->save( doc );
00594     spread.appendChild( s );
00595     QDomElement e = map()->save( doc );
00596     spread.appendChild( e );
00597 
00598     setModified( false );
00599 
00600     return doc;
00601 }
00602 
00603 bool Doc::loadChildren( KoStore* _store )
00604 {
00605     return map()->loadChildren( _store );
00606 }
00607 
00608 bool Doc::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
00609 {
00610   emitBeginOperation(true);
00611     bool result=saveOasisHelper( store, manifestWriter, SaveAll );
00612   emitEndOperation();
00613 
00614   return result;
00615 }
00616 
00617 bool Doc::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag,
00618                             QString* /*plainText*/, KoPicture* /*picture*/ )
00619 {
00620     d->m_pictureCollection.assignUniqueIds();
00621     //Terminate current cell edition, if any
00622     QPtrListIterator<KoView> it2( views() );
00623     d->m_savingWholeDocument = saveFlag == SaveAll ? true : false;
00624 
00625     /* don't pull focus away from the editor if this is just a background
00626        autosave */
00627     if (!isAutosaving())
00628     {
00629         for (; it2.current(); ++it2 )
00630             static_cast<View *>( it2.current() )->deleteEditor( true );
00631     }
00632     if ( !store->open( "content.xml" ) )
00633         return false;
00634 
00635     KoStoreDevice dev( store );
00636     KoXmlWriter* contentWriter = createOasisXmlWriter( &dev, "office:document-content" );
00637     KoGenStyles mainStyles;//for compile
00638 
00639     KTempFile contentTmpFile;
00640     //Check that temp file was successfully created
00641     if (contentTmpFile.status() != 0)
00642     {
00643         qWarning("Creation of temporary file to store document content failed.");
00644         return false;
00645     }
00646 
00647     contentTmpFile.setAutoDelete( true );
00648     QFile* tmpFile = contentTmpFile.file();
00649     KoXmlWriter contentTmpWriter( tmpFile, 1 );
00650 
00651 
00652 
00653     //todo fixme just add a element for testing saving content.xml
00654     contentTmpWriter.startElement( "office:body" );
00655     contentTmpWriter.startElement( "office:spreadsheet" );
00656 
00657     int indexObj = 1;
00658     int partIndexObj = 0;
00659 
00660     styleManager()->saveOasis( mainStyles );
00661     map()->saveOasis( contentTmpWriter, mainStyles, store,  manifestWriter, indexObj, partIndexObj );
00662 
00663     saveOasisAreaName( contentTmpWriter );
00664     contentTmpWriter.endElement(); 
00665   contentTmpWriter.endElement(); 
00666 
00667     // Done with writing out the contents to the tempfile, we can now write out the automatic styles
00668     contentWriter->startElement( "office:automatic-styles" );
00669 
00670     QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
00671     QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
00672     for ( ; it != styles.end() ; ++it ) {
00673         (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
00674     }
00675 
00676     styles = mainStyles.styles( STYLE_PAGE );
00677     it = styles.begin();
00678     for ( ; it != styles.end() ; ++it ) {
00679         (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-properties" );
00680     }
00681 
00682     styles = mainStyles.styles( STYLE_COLUMN );
00683     it = styles.begin();
00684     for ( ; it != styles.end() ; ++it ) {
00685         (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" );
00686     }
00687 
00688     styles = mainStyles.styles( STYLE_ROW );
00689     it = styles.begin();
00690     for ( ; it != styles.end() ; ++it ) {
00691         (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" );
00692     }
00693 
00694     styles = mainStyles.styles( STYLE_CELL_AUTO );
00695     it = styles.begin();
00696     for ( ; it != styles.end() ; ++it ) {
00697         (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" );
00698     }
00699 
00700     //TODO FIXME !!!!
00701     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE );
00702     it = styles.begin();
00703     for ( ; it != styles.end() ; ++it ) {
00704         (*it).style->writeStyle( contentWriter, mainStyles, "number:date-style", (*it).name, 0 /*TODO ????*/  );
00705     }
00706 
00707     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_TIME );
00708     it = styles.begin();
00709     for ( ; it != styles.end() ; ++it ) {
00710         (*it).style->writeStyle( contentWriter, mainStyles, "number:time-style", (*it).name, 0 /*TODO ????*/  );
00711     }
00712 
00713     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_FRACTION );
00714     it = styles.begin();
00715     for ( ; it != styles.end() ; ++it ) {
00716         (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/  );
00717     }
00718 
00719     //TODO FIME !!!!!
00720     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_PERCENTAGE );
00721     it = styles.begin();
00722     for ( ; it != styles.end() ; ++it ) {
00723         (*it).style->writeStyle( contentWriter, mainStyles, "number:percentage-style", (*it).name, 0 /*TODO ????*/  );
00724     }
00725 
00726     //TODO FIME !!!!!
00727     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_CURRENCY );
00728     it = styles.begin();
00729     for ( ; it != styles.end() ; ++it ) {
00730         (*it).style->writeStyle( contentWriter, mainStyles, "number:currency-style", (*it).name, 0 /*TODO ????*/  );
00731     }
00732 
00733     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_SCIENTIFIC );
00734     it = styles.begin();
00735     for ( ; it != styles.end() ; ++it ) {
00736         (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/  );
00737     }
00738 
00739 
00740     contentWriter->endElement(); // office:automatic-styles
00741 
00742 
00743    // And now we can copy over the contents from the tempfile to the real one
00744     tmpFile->close();
00745     contentWriter->addCompleteElement( tmpFile );
00746     contentTmpFile.close();
00747 
00748 
00749     contentWriter->endElement(); // root element
00750     contentWriter->endDocument();
00751     delete contentWriter;
00752     if ( !store->close() )
00753         return false;
00754     //add manifest line for content.xml
00755     manifestWriter->addManifestEntry( "content.xml",  "text/xml" );
00756 
00757     //todo add manifest line for style.xml
00758     if ( !store->open( "styles.xml" ) )
00759         return false;
00760 
00761     manifestWriter->addManifestEntry( "styles.xml",  "text/xml" );
00762     saveOasisDocumentStyles( store, mainStyles );
00763 
00764     if ( !store->close() ) // done with styles.xml
00765         return false;
00766 
00767     makeUsedPixmapList();
00768     d->m_pictureCollection.saveOasisToStore( store, d->usedPictures, manifestWriter);
00769 
00770     if(!store->open("settings.xml"))
00771         return false;
00772 
00773     KoXmlWriter* settingsWriter = createOasisXmlWriter(&dev, "office:document-settings");
00774     settingsWriter->startElement("office:settings");
00775     settingsWriter->startElement("config:config-item-set");
00776     settingsWriter->addAttribute("config:name", "view-settings");
00777 
00778     KoUnit::saveOasis(settingsWriter, unit());
00779 
00780     saveOasisSettings( *settingsWriter );
00781 
00782     settingsWriter->endElement(); // config:config-item-set
00783 
00784     settingsWriter->startElement("config:config-item-set");
00785     settingsWriter->addAttribute("config:name", "configuration-settings");
00786     settingsWriter->addConfigItem("SpellCheckerIgnoreList", d->spellListIgnoreAll.join( "," ) );
00787     settingsWriter->endElement(); // config:config-item-set
00788     settingsWriter->endElement(); // office:settings
00789     settingsWriter->endElement(); // Root:element
00790     settingsWriter->endDocument();
00791     delete settingsWriter;
00792 
00793     if(!store->close())
00794         return false;
00795 
00796     manifestWriter->addManifestEntry("settings.xml", "text/xml");
00797 
00798 
00799     if ( saveFlag == SaveSelected )
00800     {
00801       QPtrListIterator<EmbeddedObject> it(embeddedObjects() );
00802       for( ; it.current(); ++it )
00803       {
00804         if ( it.current()->getType() != OBJECT_CHART  && it.current()->getType() != OBJECT_KOFFICE_PART )
00805           continue;
00806         KoDocumentChild *embedded = dynamic_cast<EmbeddedKOfficeObject *>(it.current() )->embeddedObject();
00807             //NOTE: If an application's .desktop file lies about opendocument support (ie. it indicates that it has
00808             //a native OASIS mime type, when it doesn't, this causes a crash when trying to reload and paint
00809             //the object, since it won't have an associated document.
00810           if ( !embedded->saveOasis( store, manifestWriter ) )
00811             continue;
00812       }
00813     }
00814 
00815 
00816     setModified( false );
00817 
00818     return true;
00819 }
00820 
00821 void Doc::loadOasisSettings( const QDomDocument&settingsDoc )
00822 {
00823     KoOasisSettings settings( settingsDoc );
00824     KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
00825     if ( !viewSettings.isNull() )
00826     {
00827         setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit")));
00828     }
00829     map()->loadOasisSettings( settings );
00830     loadOasisIgnoreList( settings );
00831 }
00832 
00833 void Doc::saveOasisSettings( KoXmlWriter &settingsWriter )
00834 {
00835     settingsWriter.startElement("config:config-item-map-indexed");
00836     settingsWriter.addAttribute("config:name", "Views");
00837     settingsWriter.startElement( "config:config-item-map-entry" );
00838     map()->saveOasisSettings( settingsWriter );
00839     settingsWriter.endElement();
00840     settingsWriter.endElement();
00841 }
00842 
00843 
00844 void Doc::loadOasisIgnoreList( const KoOasisSettings& settings )
00845 {
00846     KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" );
00847     if ( !configurationSettings.isNull() )
00848     {
00849         const QString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" );
00850         //kdDebug()<<" ignorelist :"<<ignorelist<<endl;
00851         d->spellListIgnoreAll = QStringList::split( ',', ignorelist );
00852     }
00853 }
00854 
00855 
00856 void Doc::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles ) const
00857 {
00858     KoStoreDevice stylesDev( store );
00859     KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" );
00860 
00861     stylesWriter->startElement( "office:styles" );
00862     QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_USER );
00863     QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
00864     for ( ; it != styles.end() ; ++it ) {
00865         (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
00866     }
00867 
00868     styles = mainStyles.styles( Doc::STYLE_CELL_USER );
00869     it = styles.begin();
00870     for ( ; it != styles.end() ; ++it ) {
00871         if ( (*it).style->isDefaultStyle() ) {
00872           (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-cell-properties" );
00873         }
00874         else {
00875           (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" );
00876         }
00877     }
00878 
00879     styles = mainStyles.styles( KoGenStyle::STYLE_HATCH );
00880     it = styles.begin();
00881     for ( ; it != styles.end() ; ++it ) {
00882         (*it).style->writeStyle( stylesWriter, mainStyles, "draw:hatch", (*it).name, "style:graphic-properties" ,  true,  true /*add draw:name*/);
00883     }
00884     styles = mainStyles.styles( KoGenStyle::STYLE_GRAPHICAUTO );
00885     it = styles.begin();
00886     for ( ; it != styles.end() ; ++it ) {
00887         (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties"  );
00888     }
00889 
00890     stylesWriter->endElement(); // office:styles
00891 
00892     stylesWriter->startElement( "office:automatic-styles" );
00893     styles = mainStyles.styles( KoGenStyle::STYLE_PAGELAYOUT );
00894     it = styles.begin();
00895     for ( ; it != styles.end() ; ++it ) {
00896         (*it).style->writeStyle( stylesWriter, mainStyles, "style:page-layout", (*it).name, "style:page-layout-properties", false /*don't close*/ );
00897         stylesWriter->endElement();
00898     }
00899 
00900     stylesWriter->endElement(); // office:automatic-styles
00901     //code from kword
00902     stylesWriter->startElement( "office:master-styles" );
00903 
00904     styles = mainStyles.styles( Doc::STYLE_PAGEMASTER );
00905     it = styles.begin();
00906     for ( ; it != styles.end() ; ++it ) {
00907         (*it).style->writeStyle( stylesWriter, mainStyles, "style:master-page", (*it).name, "" );
00908     }
00909 
00910     stylesWriter->endElement(); // office:master-style
00911 
00912 
00913     stylesWriter->endElement(); // root element (office:document-styles)
00914     stylesWriter->endDocument();
00915     delete stylesWriter;;
00916 }
00917 
00918 bool Doc::loadOasis( const QDomDocument& doc, KoOasisStyles& oasisStyles, const QDomDocument& settings, KoStore* store)
00919 {
00920     if ( !d->m_loadingInfo )
00921         d->m_loadingInfo = new KSPLoadingInfo;
00922 
00923     QTime dt;
00924     dt.start();
00925 
00926     emit sigProgress( 0 );
00927     d->isLoading = true;
00928     d->spellListIgnoreAll.clear();
00929 
00930     d->refs.clear();
00931 
00932     QDomElement content = doc.documentElement();
00933     QDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
00934     if ( realBody.isNull() )
00935     {
00936         setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ));
00937         deleteLoadingInfo();
00938         return false;
00939     }
00940     QDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "spreadsheet" );
00941 
00942     if ( body.isNull() )
00943     {
00944         kdError(32001) << "No office:spreadsheet found!" << endl;
00945         QDomElement childElem;
00946         QString localName;
00947         forEachElement( childElem, realBody ) {
00948             localName = childElem.localName();
00949         }
00950         if ( localName.isEmpty() )
00951             setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
00952         else
00953             setErrorMessage( i18n( "This document is not a spreadsheet, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
00954         deleteLoadingInfo();
00955         return false;
00956     }
00957 
00958     KoOasisLoadingContext context( this, oasisStyles, store );
00959 
00960     //load in first
00961     styleManager()->loadOasisStyleTemplate( oasisStyles );
00962 
00963     // TODO check versions and mimetypes etc.
00964     loadOasisAreaName( body );
00965     loadOasisCellValidation( body );
00966 
00967     //pre-load auto styles
00968     QDictIterator<QDomElement> it( oasisStyles.styles("table-cell") );
00969     QDict<Style> styleElements;
00970     for (;it.current();++it)
00971     {
00972     if ( it.current()->hasAttributeNS( KoXmlNS::style , "name" ) )
00973     {
00974         QString name = it.current()->attributeNS( KoXmlNS::style , "name" , QString::null );
00975         kdDebug() << "Preloading style: " << name << endl;
00976         styleElements.insert( name , new Style());
00977         styleElements[name]->loadOasisStyle( oasisStyles , *(it.current()) );
00978     }
00979     }
00980 
00981     // all <sheet:sheet> goes to workbook
00982     if ( !map()->loadOasis( body, context, styleElements ) )
00983     {
00984         d->isLoading = false;
00985         deleteLoadingInfo();
00986         return false;
00987     }
00988 
00989 
00990     if ( !settings.isNull() )
00991     {
00992         loadOasisSettings( settings );
00993     }
00994     emit sigProgress( 90 );
00995     initConfig();
00996     emit sigProgress(-1);
00997 
00998     //delete any styles which were not used
00999     QDictIterator<Style> styleIt( styleElements );
01000     for (;styleIt.current();++styleIt)
01001     {
01002     Style* style = styleIt.current();
01003     if (style->release())
01004         delete style;
01005     }
01006 
01007 
01008     //display loading time
01009     kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl;
01010     deleteLoadingInfo();
01011     return true;
01012 }
01013 
01014 bool Doc::loadXML( QIODevice *, const QDomDocument& doc )
01015 {
01016   QTime dt;
01017   dt.start();
01018 
01019   emit sigProgress( 0 );
01020   d->isLoading = true;
01021   d->spellListIgnoreAll.clear();
01022   // <spreadsheet>
01023   QDomElement spread = doc.documentElement();
01024 
01025   if ( spread.attribute( "mime" ) != "application/x-kspread" && spread.attribute( "mime" ) != "application/vnd.kde.kspread" )
01026   {
01027     d->isLoading = false;
01028     setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kspread or application/vnd.kde.kspread, got %1" ).arg( spread.attribute("mime") ) );
01029     return false;
01030   }
01031 
01032   d->syntaxVersion = Doc::getAttribute( spread, "syntaxVersion", 0 );
01033   if ( d->syntaxVersion > CURRENT_SYNTAX_VERSION )
01034   {
01035       int ret = KMessageBox::warningContinueCancel(
01036           0, i18n("This document was created with a newer version of KSpread (syntax version: %1)\n"
01037                   "When you open it with this version of KSpread, some information may be lost.").arg(d->syntaxVersion),
01038           i18n("File Format Mismatch"), KStdGuiItem::cont() );
01039       if ( ret == KMessageBox::Cancel )
01040       {
01041           setErrorMessage( "USER_CANCELED" );
01042           return false;
01043       }
01044   }
01045 
01046   // <locale>
01047   QDomElement loc = spread.namedItem( "locale" ).toElement();
01048   if ( !loc.isNull() )
01049       ((Locale *) locale())->load( loc );
01050 
01051   emit sigProgress( 5 );
01052 
01053   QDomElement defaults = spread.namedItem( "defaults" ).toElement();
01054   if ( !defaults.isNull() )
01055   {
01056     bool ok = false;
01057     double d = defaults.attribute( "row-height" ).toDouble( &ok );
01058     if ( !ok )
01059       return false;
01060     Format::setGlobalRowHeight( d );
01061 
01062     d = defaults.attribute( "col-width" ).toDouble( &ok );
01063 
01064     if ( !ok )
01065       return false;
01066 
01067     Format::setGlobalColWidth( d );
01068   }
01069 
01070   d->refs.clear();
01071   //<areaname >
01072   QDomElement areaname = spread.namedItem( "areaname" ).toElement();
01073   if ( !areaname.isNull())
01074     loadAreaName(areaname);
01075 
01076   QDomElement ignoreAll = spread.namedItem( "SPELLCHECKIGNORELIST").toElement();
01077   if ( !ignoreAll.isNull())
01078   {
01079       QDomElement spellWord=spread.namedItem("SPELLCHECKIGNORELIST").toElement();
01080 
01081       spellWord=spellWord.firstChild().toElement();
01082       while ( !spellWord.isNull() )
01083       {
01084           if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" )
01085           {
01086               d->spellListIgnoreAll.append(spellWord.attribute("word"));
01087           }
01088           spellWord=spellWord.nextSibling().toElement();
01089       }
01090   }
01091 
01092   emit sigProgress( 40 );
01093   // In case of reload (e.g. from konqueror)
01094   map()->sheetList().clear(); // it's set to autoDelete
01095 
01096   QDomElement styles = spread.namedItem( "styles" ).toElement();
01097   if ( !styles.isNull() )
01098   {
01099     if ( !styleManager()->loadXML( styles ) )
01100     {
01101       setErrorMessage( i18n( "Styles cannot be loaded." ) );
01102       d->isLoading = false;
01103       return false;
01104     }
01105   }
01106 
01107   // <map>
01108   QDomElement mymap = spread.namedItem( "map" ).toElement();
01109   if ( mymap.isNull() )
01110   {
01111       setErrorMessage( i18n("Invalid document. No map tag.") );
01112       d->isLoading = false;
01113       return false;
01114   }
01115   if ( !map()->loadXML( mymap ) )
01116   {
01117       d->isLoading = false;
01118       return false;
01119   }
01120 
01121   //Backwards compatibility with older versions for paper layout
01122   if ( d->syntaxVersion < 1 )
01123   {
01124     QDomElement paper = spread.namedItem( "paper" ).toElement();
01125     if ( !paper.isNull() )
01126     {
01127       loadPaper( paper );
01128     }
01129   }
01130 
01131   emit sigProgress( 85 );
01132 
01133   QDomElement element( spread.firstChild().toElement() );
01134   while ( !element.isNull() )
01135   {
01136     QString tagName( element.tagName() );
01137 
01138     if ( tagName != "locale" && tagName != "map" && tagName != "styles"
01139          && tagName != "SPELLCHECKIGNORELIST" && tagName != "areaname"
01140          && tagName != "paper" )
01141     {
01142       // belongs to a plugin, load it and save it for later use
01143       m_savedDocParts[ tagName ] = element;
01144     }
01145 
01146     element = element.nextSibling().toElement();
01147   }
01148 
01149   emit sigProgress( 90 );
01150   initConfig();
01151   emit sigProgress(-1);
01152 
01153    kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl;
01154 
01155   emit sig_refreshView();
01156 
01157   return true;
01158 }
01159 
01160 void Doc::loadPaper( QDomElement const & paper )
01161 {
01162   // <paper>
01163   QString format = paper.attribute( "format" );
01164   QString orientation = paper.attribute( "orientation" );
01165 
01166   // <borders>
01167   QDomElement borders = paper.namedItem( "borders" ).toElement();
01168   if ( !borders.isNull() )
01169   {
01170     float left = borders.attribute( "left" ).toFloat();
01171     float right = borders.attribute( "right" ).toFloat();
01172     float top = borders.attribute( "top" ).toFloat();
01173     float bottom = borders.attribute( "bottom" ).toFloat();
01174 
01175     //apply to all sheet
01176     QPtrListIterator<Sheet> it ( map()->sheetList() );
01177     for( ; it.current(); ++it )
01178     {
01179       it.current()->print()->setPaperLayout( left, top, right, bottom,
01180                                              format, orientation );
01181     }
01182   }
01183 
01184   QString hleft, hright, hcenter;
01185   QString fleft, fright, fcenter;
01186   // <head>
01187   QDomElement head = paper.namedItem( "head" ).toElement();
01188   if ( !head.isNull() )
01189   {
01190     QDomElement left = head.namedItem( "left" ).toElement();
01191     if ( !left.isNull() )
01192       hleft = left.text();
01193     QDomElement center = head.namedItem( "center" ).toElement();
01194     if ( !center.isNull() )
01195       hcenter = center.text();
01196     QDomElement right = head.namedItem( "right" ).toElement();
01197     if ( !right.isNull() )
01198       hright = right.text();
01199   }
01200   // <foot>
01201   QDomElement foot = paper.namedItem( "foot" ).toElement();
01202   if ( !foot.isNull() )
01203   {
01204     QDomElement left = foot.namedItem( "left" ).toElement();
01205     if ( !left.isNull() )
01206       fleft = left.text();
01207     QDomElement center = foot.namedItem( "center" ).toElement();
01208     if ( !center.isNull() )
01209       fcenter = center.text();
01210     QDomElement right = foot.namedItem( "right" ).toElement();
01211     if ( !right.isNull() )
01212       fright = right.text();
01213   }
01214   //The macro "<sheet>" formerly was typed as "<table>"
01215   hleft   = hleft.replace(   "<table>", "<sheet>" );
01216   hcenter = hcenter.replace( "<table>", "<sheet>" );
01217   hright  = hright.replace(  "<table>", "<sheet>" );
01218   fleft   = fleft.replace(   "<table>", "<sheet>" );
01219   fcenter = fcenter.replace( "<table>", "<sheet>" );
01220   fright  = fright.replace(  "<table>", "<sheet>" );
01221 
01222   QPtrListIterator<Sheet> it ( map()->sheetList() );
01223   for( ; it.current(); ++it )
01224   {
01225     it.current()->print()->setHeadFootLine( hleft, hcenter, hright,
01226                                             fleft, fcenter, fright);
01227   }
01228 }
01229 
01230 bool Doc::completeLoading( KoStore* /* _store */ )
01231 {
01232   kdDebug(36001) << "------------------------ COMPLETING --------------------" << endl;
01233 
01234   d->isLoading = false;
01235 
01236   //  map()->update();
01237 
01238   QPtrListIterator<KoView> it( views() );
01239   for (; it.current(); ++it )
01240     ((View*)it.current())->initialPosition();
01241 
01242   kdDebug(36001) << "------------------------ COMPLETION DONE --------------------" << endl;
01243 
01244   setModified( false );
01245   return true;
01246 }
01247 
01248 
01249 void Doc::registerPlugin( Plugin * plugin )
01250 {
01251   d->plugins.append( plugin );
01252 }
01253 
01254 void Doc::deregisterPlugin( Plugin * plugin )
01255 {
01256   d->plugins.remove( plugin );
01257 }
01258 
01259 bool Doc::docData( QString const & xmlTag, QDomElement & data )
01260 {
01261   SavedDocParts::iterator iter = m_savedDocParts.find( xmlTag );
01262   if ( iter == m_savedDocParts.end() )
01263     return false;
01264 
01265   data = iter.data();
01266   m_savedDocParts.erase( iter );
01267 
01268   return true;
01269 }
01270 
01271 void Doc::setShowVerticalScrollBar(bool _show)
01272 {
01273   d->verticalScrollBar=_show;
01274 }
01275 
01276 bool Doc::showVerticalScrollBar()const
01277 {
01278   return  d->verticalScrollBar;
01279 }
01280 
01281 void Doc::setShowHorizontalScrollBar(bool _show)
01282 {
01283   d->horizontalScrollBar=_show;
01284 }
01285 
01286 bool Doc::showHorizontalScrollBar()const
01287 {
01288   return  d->horizontalScrollBar;
01289 }
01290 
01291 KGlobalSettings::Completion Doc::completionMode( ) const
01292 {
01293   return d->completionMode;
01294 }
01295 
01296 void Doc::setShowColumnHeader(bool _show)
01297 {
01298   d->columnHeader=_show;
01299 }
01300 
01301 bool Doc::showColumnHeader() const
01302 {
01303   return  d->columnHeader;
01304 }
01305 
01306 void Doc::setShowRowHeader(bool _show)
01307 {
01308   d->rowHeader=_show;
01309 }
01310 
01311 bool Doc::showRowHeader() const
01312 {
01313   return  d->rowHeader;
01314 }
01315 
01316 void Doc::setGridColor( const QColor& color )
01317 {
01318   d->gridColor = color;
01319 }
01320 
01321 QColor Doc::gridColor() const
01322 {
01323   return d->gridColor;
01324 }
01325 
01326 void Doc::setCompletionMode( KGlobalSettings::Completion complMode)
01327 {
01328   d->completionMode= complMode;
01329 }
01330 
01331 double Doc::indentValue() const
01332 {
01333   return d->indentValue;
01334 }
01335 
01336 void Doc::setIndentValue( double val )
01337 {
01338   d->indentValue = val;
01339 }
01340 
01341 void Doc::setShowStatusBar(bool _statusBar)
01342 {
01343   d->showStatusBar=_statusBar;
01344 }
01345 
01346 bool Doc::showStatusBar() const
01347 {
01348   return  d->showStatusBar;
01349 }
01350 
01351 void Doc::setShowTabBar(bool _tabbar)
01352 {
01353   d->showTabBar=_tabbar;
01354 }
01355 
01356 bool Doc::showTabBar()const
01357 {
01358   return  d->showTabBar;
01359 }
01360 
01361 void Doc::setShowFormulaBar(bool _formulaBar)
01362 {
01363   d->showFormulaBar=_formulaBar;
01364 }
01365 
01366 bool Doc::showFormulaBar() const
01367 {
01368   return  d->showFormulaBar;
01369 }
01370 
01371 void Doc::setShowMessageError(bool _show)
01372 {
01373   d->showError=_show;
01374 }
01375 
01376 bool Doc::showMessageError() const
01377 {
01378   return  d->showError;
01379 }
01380 
01381 KSpread::MoveTo Doc::getMoveToValue() const
01382 {
01383   return d->moveTo;
01384 }
01385 
01386 void Doc::setMoveToValue(KSpread::MoveTo _moveTo)
01387 {
01388   d->moveTo = _moveTo;
01389 }
01390 
01391 void Doc::setTypeOfCalc( MethodOfCalc _calc)
01392 {
01393   d->calcMethod=_calc;
01394 }
01395 
01396 MethodOfCalc Doc::getTypeOfCalc() const
01397 {
01398   return d->calcMethod;
01399 }
01400 
01401 void Doc::setKSpellConfig(KSpellConfig _kspell)
01402 {
01403   if (d->spellConfig == 0 )
01404     d->spellConfig = new KSpellConfig();
01405 
01406   d->spellConfig->setNoRootAffix(_kspell.noRootAffix ());
01407   d->spellConfig->setRunTogether(_kspell.runTogether ());
01408   d->spellConfig->setDictionary(_kspell.dictionary ());
01409   d->spellConfig->setDictFromList(_kspell.dictFromList());
01410   d->spellConfig->setEncoding(_kspell.encoding());
01411   d->spellConfig->setClient(_kspell.client());
01412 }
01413 
01414 KSpellConfig * Doc::getKSpellConfig()
01415 {
01416     if (!d->spellConfig)
01417     {
01418         KSpellConfig ksconfig;
01419 
01420         KConfig *config = Factory::global()->config();
01421         if( config->hasGroup("KSpell kspread" ) )
01422         {
01423             config->setGroup( "KSpell kspread" );
01424             ksconfig.setNoRootAffix(config->readNumEntry ("KSpell_NoRootAffix", 0));
01425             ksconfig.setRunTogether(config->readNumEntry ("KSpell_RunTogether", 0));
01426             ksconfig.setDictionary(config->readEntry ("KSpell_Dictionary", ""));
01427             ksconfig.setDictFromList(config->readNumEntry ("KSpell_DictFromList", false));
01428             ksconfig.setEncoding(config->readNumEntry ("KSpell_Encoding", KS_E_ASCII));
01429             ksconfig.setClient(config->readNumEntry ("KSpell_Client", KS_CLIENT_ISPELL));
01430             setKSpellConfig(ksconfig);
01431 
01432             setDontCheckUpperWord(config->readBoolEntry("KSpell_IgnoreUppercaseWords", false));
01433             setDontCheckTitleCase(config->readBoolEntry("KSpell_IgnoreTitleCaseWords", false));
01434         }
01435     }
01436   return d->spellConfig;
01437 }
01438 
01439 bool Doc::dontCheckUpperWord() const
01440 {
01441   return d->dontCheckUpperWord;
01442 }
01443 
01444 void Doc::setDontCheckUpperWord( bool b )
01445 {
01446   d->dontCheckUpperWord = b;
01447 }
01448 
01449 bool Doc::dontCheckTitleCase() const
01450 {
01451   return  d->dontCheckTitleCase;
01452 }
01453 
01454 void Doc::setDontCheckTitleCase( bool b )
01455 {
01456   d->dontCheckTitleCase = b;
01457 }
01458 
01459 QString Doc::unitName() const
01460 {
01461   return KoUnit::unitName( unit() );
01462 }
01463 
01464 void Doc::increaseNumOperation()
01465 {
01466   ++d->numOperations;
01467 }
01468 
01469 void Doc::decreaseNumOperation()
01470 {
01471   --d->numOperations;
01472 }
01473 
01474 void Doc::addIgnoreWordAllList( const QStringList & _lst)
01475 {
01476   d->spellListIgnoreAll = _lst;
01477 }
01478 
01479 QStringList Doc::spellListIgnoreAll() const
01480 {
01481   return d->spellListIgnoreAll;
01482 }
01483 
01484 void Doc::setZoomAndResolution( int zoom, int dpiX, int dpiY )
01485 {
01486     KoZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY );
01487 }
01488 
01489 void Doc::newZoomAndResolution( bool updateViews, bool /*forPrint*/ )
01490 {
01491 /*    layout();
01492     updateAllFrames();*/
01493     if ( updateViews )
01494     {
01495         emit sig_refreshView();
01496     }
01497 }
01498 
01499 void Doc::addCommand( KCommand* command )
01500 {
01501   if (undoLocked()) return;
01502   d->commandHistory->addCommand( command, false );
01503   setModified( true );
01504 }
01505 
01506 void Doc::addCommand( UndoAction* undo )
01507 {
01508   if (undoLocked()) return;
01509   UndoWrapperCommand* command = new UndoWrapperCommand( undo );
01510   addCommand( command );
01511   setModified( true );
01512 }
01513 
01514 void Doc::undo()
01515 {
01516   undoLock ();
01517   d->commandHistory->undo();
01518   undoUnlock ();
01519 }
01520 
01521 void Doc::redo()
01522 {
01523   undoLock ();
01524   d->commandHistory->redo();
01525   undoUnlock ();
01526 }
01527 
01528 void Doc::commandExecuted()
01529 {
01530   setModified( true );
01531 }
01532 
01533 void Doc::documentRestored()
01534 {
01535   setModified( false );
01536 }
01537 
01538 void Doc::undoLock()
01539 {
01540   d->undoLocked++;
01541 }
01542 
01543 void Doc::undoUnlock()
01544 {
01545   d->undoLocked--;
01546 }
01547 
01548 bool Doc::undoLocked() const
01549 {
01550   return (d->undoLocked > 0);
01551 }
01552 
01553 KoCommandHistory* Doc::commandHistory()
01554 {
01555   return d->commandHistory;
01556 }
01557 
01558 void Doc::enableUndo( bool _b )
01559 {
01560     QPtrListIterator<KoView> it( views() );
01561     for (; it.current(); ++it )
01562       static_cast<View *>( it.current() )->enableUndo( _b );
01563 }
01564 
01565 void Doc::enableRedo( bool _b )
01566 {
01567     QPtrListIterator<KoView> it( views() );
01568     for (; it.current(); ++it )
01569       static_cast<View *>( it.current() )->enableRedo( _b );
01570 }
01571 
01572 void Doc::paintContent( QPainter& painter, const QRect& rect,
01573                                bool transparent, double zoomX, double /*zoomY*/ )
01574 {
01575     kdDebug(36001) << "paintContent() called on " << rect << endl;
01576 
01577   //  ElapsedTime et( "Doc::paintContent1" );
01578     //kdDebug(36001) << "Doc::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << endl;
01579 
01580     // save current zoom
01581     int oldZoom = m_zoom;
01582 
01583     // choose sheet: the first or the active
01584     Sheet* sheet = 0L;
01585     if ( !d->activeSheet )
01586         sheet = map()->firstSheet();
01587     else
01588         sheet = d->activeSheet;
01589     if ( !sheet )
01590         return;
01591 
01592     // only one zoom is supported
01593     double d_zoom = 1.0;
01594     setZoomAndResolution( 100, KoGlobal::dpiX(), KoGlobal::dpiY() );
01595     if ( m_zoomedResolutionX != zoomX )
01596         d_zoom *= ( zoomX / m_zoomedResolutionX );
01597 
01598     // KSpread support zoom, therefore no need to scale with worldMatrix
01599     QWMatrix matrix = painter.worldMatrix();
01600     matrix.setMatrix( 1, 0, 0, 1, matrix.dx(), matrix.dy() );
01601     QRect prect = rect;
01602     prect.setWidth( (int) (prect.width() * painter.worldMatrix().m11()) );
01603     prect.setHeight( (int) (prect.height() * painter.worldMatrix().m22()) );
01604     setZoomAndResolution( (int) ( d_zoom * 100 ), KoGlobal::dpiX(), KoGlobal::dpiY() );
01605     // paint the content, now zoom is correctly set
01606     kdDebug(36001)<<"paintContent-------------------------------------\n";
01607     painter.save();
01608     painter.setWorldMatrix( matrix );
01609     paintContent( painter, prect, transparent, sheet, false );
01610     painter.restore();
01611 
01612     // restore zoom
01613     m_zoom = oldZoom;
01614     setZoomAndResolution( oldZoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
01615 }
01616 
01617 void Doc::paintContent( QPainter& painter, const QRect& rect, bool /*transparent*/, Sheet* sheet, bool drawCursor )
01618 {
01619     if ( isLoading() )
01620         return;
01621     //    ElapsedTime et( "Doc::paintContent2" );
01622 
01623     // if ( !transparent )
01624     // painter.eraseRect( rect );
01625 
01626     double xpos;
01627     double ypos;
01628     int left_col   = sheet->leftColumn( unzoomItX( rect.x() ), xpos );
01629     int right_col  = sheet->rightColumn( unzoomItX( rect.right() ) );
01630     int top_row    = sheet->topRow( unzoomItY( rect.y() ), ypos );
01631     int bottom_row = sheet->bottomRow( unzoomItY( rect.bottom() ) );
01632     QPen pen;
01633     pen.setWidth( 1 );
01634     painter.setPen( pen );
01635 
01636     /* Update the entire visible area. */
01637     QValueList<QRect>  cellAreaList;
01638     cellAreaList.append( QRect( left_col,
01639                                 top_row,
01640                                 right_col - left_col + 1,
01641                                 bottom_row - top_row + 1) );
01642 
01643     paintCellRegions(painter, rect, NULL, cellAreaList, sheet, drawCursor);
01644 }
01645 
01646 void Doc::paintUpdates()
01647 {
01648   //  ElapsedTime et( "Doc::paintUpdates" );
01649 
01650   QPtrListIterator<KoView> it( views() );
01651   View  * view  = NULL;
01652   Sheet * sheet = NULL;
01653 
01654   for (; it.current(); ++it )
01655   {
01656     view = static_cast<View *>( it.current() );
01657     view->paintUpdates();
01658   }
01659 
01660   for (sheet = map()->firstSheet(); sheet != NULL;
01661        sheet = map()->nextSheet())
01662   {
01663     sheet->clearPaintDirtyData();
01664   }
01665 }
01666 
01667 void Doc::paintCellRegions(QPainter& painter, const QRect &viewRect,
01668                View* view,
01669                QValueList<QRect> cellRegions,
01670                const Sheet* sheet, bool /*drawCursor*/)
01671 {
01672   //
01673   // Clip away children
01674   //
01675 
01676   QRegion rgn = painter.clipRegion();
01677   if ( rgn.isEmpty() )
01678     rgn = QRegion( QRect( 0, 0, viewRect.width(), viewRect.height() ) );
01679 
01680   QWMatrix matrix;
01681   if ( view ) {
01682     matrix.scale( zoomedResolutionX(),
01683                   zoomedResolutionY() );
01684     matrix.translate( - view->canvasWidget()->xOffset(),
01685                       - view->canvasWidget()->yOffset() );
01686   }
01687   else {
01688     matrix = painter.worldMatrix();
01689   }
01690 
01691 //   QPtrListIterator<KoDocumentChild> it( children() );
01692 //   for( ; it.current(); ++it ) {
01693 //     // if ( ((Child*)it.current())->sheet() == sheet &&
01694 //     //    !m_pView->hasDocumentInWindow( it.current()->document() ) )
01695 //     if ( ((Child*)it.current())->sheet() == sheet)
01696 //       rgn -= it.current()->region( matrix );
01697 //   }
01698   painter.setClipRegion( rgn );
01699 
01700   QPen pen;
01701   pen.setWidth( 1 );
01702   painter.setPen( pen );
01703 
01704   QRect cellRegion;
01705   KoRect unzoomedViewRect = unzoomRect( viewRect );
01706 
01707   for (unsigned int i=0; i < cellRegions.size(); i++) {
01708     cellRegion = cellRegions[i];
01709 
01710     PaintRegion(painter, unzoomedViewRect, view, cellRegion, sheet);
01711   }
01712 }
01713 
01714 
01715 void Doc::PaintRegion(QPainter &painter, const KoRect &viewRegion,
01716               View* view, const QRect &paintRegion,
01717               const Sheet* sheet)
01718 {
01719   // Paint region has cell coordinates (col,row) while viewRegion has
01720   // world coordinates.  paintRegion is the cells to update and
01721   // viewRegion is the area actually onscreen.
01722 
01723   if ( paintRegion.left() <= 0 || paintRegion.top() <= 0 )
01724     return;
01725 
01726   // Get the world coordinates of the upper left corner of the
01727   // paintRegion The view is NULL, when paintRegion is called from
01728   // paintContent, which itself is only called, when we should paint
01729   // the output for INACTIVE embedded view.  If inactive embedded,
01730   // then there is no view and we alwas start at top/left, so the
01731   // offset is 0.
01732   //
01733   KoPoint  dblCorner;
01734   if ( view == 0L ) //Most propably we are embedded and inactive, so no offset
01735     dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ),
01736              sheet->dblRowPos( paintRegion.top() ) );
01737   else
01738     dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() )
01739              - view->canvasWidget()->xOffset(),
01740              sheet->dblRowPos( paintRegion.top() )
01741              - view->canvasWidget()->yOffset() );
01742   KoPoint dblCurrentCellPos( dblCorner );
01743 
01744   int regionBottom = paintRegion.bottom();
01745   int regionRight  = paintRegion.right();
01746   int regionLeft   = paintRegion.left();
01747   int regionTop    = paintRegion.top();
01748 
01749   QValueList<QPoint>  mergedCellsPainted;
01750   for ( int y = regionTop;
01751         y <= regionBottom && dblCurrentCellPos.y() <= viewRegion.bottom();
01752         ++y )
01753   {
01754     const RowFormat * row_lay = sheet->rowFormat( y );
01755     dblCurrentCellPos.setX( dblCorner.x() );
01756 
01757     for ( int x = regionLeft;
01758           x <= regionRight && dblCurrentCellPos.x() <= viewRegion.right();
01759           ++x )
01760     {
01761       const ColumnFormat *col_lay = sheet->columnFormat( x );
01762       Cell* cell = sheet->cellAt( x, y );
01763 
01764       QPoint cellRef( x, y );
01765 
01766 #if 0
01767       bool paintBordersBottom = false;
01768       bool paintBordersRight  = false;
01769       bool paintBordersLeft   = false;
01770       bool paintBordersTop    = false;
01771 #endif
01772       int paintBorder = Cell::Border_None;
01773 
01774       QPen rightPen( cell->effRightBorderPen( x, y ) );
01775       QPen leftPen( cell->effLeftBorderPen( x, y ) );
01776       QPen topPen( cell->effTopBorderPen( x, y ) );
01777       QPen bottomPen( cell->effBottomBorderPen( x, y ) );
01778 
01779       // Paint border if outermost cell or if the pen is more "worth"
01780       // than the border pen of the cell on the other side of the
01781       // border or if the cell on the other side is not painted. In
01782       // the latter case get the pen that is of more "worth"
01783 
01784       // right border:
01785       if ( x >= KS_colMax )
01786         //paintBordersRight = true;
01787         paintBorder |= Cell::Border_Right;
01788       else if ( x == regionRight ) {
01789     paintBorder |= Cell::Border_Right;
01790     if ( cell->effRightBorderValue( x, y )
01791          < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) )
01792       rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y );
01793       }
01794       else {
01795     paintBorder |= Cell::Border_Right;
01796     if ( cell->effRightBorderValue( x, y )
01797          < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) )
01798       rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y );
01799       }
01800 
01801       // Similiar for other borders...
01802       // bottom border:
01803       if ( y >= KS_rowMax )
01804         paintBorder |= Cell::Border_Bottom;
01805       else if ( y == regionBottom ) {
01806     paintBorder |= Cell::Border_Bottom;
01807     if ( cell->effBottomBorderValue( x, y )
01808          < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) )
01809       bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 );
01810       }
01811       else {
01812         paintBorder |= Cell::Border_Bottom;
01813         if ( cell->effBottomBorderValue( x, y )
01814          < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) )
01815           bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 );
01816       }
01817 
01818       // left border:
01819       if ( x == 1 )
01820         paintBorder |= Cell::Border_Left;
01821       else if ( x == regionLeft ) {
01822     paintBorder |= Cell::Border_Left;
01823     if ( cell->effLeftBorderValue( x, y )
01824          < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) )
01825       leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y );
01826       }
01827       else {
01828         paintBorder |= Cell::Border_Left;
01829         if ( cell->effLeftBorderValue( x, y )
01830          < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) )
01831           leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y );
01832       }
01833 
01834       // top border:
01835       if ( y == 1 )
01836         paintBorder |= Cell::Border_Top;
01837       else if ( y == regionTop ) {
01838     paintBorder |= Cell::Border_Top;
01839     if ( cell->effTopBorderValue( x, y )
01840          < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) )
01841       topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 );
01842       }
01843       else {
01844         paintBorder |= Cell::Border_Top;
01845         if ( cell->effTopBorderValue( x, y )
01846          < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) )
01847           topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 );
01848       }
01849 
01850 #if 0
01851       cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef,
01852                paintBordersRight, paintBordersBottom,
01853                paintBordersLeft, paintBordersTop,
01854                rightPen, bottomPen, leftPen, topPen,
01855                mergedCellsPainted, false );
01856 
01857       Cell::BorderSides highlightBorder=Cell::Border_None;
01858       QPen highlightPen;
01859 #endif
01860 
01861       cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef,
01862                paintBorder,
01863                rightPen, bottomPen, leftPen, topPen,
01864                mergedCellsPainted, false );
01865 
01866 
01867       dblCurrentCellPos.setX( dblCurrentCellPos.x() + col_lay->dblWidth() );
01868     }
01869     dblCurrentCellPos.setY( dblCurrentCellPos.y() + row_lay->dblHeight() );
01870   }
01871 }
01872 
01873 
01874 DCOPObject* Doc::dcopObject()
01875 {
01876     if ( !d->dcop )
01877         d->dcop = new DocIface( this );
01878 
01879     return d->dcop;
01880 }
01881 
01882 void Doc::addAreaName(const QRect &_rect,const QString & name,const QString & sheetName)
01883 {
01884   setModified( true );
01885   Reference tmp;
01886   tmp.rect = _rect;
01887   tmp.sheet_name = sheetName;
01888   tmp.ref_name = name;
01889   d->refs.append( tmp);
01890   emit sig_addAreaName( name );
01891 }
01892 
01893 void Doc::removeArea( const QString & name)
01894 {
01895     QValueList<Reference>::Iterator it2;
01896     for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
01897     {
01898         if((*it2).ref_name==name)
01899         {
01900             d->refs.remove(it2);
01901             emit sig_removeAreaName( name );
01902             return;
01903         }
01904     }
01905 }
01906 
01907 void Doc::changeAreaSheetName(const QString & oldName,const QString & sheetName)
01908 {
01909   QValueList<Reference>::Iterator it2;
01910   for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
01911         {
01912         if((*it2).sheet_name==oldName)
01913                    (*it2).sheet_name=sheetName;
01914         }
01915 }
01916 
01917 QRect Doc::getRectArea(const QString  &_sheetName)
01918 {
01919   QValueList<Reference>::Iterator it2;
01920   for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
01921         {
01922         if((*it2).ref_name==_sheetName)
01923                 {
01924                 return (*it2).rect;
01925                 }
01926         }
01927   return QRect(-1,-1,-1,-1);
01928 }
01929 
01930 QDomElement Doc::saveAreaName( QDomDocument& doc )
01931 {
01932    QDomElement element = doc.createElement( "areaname" );
01933    QValueList<Reference>::Iterator it2;
01934    for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 )
01935    {
01936         QDomElement e = doc.createElement("reference");
01937         QDomElement tabname = doc.createElement( "tabname" );
01938         tabname.appendChild( doc.createTextNode( (*it2).sheet_name ) );
01939         e.appendChild( tabname );
01940 
01941         QDomElement refname = doc.createElement( "refname" );
01942         refname.appendChild( doc.createTextNode( (*it2).ref_name ) );
01943         e.appendChild( refname );
01944 
01945         QDomElement rect = doc.createElement( "rect" );
01946         rect.setAttribute( "left-rect", ((*it2).rect).left() );
01947         rect.setAttribute( "right-rect",((*it2).rect).right() );
01948         rect.setAttribute( "top-rect", ((*it2).rect).top() );
01949         rect.setAttribute( "bottom-rect", ((*it2).rect).bottom() );
01950         e.appendChild( rect );
01951         element.appendChild(e);
01952    }
01953    return element;
01954 }
01955 
01956 void Doc::loadOasisCellValidation( const QDomElement&body )
01957 {
01958     QDomNode validation = KoDom::namedItemNS( body, KoXmlNS::table, "content-validations" );
01959     kdDebug()<<"void Doc::loadOasisCellValidation( const QDomElement&body ) \n";
01960     kdDebug()<<"validation.isNull ? "<<validation.isNull()<<endl;
01961     if ( !validation.isNull() )
01962     {
01963         QDomNode n = validation.firstChild();
01964         for( ; !n.isNull(); n = n.nextSibling() )
01965         {
01966             if ( n.isElement() )
01967             {
01968                 QDomElement element = n.toElement();
01969                 //kdDebug()<<" loadOasisCellValidation element.tagName() :"<<element.tagName()<<endl;
01970                 if ( element.tagName() ==  "content-validation" && element.namespaceURI() == KoXmlNS::table ) {
01971                     d->m_loadingInfo->appendValidation(element.attributeNS( KoXmlNS::table, "name", QString::null ), element );
01972                     kdDebug()<<" validation found :"<<element.attributeNS( KoXmlNS::table, "name", QString::null )<<endl;
01973                 }
01974                 else {
01975                     kdDebug()<<" Tag not recognize :"<<element.tagName()<<endl;
01976                 }
01977             }
01978         }
01979     }
01980 }
01981 
01982 void Doc::saveOasisAreaName( KoXmlWriter & xmlWriter )
01983 {
01984     if ( listArea().count()>0 )
01985     {
01986         xmlWriter.startElement( "table:named-expressions" );
01987         QValueList<Reference>::Iterator it;
01988         for ( it = d->refs.begin(); it != d->refs.end(); ++it )
01989         {
01990             xmlWriter.startElement( "table:named-range" );
01991 
01992             xmlWriter.addAttribute( "table:name", ( *it ).ref_name );
01993             xmlWriter.addAttribute( "table:base-cell-address", convertRefToBase( ( *it ).sheet_name, ( *it ).rect ) );
01994             xmlWriter.addAttribute( "table:cell-range-address", convertRefToRange( ( *it ).sheet_name, ( *it ).rect ) );
01995 
01996             xmlWriter.endElement();
01997         }
01998         xmlWriter.endElement();
01999     }
02000 }
02001 
02002 void Doc::loadOasisAreaName( const QDomElement& body )
02003 {
02004     kdDebug()<<"void Doc::loadOasisAreaName( const QDomElement& body ) \n";
02005     QDomNode namedAreas = KoDom::namedItemNS( body, KoXmlNS::table, "named-expressions" );
02006     if ( !namedAreas.isNull() )
02007     {
02008         kdDebug()<<" area name exist \n";
02009         QDomNode area = namedAreas.firstChild();
02010         while ( !area.isNull() )
02011         {
02012             QDomElement e = area.toElement();
02013             if ( e.isNull() || !e.hasAttributeNS( KoXmlNS::table, "name" ) || !e.hasAttributeNS( KoXmlNS::table, "cell-range-address" ) )
02014             {
02015                 kdDebug() << "Reading in named area failed" << endl;
02016                 area = area.nextSibling();
02017                 continue;
02018             }
02019 
02020             // TODO: what is: sheet:base-cell-address
02021             QString name  = e.attributeNS( KoXmlNS::table, "name", QString::null );
02022             QString range = e.attributeNS( KoXmlNS::table, "cell-range-address", QString::null );
02023             kdDebug()<<"area name : "<<name<<" range :"<<range<<endl;
02024             d->m_loadingInfo->addWordInAreaList( name );
02025             kdDebug() << "Reading in named area, name: " << name << ", area: " << range << endl;
02026 
02027             range = Oasis::decodeFormula( range );
02028 
02029             if ( range.find( ':' ) == -1 )
02030             {
02031                 Point p( range );
02032 
02033                 int n = range.find( '!' );
02034                 if ( n > 0 )
02035                     range = range + ":" + range.right( range.length() - n - 1);
02036 
02037                 kdDebug() << "=> Area: " << range << endl;
02038             }
02039 
02040             Range p( range );
02041 
02042             addAreaName( p.range(), name, p.sheetName() );
02043             kdDebug() << "Area range: " << p.sheetName() << endl;
02044 
02045             area = area.nextSibling();
02046         }
02047     }
02048 }
02049 
02050 void Doc::loadAreaName( const QDomElement& element )
02051 {
02052   QDomElement tmp=element.firstChild().toElement();
02053   for( ; !tmp.isNull(); tmp=tmp.nextSibling().toElement()  )
02054   {
02055     if ( tmp.tagName() == "reference" )
02056     {
02057         QString tabname;
02058         QString refname;
02059         int left=0;
02060         int right=0;
02061         int top=0;
02062         int bottom=0;
02063         QDomElement sheetName = tmp.namedItem( "tabname" ).toElement();
02064         if ( !sheetName.isNull() )
02065         {
02066           tabname=sheetName.text();
02067         }
02068         QDomElement referenceName = tmp.namedItem( "refname" ).toElement();
02069         if ( !referenceName.isNull() )
02070         {
02071           refname=referenceName.text();
02072         }
02073         QDomElement rect =tmp.namedItem( "rect" ).toElement();
02074         if (!rect.isNull())
02075         {
02076           bool ok;
02077           if ( rect.hasAttribute( "left-rect" ) )
02078             left=rect.attribute("left-rect").toInt( &ok );
02079           if ( rect.hasAttribute( "right-rect" ) )
02080             right=rect.attribute("right-rect").toInt( &ok );
02081           if ( rect.hasAttribute( "top-rect" ) )
02082             top=rect.attribute("top-rect").toInt( &ok );
02083           if ( rect.hasAttribute( "bottom-rect" ) )
02084             bottom=rect.attribute("bottom-rect").toInt( &ok );
02085         }
02086         QRect _rect;
02087         _rect.setCoords(left,top,right,bottom);
02088         addAreaName(_rect,refname,tabname);
02089     }
02090   }
02091 }
02092 
02093 void Doc::addStringCompletion(const QString &stringCompletion)
02094 {
02095   if ( d->listCompletion.items().contains(stringCompletion) == 0 )
02096     d->listCompletion.addItem( stringCompletion );
02097 }
02098 
02099 void Doc::refreshInterface()
02100 {
02101   emit sig_refreshView();
02102 }
02103 
02104 void Doc::refreshLocale()
02105 {
02106     emit sig_refreshLocale();
02107 }
02108 
02109 
02110 void Doc::emitBeginOperation(bool waitCursor)
02111 {
02112     //If an emitBeginOperation occurs with waitCursor enabled, then the waiting cursor is set
02113     //until all operations have been completed.
02114     //
02115     //The reason being that any operations started before the first one with waitCursor set
02116     //are expected to be completed in a short time anyway.
02117     QCursor* activeOverride = QApplication::overrideCursor();
02118 
02119     if (waitCursor && ( (!activeOverride) || (activeOverride->shape() != Qt::waitCursor.shape()) )  )
02120     {
02121         QApplication::setOverrideCursor(Qt::waitCursor);
02122     }
02123 
02124 //    /* just duplicate the current cursor on the stack, then */
02125 //  else if (QApplication::overrideCursor() != NULL)
02126 //    {
02127 //        QApplication::setOverrideCursor(QApplication::overrideCursor()->shape());
02128 //    }
02129 
02130     KoDocument::emitBeginOperation();
02131     d->delayCalculation = true;
02132     d->numOperations++;
02133 }
02134 
02135 void Doc::emitBeginOperation(void)
02136 {
02137   emitBeginOperation(true);
02138 }
02139 
02140 
02141 void Doc::emitEndOperation()
02142 {
02143    d->numOperations--;
02144 
02145    if (d->numOperations <= 0)
02146    {
02147      d->numOperations = 0;
02148      d->delayCalculation = false;
02149    }
02150 
02151    KoDocument::emitEndOperation();
02152 
02153    if (d->numOperations == 0)
02154    {
02155     QApplication::restoreOverrideCursor();
02156 
02157      /* do this after the parent class emitEndOperation because that allows updates
02158         on the view again
02159      */
02160      paintUpdates();
02161    }
02162 }
02163 
02164 void Doc::emitEndOperation( const Region& /*region*/ )
02165 {
02166   d->numOperations--;
02167 
02168   if ( d->numOperations > 0 || !d->activeSheet )
02169   {
02170     KoDocument::emitEndOperation();
02171     return;
02172   }
02173 
02174   d->numOperations = 0;
02175   d->delayCalculation = false;
02176 
02177   KoDocument::emitEndOperation();
02178 
02179   QApplication::restoreOverrideCursor();
02180 
02181     /* do this after the parent class emitEndOperation because that allows updates
02182     on the view again
02183     */
02184   paintUpdates();
02185 }
02186 
02187 bool Doc::delayCalculation() const
02188 {
02189    return d->delayCalculation;
02190 }
02191 
02192 void Doc::updateBorderButton()
02193 {
02194     QPtrListIterator<KoView> it( views() );
02195     for (; it.current(); ++it )
02196       static_cast<View *>( it.current() )->updateBorderButton();
02197 }
02198 
02199 void Doc::insertSheet( Sheet * sheet )
02200 {
02201     QPtrListIterator<KoView> it( views() );
02202     for (; it.current(); ++it )
02203   ((View*)it.current())->insertSheet( sheet );
02204 }
02205 
02206 void Doc::takeSheet( Sheet * sheet )
02207 {
02208     QPtrListIterator<KoView> it( views() );
02209     for (; it.current(); ++it )
02210   ((View*)it.current())->removeSheet( sheet );
02211 }
02212 
02213 void Doc::addIgnoreWordAll( const QString & word)
02214 {
02215     if( d->spellListIgnoreAll.findIndex( word )==-1)
02216         d->spellListIgnoreAll.append( word );
02217 }
02218 
02219 void Doc::clearIgnoreWordAll( )
02220 {
02221     d->spellListIgnoreAll.clear();
02222 }
02223 
02224 void Doc::setDisplaySheet(Sheet *_sheet )
02225 {
02226     d->activeSheet = _sheet;
02227 }
02228 
02229 KSPLoadingInfo * Doc::loadingInfo() const
02230 {
02231     return d->m_loadingInfo;
02232 }
02233 
02234 Sheet * Doc::displaySheet() const
02235 {
02236     return d->activeSheet;
02237 }
02238 
02239 void Doc::addView( KoView *_view )
02240 {
02241     KoDocument::addView( _view );
02242     QPtrListIterator<KoView> it( views() );
02243     for (; it.current(); ++it )
02244   ((View*)it.current())->closeEditor();
02245 }
02246 
02247 void Doc::addDamage( Damage* damage )
02248 {
02249     d->damages.append( damage );
02250 
02251     if( d->damages.count() == 1 )
02252         QTimer::singleShot( 0, this, SLOT( flushDamages() ) );
02253 }
02254 
02255 void Doc::flushDamages()
02256 {
02257     emit damagesFlushed( d->damages );
02258     QValueList<Damage*>::Iterator it;
02259     for( it = d->damages.begin(); it != d->damages.end(); ++it )
02260       delete *it;
02261     d->damages.clear();
02262 }
02263 
02264 void Doc::loadConfigFromFile()
02265 {
02266     d->configLoadFromFile = true;
02267 }
02268 
02269 bool Doc::configLoadFromFile() const
02270 {
02271     return d->configLoadFromFile;
02272 }
02273 
02274 
02275 void Doc::insertObject( EmbeddedObject * obj )
02276 {
02277   switch ( obj->getType() )
02278   {
02279     case OBJECT_KOFFICE_PART: case OBJECT_CHART:
02280     {
02281       KoDocument::insertChild( dynamic_cast<EmbeddedKOfficeObject*>(obj)->embeddedObject() );
02282       break;
02283     }
02284     default:
02285       ;
02286   }
02287   d->m_embeddedObjects.append( obj );
02288 }
02289 
02290 QPtrList<EmbeddedObject>& Doc::embeddedObjects()
02291 {
02292     return d->m_embeddedObjects;
02293 }
02294 
02295 KoPictureCollection *Doc::pictureCollection()
02296 {
02297   return &d->m_pictureCollection;
02298 }
02299 
02300 void Doc::repaint( const QRect& rect )
02301 {
02302   QRect r;
02303   QPtrListIterator<KoView> it( views() );
02304   for( ; it.current(); ++it )
02305   {
02306     r = rect;
02307     Canvas* canvas = ((View*)it.current())->canvasWidget();
02308     r.moveTopLeft( QPoint( r.x() - (int) canvas->xOffset(),
02309                            r.y() - (int) canvas->yOffset() ) );
02310     canvas->update( r );
02311   }
02312 }
02313 
02314 void Doc::repaint( EmbeddedObject *obj )
02315 {
02316   QPtrListIterator<KoView> it( views() );
02317   for( ; it.current(); ++it )
02318   {
02319     Canvas* canvas = ((View*)it.current())->canvasWidget();
02320     if ( obj->sheet() == canvas->activeSheet() )
02321         canvas->repaintObject( obj );
02322   }
02323 }
02324 
02325 void Doc::repaint( const KoRect& rect )
02326 {
02327   QRect r;
02328   QPtrListIterator<KoView> it( views() );
02329   for( ; it.current(); ++it )
02330   {
02331     Canvas* canvas = ((View*)it.current())->canvasWidget();
02332 
02333     r = zoomRect( rect );
02334     r.moveBy( (int)( -canvas->xOffset()*zoomedResolutionX() ) ,
02335                         (int)( -canvas->yOffset() *zoomedResolutionY()) );
02336     canvas->update( r );
02337   }
02338 }
02339 
02340 void Doc::addShell( KoMainWindow *shell )
02341 {
02342   connect( shell, SIGNAL( documentSaved() ), d->commandHistory, SLOT( documentSaved() ) );
02343   KoDocument::addShell( shell );
02344 }
02345 
02346 int Doc::undoRedoLimit() const
02347 {
02348   return d->commandHistory->undoLimit();
02349 }
02350 
02351 void Doc::setUndoRedoLimit(int val)
02352 {
02353   d->commandHistory->setUndoLimit(val);
02354   d->commandHistory->setRedoLimit(val);
02355 }
02356 
02357 void Doc::insertPixmapKey( KoPictureKey key )
02358 {
02359     if ( !d->usedPictures.contains( key ) )
02360         d->usedPictures.append( key );
02361 }
02362 
02363 void Doc::makeUsedPixmapList()
02364 {
02365     d->usedPictures.clear();
02366     QPtrListIterator<EmbeddedObject> it( d->m_embeddedObjects );
02367     for ( ; it.current() ; ++it )
02368     {
02369         if( it.current()->getType() == OBJECT_PICTURE && ( d->m_savingWholeDocument || it.current()->isSelected() ) )
02370             insertPixmapKey( static_cast<EmbeddedPictureObject*>( it.current() )->getKey() );
02371     }
02372 }
02373 
02374 bool Doc::savingWholeDocument()
02375 {
02376     return d->m_savingWholeDocument;
02377 }
02378 
02379 #include "kspread_doc.moc"
02380 
KDE Home | KDE Accessibility Home | Description of Access Keys