/* This file is part of the KDE project Copyright (C) 2005-2006 Inge Wallin (C) 2004 Ariya Hidayat (C) 2002-2003 Norbert Andres (C) 2000-2002 Laurent Montel (C) 2002 John Dailey (C) 2002 Phillip Mueller (C) 2000 Werner Trobin (C) 1999-2000 Simon Hausmann (C) 1999 David Faure (C) 1998-2000 Torben Weis This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kspread_canvas.h" #include "kspread_locale.h" #include "kspread_map.h" #include "kspread_sheet.h" #include "kspread_sheetprint.h" #include "kspread_style_manager.h" #include "kspread_undo.h" #include "kspread_util.h" #include "kspread_view.h" #include "commands.h" #include "damages.h" #include "formula.h" #include "functions.h" #include "ksploadinginfo.h" #include "selection.h" #include "valuecalc.h" #include "valueconverter.h" #include "valueformatter.h" #include "valueparser.h" #include "KSpreadDocIface.h" #include "kspread_doc.h" using namespace std; using namespace KSpread; static const int CURRENT_SYNTAX_VERSION = 1; // Make sure an appropriate DTD is available in www/koffice/DTD if changing this value static const char * CURRENT_DTD_VERSION = "1.2"; class Doc::Private { public: Map *map; TDELocale *locale; StyleManager *styleManager; ValueParser *parser; ValueFormatter *formatter; ValueConverter *converter; ValueCalc *calc; Sheet *activeSheet; KSPLoadingInfo *m_loadingInfo; static TQValueList s_docs; static int s_docId; DCOPObject* dcop; // URL of the this part. This variable is only set if the load() function // had been called with an URL as argument. TQString fileURL; // for undo/redo int undoLocked; KoCommandHistory* commandHistory; // true if loading is in process, otherwise false. // This flag is used to avoid updates etc. during loading. bool isLoading; TQColor pageBorderColor; TQPtrList plugins; TQValueList refs; TDECompletion listCompletion; int numOperations; TQValueList damages; // document properties int syntaxVersion; bool verticalScrollBar:1; bool horizontalScrollBar:1; bool columnHeader:1; bool rowHeader:1; TQColor gridColor; double indentValue; bool showStatusBar:1; bool showTabBar:1; bool showFormulaBar:1; bool showError:1; TDEGlobalSettings::Completion completionMode; KSpread::MoveTo moveTo; MethodOfCalc calcMethod; bool delayCalculation:1; KSpellConfig *spellConfig; bool dontCheckUpperWord:1; bool dontCheckTitleCase:1; bool configLoadFromFile:1; TQStringList spellListIgnoreAll; /// list of all objects TQPtrList m_embeddedObjects; KoPictureCollection m_pictureCollection; TQValueList usedPictures; bool m_savingWholeDocument; }; /***************************************************************************** * * Doc * *****************************************************************************/ TQValueList Doc::Private::s_docs; int Doc::Private::s_docId = 0; Doc::Doc( TQWidget *parentWidget, const char *widgetName, TQObject* parent, const char* name, bool singleViewMode ) : KoDocument( parentWidget, widgetName, parent, name, singleViewMode ) { d = new Private; d->m_loadingInfo = 0L; d->map = new Map( this, "Map" ); d->locale = new Locale; d->styleManager = new StyleManager(); d->parser = new ValueParser( d->locale ); d->converter = new ValueConverter ( d->parser ); d->calc = new ValueCalc( d->converter ); d->calc->setDoc (this); d->formatter = new ValueFormatter( d->converter ); d->activeSheet = 0; d->pageBorderColor = TQt::red; d->configLoadFromFile = false; TQFont f( KoGlobal::defaultFont() ); Format::setGlobalRowHeight( f.pointSizeFloat() + 3 ); Format::setGlobalColWidth( ( f.pointSizeFloat() + 3 ) * 5 ); d->plugins.setAutoDelete( false ); d->delayCalculation = false; documents().append( this ); setInstance( Factory::global(), false ); setTemplateType( "kspread_template" ); d->dcop = 0; d->isLoading = false; d->numOperations = 1; // don't start repainting before the GUI is done... d->undoLocked = 0; d->commandHistory = new KoCommandHistory( actionCollection() ); connect( d->commandHistory, TQ_SIGNAL( commandExecuted() ), TQ_SLOT( commandExecuted() ) ); connect( d->commandHistory, TQ_SIGNAL( documentRestored() ), TQ_SLOT( documentRestored() ) ); // Make us scripsheet if the document has a name // Set a name if there is no name specified if ( !name ) { TQString tmp( "Document%1" ); tmp = tmp.arg( d->s_docId++ ); setName( tmp.local8Bit());//tmp.latin1() ); dcopObject(); } else dcopObject(); // default document properties d->syntaxVersion = CURRENT_SYNTAX_VERSION; d->verticalScrollBar = true; d->horizontalScrollBar = true; d->columnHeader = true; d->rowHeader = true; d->gridColor = TQt::lightGray; d->indentValue = 10.0; d->showStatusBar = true; d->showFormulaBar = true; d->showTabBar = true; d->showError = false; d->calcMethod = SumOfNumber; d->moveTo = KSpread::Bottom; d->completionMode = TDEGlobalSettings::CompletionAuto; d->spellConfig = 0; d->dontCheckUpperWord = false; d->dontCheckTitleCase = false; } Doc::~Doc() { //don't save config when kword is embedded into konqueror if(isReadWrite()) saveConfig(); delete d->dcop; d->s_docs.remove( this ); kdDebug(36001) << "alive 1" << endl; delete d->commandHistory; delete d->spellConfig; delete d->locale; delete d->map; delete d->styleManager; delete d->parser; delete d->formatter; delete d->converter; delete d->calc; delete d; } TQValueList Doc::documents() { return Private::s_docs; } bool Doc::initDoc(InitDocFlags flags, TQWidget* parentWidget) { // ElapsedTime et( " initDoc " ); TQString f; if (flags==KoDocument::InitDocEmpty) { TDEConfig *config = Factory::global()->config(); int _page=1; if( config->hasGroup("Parameters" )) { config->setGroup( "Parameters" ); _page=config->readNumEntry( "NbPage",1 ) ; } for( int i=0; i<_page; i++ ) map()->addNewSheet(); resetURL(); setEmpty(); initConfig(); styleManager()->createBuiltinStyles(); return true; } KoTemplateChooseDia::ReturnType ret; KoTemplateChooseDia::DialogType dlgtype; if (flags != KoDocument::InitDocFileNew ) dlgtype = KoTemplateChooseDia::Everything; else dlgtype = KoTemplateChooseDia::OnlyTemplates; ret = KoTemplateChooseDia::choose( Factory::global(), f, dlgtype, "kspread_template", parentWidget ); if ( ret == KoTemplateChooseDia::File ) { KURL url( f ); bool ok=openURL(url); while (KoDocument::isLoading()) kapp->processEvents(); return ok; } if ( ret == KoTemplateChooseDia::Empty ) { TDEConfig *config = Factory::global()->config(); int _page=1; if( config->hasGroup("Parameters" )) { config->setGroup( "Parameters" ); _page=config->readNumEntry( "NbPage",1 ) ; } for( int i=0; i<_page; i++ ) map()->addNewSheet (); resetURL(); setEmpty(); initConfig(); styleManager()->createBuiltinStyles(); return true; } if ( ret == KoTemplateChooseDia::Template ) { resetURL(); d->m_loadingInfo = new KSPLoadingInfo; d->m_loadingInfo->setLoadTemplate( true ); bool ok = loadNativeFormat( f ); if ( !ok ) { showLoadingErrorDialog(); deleteLoadingInfo(); } setEmpty(); initConfig(); return ok; } return false; } void Doc::openTemplate (const TQString& file) { d->m_loadingInfo = new KSPLoadingInfo; d->m_loadingInfo->setLoadTemplate( true ); KoDocument::openTemplate( file ); deleteLoadingInfo(); initConfig(); } void Doc::initEmpty() { TDEConfig *config = Factory::global()->config(); int _page=1; if( config->hasGroup("Parameters" )) { config->setGroup( "Parameters" ); _page=config->readNumEntry( "NbPage",1 ) ; } for( int i=0; i<_page; i++ ) map()->addNewSheet(); resetURL(); initConfig(); styleManager()->createBuiltinStyles(); KoDocument::initEmpty(); } TDELocale *Doc::locale () const { return d->locale; } Map *Doc::map () const { return d->map; } StyleManager *Doc::styleManager () const { return d->styleManager; } ValueParser *Doc::parser () const { return d->parser; } ValueFormatter *Doc::formatter () const { return d->formatter; } ValueConverter *Doc::converter () const { return d->converter; } ValueCalc *Doc::calc () const { return d->calc; } void Doc::saveConfig() { if ( isEmbedded() ||!isReadWrite()) return; TDEConfig *config = Factory::global()->config(); config->setGroup( "Parameters" ); config->writeEntry( "Zoom", m_zoom ); } void Doc::initConfig() { TDEConfig *config = Factory::global()->config(); if( config->hasGroup("KSpread Page Layout" )) { config->setGroup( "KSpread Page Layout" ); setUnit( (KoUnit::Unit)config->readNumEntry( "Default unit page" ,0)); } if( config->hasGroup("Parameters" )) { config->setGroup( "Parameters" ); m_zoom = config->readNumEntry( "Zoom", 100 ); } else m_zoom = 100; int undo=30; if(config->hasGroup("Misc" ) ) { config->setGroup( "Misc" ); undo=config->readNumEntry("UndoRedo",-1); } if(undo!=-1) setUndoRedoLimit(undo); setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); } int Doc::syntaxVersion() const { return d->syntaxVersion; } bool Doc::isLoading() const { return d->isLoading || KoDocument::isLoading(); } void Doc::doNotPaint(bool status) { d->isLoading = status; } TQColor Doc::pageBorderColor() const { return d->pageBorderColor; } void Doc::changePageBorderColor( const TQColor & _color) { d->pageBorderColor = _color; } const TQValueList &Doc::listArea() { return d->refs; } TDECompletion& Doc::completion() { return d->listCompletion; } KoView* Doc::createViewInstance( TQWidget* parent, const char* name ) { if ( name == 0 ) name = "View"; return new View( parent, name, this ); } bool Doc::saveChildren( KoStore* _store ) { return map()->saveChildren( _store ); } int Doc::supportedSpecialFormats() const { return KoDocument::supportedSpecialFormats(); } bool Doc::completeSaving( KoStore* _store ) { d->m_pictureCollection.saveToStore( KoPictureCollection::CollectionPicture, _store, d->usedPictures ); return true; } TQDomDocument Doc::saveXML() { //Terminate current cell edition, if any TQPtrListIterator it( views() ); /* don't pull focus away from the editor if this is just a background autosave */ if (!isAutosaving()) { for (; it.current(); ++it ) static_cast( it.current() )->deleteEditor( true ); } TQDomDocument doc = createDomDocument( "spreadsheet", CURRENT_DTD_VERSION ); TQDomElement spread = doc.documentElement(); spread.setAttribute( "editor", "KSpread" ); spread.setAttribute( "mime", "application/x-kspread" ); spread.setAttribute( "syntaxVersion", CURRENT_SYNTAX_VERSION ); TQDomElement dlocale = ((Locale *)locale())->save( doc ); spread.appendChild( dlocale ); if (d->refs.count() != 0 ) { TQDomElement areaname = saveAreaName( doc ); spread.appendChild( areaname ); } if( !d->spellListIgnoreAll.isEmpty() ) { TQDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" ); spread.appendChild( spellCheckIgnore ); for ( TQStringList::Iterator it = d->spellListIgnoreAll.begin(); it != d->spellListIgnoreAll.end(); ++it ) { TQDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" ); spellCheckIgnore.appendChild( spellElem ); spellElem.setAttribute( "word", *it ); } } SavedDocParts::const_iterator iter = m_savedDocParts.begin(); SavedDocParts::const_iterator end = m_savedDocParts.end(); while ( iter != end ) { // save data we loaded in the beginning and which has no owner back to file spread.appendChild( iter.data() ); ++iter; } TQDomElement defaults = doc.createElement( "defaults" ); defaults.setAttribute( "row-height", Format::globalRowHeight() ); defaults.setAttribute( "col-width", Format::globalColWidth() ); spread.appendChild( defaults ); Plugin * plugin = d->plugins.first(); for ( ; plugin != 0; plugin = d->plugins.next() ) { TQDomElement data( plugin->saveXML( doc ) ); if ( !data.isNull() ) spread.appendChild( data ); } TQDomElement s = styleManager()->save( doc ); spread.appendChild( s ); TQDomElement e = map()->save( doc ); spread.appendChild( e ); setModified( false ); return doc; } bool Doc::loadChildren( KoStore* _store ) { return map()->loadChildren( _store ); } bool Doc::saveOasis( KoStore* store, KoXmlWriter* manifestWriter ) { emitBeginOperation(true); bool result=saveOasisHelper( store, manifestWriter, SaveAll ); emitEndOperation(); return result; } bool Doc::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag, TQString* /*plainText*/, KoPicture* /*picture*/ ) { d->m_pictureCollection.assignUniqueIds(); //Terminate current cell edition, if any TQPtrListIterator it2( views() ); d->m_savingWholeDocument = saveFlag == SaveAll ? true : false; /* don't pull focus away from the editor if this is just a background autosave */ if (!isAutosaving()) { for (; it2.current(); ++it2 ) static_cast( it2.current() )->deleteEditor( true ); } if ( !store->open( "content.xml" ) ) return false; KoStoreDevice dev( store ); KoXmlWriter* contentWriter = createOasisXmlWriter( &dev, "office:document-content" ); KoGenStyles mainStyles;//for compile KTempFile contentTmpFile; //Check that temp file was successfully created if (contentTmpFile.status() != 0) { tqWarning("Creation of temporary file to store document content failed."); return false; } contentTmpFile.setAutoDelete( true ); TQFile* tmpFile = contentTmpFile.file(); KoXmlWriter contentTmpWriter( tmpFile, 1 ); //todo fixme just add a element for testing saving content.xml contentTmpWriter.startElement( "office:body" ); contentTmpWriter.startElement( "office:spreadsheet" ); int indexObj = 1; int partIndexObj = 0; // Saving the custom cell styles including the default cell style. styleManager()->saveOasis( mainStyles ); // Saving the default column style KoGenStyle defaultColumnStyle( Doc::STYLE_COLUMN_USER, "table-column" ); defaultColumnStyle.addPropertyPt( "style:column-width", Format::globalColWidth() ); defaultColumnStyle.setDefaultStyle( true ); mainStyles.lookup( defaultColumnStyle, "Default", KoGenStyles::DontForceNumbering ); // Saving the default row style KoGenStyle defaultRowStyle( Doc::STYLE_ROW_USER, "table-row" ); defaultRowStyle.addPropertyPt( "style:row-height", Format::globalRowHeight() ); defaultRowStyle.setDefaultStyle( true ); mainStyles.lookup( defaultRowStyle, "Default", KoGenStyles::DontForceNumbering ); // Saving the map. map()->saveOasis( contentTmpWriter, mainStyles, store, manifestWriter, indexObj, partIndexObj ); saveOasisAreaName( contentTmpWriter ); contentTmpWriter.endElement(); ////office:spreadsheet contentTmpWriter.endElement(); ////office:body // Done with writing out the contents to the tempfile, we can now write out the automatic styles contentWriter->startElement( "office:automatic-styles" ); TQValueList styles = mainStyles.styles( KoGenStyle::STYLE_AUTO ); TQValueList::const_iterator it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" ); } styles = mainStyles.styles( STYLE_PAGE ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-properties" ); } styles = mainStyles.styles( STYLE_COLUMN_AUTO ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" ); } styles = mainStyles.styles( STYLE_ROW_AUTO ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" ); } styles = mainStyles.styles( STYLE_CELL_AUTO ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" ); } styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_NUMBER ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); } //TODO FIXME !!!! styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:date-style", (*it).name, 0 /*TODO ????*/ ); } styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_TIME ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:time-style", (*it).name, 0 /*TODO ????*/ ); } styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_FRACTION ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); } //TODO FIME !!!!! styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_PERCENTAGE ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:percentage-style", (*it).name, 0 /*TODO ????*/ ); } //TODO FIME !!!!! styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_CURRENCY ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:currency-style", (*it).name, 0 /*TODO ????*/ ); } styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_SCIENTIFIC ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", (*it).name, 0 /*TODO ????*/ ); } contentWriter->endElement(); // office:automatic-styles // And now we can copy over the contents from the tempfile to the real one tmpFile->close(); contentWriter->addCompleteElement( tmpFile ); contentTmpFile.close(); contentWriter->endElement(); // root element contentWriter->endDocument(); delete contentWriter; if ( !store->close() ) return false; //add manifest line for content.xml manifestWriter->addManifestEntry( "content.xml", "text/xml" ); //todo add manifest line for style.xml if ( !store->open( "styles.xml" ) ) return false; manifestWriter->addManifestEntry( "styles.xml", "text/xml" ); saveOasisDocumentStyles( store, mainStyles ); if ( !store->close() ) // done with styles.xml return false; makeUsedPixmapList(); d->m_pictureCollection.saveOasisToStore( store, d->usedPictures, manifestWriter); if(!store->open("settings.xml")) return false; KoXmlWriter* settingsWriter = createOasisXmlWriter(&dev, "office:document-settings"); settingsWriter->startElement("office:settings"); settingsWriter->startElement("config:config-item-set"); settingsWriter->addAttribute("config:name", "view-settings"); KoUnit::saveOasis(settingsWriter, unit()); saveOasisSettings( *settingsWriter ); settingsWriter->endElement(); // config:config-item-set settingsWriter->startElement("config:config-item-set"); settingsWriter->addAttribute("config:name", "configuration-settings"); settingsWriter->addConfigItem("SpellCheckerIgnoreList", d->spellListIgnoreAll.join( "," ) ); settingsWriter->endElement(); // config:config-item-set settingsWriter->endElement(); // office:settings settingsWriter->endElement(); // Root:element settingsWriter->endDocument(); delete settingsWriter; if(!store->close()) return false; manifestWriter->addManifestEntry("settings.xml", "text/xml"); if ( saveFlag == SaveSelected ) { TQPtrListIterator it(embeddedObjects() ); for( ; it.current(); ++it ) { if ( it.current()->getType() != OBJECT_CHART && it.current()->getType() != OBJECT_KOFFICE_PART ) continue; KoDocumentChild *embedded = dynamic_cast(it.current() )->embeddedObject(); //NOTE: If an application's .desktop file lies about opendocument support (ie. it indicates that it has //a native OASIS mime type, when it doesn't, this causes a crash when trying to reload and paint //the object, since it won't have an associated document. if ( !embedded->saveOasis( store, manifestWriter ) ) continue; } } setModified( false ); return true; } void Doc::loadOasisSettings( const TQDomDocument&settingsDoc ) { KoOasisSettings settings( settingsDoc ); KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" ); if ( !viewSettings.isNull() ) { setUnit(KoUnit::unit(viewSettings.parseConfigItemString("unit"))); } map()->loadOasisSettings( settings ); loadOasisIgnoreList( settings ); } void Doc::saveOasisSettings( KoXmlWriter &settingsWriter ) { settingsWriter.startElement("config:config-item-map-indexed"); settingsWriter.addAttribute("config:name", "Views"); settingsWriter.startElement( "config:config-item-map-entry" ); map()->saveOasisSettings( settingsWriter ); settingsWriter.endElement(); settingsWriter.endElement(); } void Doc::loadOasisIgnoreList( const KoOasisSettings& settings ) { KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" ); if ( !configurationSettings.isNull() ) { const TQString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" ); //kdDebug()<<" ignorelist :"<spellListIgnoreAll = TQStringList::split( ',', ignorelist ); } } void Doc::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles ) const { KoStoreDevice stylesDev( store ); KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" ); stylesWriter->startElement( "office:styles" ); TQValueList styles = mainStyles.styles( KoGenStyle::STYLE_USER ); TQValueList::const_iterator it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" ); } // Writing out the common column styles. styles = mainStyles.styles( Doc::STYLE_COLUMN_USER ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { if ( (*it).style->isDefaultStyle() ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-column-properties" ); } else { (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-column-properties" ); } } // Writing out the row column styles. styles = mainStyles.styles( Doc::STYLE_ROW_USER ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { if ( (*it).style->isDefaultStyle() ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-row-properties" ); } else { (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-row-properties" ); } } // Writing out the common cell styles. styles = mainStyles.styles( Doc::STYLE_CELL_USER ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { if ( (*it).style->isDefaultStyle() ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:default-style", (*it).name, "style:table-cell-properties" ); } else { (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:table-cell-properties" ); } } styles = mainStyles.styles( KoGenStyle::STYLE_HATCH ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( stylesWriter, mainStyles, "draw:hatch", (*it).name, "style:graphic-properties" , true, true /*add draw:name*/); } styles = mainStyles.styles( KoGenStyle::STYLE_GRAPHICAUTO ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" ); } stylesWriter->endElement(); // office:styles stylesWriter->startElement( "office:automatic-styles" ); styles = mainStyles.styles( KoGenStyle::STYLE_PAGELAYOUT ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:page-layout", (*it).name, "style:page-layout-properties", false /*don't close*/ ); stylesWriter->endElement(); } stylesWriter->endElement(); // office:automatic-styles //code from kword stylesWriter->startElement( "office:master-styles" ); styles = mainStyles.styles( Doc::STYLE_PAGEMASTER ); it = styles.begin(); for ( ; it != styles.end() ; ++it ) { (*it).style->writeStyle( stylesWriter, mainStyles, "style:master-page", (*it).name, "" ); } stylesWriter->endElement(); // office:master-style stylesWriter->endElement(); // root element (office:document-styles) stylesWriter->endDocument(); delete stylesWriter;; } bool Doc::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* store) { if ( !d->m_loadingInfo ) d->m_loadingInfo = new KSPLoadingInfo; TQTime dt; dt.start(); emit sigProgress( 0 ); d->isLoading = true; d->spellListIgnoreAll.clear(); d->refs.clear(); TQDomElement content = doc.documentElement(); TQDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) ); if ( realBody.isNull() ) { setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." )); deleteLoadingInfo(); return false; } TQDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "spreadsheet" ); if ( body.isNull() ) { kdError(32001) << "No office:spreadsheet found!" << endl; TQDomElement childElem; TQString localName; forEachElement( childElem, realBody ) { localName = childElem.localName(); } if ( localName.isEmpty() ) setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) ); else setErrorMessage( i18n( "This document is not a spreadsheet, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) ); deleteLoadingInfo(); return false; } KoOasisLoadingContext context( this, oasisStyles, store ); //load in first styleManager()->loadOasisStyleTemplate( oasisStyles ); // load default column style const TQDomElement* defaultColumnStyle = oasisStyles.defaultStyle( "table-column" ); if ( defaultColumnStyle ) { // kDebug() << "style:default-style style:family=\"table-column\"" << endl; KoStyleStack styleStack; styleStack.push( *defaultColumnStyle ); styleStack.setTypeProperties( "table-column" ); if ( styleStack.hasAttributeNS( KoXmlNS::style, "column-width" ) ) { const double width = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "column-width" ), -1.0 ); if ( width != -1.0 ) { // kDebug() << "\tstyle:column-width: " << width << endl; Format::setGlobalColWidth( width ); } } } // load default row style const TQDomElement* defaultRowStyle = oasisStyles.defaultStyle( "table-row" ); if ( defaultRowStyle ) { // kDebug() << "style:default-style style:family=\"table-row\"" << endl; KoStyleStack styleStack; styleStack.push( *defaultRowStyle ); styleStack.setTypeProperties( "table-row" ); if ( styleStack.hasAttributeNS( KoXmlNS::style, "row-height" ) ) { const double height = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "row-height" ), -1.0 ); if ( height != -1.0 ) { // kDebug() << "\tstyle:row-height: " << height << endl; Format::setGlobalRowHeight( height ); } } } // TODO check versions and mimetypes etc. loadOasisAreaName( body ); loadOasisCellValidation( body ); // all goes to workbook if ( !map()->loadOasis( body, context ) ) { d->isLoading = false; deleteLoadingInfo(); return false; } if ( !settings.isNull() ) { loadOasisSettings( settings ); } emit sigProgress( 90 ); initConfig(); emit sigProgress(-1); //display loading time kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl; return true; } bool Doc::loadXML( TQIODevice *, const TQDomDocument& doc ) { TQTime dt; dt.start(); emit sigProgress( 0 ); d->isLoading = true; d->spellListIgnoreAll.clear(); // TQDomElement spread = doc.documentElement(); if ( spread.attribute( "mime" ) != "application/x-kspread" && spread.attribute( "mime" ) != "application/vnd.kde.kspread" ) { d->isLoading = false; setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kspread or application/vnd.kde.kspread, got %1" ).arg( spread.attribute("mime") ) ); return false; } d->syntaxVersion = Doc::getAttribute( spread, "syntaxVersion", 0 ); if ( d->syntaxVersion > CURRENT_SYNTAX_VERSION ) { int ret = KMessageBox::warningContinueCancel( 0, i18n("This document was created with a newer version of KSpread (syntax version: %1)\n" "When you open it with this version of KSpread, some information may be lost.").arg(d->syntaxVersion), i18n("File Format Mismatch"), KStdGuiItem::cont() ); if ( ret == KMessageBox::Cancel ) { setErrorMessage( "USER_CANCELED" ); return false; } } // TQDomElement loc = spread.namedItem( "locale" ).toElement(); if ( !loc.isNull() ) ((Locale *) locale())->load( loc ); emit sigProgress( 5 ); TQDomElement defaults = spread.namedItem( "defaults" ).toElement(); if ( !defaults.isNull() ) { bool ok = false; double d = defaults.attribute( "row-height" ).toDouble( &ok ); if ( !ok ) return false; Format::setGlobalRowHeight( d ); d = defaults.attribute( "col-width" ).toDouble( &ok ); if ( !ok ) return false; Format::setGlobalColWidth( d ); } d->refs.clear(); // TQDomElement areaname = spread.namedItem( "areaname" ).toElement(); if ( !areaname.isNull()) loadAreaName(areaname); TQDomElement ignoreAll = spread.namedItem( "SPELLCHECKIGNORELIST").toElement(); if ( !ignoreAll.isNull()) { TQDomElement spellWord=spread.namedItem("SPELLCHECKIGNORELIST").toElement(); spellWord=spellWord.firstChild().toElement(); while ( !spellWord.isNull() ) { if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" ) { d->spellListIgnoreAll.append(spellWord.attribute("word")); } spellWord=spellWord.nextSibling().toElement(); } } emit sigProgress( 40 ); // In case of reload (e.g. from konqueror) map()->sheetList().clear(); // it's set to autoDelete TQDomElement styles = spread.namedItem( "styles" ).toElement(); if ( !styles.isNull() ) { if ( !styleManager()->loadXML( styles ) ) { setErrorMessage( i18n( "Styles cannot be loaded." ) ); d->isLoading = false; return false; } } // TQDomElement mymap = spread.namedItem( "map" ).toElement(); if ( mymap.isNull() ) { setErrorMessage( i18n("Invalid document. No map tag.") ); d->isLoading = false; return false; } if ( !map()->loadXML( mymap ) ) { d->isLoading = false; return false; } //Backwards compatibility with older versions for paper layout if ( d->syntaxVersion < 1 ) { TQDomElement paper = spread.namedItem( "paper" ).toElement(); if ( !paper.isNull() ) { loadPaper( paper ); } } emit sigProgress( 85 ); TQDomElement element( spread.firstChild().toElement() ); while ( !element.isNull() ) { TQString tagName( element.tagName() ); if ( tagName != "locale" && tagName != "map" && tagName != "styles" && tagName != "SPELLCHECKIGNORELIST" && tagName != "areaname" && tagName != "paper" ) { // belongs to a plugin, load it and save it for later use m_savedDocParts[ tagName ] = element; } element = element.nextSibling().toElement(); } emit sigProgress( 90 ); initConfig(); emit sigProgress(-1); kdDebug(36001) << "Loading took " << (float)(dt.elapsed()) / 1000.0 << " seconds" << endl; emit sig_refreshView(); return true; } void Doc::loadPaper( TQDomElement const & paper ) { // TQString format = paper.attribute( "format" ); TQString orientation = paper.attribute( "orientation" ); // TQDomElement borders = paper.namedItem( "borders" ).toElement(); if ( !borders.isNull() ) { float left = borders.attribute( "left" ).toFloat(); float right = borders.attribute( "right" ).toFloat(); float top = borders.attribute( "top" ).toFloat(); float bottom = borders.attribute( "bottom" ).toFloat(); //apply to all sheet TQPtrListIterator it ( map()->sheetList() ); for( ; it.current(); ++it ) { it.current()->print()->setPaperLayout( left, top, right, bottom, format, orientation ); } } TQString hleft, hright, hcenter; TQString fleft, fright, fcenter; // TQDomElement head = paper.namedItem( "head" ).toElement(); if ( !head.isNull() ) { TQDomElement left = head.namedItem( "left" ).toElement(); if ( !left.isNull() ) hleft = left.text(); TQDomElement center = head.namedItem( "center" ).toElement(); if ( !center.isNull() ) hcenter = center.text(); TQDomElement right = head.namedItem( "right" ).toElement(); if ( !right.isNull() ) hright = right.text(); } // TQDomElement foot = paper.namedItem( "foot" ).toElement(); if ( !foot.isNull() ) { TQDomElement left = foot.namedItem( "left" ).toElement(); if ( !left.isNull() ) fleft = left.text(); TQDomElement center = foot.namedItem( "center" ).toElement(); if ( !center.isNull() ) fcenter = center.text(); TQDomElement right = foot.namedItem( "right" ).toElement(); if ( !right.isNull() ) fright = right.text(); } //The macro "" formerly was typed as "" hleft = hleft.replace( "
", "" ); hcenter = hcenter.replace( "
", "" ); hright = hright.replace( "
", "" ); fleft = fleft.replace( "
", "" ); fcenter = fcenter.replace( "
", "" ); fright = fright.replace( "
", "" ); TQPtrListIterator it ( map()->sheetList() ); for( ; it.current(); ++it ) { it.current()->print()->setHeadFootLine( hleft, hcenter, hright, fleft, fcenter, fright); } } bool Doc::completeLoading( KoStore* /* _store */ ) { kdDebug(36001) << "------------------------ COMPLETING --------------------" << endl; d->isLoading = false; // map()->update(); TQPtrListIterator it( views() ); for (; it.current(); ++it ) ((View*)it.current())->initialPosition(); kdDebug(36001) << "------------------------ COMPLETION DONE --------------------" << endl; setModified( false ); return true; } void Doc::registerPlugin( Plugin * plugin ) { d->plugins.append( plugin ); } void Doc::deregisterPlugin( Plugin * plugin ) { d->plugins.remove( plugin ); } bool Doc::docData( TQString const & xmlTag, TQDomElement & data ) { SavedDocParts::iterator iter = m_savedDocParts.find( xmlTag ); if ( iter == m_savedDocParts.end() ) return false; data = iter.data(); m_savedDocParts.erase( iter ); return true; } void Doc::setShowVerticalScrollBar(bool _show) { d->verticalScrollBar=_show; } bool Doc::showVerticalScrollBar()const { return d->verticalScrollBar; } void Doc::setShowHorizontalScrollBar(bool _show) { d->horizontalScrollBar=_show; } bool Doc::showHorizontalScrollBar()const { return d->horizontalScrollBar; } TDEGlobalSettings::Completion Doc::completionMode( ) const { return d->completionMode; } void Doc::setShowColumnHeader(bool _show) { d->columnHeader=_show; } bool Doc::showColumnHeader() const { return d->columnHeader; } void Doc::setShowRowHeader(bool _show) { d->rowHeader=_show; } bool Doc::showRowHeader() const { return d->rowHeader; } void Doc::setGridColor( const TQColor& color ) { d->gridColor = color; } TQColor Doc::gridColor() const { return d->gridColor; } void Doc::setCompletionMode( TDEGlobalSettings::Completion complMode) { d->completionMode= complMode; } double Doc::indentValue() const { return d->indentValue; } void Doc::setIndentValue( double val ) { d->indentValue = val; } void Doc::setShowStatusBar(bool _statusBar) { d->showStatusBar=_statusBar; } bool Doc::showStatusBar() const { return d->showStatusBar; } void Doc::setShowTabBar(bool _tabbar) { d->showTabBar=_tabbar; } bool Doc::showTabBar()const { return d->showTabBar; } void Doc::setShowFormulaBar(bool _formulaBar) { d->showFormulaBar=_formulaBar; } bool Doc::showFormulaBar() const { return d->showFormulaBar; } void Doc::setShowMessageError(bool _show) { d->showError=_show; } bool Doc::showMessageError() const { return d->showError; } KSpread::MoveTo Doc::getMoveToValue() const { return d->moveTo; } void Doc::setMoveToValue(KSpread::MoveTo _moveTo) { d->moveTo = _moveTo; } void Doc::setTypeOfCalc( MethodOfCalc _calc) { d->calcMethod=_calc; } MethodOfCalc Doc::getTypeOfCalc() const { return d->calcMethod; } void Doc::setKSpellConfig(KSpellConfig _tdespell) { if (d->spellConfig == 0 ) d->spellConfig = new KSpellConfig(); d->spellConfig->setNoRootAffix(_tdespell.noRootAffix ()); d->spellConfig->setRunTogether(_tdespell.runTogether ()); d->spellConfig->setDictionary(_tdespell.dictionary ()); d->spellConfig->setDictFromList(_tdespell.dictFromList()); d->spellConfig->setEncoding(_tdespell.encoding()); d->spellConfig->setClient(_tdespell.client()); } KSpellConfig * Doc::getKSpellConfig() { if (!d->spellConfig) { KSpellConfig ksconfig; TDEConfig *config = Factory::global()->config(); if( config->hasGroup("KSpell kspread" ) ) { config->setGroup( "KSpell kspread" ); ksconfig.setNoRootAffix(config->readNumEntry ("KSpell_NoRootAffix", 0)); ksconfig.setRunTogether(config->readNumEntry ("KSpell_RunTogether", 0)); ksconfig.setDictionary(config->readEntry ("KSpell_Dictionary", "")); ksconfig.setDictFromList(config->readNumEntry ("KSpell_DictFromList", false)); ksconfig.setEncoding(config->readNumEntry ("KSpell_Encoding", KS_E_ASCII)); ksconfig.setClient(config->readNumEntry ("KSpell_Client", KS_CLIENT_ISPELL)); setKSpellConfig(ksconfig); setDontCheckUpperWord(config->readBoolEntry("KSpell_IgnoreUppercaseWords", false)); setDontCheckTitleCase(config->readBoolEntry("KSpell_IgnoreTitleCaseWords", false)); } } return d->spellConfig; } bool Doc::dontCheckUpperWord() const { return d->dontCheckUpperWord; } void Doc::setDontCheckUpperWord( bool b ) { d->dontCheckUpperWord = b; } bool Doc::dontCheckTitleCase() const { return d->dontCheckTitleCase; } void Doc::setDontCheckTitleCase( bool b ) { d->dontCheckTitleCase = b; } TQString Doc::unitName() const { return KoUnit::unitName( unit() ); } void Doc::increaseNumOperation() { ++d->numOperations; } void Doc::decreaseNumOperation() { --d->numOperations; } void Doc::addIgnoreWordAllList( const TQStringList & _lst) { d->spellListIgnoreAll = _lst; } TQStringList Doc::spellListIgnoreAll() const { return d->spellListIgnoreAll; } void Doc::setZoomAndResolution( int zoom, int dpiX, int dpiY ) { KoZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY ); } void Doc::newZoomAndResolution( bool updateViews, bool /*forPrint*/ ) { /* layout(); updateAllFrames();*/ if ( updateViews ) { emit sig_refreshView(); } } void Doc::addCommand( KCommand* command ) { if (undoLocked()) return; d->commandHistory->addCommand( command, false ); setModified( true ); } void Doc::addCommand( UndoAction* undo ) { if (undoLocked()) return; UndoWrapperCommand* command = new UndoWrapperCommand( undo ); addCommand( command ); setModified( true ); } void Doc::undo() { undoLock (); d->commandHistory->undo(); undoUnlock (); } void Doc::redo() { undoLock (); d->commandHistory->redo(); undoUnlock (); } void Doc::commandExecuted() { setModified( true ); } void Doc::documentRestored() { setModified( false ); } void Doc::undoLock() { d->undoLocked++; } void Doc::undoUnlock() { d->undoLocked--; } bool Doc::undoLocked() const { return (d->undoLocked > 0); } KoCommandHistory* Doc::commandHistory() { return d->commandHistory; } void Doc::enableUndo( bool _b ) { TQPtrListIterator it( views() ); for (; it.current(); ++it ) static_cast( it.current() )->enableUndo( _b ); } void Doc::enableRedo( bool _b ) { TQPtrListIterator it( views() ); for (; it.current(); ++it ) static_cast( it.current() )->enableRedo( _b ); } void Doc::paintContent( TQPainter& painter, const TQRect& rect, bool transparent, double zoomX, double /*zoomY*/ ) { kdDebug(36001) << "paintContent() called on " << rect << endl; // ElapsedTime et( "Doc::paintContent1" ); //kdDebug(36001) << "Doc::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << endl; // save current zoom int oldZoom = m_zoom; // choose sheet: the first or the active Sheet* sheet = 0L; if ( !d->activeSheet ) sheet = map()->firstSheet(); else sheet = d->activeSheet; if ( !sheet ) return; // only one zoom is supported double d_zoom = 1.0; setZoomAndResolution( 100, KoGlobal::dpiX(), KoGlobal::dpiY() ); if ( m_zoomedResolutionX != zoomX ) d_zoom *= ( zoomX / m_zoomedResolutionX ); // KSpread support zoom, therefore no need to scale with worldMatrix TQWMatrix matrix = painter.worldMatrix(); matrix.setMatrix( 1, 0, 0, 1, matrix.dx(), matrix.dy() ); TQRect prect = rect; prect.setWidth( (int) (prect.width() * painter.worldMatrix().m11()) ); prect.setHeight( (int) (prect.height() * painter.worldMatrix().m22()) ); setZoomAndResolution( (int) ( d_zoom * 100 ), KoGlobal::dpiX(), KoGlobal::dpiY() ); // paint the content, now zoom is correctly set kdDebug(36001)<<"paintContent-------------------------------------\n"; painter.save(); painter.setWorldMatrix( matrix ); paintContent( painter, prect, transparent, sheet, false ); painter.restore(); // restore zoom m_zoom = oldZoom; setZoomAndResolution( oldZoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); } void Doc::paintContent( TQPainter& painter, const TQRect& rect, bool /*transparent*/, Sheet* sheet, bool drawCursor ) { if ( isLoading() ) return; // ElapsedTime et( "Doc::paintContent2" ); // if ( !transparent ) // painter.eraseRect( rect ); double xpos; double ypos; int left_col = sheet->leftColumn( unzoomItX( rect.x() ), xpos ); int right_col = sheet->rightColumn( unzoomItX( rect.right() ) ); int top_row = sheet->topRow( unzoomItY( rect.y() ), ypos ); int bottom_row = sheet->bottomRow( unzoomItY( rect.bottom() ) ); TQPen pen; pen.setWidth( 1 ); painter.setPen( pen ); /* Update the entire visible area. */ TQValueList cellAreaList; cellAreaList.append( TQRect( left_col, top_row, right_col - left_col + 1, bottom_row - top_row + 1) ); paintCellRegions(painter, rect, NULL, cellAreaList, sheet, drawCursor); } void Doc::paintUpdates() { // ElapsedTime et( "Doc::paintUpdates" ); TQPtrListIterator it( views() ); View * view = NULL; Sheet * sheet = NULL; for (; it.current(); ++it ) { view = static_cast( it.current() ); view->paintUpdates(); } for (sheet = map()->firstSheet(); sheet != NULL; sheet = map()->nextSheet()) { sheet->clearPaintDirtyData(); } } void Doc::paintCellRegions(TQPainter& painter, const TQRect &viewRect, View* view, TQValueList cellRegions, const Sheet* sheet, bool /*drawCursor*/) { // // Clip away children // TQRegion rgn = painter.clipRegion(); if ( rgn.isEmpty() ) rgn = TQRegion( TQRect( 0, 0, viewRect.width(), viewRect.height() ) ); TQWMatrix matrix; if ( view ) { matrix.scale( zoomedResolutionX(), zoomedResolutionY() ); matrix.translate( - view->canvasWidget()->xOffset(), - view->canvasWidget()->yOffset() ); } else { matrix = painter.worldMatrix(); } // TQPtrListIterator it( children() ); // for( ; it.current(); ++it ) { // // if ( ((Child*)it.current())->sheet() == sheet && // // !m_pView->hasDocumentInWindow( it.current()->document() ) ) // if ( ((Child*)it.current())->sheet() == sheet) // rgn -= it.current()->region( matrix ); // } painter.setClipRegion( rgn ); TQPen pen; pen.setWidth( 1 ); painter.setPen( pen ); TQRect cellRegion; KoRect unzoomedViewRect = unzoomRect( viewRect ); for (unsigned int i=0; i < cellRegions.size(); i++) { cellRegion = cellRegions[i]; PaintRegion(painter, unzoomedViewRect, view, cellRegion, sheet); } } void Doc::PaintRegion(TQPainter &painter, const KoRect &viewRegion, View* view, const TQRect &paintRegion, const Sheet* sheet) { // Paint region has cell coordinates (col,row) while viewRegion has // world coordinates. paintRegion is the cells to update and // viewRegion is the area actually onscreen. if ( paintRegion.left() <= 0 || paintRegion.top() <= 0 ) return; // Get the world coordinates of the upper left corner of the // paintRegion The view is NULL, when paintRegion is called from // paintContent, which itself is only called, when we should paint // the output for INACTIVE embedded view. If inactive embedded, // then there is no view and we alwas start at top/left, so the // offset is 0. // KoPoint dblCorner; if ( view == 0L ) //Most propably we are embedded and inactive, so no offset dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ), sheet->dblRowPos( paintRegion.top() ) ); else dblCorner = KoPoint( sheet->dblColumnPos( paintRegion.left() ) - view->canvasWidget()->xOffset(), sheet->dblRowPos( paintRegion.top() ) - view->canvasWidget()->yOffset() ); KoPoint dblCurrentCellPos( dblCorner ); int regionBottom = paintRegion.bottom(); int regionRight = paintRegion.right(); int regionLeft = paintRegion.left(); int regionTop = paintRegion.top(); TQValueList mergedCellsPainted; for ( int y = regionTop; y <= regionBottom && dblCurrentCellPos.y() <= viewRegion.bottom(); ++y ) { const RowFormat * row_lay = sheet->rowFormat( y ); dblCurrentCellPos.setX( dblCorner.x() ); for ( int x = regionLeft; x <= regionRight && dblCurrentCellPos.x() <= viewRegion.right(); ++x ) { const ColumnFormat *col_lay = sheet->columnFormat( x ); Cell* cell = sheet->cellAt( x, y ); TQPoint cellRef( x, y ); #if 0 bool paintBordersBottom = false; bool paintBordersRight = false; bool paintBordersLeft = false; bool paintBordersTop = false; #endif int paintBorder = Cell::Border_None; TQPen rightPen( cell->effRightBorderPen( x, y ) ); TQPen leftPen( cell->effLeftBorderPen( x, y ) ); TQPen topPen( cell->effTopBorderPen( x, y ) ); TQPen bottomPen( cell->effBottomBorderPen( x, y ) ); // Paint border if outermost cell or if the pen is more "worth" // than the border pen of the cell on the other side of the // border or if the cell on the other side is not painted. In // the latter case get the pen that is of more "worth" // right border: if ( x >= KS_colMax ) //paintBordersRight = true; paintBorder |= Cell::Border_Right; else if ( x == regionRight ) { paintBorder |= Cell::Border_Right; if ( cell->effRightBorderValue( x, y ) < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); } else { paintBorder |= Cell::Border_Right; if ( cell->effRightBorderValue( x, y ) < sheet->cellAt( x + 1, y )->effLeftBorderValue( x + 1, y ) ) rightPen = sheet->cellAt( x + 1, y )->effLeftBorderPen( x + 1, y ); } // Similiar for other borders... // bottom border: if ( y >= KS_rowMax ) paintBorder |= Cell::Border_Bottom; else if ( y == regionBottom ) { paintBorder |= Cell::Border_Bottom; if ( cell->effBottomBorderValue( x, y ) < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) ) bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); } else { paintBorder |= Cell::Border_Bottom; if ( cell->effBottomBorderValue( x, y ) < sheet->cellAt( x, y + 1 )->effTopBorderValue( x, y + 1) ) bottomPen = sheet->cellAt( x, y + 1 )->effTopBorderPen( x, y + 1 ); } // left border: if ( x == 1 ) paintBorder |= Cell::Border_Left; else if ( x == regionLeft ) { paintBorder |= Cell::Border_Left; if ( cell->effLeftBorderValue( x, y ) < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); } else { paintBorder |= Cell::Border_Left; if ( cell->effLeftBorderValue( x, y ) < sheet->cellAt( x - 1, y )->effRightBorderValue( x - 1, y ) ) leftPen = sheet->cellAt( x - 1, y )->effRightBorderPen( x - 1, y ); } // top border: if ( y == 1 ) paintBorder |= Cell::Border_Top; else if ( y == regionTop ) { paintBorder |= Cell::Border_Top; if ( cell->effTopBorderValue( x, y ) < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); } else { paintBorder |= Cell::Border_Top; if ( cell->effTopBorderValue( x, y ) < sheet->cellAt( x, y - 1 )->effBottomBorderValue( x, y - 1 ) ) topPen = sheet->cellAt( x, y - 1 )->effBottomBorderPen( x, y - 1 ); } #if 0 cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef, paintBordersRight, paintBordersBottom, paintBordersLeft, paintBordersTop, rightPen, bottomPen, leftPen, topPen, mergedCellsPainted, false ); Cell::BorderSides highlightBorder=Cell::Border_None; TQPen highlightPen; #endif cell->paintCell( viewRegion, painter, view, dblCurrentCellPos, cellRef, paintBorder, rightPen, bottomPen, leftPen, topPen, mergedCellsPainted, false ); dblCurrentCellPos.setX( dblCurrentCellPos.x() + col_lay->dblWidth() ); } dblCurrentCellPos.setY( dblCurrentCellPos.y() + row_lay->dblHeight() ); } } DCOPObject* Doc::dcopObject() { if ( !d->dcop ) d->dcop = new DocIface( this ); return d->dcop; } void Doc::addAreaName(const TQRect &_rect,const TQString & name,const TQString & sheetName) { setModified( true ); Reference tmp; tmp.rect = _rect; tmp.sheet_name = sheetName; tmp.ref_name = name; d->refs.append( tmp); emit sig_addAreaName( name ); } void Doc::removeArea( const TQString & name) { TQValueList::Iterator it2; for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) { if((*it2).ref_name==name) { d->refs.remove(it2); emit sig_removeAreaName( name ); return; } } } void Doc::changeAreaSheetName(const TQString & oldName,const TQString & sheetName) { TQValueList::Iterator it2; for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) { if((*it2).sheet_name==oldName) (*it2).sheet_name=sheetName; } } TQRect Doc::getRectArea(const TQString &_sheetName) { TQValueList::Iterator it2; for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) { if((*it2).ref_name==_sheetName) { return (*it2).rect; } } return TQRect(-1,-1,-1,-1); } TQDomElement Doc::saveAreaName( TQDomDocument& doc ) { TQDomElement element = doc.createElement( "areaname" ); TQValueList::Iterator it2; for ( it2 = d->refs.begin(); it2 != d->refs.end(); ++it2 ) { TQDomElement e = doc.createElement("reference"); TQDomElement tabname = doc.createElement( "tabname" ); tabname.appendChild( doc.createTextNode( (*it2).sheet_name ) ); e.appendChild( tabname ); TQDomElement refname = doc.createElement( "refname" ); refname.appendChild( doc.createTextNode( (*it2).ref_name ) ); e.appendChild( refname ); TQDomElement rect = doc.createElement( "rect" ); rect.setAttribute( "left-rect", ((*it2).rect).left() ); rect.setAttribute( "right-rect",((*it2).rect).right() ); rect.setAttribute( "top-rect", ((*it2).rect).top() ); rect.setAttribute( "bottom-rect", ((*it2).rect).bottom() ); e.appendChild( rect ); element.appendChild(e); } return element; } void Doc::loadOasisCellValidation( const TQDomElement&body ) { TQDomNode validation = KoDom::namedItemNS( body, KoXmlNS::table, "content-validations" ); kdDebug()<<"void Doc::loadOasisCellValidation( const TQDomElement&body ) \n"; kdDebug()<<"validation.isNull ? "<m_loadingInfo->appendValidation(element.attributeNS( KoXmlNS::table, "name", TQString() ), element ); kdDebug()<<" validation found :"<0 ) { xmlWriter.startElement( "table:named-expressions" ); TQValueList::Iterator it; for ( it = d->refs.begin(); it != d->refs.end(); ++it ) { xmlWriter.startElement( "table:named-range" ); xmlWriter.addAttribute( "table:name", ( *it ).ref_name ); xmlWriter.addAttribute( "table:base-cell-address", convertRefToBase( ( *it ).sheet_name, ( *it ).rect ) ); xmlWriter.addAttribute( "table:cell-range-address", convertRefToRange( ( *it ).sheet_name, ( *it ).rect ) ); xmlWriter.endElement(); } xmlWriter.endElement(); } } void Doc::loadOasisAreaName( const TQDomElement& body ) { kdDebug()<<"void Doc::loadOasisAreaName( const TQDomElement& body ) \n"; TQDomNode namedAreas = KoDom::namedItemNS( body, KoXmlNS::table, "named-expressions" ); if ( !namedAreas.isNull() ) { kdDebug()<<" area name exist \n"; TQDomNode area = namedAreas.firstChild(); while ( !area.isNull() ) { TQDomElement e = area.toElement(); if ( e.localName() == "named-range" ) { if ( !e.hasAttributeNS( KoXmlNS::table, "name" ) || !e.hasAttributeNS( KoXmlNS::table, "cell-range-address" ) ) { kdDebug() << "Reading in named area failed" << endl; area = area.nextSibling(); continue; } // TODO: what is: sheet:base-cell-address TQString name = e.attributeNS( KoXmlNS::table, "name", TQString() ); TQString range = e.attributeNS( KoXmlNS::table, "cell-range-address", TQString() ); kdDebug()<<"area name : "<m_loadingInfo->addWordInAreaList( name ); kdDebug() << "Reading in named area, name: " << name << ", area: " << range << endl; range = Oasis::decodeFormula( range ); if ( range.find( ':' ) == -1 ) { Point p( range ); int n = range.find( '!' ); if ( n > 0 ) range = range + ":" + range.right( range.length() - n - 1); kdDebug() << "=> Area: " << range << endl; } if ( range.contains( '!' ) && range[0] == '$' ) { // cut absolute sheet indicator range.remove( 0, 1 ); } Range p( range ); addAreaName( p.range(), name, p.sheetName() ); kdDebug() << "Area range: " << p.toString() << endl; } else if ( e.localName() == "named-expression" ) { kdDebug() << "Named expression found." << endl; // TODO } area = area.nextSibling(); } } } void Doc::loadAreaName( const TQDomElement& element ) { TQDomElement tmp=element.firstChild().toElement(); for( ; !tmp.isNull(); tmp=tmp.nextSibling().toElement() ) { if ( tmp.tagName() == "reference" ) { TQString tabname; TQString refname; int left=0; int right=0; int top=0; int bottom=0; TQDomElement sheetName = tmp.namedItem( "tabname" ).toElement(); if ( !sheetName.isNull() ) { tabname=sheetName.text(); } TQDomElement referenceName = tmp.namedItem( "refname" ).toElement(); if ( !referenceName.isNull() ) { refname=referenceName.text(); } TQDomElement rect =tmp.namedItem( "rect" ).toElement(); if (!rect.isNull()) { bool ok; if ( rect.hasAttribute( "left-rect" ) ) left=rect.attribute("left-rect").toInt( &ok ); if ( rect.hasAttribute( "right-rect" ) ) right=rect.attribute("right-rect").toInt( &ok ); if ( rect.hasAttribute( "top-rect" ) ) top=rect.attribute("top-rect").toInt( &ok ); if ( rect.hasAttribute( "bottom-rect" ) ) bottom=rect.attribute("bottom-rect").toInt( &ok ); } TQRect _rect; _rect.setCoords(left,top,right,bottom); addAreaName(_rect,refname,tabname); } } } void Doc::addStringCompletion(const TQString &stringCompletion) { if ( d->listCompletion.items().contains(stringCompletion) == 0 ) d->listCompletion.addItem( stringCompletion ); } void Doc::refreshInterface() { emit sig_refreshView(); } void Doc::refreshLocale() { emit sig_refreshLocale(); } void Doc::emitBeginOperation(bool waitCursor) { //If an emitBeginOperation occurs with waitCursor enabled, then the waiting cursor is set //until all operations have been completed. // //The reason being that any operations started before the first one with waitCursor set //are expected to be completed in a short time anyway. TQCursor* activeOverride = static_cast(TQApplication::overrideCursor()); if (waitCursor && ( (!activeOverride) || (activeOverride->shape() != TQt::waitCursor.shape()) ) ) { TQApplication::setOverrideCursor(TQt::waitCursor); } // /* just duplicate the current cursor on the stack, then */ // else if (TQApplication::overrideCursor() != NULL) // { // TQApplication::setOverrideCursor(TQApplication::overrideCursor()->shape()); // } KoDocument::emitBeginOperation(); d->delayCalculation = true; d->numOperations++; } void Doc::emitBeginOperation(void) { emitBeginOperation(true); } void Doc::emitEndOperation() { d->numOperations--; if (d->numOperations <= 0) { d->numOperations = 0; d->delayCalculation = false; } KoDocument::emitEndOperation(); if (d->numOperations == 0) { TQApplication::restoreOverrideCursor(); /* do this after the parent class emitEndOperation because that allows updates on the view again */ paintUpdates(); } } void Doc::emitEndOperation( const Region& /*region*/ ) { d->numOperations--; if ( d->numOperations > 0 || !d->activeSheet ) { KoDocument::emitEndOperation(); return; } d->numOperations = 0; d->delayCalculation = false; KoDocument::emitEndOperation(); TQApplication::restoreOverrideCursor(); /* do this after the parent class emitEndOperation because that allows updates on the view again */ paintUpdates(); } bool Doc::delayCalculation() const { return d->delayCalculation; } void Doc::updateBorderButton() { TQPtrListIterator it( views() ); for (; it.current(); ++it ) static_cast( it.current() )->updateBorderButton(); } void Doc::insertSheet( Sheet * sheet ) { TQPtrListIterator it( views() ); for (; it.current(); ++it ) ((View*)it.current())->insertSheet( sheet ); } void Doc::takeSheet( Sheet * sheet ) { TQPtrListIterator it( views() ); for (; it.current(); ++it ) ((View*)it.current())->removeSheet( sheet ); } void Doc::addIgnoreWordAll( const TQString & word) { if( d->spellListIgnoreAll.findIndex( word )==-1) d->spellListIgnoreAll.append( word ); } void Doc::clearIgnoreWordAll( ) { d->spellListIgnoreAll.clear(); } void Doc::setDisplaySheet(Sheet *_sheet ) { d->activeSheet = _sheet; } KSPLoadingInfo * Doc::loadingInfo() const { return d->m_loadingInfo; } void Doc::deleteLoadingInfo() { delete d->m_loadingInfo; d->m_loadingInfo = 0; } Sheet * Doc::displaySheet() const { return d->activeSheet; } void Doc::addView( KoView *_view ) { KoDocument::addView( _view ); TQPtrListIterator it( views() ); for (; it.current(); ++it ) ((View*)it.current())->closeEditor(); } void Doc::addDamage( Damage* damage ) { d->damages.append( damage ); if( d->damages.count() == 1 ) TQTimer::singleShot( 0, this, TQ_SLOT( flushDamages() ) ); } void Doc::flushDamages() { emit damagesFlushed( d->damages ); TQValueList::Iterator it; for( it = d->damages.begin(); it != d->damages.end(); ++it ) delete *it; d->damages.clear(); } void Doc::loadConfigFromFile() { d->configLoadFromFile = true; } bool Doc::configLoadFromFile() const { return d->configLoadFromFile; } void Doc::insertObject( EmbeddedObject * obj ) { switch ( obj->getType() ) { case OBJECT_KOFFICE_PART: case OBJECT_CHART: { KoDocument::insertChild( dynamic_cast(obj)->embeddedObject() ); break; } default: ; } d->m_embeddedObjects.append( obj ); } TQPtrList& Doc::embeddedObjects() { return d->m_embeddedObjects; } KoPictureCollection *Doc::pictureCollection() { return &d->m_pictureCollection; } void Doc::repaint( const TQRect& rect ) { TQRect r; TQPtrListIterator it( views() ); for( ; it.current(); ++it ) { r = rect; Canvas* canvas = ((View*)it.current())->canvasWidget(); r.moveTopLeft( TQPoint( r.x() - (int) canvas->xOffset(), r.y() - (int) canvas->yOffset() ) ); canvas->update( r ); } } void Doc::repaint( EmbeddedObject *obj ) { TQPtrListIterator it( views() ); for( ; it.current(); ++it ) { Canvas* canvas = ((View*)it.current())->canvasWidget(); if ( obj->sheet() == canvas->activeSheet() ) canvas->repaintObject( obj ); } } void Doc::repaint( const KoRect& rect ) { TQRect r; TQPtrListIterator it( views() ); for( ; it.current(); ++it ) { Canvas* canvas = ((View*)it.current())->canvasWidget(); r = zoomRect( rect ); r.moveBy( (int)( -canvas->xOffset()*zoomedResolutionX() ) , (int)( -canvas->yOffset() *zoomedResolutionY()) ); canvas->update( r ); } } void Doc::addShell( KoMainWindow *shell ) { connect( shell, TQ_SIGNAL( documentSaved() ), d->commandHistory, TQ_SLOT( documentSaved() ) ); KoDocument::addShell( shell ); } int Doc::undoRedoLimit() const { return d->commandHistory->undoLimit(); } void Doc::setUndoRedoLimit(int val) { d->commandHistory->setUndoLimit(val); d->commandHistory->setRedoLimit(val); } void Doc::insertPixmapKey( KoPictureKey key ) { if ( !d->usedPictures.contains( key ) ) d->usedPictures.append( key ); } void Doc::makeUsedPixmapList() { d->usedPictures.clear(); TQPtrListIterator it( d->m_embeddedObjects ); for ( ; it.current() ; ++it ) { if( it.current()->getType() == OBJECT_PICTURE && ( d->m_savingWholeDocument || it.current()->isSelected() ) ) insertPixmapKey( static_cast( it.current() )->getKey() ); } } bool Doc::savingWholeDocument() { return d->m_savingWholeDocument; } #include "kspread_doc.moc"