kspread Library API Documentation

kspread_doc.cc

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