You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
525 lines
14 KiB
525 lines
14 KiB
15 years ago
|
/* 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>
|
||
|
|
||
14 years ago
|
#include <tqfile.h>
|
||
15 years ago
|
|
||
|
#include <kmdcodec.h>
|
||
12 years ago
|
#include <tdetempfile.h>
|
||
15 years ago
|
|
||
|
#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)
|
||
14 years ago
|
: TQObject( doc, name ),
|
||
15 years ago
|
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;
|
||
|
}
|
||
|
|
||
14 years ago
|
void Map::setProtected( TQCString const & passwd )
|
||
15 years ago
|
{
|
||
|
m_strPassword = passwd;
|
||
|
}
|
||
|
|
||
|
Sheet* Map::createSheet()
|
||
|
{
|
||
14 years ago
|
TQString s( i18n("Sheet%1") );
|
||
13 years ago
|
s = s.arg( tableId++ );
|
||
15 years ago
|
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;
|
||
|
}
|
||
|
|
||
14 years ago
|
void Map::moveSheet( const TQString & _from, const TQString & _to, bool _before )
|
||
15 years ago
|
{
|
||
|
Sheet* sheetfrom = findSheet( _from );
|
||
|
Sheet* sheetto = findSheet( _to );
|
||
|
|
||
13 years ago
|
int from = m_lstSheets.find( sheetfrom ) ;
|
||
|
int to = m_lstSheets.find( sheetto ) ;
|
||
15 years ago
|
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() )
|
||
|
{
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it.current(); ++it )
|
||
|
{
|
||
|
it.current()->loadOasisSettings( sheetsMap );
|
||
|
}
|
||
|
}
|
||
|
|
||
14 years ago
|
TQString activeSheet = firstView.parseConfigItemString( "ActiveTable" );
|
||
15 years ago
|
kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) activeSheet :"<<activeSheet<<endl;
|
||
|
|
||
|
if (!activeSheet.isEmpty())
|
||
|
{
|
||
|
// Used by View's constructor
|
||
|
m_initialActiveSheet = findSheet( activeSheet );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void Map::saveOasisSettings( KoXmlWriter &settingsWriter )
|
||
|
{
|
||
13 years ago
|
settingsWriter.addConfigItem( "ViewId", TQString::fromLatin1( "View1" ) );
|
||
15 years ago
|
// 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" );
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it.current(); ++it )
|
||
|
{
|
||
|
settingsWriter.startElement( "config:config-item-map-entry" );
|
||
|
settingsWriter.addAttribute( "config:name", ( *it )->sheetName() );
|
||
|
if ( view )
|
||
|
{
|
||
14 years ago
|
TQPoint marker = view->markerFromSheet( *it );
|
||
15 years ago
|
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" );
|
||
14 years ago
|
TQCString str = KCodecs::base64Encode( m_strPassword );
|
||
|
xmlWriter.addAttribute("table:protection-key", TQString( str.data() ) );/* FIXME !!!!*/
|
||
15 years ago
|
}
|
||
|
|
||
|
GenValidationStyles valStyle;
|
||
|
|
||
|
KTempFile bodyTmpFile;
|
||
|
//Check that creation of temp file was successful
|
||
|
if (bodyTmpFile.status() != 0)
|
||
|
{
|
||
13 years ago
|
tqWarning("Creation of temporary file to store document body failed.");
|
||
15 years ago
|
return false;
|
||
|
}
|
||
|
|
||
|
bodyTmpFile.setAutoDelete( true );
|
||
14 years ago
|
TQFile* tmpFile = bodyTmpFile.file();
|
||
|
KoXmlWriter bodyTmpWriter( TQT_TQIODEVICE(tmpFile) );
|
||
15 years ago
|
|
||
|
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it.current(); ++it )
|
||
|
{
|
||
|
it.current()->saveOasis( bodyTmpWriter, mainStyles, valStyle, store, manifestWriter, _indexObj, _partIndexObj );
|
||
|
}
|
||
|
|
||
|
valStyle.writeStyle( xmlWriter );
|
||
|
|
||
|
|
||
|
tmpFile->close();
|
||
14 years ago
|
xmlWriter.addCompleteElement( TQT_TQIODEVICE(tmpFile) );
|
||
15 years ago
|
bodyTmpFile.close();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
14 years ago
|
TQDomElement Map::save( TQDomDocument& doc )
|
||
15 years ago
|
{
|
||
14 years ago
|
TQDomElement mymap = doc.createElement( "map" );
|
||
15 years ago
|
// 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 )
|
||
|
{
|
||
14 years ago
|
TQCString str = KCodecs::base64Encode( m_strPassword );
|
||
|
mymap.setAttribute( "protected", TQString( str.data() ) );
|
||
15 years ago
|
}
|
||
|
else
|
||
|
mymap.setAttribute( "protected", "" );
|
||
|
}
|
||
|
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it.current(); ++it )
|
||
|
{
|
||
14 years ago
|
TQDomElement e = it.current()->saveXML( doc );
|
||
15 years ago
|
if ( e.isNull() )
|
||
|
return e;
|
||
|
mymap.appendChild( e );
|
||
|
}
|
||
|
return mymap;
|
||
|
}
|
||
|
|
||
14 years ago
|
bool Map::loadOasis( const TQDomElement& body, KoOasisLoadingContext& oasisContext )
|
||
15 years ago
|
{
|
||
|
if ( body.hasAttributeNS( KoXmlNS::table, "structure-protected" ) )
|
||
|
{
|
||
14 years ago
|
TQCString passwd( "" );
|
||
15 years ago
|
if ( body.hasAttributeNS( KoXmlNS::table, "protection-key" ) )
|
||
|
{
|
||
14 years ago
|
TQString p = body.attributeNS( KoXmlNS::table, "protection-key", TQString() );
|
||
|
TQCString str( p.latin1() );
|
||
15 years ago
|
passwd = KCodecs::base64Decode( str );
|
||
|
}
|
||
|
m_strPassword = passwd;
|
||
|
}
|
||
14 years ago
|
TQDomNode sheetNode = KoDom::namedItemNS( body, KoXmlNS::table, "table" );
|
||
15 years ago
|
|
||
|
// sanity check
|
||
|
if ( sheetNode.isNull() ) return false;
|
||
|
|
||
|
while ( !sheetNode.isNull() )
|
||
|
{
|
||
14 years ago
|
TQDomElement sheetElement = sheetNode.toElement();
|
||
15 years ago
|
if( !sheetElement.isNull() )
|
||
|
{
|
||
|
//kdDebug()<<" Map::loadOasis tableElement is not null \n";
|
||
|
//kdDebug()<<"tableElement.nodeName() :"<<sheetElement.nodeName()<<endl;
|
||
|
if( sheetElement.nodeName() == "table:table" )
|
||
|
{
|
||
14 years ago
|
if( !sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ).isEmpty() )
|
||
15 years ago
|
{
|
||
|
Sheet* sheet = addNewSheet();
|
||
14 years ago
|
sheet->setSheetName( sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ), true, false );
|
||
15 years ago
|
}
|
||
|
}
|
||
|
}
|
||
|
sheetNode = sheetNode.nextSibling();
|
||
|
}
|
||
|
|
||
|
//pre-load auto styles
|
||
14 years ago
|
TQDict<Style> autoStyles = doc()->styleManager()->loadOasisAutoStyles( oasisContext.oasisStyles() );
|
||
15 years ago
|
|
||
|
// load the sheet
|
||
|
sheetNode = body.firstChild();
|
||
|
while ( !sheetNode.isNull() )
|
||
|
{
|
||
14 years ago
|
TQDomElement sheetElement = sheetNode.toElement();
|
||
15 years ago
|
if( !sheetElement.isNull() )
|
||
|
{
|
||
|
//kdDebug()<<"tableElement.nodeName() bis :"<<sheetElement.nodeName()<<endl;
|
||
|
if( sheetElement.nodeName() == "table:table" )
|
||
|
{
|
||
14 years ago
|
if( !sheetElement.attributeNS( KoXmlNS::table, "name", TQString() ).isEmpty() )
|
||
15 years ago
|
{
|
||
14 years ago
|
TQString name = sheetElement.attributeNS( KoXmlNS::table, "name", TQString() );
|
||
15 years ago
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
14 years ago
|
bool Map::loadXML( const TQDomElement& mymap )
|
||
15 years ago
|
{
|
||
14 years ago
|
TQString activeSheet = mymap.attribute( "activeTable" );
|
||
15 years ago
|
m_initialMarkerColumn = mymap.attribute( "markerColumn" ).toInt();
|
||
|
m_initialMarkerRow = mymap.attribute( "markerRow" ).toInt();
|
||
|
m_initialXOffset = mymap.attribute( "xOffset" ).toDouble();
|
||
|
m_initialYOffset = mymap.attribute( "yOffset" ).toDouble();
|
||
|
|
||
14 years ago
|
TQDomNode n = mymap.firstChild();
|
||
15 years ago
|
if ( n.isNull() )
|
||
|
{
|
||
|
// We need at least one sheet !
|
||
|
doc()->setErrorMessage( i18n("This document has no sheets (tables).") );
|
||
|
return false;
|
||
|
}
|
||
|
while( !n.isNull() )
|
||
|
{
|
||
14 years ago
|
TQDomElement e = n.toElement();
|
||
15 years ago
|
if ( !e.isNull() && e.tagName() == "table" )
|
||
|
{
|
||
|
Sheet *t = addNewSheet();
|
||
|
if ( !t->loadXML( e ) )
|
||
|
return false;
|
||
|
}
|
||
|
n = n.nextSibling();
|
||
|
}
|
||
|
|
||
|
if ( mymap.hasAttribute( "protected" ) )
|
||
|
{
|
||
14 years ago
|
TQString passwd = mymap.attribute( "protected" );
|
||
15 years ago
|
|
||
|
if ( passwd.length() > 0 )
|
||
|
{
|
||
14 years ago
|
TQCString str( passwd.latin1() );
|
||
15 years ago
|
m_strPassword = KCodecs::base64Decode( str );
|
||
|
}
|
||
|
else
|
||
14 years ago
|
m_strPassword = TQCString( "" );
|
||
15 years ago
|
}
|
||
|
|
||
|
if (!activeSheet.isEmpty())
|
||
|
{
|
||
|
// Used by View's constructor
|
||
|
m_initialActiveSheet = findSheet( activeSheet );
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Map::update()
|
||
|
{
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it.current(); ++it )
|
||
|
it.current()->recalc();
|
||
|
}
|
||
|
|
||
14 years ago
|
Sheet* Map::findSheet( const TQString & _name )
|
||
15 years ago
|
{
|
||
|
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 )
|
||
|
{
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
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 )
|
||
|
{
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
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 )
|
||
|
{
|
||
13 years ago
|
int pos = m_lstSheets.findRef( sheet );
|
||
15 years ago
|
m_lstSheets.take( pos );
|
||
|
m_lstDeletedSheets.append( sheet );
|
||
|
}
|
||
|
|
||
|
void Map::insertSheet( Sheet * sheet )
|
||
|
{
|
||
13 years ago
|
int pos = m_lstDeletedSheets.findRef( sheet );
|
||
15 years ago
|
if ( pos != -1 )
|
||
|
m_lstDeletedSheets.take( pos );
|
||
|
m_lstSheets.append(sheet);
|
||
|
}
|
||
|
|
||
|
// FIXME cache this for faster operation
|
||
14 years ago
|
TQStringList Map::visibleSheets() const
|
||
15 years ago
|
{
|
||
14 years ago
|
TQStringList result;
|
||
15 years ago
|
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it; ++it )
|
||
|
{
|
||
|
Sheet* sheet = it.current();
|
||
|
if( !sheet->isHidden() )
|
||
|
result.append( sheet->sheetName() );
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// FIXME cache this for faster operation
|
||
14 years ago
|
TQStringList Map::hiddenSheets() const
|
||
15 years ago
|
{
|
||
14 years ago
|
TQStringList result;
|
||
15 years ago
|
|
||
14 years ago
|
TQPtrListIterator<Sheet> it( m_lstSheets );
|
||
15 years ago
|
for( ; it; ++it )
|
||
|
{
|
||
|
Sheet* sheet = it.current();
|
||
|
if( sheet->isHidden() )
|
||
|
result.append( sheet->sheetName() );
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
#include "kspread_map.moc"
|
||
|
|