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