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