00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdlib.h>
00021 #include <time.h>
00022
00023 #include <qfile.h>
00024
00025 #include <kmdcodec.h>
00026 #include <ktempfile.h>
00027
00028 #include <KoDom.h>
00029 #include <KoGenStyles.h>
00030 #include <KoOasisSettings.h>
00031 #include <KoOasisStyles.h>
00032 #include <KoXmlNS.h>
00033 #include <KoXmlWriter.h>
00034
00035 #include "kspread_canvas.h"
00036 #include "kspread_doc.h"
00037 #include "kspread_genvalidationstyle.h"
00038 #include "kspread_locale.h"
00039 #include "kspread_sheet.h"
00040 #include "kspread_style.h"
00041 #include "kspread_style_manager.h"
00042 #include "kspread_view.h"
00043 #include "KSpreadMapIface.h"
00044
00045 #include "kspread_map.h"
00046
00047 using namespace KSpread;
00048
00049 bool Map::respectCase = true;
00050
00051 Map::Map ( Doc* doc, const char* name)
00052 : QObject( doc, name ),
00053 m_doc( doc ),
00054 m_initialActiveSheet( 0 ),
00055 m_initialMarkerColumn( 0 ),
00056 m_initialMarkerRow( 0 ),
00057 m_initialXOffset(0.0),
00058 m_initialYOffset(0.0),
00059 tableId (1),
00060 m_dcop( 0 )
00061 {
00062 m_lstSheets.setAutoDelete( true );
00063 }
00064
00065 Map::~Map()
00066 {
00067 delete m_dcop;
00068 }
00069
00070 Doc* Map::doc() const
00071 {
00072 return m_doc;
00073 }
00074
00075 void Map::setProtected( QCString const & passwd )
00076 {
00077 m_strPassword = passwd;
00078 }
00079
00080 Sheet* Map::createSheet()
00081 {
00082 QString s( i18n("Sheet%1") );
00083 s = s.arg( tableId++ );
00084 Sheet *t = new Sheet ( this, s , s.utf8());
00085 t->setSheetName( s, true );
00086 return t;
00087 }
00088
00089 void Map::addSheet( Sheet *_sheet )
00090 {
00091 m_lstSheets.append( _sheet );
00092
00093 m_doc->setModified( true );
00094
00095 emit sig_addSheet( _sheet );
00096 }
00097
00098 Sheet *Map::addNewSheet ()
00099 {
00100 Sheet *t = createSheet ();
00101 addSheet (t);
00102 return t;
00103 }
00104
00105 void Map::moveSheet( const QString & _from, const QString & _to, bool _before )
00106 {
00107 Sheet* sheetfrom = findSheet( _from );
00108 Sheet* sheetto = findSheet( _to );
00109
00110 int from = m_lstSheets.find( sheetfrom ) ;
00111 int to = m_lstSheets.find( sheetto ) ;
00112 if ( !_before )
00113 ++to;
00114
00115 if ( to > (int)m_lstSheets.count() )
00116 {
00117 m_lstSheets.append( sheetfrom );
00118 m_lstSheets.take( from );
00119 }
00120 else if ( from < to )
00121 {
00122 m_lstSheets.insert( to, sheetfrom );
00123 m_lstSheets.take( from );
00124 }
00125 else
00126 {
00127 m_lstSheets.take( from );
00128 m_lstSheets.insert( to, sheetfrom );
00129 }
00130 }
00131
00132 void Map::loadOasisSettings( KoOasisSettings &settings )
00133 {
00134 KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
00135 KoOasisSettings::IndexedMap viewMap = viewSettings.indexedMap( "Views" );
00136 KoOasisSettings::Items firstView = viewMap.entry( 0 );
00137
00138 KoOasisSettings::NamedMap sheetsMap = firstView.namedMap( "Tables" );
00139 kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) exist : "<< !sheetsMap.isNull() <<endl;
00140 if ( !sheetsMap.isNull() )
00141 {
00142 QPtrListIterator<Sheet> it( m_lstSheets );
00143 for( ; it.current(); ++it )
00144 {
00145 it.current()->loadOasisSettings( sheetsMap );
00146 }
00147 }
00148
00149 QString activeSheet = firstView.parseConfigItemString( "ActiveTable" );
00150 kdDebug()<<" loadOasisSettings( KoOasisSettings &settings ) activeSheet :"<<activeSheet<<endl;
00151
00152 if (!activeSheet.isEmpty())
00153 {
00154
00155 m_initialActiveSheet = findSheet( activeSheet );
00156 }
00157
00158 }
00159
00160 void Map::saveOasisSettings( KoXmlWriter &settingsWriter )
00161 {
00162 settingsWriter.addConfigItem( "ViewId", QString::fromLatin1( "View1" ) );
00163
00164
00165 View * view = static_cast<View*>( m_doc->views().getFirst());
00166 if ( view )
00167 {
00168
00169 view->saveCurrentSheetSelection();
00170
00171 settingsWriter.addConfigItem( "ActiveTable", view->activeSheet()->sheetName() );
00172 }
00173
00174
00175 settingsWriter.startElement("config:config-item-map-named" );
00176 settingsWriter.addAttribute("config:name","Tables" );
00177 QPtrListIterator<Sheet> it( m_lstSheets );
00178 for( ; it.current(); ++it )
00179 {
00180 settingsWriter.startElement( "config:config-item-map-entry" );
00181 settingsWriter.addAttribute( "config:name", ( *it )->sheetName() );
00182 if ( view )
00183 {
00184 QPoint marker = view->markerFromSheet( *it );
00185 KoPoint offset = view->offsetFromSheet( *it );
00186 settingsWriter.addConfigItem( "CursorPositionX", marker.x() );
00187 settingsWriter.addConfigItem( "CursorPositionY", marker.y() );
00188 settingsWriter.addConfigItem( "xOffset", offset.x() );
00189 settingsWriter.addConfigItem( "yOffset", offset.y() );
00190 }
00191 it.current()->saveOasisSettings( settingsWriter );
00192 settingsWriter.endElement();
00193 }
00194 settingsWriter.endElement();
00195 }
00196
00197
00198 bool Map::saveOasis( KoXmlWriter & xmlWriter, KoGenStyles & mainStyles, KoStore *store, KoXmlWriter* manifestWriter, int &_indexObj, int &_partIndexObj )
00199 {
00200 if ( !m_strPassword.isEmpty() )
00201 {
00202 xmlWriter.addAttribute("table:structure-protected", "true" );
00203 QCString str = KCodecs::base64Encode( m_strPassword );
00204 xmlWriter.addAttribute("table:protection-key", QString( str.data() ) );
00205 }
00206
00207 GenValidationStyles valStyle;
00208
00209 KTempFile bodyTmpFile;
00210
00211 if (bodyTmpFile.status() != 0)
00212 {
00213 qWarning("Creation of temporary file to store document body failed.");
00214 return false;
00215 }
00216
00217 bodyTmpFile.setAutoDelete( true );
00218 QFile* tmpFile = bodyTmpFile.file();
00219 KoXmlWriter bodyTmpWriter( tmpFile );
00220
00221
00222 QPtrListIterator<Sheet> it( m_lstSheets );
00223 for( ; it.current(); ++it )
00224 {
00225 it.current()->saveOasis( bodyTmpWriter, mainStyles, valStyle, store, manifestWriter, _indexObj, _partIndexObj );
00226 }
00227
00228 valStyle.writeStyle( xmlWriter );
00229
00230
00231 tmpFile->close();
00232 xmlWriter.addCompleteElement( tmpFile );
00233 bodyTmpFile.close();
00234
00235 return true;
00236 }
00237
00238 QDomElement Map::save( QDomDocument& doc )
00239 {
00240 QDomElement mymap = doc.createElement( "map" );
00241
00242
00243 View * view = static_cast<View*>(m_doc->views().getFirst());
00244 if ( view )
00245 {
00246 Canvas * canvas = view->canvasWidget();
00247 mymap.setAttribute( "activeTable", canvas->activeSheet()->sheetName() );
00248 mymap.setAttribute( "markerColumn", canvas->markerColumn() );
00249 mymap.setAttribute( "markerRow", canvas->markerRow() );
00250 mymap.setAttribute( "xOffset", canvas->xOffset() );
00251 mymap.setAttribute( "yOffset", canvas->yOffset() );
00252 }
00253
00254 if ( !m_strPassword.isNull() )
00255 {
00256 if ( m_strPassword.size() > 0 )
00257 {
00258 QCString str = KCodecs::base64Encode( m_strPassword );
00259 mymap.setAttribute( "protected", QString( str.data() ) );
00260 }
00261 else
00262 mymap.setAttribute( "protected", "" );
00263 }
00264
00265 QPtrListIterator<Sheet> it( m_lstSheets );
00266 for( ; it.current(); ++it )
00267 {
00268 QDomElement e = it.current()->saveXML( doc );
00269 if ( e.isNull() )
00270 return e;
00271 mymap.appendChild( e );
00272 }
00273 return mymap;
00274 }
00275
00276 bool Map::loadOasis( const QDomElement& body, KoOasisLoadingContext& oasisContext )
00277 {
00278 if ( body.hasAttributeNS( KoXmlNS::table, "structure-protected" ) )
00279 {
00280 QCString passwd( "" );
00281 if ( body.hasAttributeNS( KoXmlNS::table, "protection-key" ) )
00282 {
00283 QString p = body.attributeNS( KoXmlNS::table, "protection-key", QString::null );
00284 QCString str( p.latin1() );
00285 passwd = KCodecs::base64Decode( str );
00286 }
00287 m_strPassword = passwd;
00288 }
00289 QDomNode sheetNode = KoDom::namedItemNS( body, KoXmlNS::table, "table" );
00290
00291
00292 if ( sheetNode.isNull() ) return false;
00293
00294 while ( !sheetNode.isNull() )
00295 {
00296 QDomElement sheetElement = sheetNode.toElement();
00297 if( !sheetElement.isNull() )
00298 {
00299
00300
00301 if( sheetElement.nodeName() == "table:table" )
00302 {
00303 if( !sheetElement.attributeNS( KoXmlNS::table, "name", QString::null ).isEmpty() )
00304 {
00305 Sheet* sheet = addNewSheet();
00306 sheet->setSheetName( sheetElement.attributeNS( KoXmlNS::table, "name", QString::null ), true, false );
00307 }
00308 }
00309 }
00310 sheetNode = sheetNode.nextSibling();
00311 }
00312
00313
00314 QDict<Style> autoStyles = doc()->styleManager()->loadOasisAutoStyles( oasisContext.oasisStyles() );
00315
00316
00317 sheetNode = body.firstChild();
00318 while ( !sheetNode.isNull() )
00319 {
00320 QDomElement sheetElement = sheetNode.toElement();
00321 if( !sheetElement.isNull() )
00322 {
00323
00324 if( sheetElement.nodeName() == "table:table" )
00325 {
00326 if( !sheetElement.attributeNS( KoXmlNS::table, "name", QString::null ).isEmpty() )
00327 {
00328 QString name = sheetElement.attributeNS( KoXmlNS::table, "name", QString::null );
00329 Sheet* sheet = findSheet( name );
00330 if( sheet )
00331 sheet->loadOasis( sheetElement, oasisContext, autoStyles );
00332 }
00333 }
00334 }
00335 sheetNode = sheetNode.nextSibling();
00336 }
00337
00338
00339 doc()->styleManager()->releaseUnusedAutoStyles( autoStyles );
00340
00341 return true;
00342 }
00343
00344
00345 bool Map::loadXML( const QDomElement& mymap )
00346 {
00347 QString activeSheet = mymap.attribute( "activeTable" );
00348 m_initialMarkerColumn = mymap.attribute( "markerColumn" ).toInt();
00349 m_initialMarkerRow = mymap.attribute( "markerRow" ).toInt();
00350 m_initialXOffset = mymap.attribute( "xOffset" ).toDouble();
00351 m_initialYOffset = mymap.attribute( "yOffset" ).toDouble();
00352
00353 QDomNode n = mymap.firstChild();
00354 if ( n.isNull() )
00355 {
00356
00357 doc()->setErrorMessage( i18n("This document has no sheets (tables).") );
00358 return false;
00359 }
00360 while( !n.isNull() )
00361 {
00362 QDomElement e = n.toElement();
00363 if ( !e.isNull() && e.tagName() == "table" )
00364 {
00365 Sheet *t = addNewSheet();
00366 if ( !t->loadXML( e ) )
00367 return false;
00368 }
00369 n = n.nextSibling();
00370 }
00371
00372 if ( mymap.hasAttribute( "protected" ) )
00373 {
00374 QString passwd = mymap.attribute( "protected" );
00375
00376 if ( passwd.length() > 0 )
00377 {
00378 QCString str( passwd.latin1() );
00379 m_strPassword = KCodecs::base64Decode( str );
00380 }
00381 else
00382 m_strPassword = QCString( "" );
00383 }
00384
00385 if (!activeSheet.isEmpty())
00386 {
00387
00388 m_initialActiveSheet = findSheet( activeSheet );
00389 }
00390
00391 return true;
00392 }
00393
00394 void Map::update()
00395 {
00396 QPtrListIterator<Sheet> it( m_lstSheets );
00397 for( ; it.current(); ++it )
00398 it.current()->recalc();
00399 }
00400
00401 Sheet* Map::findSheet( const QString & _name )
00402 {
00403 Sheet * t;
00404
00405 for ( t = m_lstSheets.first(); t != 0L; t = m_lstSheets.next() )
00406 {
00407 if ( _name.lower() == t->sheetName().lower() )
00408 return t;
00409 }
00410
00411 return 0L;
00412 }
00413
00414 Sheet * Map::nextSheet( Sheet * currentSheet )
00415 {
00416 Sheet * t;
00417
00418 if( currentSheet == m_lstSheets.last())
00419 return currentSheet;
00420
00421 for ( t = m_lstSheets.first(); t != 0L; t = m_lstSheets.next() )
00422 {
00423 if ( t == currentSheet )
00424 return m_lstSheets.next();
00425 }
00426
00427 return 0L;
00428 }
00429
00430 Sheet * Map::previousSheet( Sheet * currentSheet )
00431 {
00432 Sheet * t;
00433
00434 if( currentSheet == m_lstSheets.first())
00435 return currentSheet;
00436
00437 for ( t = m_lstSheets.first(); t != 0L; t = m_lstSheets.next() )
00438 {
00439 if ( t == currentSheet )
00440 return m_lstSheets.prev();
00441 }
00442
00443 return 0L;
00444 }
00445
00446 bool Map::saveChildren( KoStore * _store )
00447 {
00448 QPtrListIterator<Sheet> it( m_lstSheets );
00449 for( ; it.current(); ++it )
00450 {
00451
00452 if ( !it.current()->saveChildren( _store, it.current()->sheetName() ) )
00453 return false;
00454 }
00455 return true;
00456 }
00457
00458 bool Map::loadChildren( KoStore * _store )
00459 {
00460 QPtrListIterator<Sheet> it( m_lstSheets );
00461 for( ; it.current(); ++it )
00462 if ( !it.current()->loadChildren( _store ) )
00463 return false;
00464
00465 return true;
00466 }
00467
00468 DCOPObject * Map::dcopObject()
00469 {
00470 if ( !m_dcop )
00471 m_dcop = new MapIface( this );
00472
00473 return m_dcop;
00474 }
00475
00476 void Map::takeSheet( Sheet * sheet )
00477 {
00478 int pos = m_lstSheets.findRef( sheet );
00479 m_lstSheets.take( pos );
00480 m_lstDeletedSheets.append( sheet );
00481 }
00482
00483 void Map::insertSheet( Sheet * sheet )
00484 {
00485 int pos = m_lstDeletedSheets.findRef( sheet );
00486 if ( pos != -1 )
00487 m_lstDeletedSheets.take( pos );
00488 m_lstSheets.append(sheet);
00489 }
00490
00491
00492 QStringList Map::visibleSheets() const
00493 {
00494 QStringList result;
00495
00496 QPtrListIterator<Sheet> it( m_lstSheets );
00497 for( ; it; ++it )
00498 {
00499 Sheet* sheet = it.current();
00500 if( !sheet->isHidden() )
00501 result.append( sheet->sheetName() );
00502 }
00503
00504 return result;
00505 }
00506
00507
00508 QStringList Map::hiddenSheets() const
00509 {
00510 QStringList result;
00511
00512 QPtrListIterator<Sheet> it( m_lstSheets );
00513 for( ; it; ++it )
00514 {
00515 Sheet* sheet = it.current();
00516 if( sheet->isHidden() )
00517 result.append( sheet->sheetName() );
00518 }
00519
00520 return result;
00521 }
00522
00523 #include "kspread_map.moc"
00524