diff options
Diffstat (limited to 'kspread/kspread_map.cpp')
-rw-r--r-- | kspread/kspread_map.cpp | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/kspread/kspread_map.cpp b/kspread/kspread_map.cpp new file mode 100644 index 00000000..d54c340a --- /dev/null +++ b/kspread/kspread_map.cpp @@ -0,0 +1,524 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + + 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 <stdlib.h> +#include <time.h> + +#include <tqfile.h> + +#include <kmdcodec.h> +#include <tdetempfile.h> + +#include <KoDom.h> +#include <KoGenStyles.h> +#include <KoOasisSettings.h> +#include <KoOasisStyles.h> +#include <KoXmlNS.h> +#include <KoXmlWriter.h> + +#include "kspread_canvas.h" +#include "kspread_doc.h" +#include "kspread_genvalidationstyle.h" +#include "kspread_locale.h" +#include "kspread_sheet.h" +#include "kspread_style.h" +#include "kspread_style_manager.h" +#include "kspread_view.h" +#include "KSpreadMapIface.h" + +#include "kspread_map.h" + +using namespace KSpread; + +bool Map::respectCase = true; + +Map::Map ( Doc* doc, const char* name) + : TQObject( doc, name ), + m_doc( doc ), + m_initialActiveSheet( 0 ), + m_initialMarkerColumn( 0 ), + m_initialMarkerRow( 0 ), + m_initialXOffset(0.0), + m_initialYOffset(0.0), + tableId (1), + m_dcop( 0 ) +{ + m_lstSheets.setAutoDelete( true ); +} + +Map::~Map() +{ + delete m_dcop; +} + +Doc* Map::doc() const +{ + return m_doc; +} + +void Map::setProtected( TQCString const & passwd ) +{ + m_strPassword = passwd; +} + +Sheet* Map::createSheet() +{ + TQString s( i18n("Sheet%1") ); + s = s.arg( tableId++ ); + Sheet *t = new Sheet ( this, s , s.utf8()); + t->setSheetName( s, true ); // huh? (Werner) + return t; +} + +void Map::addSheet( Sheet *_sheet ) +{ + m_lstSheets.append( _sheet ); + + m_doc->setModified( true ); + + emit sig_addSheet( _sheet ); +} + +Sheet *Map::addNewSheet () +{ + Sheet *t = createSheet (); + addSheet (t); + return t; +} + +void Map::moveSheet( const TQString & _from, const TQString & _to, bool _before ) +{ + Sheet* sheetfrom = findSheet( _from ); + Sheet* sheetto = findSheet( _to ); + + int from = m_lstSheets.find( sheetfrom ) ; + int to = m_lstSheets.find( sheetto ) ; + if ( !_before ) + ++to; + + if ( to > (int)m_lstSheets.count() ) + { + m_lstSheets.append( sheetfrom ); + m_lstSheets.take( from ); + } + else if ( from < to ) + { + m_lstSheets.insert( to, sheetfrom ); + m_lstSheets.take( from ); + } + else + { + m_lstSheets.take( from ); + m_lstSheets.insert( to, sheetfrom ); + } +} + +void Map::loadOasisSettings( KoOasisSettings &settings ) +{ + KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" ); + KoOasisSettings::IndexedMap viewMap = viewSettings.indexedMap( "Views" ); + KoOasisSettings::Items firstView = viewMap.entry( 0 ); + + KoOasisSettings::NamedMap sheetsMap = firstView.namedMap( "Tables" ); + kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) exist : "<< !sheetsMap.isNull() <<endl; + if ( !sheetsMap.isNull() ) + { + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + { + it.current()->loadOasisSettings( sheetsMap ); + } + } + + TQString activeSheet = firstView.parseConfigItemString( "ActiveTable" ); + kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) activeSheet :"<<activeSheet<<endl; + + if (!activeSheet.isEmpty()) + { + // Used by View's constructor + m_initialActiveSheet = findSheet( activeSheet ); + } + +} + +void Map::saveOasisSettings( KoXmlWriter &settingsWriter ) +{ + settingsWriter.addConfigItem( "ViewId", TQString::fromLatin1( "View1" ) ); + // Save visual info for the first view, such as active sheet and active cell + // It looks like a hack, but reopening a document creates only one view anyway (David) + View * view = m_doc->views().isEmpty() ? 0 : dynamic_cast<View*>(m_doc->views().getFirst()); + if ( view ) // no view if embedded document + { + // save current sheet selection before to save marker, otherwise current pos is not saved + view->saveCurrentSheetSelection(); + //<config:config-item config:name="ActiveTable" config:type="string">Feuille1</config:config-item> + settingsWriter.addConfigItem( "ActiveTable", view->activeSheet()->sheetName() ); + } + + //<config:config-item-map-named config:name="Tables"> + settingsWriter.startElement("config:config-item-map-named" ); + settingsWriter.addAttribute("config:name","Tables" ); + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + { + settingsWriter.startElement( "config:config-item-map-entry" ); + settingsWriter.addAttribute( "config:name", ( *it )->sheetName() ); + if ( view ) + { + TQPoint marker = view->markerFromSheet( *it ); + KoPoint offset = view->offsetFromSheet( *it ); + settingsWriter.addConfigItem( "CursorPositionX", marker.x() ); + settingsWriter.addConfigItem( "CursorPositionY", marker.y() ); + settingsWriter.addConfigItem( "xOffset", offset.x() ); + settingsWriter.addConfigItem( "yOffset", offset.y() ); + } + it.current()->saveOasisSettings( settingsWriter ); + settingsWriter.endElement(); + } + settingsWriter.endElement(); +} + + +bool Map::saveOasis( KoXmlWriter & xmlWriter, KoGenStyles & mainStyles, KoStore *store, KoXmlWriter* manifestWriter, int &_indexObj, int &_partIndexObj ) +{ + if ( !m_strPassword.isEmpty() ) + { + xmlWriter.addAttribute("table:structure-protected", "true" ); + TQCString str = KCodecs::base64Encode( m_strPassword ); + xmlWriter.addAttribute("table:protection-key", TQString( str.data() ) );/* FIXME !!!!*/ + } + + GenValidationStyles valStyle; + + KTempFile bodyTmpFile; + //Check that creation of temp file was successful + if (bodyTmpFile.status() != 0) + { + tqWarning("Creation of temporary file to store document body failed."); + return false; + } + + bodyTmpFile.setAutoDelete( true ); + TQFile* tmpFile = bodyTmpFile.file(); + KoXmlWriter bodyTmpWriter( TQT_TQIODEVICE(tmpFile) ); + + + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + { + it.current()->saveOasis( bodyTmpWriter, mainStyles, valStyle, store, manifestWriter, _indexObj, _partIndexObj ); + } + + valStyle.writeStyle( xmlWriter ); + + + tmpFile->close(); + xmlWriter.addCompleteElement( TQT_TQIODEVICE(tmpFile) ); + bodyTmpFile.close(); + + return true; +} + +TQDomElement Map::save( TQDomDocument& doc ) +{ + TQDomElement mymap = doc.createElement( "map" ); + // Save visual info for the first view, such as active sheet and active cell + // It looks like a hack, but reopening a document creates only one view anyway (David) + View * view = static_cast<View*>(m_doc->views().getFirst()); + if ( view ) // no view if embedded document + { + Canvas * canvas = view->canvasWidget(); + mymap.setAttribute( "activeTable", canvas->activeSheet()->sheetName() ); + mymap.setAttribute( "markerColumn", canvas->markerColumn() ); + mymap.setAttribute( "markerRow", canvas->markerRow() ); + mymap.setAttribute( "xOffset", canvas->xOffset() ); + mymap.setAttribute( "yOffset", canvas->yOffset() ); + } + + if ( !m_strPassword.isNull() ) + { + if ( m_strPassword.size() > 0 ) + { + TQCString str = KCodecs::base64Encode( m_strPassword ); + mymap.setAttribute( "protected", TQString( str.data() ) ); + } + else + mymap.setAttribute( "protected", "" ); + } + + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + { + TQDomElement e = it.current()->saveXML( doc ); + if ( e.isNull() ) + return e; + mymap.appendChild( e ); + } + return mymap; +} + +bool Map::loadOasis( const TQDomElement& body, KoOasisLoadingContext& oasisContext ) +{ + if ( body.hasAttributeNS( KoXmlNS::table, "structure-protected" ) ) + { + TQCString passwd( "" ); + if ( body.hasAttributeNS( KoXmlNS::table, "protection-key" ) ) + { + TQString p = body.attributeNS( KoXmlNS::table, "protection-key", TQString() ); + TQCString str( p.latin1() ); + passwd = KCodecs::base64Decode( str ); + } + m_strPassword = passwd; + } + TQDomNode sheetNode = KoDom::namedItemNS( body, KoXmlNS::table, "table" ); + + // sanity check + if ( sheetNode.isNull() ) return false; + + while ( !sheetNode.isNull() ) + { + TQDomElement sheetElement = sheetNode.toElement(); + if( !sheetElement.isNull() ) + { + //kdDebug()<<" Map::loadOasis tableElement is not null \n"; + //kdDebug()<<"tableElement.nodeName() :"<<sheetElement.nodeName()<<endl; + if( sheetElement.nodeName() == "table:table" ) + { + if( !sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ).isEmpty() ) + { + Sheet* sheet = addNewSheet(); + sheet->setSheetName( sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ), true, false ); + } + } + } + sheetNode = sheetNode.nextSibling(); + } + + //pre-load auto styles + TQDict<Style> autoStyles = doc()->styleManager()->loadOasisAutoStyles( oasisContext.oasisStyles() ); + + // load the sheet + sheetNode = body.firstChild(); + while ( !sheetNode.isNull() ) + { + TQDomElement sheetElement = sheetNode.toElement(); + if( !sheetElement.isNull() ) + { + //kdDebug()<<"tableElement.nodeName() bis :"<<sheetElement.nodeName()<<endl; + if( sheetElement.nodeName() == "table:table" ) + { + if( !sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ).isEmpty() ) + { + TQString name = sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ); + Sheet* sheet = findSheet( name ); + if( sheet ) + sheet->loadOasis( sheetElement, oasisContext, autoStyles ); + } + } + } + sheetNode = sheetNode.nextSibling(); + } + + //delete any styles which were not used + doc()->styleManager()->releaseUnusedAutoStyles( autoStyles ); + + return true; +} + + +bool Map::loadXML( const TQDomElement& mymap ) +{ + TQString activeSheet = mymap.attribute( "activeTable" ); + m_initialMarkerColumn = mymap.attribute( "markerColumn" ).toInt(); + m_initialMarkerRow = mymap.attribute( "markerRow" ).toInt(); + m_initialXOffset = mymap.attribute( "xOffset" ).toDouble(); + m_initialYOffset = mymap.attribute( "yOffset" ).toDouble(); + + TQDomNode n = mymap.firstChild(); + if ( n.isNull() ) + { + // We need at least one sheet ! + doc()->setErrorMessage( i18n("This document has no sheets (tables).") ); + return false; + } + while( !n.isNull() ) + { + TQDomElement e = n.toElement(); + if ( !e.isNull() && e.tagName() == "table" ) + { + Sheet *t = addNewSheet(); + if ( !t->loadXML( e ) ) + return false; + } + n = n.nextSibling(); + } + + if ( mymap.hasAttribute( "protected" ) ) + { + TQString passwd = mymap.attribute( "protected" ); + + if ( passwd.length() > 0 ) + { + TQCString str( passwd.latin1() ); + m_strPassword = KCodecs::base64Decode( str ); + } + else + m_strPassword = TQCString( "" ); + } + + if (!activeSheet.isEmpty()) + { + // Used by View's constructor + m_initialActiveSheet = findSheet( activeSheet ); + } + + return true; +} + +void Map::update() +{ + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + it.current()->recalc(); +} + +Sheet* Map::findSheet( const TQString & _name ) +{ + Sheet * t; + + for ( t = m_lstSheets.first(); t != 0L; t = m_lstSheets.next() ) + { + if ( _name.lower() == t->sheetName().lower() ) + return t; + } + + return 0L; +} + +Sheet * Map::nextSheet( Sheet * currentSheet ) +{ + Sheet * t; + + if( currentSheet == m_lstSheets.last()) + return currentSheet; + + for ( t = m_lstSheets.first(); t != 0L; t = m_lstSheets.next() ) + { + if ( t == currentSheet ) + return m_lstSheets.next(); + } + + return 0L; +} + +Sheet * Map::previousSheet( Sheet * currentSheet ) +{ + Sheet * t; + + if( currentSheet == m_lstSheets.first()) + return currentSheet; + + for ( t = m_lstSheets.first(); t != 0L; t = m_lstSheets.next() ) + { + if ( t == currentSheet ) + return m_lstSheets.prev(); + } + + return 0L; +} + +bool Map::saveChildren( KoStore * _store ) +{ + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + { + // set the child document's url to an internal url (ex: "tar:/0/1") + if ( !it.current()->saveChildren( _store, it.current()->sheetName() ) ) + return false; + } + return true; +} + +bool Map::loadChildren( KoStore * _store ) +{ + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it.current(); ++it ) + if ( !it.current()->loadChildren( _store ) ) + return false; + + return true; +} + +DCOPObject * Map::dcopObject() +{ + if ( !m_dcop ) + m_dcop = new MapIface( this ); + + return m_dcop; +} + +void Map::takeSheet( Sheet * sheet ) +{ + int pos = m_lstSheets.findRef( sheet ); + m_lstSheets.take( pos ); + m_lstDeletedSheets.append( sheet ); +} + +void Map::insertSheet( Sheet * sheet ) +{ + int pos = m_lstDeletedSheets.findRef( sheet ); + if ( pos != -1 ) + m_lstDeletedSheets.take( pos ); + m_lstSheets.append(sheet); +} + +// FIXME cache this for faster operation +TQStringList Map::visibleSheets() const +{ + TQStringList result; + + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it; ++it ) + { + Sheet* sheet = it.current(); + if( !sheet->isHidden() ) + result.append( sheet->sheetName() ); + } + + return result; +} + +// FIXME cache this for faster operation +TQStringList Map::hiddenSheets() const +{ + TQStringList result; + + TQPtrListIterator<Sheet> it( m_lstSheets ); + for( ; it; ++it ) + { + Sheet* sheet = it.current(); + if( sheet->isHidden() ) + result.append( sheet->sheetName() ); + } + + return result; +} + +#include "kspread_map.moc" + |