filters

opencalcimport.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 Norbert Andres <nandres@web.de>
00003    Copyright (C) 2004 - 2005  Laurent Montel <montel@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <float.h>
00022 #include <math.h>
00023 
00024 #include <qcolor.h>
00025 #include <qfile.h>
00026 #include <qfont.h>
00027 #include <qpen.h>
00028 #include <qxml.h>
00029 
00030 #include "opencalcimport.h"
00031 
00032 #include <kdebug.h>
00033 #include <KoDocumentInfo.h>
00034 #include <kgenericfactory.h>
00035 #include <kmessagebox.h>
00036 #include <kmdcodec.h>
00037 #include <KoFilterChain.h>
00038 #include <KoGlobal.h>
00039 #include <KoUnit.h>
00040 #include <KoStyleStack.h>
00041 #include <KoDom.h>
00042 #include <ooutils.h>
00043 
00044 #include <kspread_cell.h>
00045 #include <kspread_condition.h>
00046 #include <kspread_doc.h>
00047 #include <kspread_global.h>
00048 #include <kspread_map.h>
00049 #include <kspread_sheet.h>
00050 #include <kspread_sheetprint.h>
00051 #include <kspread_style.h>
00052 #include <kspread_style_manager.h>
00053 #include <kspread_util.h>
00054 #include <kspread_value.h>
00055 
00056 #define SECSPERDAY (24 * 60 * 60)
00057 
00058 using namespace KSpread;
00059 
00060 class OpenCalcImportFactory : KGenericFactory<OpenCalcImport, KoFilter>
00061 {
00062 public:
00063     OpenCalcImportFactory(void) : KGenericFactory<OpenCalcImport, KoFilter> ("kspreadopencalcimport")
00064     {}
00065 protected:
00066     virtual void setupTranslations( void )
00067     {
00068         KGlobal::locale()->insertCatalogue( "kofficefilters" );
00069     }
00070 };
00071 
00072 K_EXPORT_COMPONENT_FACTORY( libopencalcimport, OpenCalcImportFactory() )
00073 
00074 OpenCalcImport::OpenCalcPoint::OpenCalcPoint( QString const & str )
00075   : isRange( false )
00076 {
00077   bool inQuote = false;
00078 
00079   int l = str.length();
00080   int colonPos = -1;
00081   QString range;
00082 
00083   // replace '.' with '!'
00084   for ( int i = 0; i < l; ++i )
00085   {
00086     if ( str[i] == '$' )
00087       continue;
00088     if ( str[i] == '\'' )
00089     {
00090       inQuote = !inQuote;
00091     }
00092     else if ( str[i] == '.' )
00093     {
00094       if ( !inQuote )
00095       {
00096         if ( i != 0 && i != (colonPos + 1) ) // no empty table names
00097           range += '!';
00098       }
00099       else
00100         range += '.';
00101     }
00102     else if ( str[i] == ':' )
00103     {
00104       if ( !inQuote )
00105       {
00106         isRange  = true;
00107         colonPos = i;
00108       }
00109       range += ':';
00110     }
00111     else
00112       range += str[i];
00113   }
00114 
00115   translation = range;
00116 
00117   if ( isRange )
00118   {
00119       KSpread::Range newRange( range );
00120     table    = newRange.sheetName();
00121     topLeft  = newRange.range().topLeft();
00122     botRight = newRange.range().bottomRight();
00123   }
00124   else
00125   {
00126     Point newPoint( range );
00127     table    = newPoint.sheetName();
00128     topLeft  = newPoint.pos();
00129     botRight = newPoint.pos();
00130   }
00131 }
00132 
00133 
00134 OpenCalcImport::OpenCalcImport( KoFilter *, const char *, const QStringList & )
00135   : KoFilter(),
00136     m_styles( 17, true ),
00137     m_defaultStyles( 17, true ),
00138     m_formats( 17, true )
00139 {
00140   m_styles.setAutoDelete( true );
00141   m_defaultStyles.setAutoDelete( true );
00142   m_formats.setAutoDelete( true );
00143 }
00144 
00145 OpenCalcImport::~OpenCalcImport()
00146 {
00147 }
00148 
00149 double timeToNum( int h, int m, int s )
00150 {
00151   int secs = h * 3600 + m * 60 + s;
00152   return (double) secs / (double) SECSPERDAY;
00153 }
00154 
00155 bool OpenCalcImport::readRowFormat( QDomElement & rowNode, QDomElement * rowStyle,
00156                                     Sheet * table, int & row, int & number,
00157                                     bool isLast )
00158 {
00159   if ( rowNode.isNull() )
00160     return false;
00161 
00162   QDomNode node;
00163   if ( rowStyle )
00164   {
00165     node = rowStyle->firstChild();
00166     kdDebug(30518) << "RowStyle: " << rowStyle << ", " << rowStyle->tagName() << endl;
00167   }
00168 
00169   double height = -1.0;
00170   bool insertPageBreak = false;
00171   Format layout( table, table->doc()->styleManager()->defaultStyle() );
00172 
00173   while( !node.isNull() )
00174   {
00175     QDomElement property = node.toElement();
00176 
00177     kdDebug(30518) << "Row: Child exists: " << property.tagName() << endl;
00178     if ( !property.isNull() && property.localName() == "properties" && property.namespaceURI() == ooNS::style )
00179     {
00180       if ( property.hasAttributeNS( ooNS::style, "row-height" ) )
00181       {
00182           height = KoUnit::parseValue( property.attributeNS( ooNS::style, "row-height", QString::null ) , -1 );
00183       }
00184 
00185       if ( property.hasAttributeNS( ooNS::fo, "break-before" ) )
00186       {
00187         if ( property.attributeNS( ooNS::fo, "break-before", QString::null ) == "page" )
00188         {
00189           insertPageBreak = true;
00190         }
00191       }
00192 
00193       loadStyleProperties( &layout, property );
00194     }
00195 
00196     node = node.nextSibling();
00197   }
00198 
00199   if ( rowNode.hasAttributeNS( ooNS::table, "number-rows-repeated" ) )
00200   {
00201     bool ok = true;
00202     int n = rowNode.attributeNS( ooNS::table, "number-rows-repeated", QString::null ).toInt( &ok );
00203     if ( ok )
00204       number = n;
00205     kdDebug(30518) << "Row repeated: " << number << endl;
00206   }
00207 
00208   if ( isLast )
00209   {
00210     if ( number > 30 )
00211       number = 30;
00212   }
00213   else
00214   {
00215     if ( number > 256 )
00216       number = 256;
00217   }
00218 
00219   for ( int i = 0; i < number; ++i )
00220   {
00221     RowFormat * rowL = table->nonDefaultRowFormat( row );
00222     rowL->copy( layout );
00223 
00224     if ( height != -1 )
00225     {
00226       kdDebug(30518) << "Setting row height to " << height << endl;
00227       rowL->setHeight( int( height ) );
00228     }
00229 
00230     // if ( insertPageBreak ) TODO:
00231     //   rowL->setPageBreak( true )
00232 
00233     //    kdDebug(30518) << "Added RowFormat: " << row << endl;
00234     ++row;
00235   }
00236 
00237   return true;
00238 }
00239 
00240 QString OpenCalcImport::translatePar( QString & par ) const
00241 {
00242   OpenCalcPoint point( par );
00243   kdDebug(30518) << "   Parameter: " << par << ", Translation: " << point.translation << endl;
00244 
00245   return point.translation;
00246 }
00247 
00248 void OpenCalcImport::checkForNamedAreas( QString & formula ) const
00249 {
00250   int l = formula.length();
00251   int i = 0;
00252   QString word;
00253   int start = 0;
00254   while ( i < l )
00255   {
00256     if ( formula[i].isLetterOrNumber() )
00257     {
00258       word += formula[i];
00259       ++i;
00260       continue;
00261     }
00262     if ( word.length() > 0 )
00263     {
00264       if ( m_namedAreas.find( word ) != m_namedAreas.end() )
00265       {
00266         formula = formula.replace( start, word.length(), "'" + word + "'" );
00267         l = formula.length();
00268         ++i;
00269         kdDebug(30518) << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
00270       }
00271     }
00272 
00273     ++i;
00274     word = "";
00275     start = i;
00276   }
00277   if ( word.length() > 0 )
00278   {
00279     if ( m_namedAreas.find( word ) != m_namedAreas.end() )
00280     {
00281       formula = formula.replace( start, word.length(), "'" + word + "'" );
00282       l = formula.length();
00283       ++i;
00284       kdDebug(30518) << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
00285     }
00286   }
00287 }
00288 
00289 void OpenCalcImport::convertFormula( QString & text, QString const & f ) const
00290 {
00291   kdDebug(30518) << "Parsing formula: " << f << endl;
00292 
00293   QString formula;
00294   QString parameter;
00295 
00296   int l = f.length();
00297   int p = 0;
00298 
00299   while ( p < l )
00300   {
00301     if ( f[p] == '(' || f[p] == '[' )
00302     {
00303       break;
00304     }
00305 
00306     formula += f[p];
00307     ++p;
00308   }
00309 
00310   if ( parameter.isEmpty() )
00311   {
00312     checkForNamedAreas( formula );
00313   }
00314 
00315   kdDebug(30518) << "Formula: " << formula << ", Parameter: " << parameter << ", P: " << p << endl;
00316 
00317 
00318   // replace formula names here
00319   if ( formula == "=MULTIPLE.OPERATIONS" )
00320     formula = "=MULTIPLEOPERATIONS";
00321 
00322   QString par;
00323   bool isPar   = false;
00324   bool inQuote = false;
00325 
00326   while ( p < l )
00327   {
00328     if ( f[p] == '"' )
00329     {
00330       inQuote = !inQuote;
00331       parameter += '"';
00332     }
00333     else if ( f[p] == '[' )
00334     {
00335       if ( !inQuote )
00336         isPar = true;
00337       else
00338         parameter += '[';
00339     }
00340     else if ( f[p] == ']' )
00341     {
00342       if ( inQuote )
00343       {
00344         parameter += ']';
00345         continue;
00346       }
00347 
00348       isPar = false;
00349       parameter += translatePar( par );
00350       par = "";
00351     }
00352     else if ( isPar )
00353     {
00354       par += f[p];
00355     }
00356     else if ( f[p] == '=' ) // TODO: check if StarCalc has a '==' sometimes
00357     {
00358       if ( inQuote )
00359         parameter += '=';
00360       else
00361         parameter += "==";
00362     }
00363     else if ( f[p] == ')' )
00364     {
00365       if ( !inQuote )
00366         parameter += ")";
00367     }
00368     else
00369       parameter += f[p];
00370 
00371     ++p;
00372     if ( p == l )
00373       checkForNamedAreas( parameter );
00374   }
00375 
00376   text = formula + parameter;
00377   kdDebug(30518) << "New formula: " << text << endl;
00378 }
00379 
00380 bool OpenCalcImport::readCells( QDomElement & rowNode, Sheet  * table, int row, int & columns )
00381 {
00382   bool ok = true;
00383   int spanC = 1;
00384   int spanR = 1;
00385   //Cell* defCell = table->defaultCell();
00386 
00387   QDomNode cellNode = KoDom::namedItemNS( rowNode, ooNS::table, "table-cell" );
00388 
00389   while ( !cellNode.isNull() )
00390   {
00391     spanR = 1; spanC = 1;
00392 
00393     QDomElement e = cellNode.toElement();
00394     if ( e.isNull() )
00395     {
00396       ++columns;
00397 
00398       cellNode = cellNode.nextSibling();
00399       continue;
00400     }
00401 
00402     Cell* cell = 0;
00403 
00404     kdDebug(30518) << " Cell: " << columns << ", " << row << endl;
00405 
00406     // ="3" table:number-rows-spanned="1"
00407     if ( e.hasAttributeNS( ooNS::table, "number-columns-spanned" ) )
00408     {
00409       int span = e.attributeNS( ooNS::table, "number-columns-spanned", QString::null ).toInt( &ok );
00410       if ( ok )
00411         spanC = span;
00412     }
00413     if ( e.hasAttributeNS( ooNS::table, "number-rows-spanned" ) )
00414     {
00415       int span = e.attributeNS( ooNS::table, "number-rows-spanned", QString::null ).toInt( &ok );
00416       if ( ok )
00417         spanR = span;
00418     }
00419 
00420     QString text;
00421     QDomElement textP = KoDom::namedItemNS( e, ooNS::text, "p" );
00422     if ( !textP.isNull() )
00423     {
00424       QDomElement subText = textP.firstChild().toElement(); // ## wrong
00425       if ( !subText.isNull() )
00426       {
00427         // something in <text:p>, e.g. links
00428         text = subText.text();
00429 
00430         if ( subText.hasAttributeNS( ooNS::xlink, "href" ) )
00431         {
00432           QString link = subText.attributeNS( ooNS::xlink, "href", QString::null );
00433           if ( link[0]=='#' )
00434               link=link.remove( 0, 1 );
00435           if ( !cell )
00436               cell = table->nonDefaultCell( columns, row );
00437           cell->setLink( link );
00438         }
00439       }
00440       else
00441         text = textP.text(); // our text, could contain formating for value or result of formula
00442     }
00443     QDomElement annotation = KoDom::namedItemNS( e, ooNS::office, "annotation" );
00444     if ( !annotation.isNull() )
00445     {
00446        QString comment;
00447         QDomNode node = annotation.firstChild();
00448         while( !node.isNull() )
00449         {
00450             QDomElement commentElement = node.toElement();
00451             if( !commentElement.isNull() )
00452                 if ( commentElement.localName() == "p" && e.namespaceURI()==ooNS::text)
00453                 {
00454                     if( !comment.isEmpty() ) comment.append( '\n' );
00455                     comment.append( commentElement.text() );
00456                 }
00457 
00458             node = node.nextSibling();
00459         }
00460 
00461         if( !comment.isEmpty() )
00462         {
00463             if ( !cell )
00464                 cell = table->nonDefaultCell( columns, row );
00465             kdDebug(30518)<<" columns :"<<columns<<" row :"<<row<<endl;
00466             cell->format()->setComment( comment );
00467         }
00468     }
00469 
00470     kdDebug(30518) << "Contains: " << text << endl;
00471     bool isFormula = false;
00472 
00473     if ( e.hasAttributeNS( ooNS::table, "style-name" ) )
00474     {
00475       if ( !cell )
00476         cell = table->nonDefaultCell( columns, row );
00477 
00478       QString psName( "Default" );
00479       if ( e.hasAttributeNS( ooNS::style, "parent-style-name" ) )
00480         psName = e.attributeNS( ooNS::style, "parent-style-name", QString::null );
00481 
00482       kdDebug(30518) << "Default style: " << psName << endl;
00483       Format * layout = m_defaultStyles[psName];
00484 
00485       if ( layout )
00486         cell->format()->copy( *layout );
00487 
00488       QDomElement * st = 0;
00489       if ( e.hasAttributeNS( ooNS::table, "style-name" ) )
00490       {
00491         kdDebug(30518) << "Style: " << e.attributeNS( ooNS::table, "style-name", QString::null ) << endl;
00492         st = m_styles[ e.attributeNS( ooNS::table, "style-name", QString::null ) ];
00493       }
00494       if ( st )
00495       {
00496         kdDebug(30518) << "Style: adapting " << endl;
00497         QDomNode node = st->firstChild();
00498         bool foundValidation = false;
00499         while( !node.isNull() )
00500         {
00501           QDomElement property = node.toElement();
00502           if ( !property.isNull() )
00503           {
00504             kdDebug(30518)<<"property.tagName() :"<<property.tagName()<<endl;
00505             if ( property.localName()=="map" && property.namespaceURI() == ooNS::style && !foundValidation)
00506             {
00507               loadCondition( cell, property );
00508               foundValidation = true;
00509             }
00510             if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
00511             {
00512               loadStyleProperties( cell->format(), property );
00513               if ( cell->format()->getAngle( columns, row ) != 0 )
00514               {
00515                 QFontMetrics fm( cell->format()->textFont( columns, row ) );
00516                 int tmpAngle = cell->format()->getAngle( columns, row );
00517                 int textHeight = static_cast<int>( cos( tmpAngle * M_PI / 180 )
00518                                                    * ( fm.ascent() + fm.descent() )
00519                                                    + abs ( ( int )(  fm.width( cell->strOutText() )
00520                                                                      * sin( tmpAngle * M_PI / 180 )  ) ) );
00521                 /*
00522                   int textWidth = static_cast<int>( abs ( ( int ) ( sin( tmpAngle * M_PI / 180 )
00523                   * ( fm.ascent() + fm.descent() ) ) )
00524                   + fm.width( cell->strOutText() )
00525                   * cos( tmpAngle * M_PI / 180 ) );
00526                   */
00527                 kdDebug(30518) << "Rotation: height: " << textHeight << endl;
00528 
00529                 RowFormat * l = table->rowFormat( row );
00530                 if ( l->height() < textHeight )
00531                 {
00532                   if ( l->isDefault() )
00533                     l = table->nonDefaultRowFormat( row );
00534 
00535                   l->setHeight( textHeight + 2 );
00536                 }
00537               }
00538             }
00539           }
00540           node = node.nextSibling();
00541         }
00542       }
00543     }
00544     else
00545     {
00546       if ( !cell )
00547         cell = table->nonDefaultCell( columns, row );
00548 
00549       QString psName( "Default" );
00550       kdDebug(30518) << "Default style: " << psName << endl;
00551       Format * layout = m_defaultStyles[psName];
00552 
00553       if ( layout )
00554         cell->format()->copy( *layout );
00555     }
00556     if ( e.hasAttributeNS( ooNS::table, "formula" ) )
00557     {
00558       isFormula = true;
00559       QString formula;
00560       convertFormula( formula, e.attributeNS( ooNS::table, "formula", QString::null ) );
00561 
00562       if ( !cell )
00563         cell = table->nonDefaultCell( columns, row );
00564       cell->setCellText( formula );
00565     }
00566     if ( e.hasAttributeNS( ooNS::table, "validation-name" ) )
00567     {
00568         kdDebug(30518)<<" Celle has a validation :"<<e.attributeNS( ooNS::table, "validation-name", QString::null )<<endl;
00569         loadOasisValidation( cell->getValidity(), e.attributeNS( ooNS::table, "validation-name", QString::null ) );
00570     }
00571     if ( e.hasAttributeNS( ooNS::table, "value-type" ) )
00572     {
00573       if ( !cell )
00574         cell = table->nonDefaultCell( columns, row );
00575 
00576       cell->setCellText( text );
00577 
00578       QString value = e.attributeNS( ooNS::table, "value", QString::null );
00579       QString type  = e.attributeNS( ooNS::table, "value-type", QString::null );
00580 
00581       kdDebug(30518) << "Value: " << value << ", type: " << type << endl;
00582 
00583       bool ok = false;
00584       double dv = 0.0;
00585 
00586       if ( ( type == "float" ) || ( type == "currency" ) )
00587       {
00588         dv = value.toDouble( &ok );
00589         if ( ok )
00590         {
00591           if ( !isFormula )
00592             cell->setValue( dv );
00593 
00594           if ( type == "currency" )
00595           {
00596             cell->format()->setCurrency( 1, e.attributeNS( ooNS::table, "currency", QString::null ) );
00597             cell->format()->setFormatType( Money_format );
00598           }
00599         }
00600       }
00601       else
00602         if ( type == "percentage" )
00603         {
00604           dv = value.toDouble( &ok );
00605           if ( ok )
00606           {
00607             if ( !isFormula )
00608               cell->setValue( dv );
00609             //TODO fixme
00610             //cell->setFactor( 100 );
00611             // TODO: replace with custom...
00612             cell->format()->setFormatType( Percentage_format );
00613           }
00614         }
00615         else if ( type == "boolean" )
00616         {
00617           if ( value.isEmpty() )
00618             value = e.attributeNS( ooNS::table, "boolean-value", QString::null );
00619 
00620           kdDebug(30518) << "Type: boolean" << endl;
00621           if ( value == "true" )
00622             cell->setValue( true );
00623           else
00624             cell->setValue( false );
00625           ok = true;
00626           cell->format()->setFormatType( Custom_format );
00627         }
00628         else if ( type == "date" )
00629         {
00630           if ( value.isEmpty() )
00631             value = e.attributeNS( ooNS::table, "date-value", QString::null );
00632           kdDebug(30518) << "Type: date, value: " << value << endl;
00633 
00634           // "1980-10-15"
00635           int year=0, month=0, day=0;
00636           ok = false;
00637 
00638           int p1 = value.find( '-' );
00639           if ( p1 > 0 )
00640             year  = value.left( p1 ).toInt( &ok );
00641 
00642           kdDebug(30518) << "year: " << value.left( p1 ) << endl;
00643 
00644           int p2 = value.find( '-', ++p1 );
00645 
00646           if ( ok )
00647             month = value.mid( p1, p2 - p1  ).toInt( &ok );
00648 
00649           kdDebug(30518) << "month: " << value.mid( p1, p2 - p1 ) << endl;
00650 
00651           if ( ok )
00652             day = value.right( value.length() - p2 - 1 ).toInt( &ok );
00653 
00654           kdDebug(30518) << "day: " << value.right( value.length() - p2 ) << endl;
00655 
00656           if ( ok )
00657           {
00658             QDateTime dt( QDate( year, month, day ) );
00659             //            KSpreadValue kval( dt );
00660             // cell->setValue( kval );
00661             cell->setValue( QDate( year, month, day ) );
00662             kdDebug(30518) << "Set QDate: " << year << " - " << month << " - " << day << endl;
00663           }
00664         }
00665         else if ( type == "time" )
00666         {
00667           if ( value.isEmpty() )
00668             value = e.attributeNS( ooNS::table, "time-value", QString::null );
00669 
00670           kdDebug(30518) << "Type: time: " << value << endl;
00671           // "PT15H10M12S"
00672           int hours=0, minutes=0, seconds=0;
00673           int l = value.length();
00674           QString num;
00675 
00676           for ( int i = 0; i < l; ++i )
00677           {
00678             if ( value[i].isNumber() )
00679             {
00680               num += value[i];
00681               continue;
00682             }
00683             else if ( value[i] == 'H' )
00684               hours   = num.toInt( &ok );
00685             else if ( value[i] == 'M' )
00686               minutes = num.toInt( &ok );
00687             else if ( value[i] == 'S' )
00688               seconds = num.toInt( &ok );
00689             else
00690               continue;
00691 
00692             kdDebug(30518) << "Num: " << num << endl;
00693 
00694             num = "";
00695             if ( !ok )
00696               break;
00697           }
00698 
00699           kdDebug(30518) << "Hours: " << hours << ", " << minutes << ", " << seconds << endl;
00700 
00701           if ( ok )
00702           {
00703             // KSpreadValue kval( timeToNum( hours, minutes, seconds ) );
00704             // cell->setValue( kval );
00705             cell->setValue( QTime( hours % 24, minutes, seconds ) );
00706             cell->format()->setFormatType( Custom_format );
00707           }
00708         }
00709 
00710 
00711       if ( !ok ) // just in case we couldn't set the value directly
00712         cell->setCellText( text );
00713     }
00714     else if ( !text.isEmpty() )
00715     {
00716       if ( !cell )
00717         cell = table->nonDefaultCell( columns, row );
00718       cell->setCellText( text );
00719     }
00720 
00721     if ( spanR > 1 || spanC > 1 )
00722     {
00723       if ( !cell )
00724         cell = table->nonDefaultCell( columns, row );
00725       cell->mergeCells( columns, row, spanC - 1, spanR - 1 );
00726     }
00727 
00728     cellNode = cellNode.nextSibling();
00729 
00730     if ( e.hasAttributeNS( ooNS::table, "number-columns-repeated" ) )
00731     {
00732       // copy cell from left
00733       bool ok = false;
00734       int number = e.attributeNS( ooNS::table, "number-columns-repeated", QString::null ).toInt( &ok );
00735       Cell* cellDest = 0;
00736 
00737       // don't repeat more than 10 if it is the last cell and empty
00738       if ( !ok || cellNode.isNull() )
00739       {
00740         if ( number > 10 )
00741           number = 10;
00742       }
00743 
00744       for ( int i = 1; i < number; ++i )
00745       {
00746         ++columns;
00747 
00748         if ( cell )
00749         {
00750           cellDest = table->nonDefaultCell( columns, row );
00751           cellDest->copyAll( cell );
00752         }
00753       }
00754     }
00755 
00756     ++columns;
00757   }
00758 
00759   return true;
00760 }
00761 
00762 
00763 void OpenCalcImport::loadCondition( Cell*cell,const QDomElement &property )
00764 {
00765     kdDebug(30518)<<"void OpenCalcImport::loadCondition( Cell*cell,const QDomElement &property )*******\n";
00766     loadOasisCondition( cell, property );
00767 }
00768 
00769 void OpenCalcImport::loadOasisCondition(Cell*cell,const QDomElement &property )
00770 {
00771     QDomElement elementItem( property );
00772     StyleManager * manager = cell->sheet()->doc()->styleManager();
00773 
00774     QValueList<Conditional> cond;
00775     while ( !elementItem.isNull() )
00776     {
00777         kdDebug(30518)<<"elementItem.tagName() :"<<elementItem.tagName()<<endl;
00778 
00779         if ( elementItem.localName()== "map" && property.namespaceURI() == ooNS::style )
00780         {
00781             bool ok = true;
00782             kdDebug(30518)<<"elementItem.attribute(style:condition ) :"<<elementItem.attributeNS( ooNS::style, "condition", QString::null )<<endl;
00783             Conditional newCondition;
00784             loadOasisConditionValue( elementItem.attributeNS( ooNS::style, "condition", QString::null ), newCondition );
00785             if ( elementItem.hasAttributeNS( ooNS::style, "apply-style-name" ) )
00786             {
00787                 kdDebug(30518)<<"elementItem.attribute( style:apply-style-name ) :"<<elementItem.attributeNS( ooNS::style, "apply-style-name", QString::null )<<endl;
00788                 newCondition.styleName = new QString( elementItem.attributeNS( ooNS::style, "apply-style-name", QString::null ) );
00789                 newCondition.style = manager->style( *newCondition.styleName );
00790                 if ( !newCondition.style )
00791                     ok = false;
00792                 else
00793                     ok = true;
00794             }
00795 
00796             if ( ok )
00797                 cond.append( newCondition );
00798             else
00799                 kdDebug(30518) << "Error loading condition " << elementItem.nodeName()<< endl;
00800         }
00801         elementItem = elementItem.nextSibling().toElement();
00802     }
00803     if ( !cond.isEmpty() )
00804         cell->setConditionList( cond );
00805 }
00806 
00807 void OpenCalcImport::loadOasisConditionValue( const QString &styleCondition, Conditional &newCondition )
00808 {
00809     QString val( styleCondition );
00810     if ( val.contains( "cell-content()" ) )
00811     {
00812         val = val.remove( "cell-content()" );
00813         loadOasisCondition( val,newCondition );
00814     }
00815     //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
00816     //for the moment we support just int/double value, not text/date/time :(
00817     if ( val.contains( "cell-content-is-between(" ) )
00818     {
00819         val = val.remove( "cell-content-is-between(" );
00820         val = val.remove( ")" );
00821         QStringList listVal = QStringList::split( "," , val );
00822         loadOasisValidationValue( listVal, newCondition );
00823         newCondition.cond = Conditional::Between;
00824     }
00825     if ( val.contains( "cell-content-is-not-between(" ) )
00826     {
00827         val = val.remove( "cell-content-is-not-between(" );
00828         val = val.remove( ")" );
00829         QStringList listVal = QStringList::split( ",", val );
00830         loadOasisValidationValue( listVal,newCondition );
00831         newCondition.cond = Conditional::Different;
00832     }
00833 
00834 }
00835 
00836 
00837 void OpenCalcImport::loadOasisCondition( QString &valExpression, Conditional &newCondition )
00838 {
00839     QString value;
00840     if (valExpression.find( "<=" )==0 )
00841     {
00842         value = valExpression.remove( 0,2 );
00843         newCondition.cond = Conditional::InferiorEqual;
00844     }
00845     else if (valExpression.find( ">=" )==0 )
00846     {
00847         value = valExpression.remove( 0,2 );
00848         newCondition.cond = Conditional::SuperiorEqual;
00849     }
00850     else if (valExpression.find( "!=" )==0 )
00851     {
00852         //add Differentto attribute
00853         value = valExpression.remove( 0,2 );
00854         newCondition.cond = Conditional::DifferentTo;
00855     }
00856     else if ( valExpression.find( "<" )==0 )
00857     {
00858         value = valExpression.remove( 0,1 );
00859         newCondition.cond = Conditional::Inferior;
00860     }
00861     else if(valExpression.find( ">" )==0 )
00862     {
00863         value = valExpression.remove( 0,1 );
00864         newCondition.cond = Conditional::Superior;
00865     }
00866     else if (valExpression.find( "=" )==0 )
00867     {
00868         value = valExpression.remove( 0,1 );
00869         newCondition.cond = Conditional::Equal;
00870     }
00871     else
00872         kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl;
00873     kdDebug(30518)<<" value :"<<value<<endl;
00874     bool ok = false;
00875     newCondition.val1 = value.toDouble(&ok);
00876     if ( !ok )
00877     {
00878         newCondition.val1 = value.toInt(&ok);
00879         if ( !ok )
00880         {
00881             newCondition.strVal1 = new QString( value );
00882             kdDebug(30518)<<" Try to parse this value :"<<value<<endl;
00883         }
00884 
00885     }
00886 }
00887 
00888 
00889 void OpenCalcImport::loadOasisValidationValue( const QStringList &listVal, Conditional &newCondition )
00890 {
00891     bool ok = false;
00892     kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
00893 
00894     newCondition.val1 = listVal[0].toDouble(&ok);
00895     if ( !ok )
00896     {
00897         newCondition.val1 = listVal[0].toInt(&ok);
00898         if ( !ok )
00899         {
00900             newCondition.strVal1 = new QString( listVal[0] );
00901             kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl;
00902         }
00903     }
00904     ok=false;
00905     newCondition.val2 = listVal[1].toDouble(&ok);
00906     if ( !ok )
00907     {
00908         newCondition.val2 = listVal[1].toInt(&ok);
00909         if ( !ok )
00910         {
00911             newCondition.strVal2 = new QString( listVal[1] );
00912             kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl;
00913         }
00914     }
00915 }
00916 
00917 
00918 bool OpenCalcImport::readRowsAndCells( QDomElement & content, Sheet * table )
00919 {
00920   kdDebug(30518) << endl << "Reading in rows " << endl;
00921 
00922   int i   = 1;
00923   int row = 1;
00924   int columns = 1;
00925   int backupRow = 1;
00926   QDomElement * rowStyle = 0;
00927   //Cell* cell = 0;
00928   //Cell* cellDest = 0;
00929   //Cell* defCell = table->defaultCell();
00930   QDomNode rowNode = KoDom::namedItemNS( content, ooNS::table, "table-row" );
00931 
00932   while ( !rowNode.isNull() )
00933   {
00934     bool collapsed = false;
00935 
00936     int number = 1;
00937     QDomElement r = rowNode.toElement();
00938 
00939     if ( r.isNull() )
00940       return false;
00941 
00942     if ( r.hasAttributeNS( ooNS::table, "style-name" ) )
00943     {
00944       QString style = r.attributeNS( ooNS::table, "style-name", QString::null );
00945       rowStyle = m_styles[ style ];
00946       kdDebug(30518) << "Row style: " << style << endl;
00947     }
00948 
00949     collapsed = ( r.attributeNS( ooNS::table, "visibility", QString::null ) == "collapse" );
00950 
00951     backupRow = row;
00952 
00953     rowNode = rowNode.nextSibling();
00954 
00955     if ( !readRowFormat( r, rowStyle, table, row, number, rowNode.isNull() ) ) // updates "row"
00956       return false;
00957 
00958     if ( !readCells( r, table, backupRow, columns ) )
00959       return false;
00960 
00961     RowFormat * srcLayout = table->nonDefaultRowFormat( backupRow );
00962     RowFormat * layout = 0;
00963 
00964     if ( collapsed )
00965       srcLayout->setHide( true );
00966 
00967     for ( i = 1; i < number; ++i )
00968     {
00969       layout = table->nonDefaultRowFormat( backupRow + i );
00970 
00971       layout->copy( *srcLayout );
00972 
00973       /*
00974        * TODO: Test: do we need to copy the cells, too?
00975        *       if so we will probably also need to copy them for repeated col layouts.
00976       for ( j = 1; j <= columns; ++j )
00977       {
00978         Cell* cell = table->cellAt( j, backupRow );
00979 
00980         kdDebug(30518) << "Cell: " << cell << "DefCell: " << defCell << endl;
00981         if ( cell && (cell != defCell) )
00982         {
00983           cellDest = table->nonDefaultCell( j, backupRow + i );
00984           cellDest->copyAll( cell );
00985         }
00986       }
00987       */
00988     }
00989 
00990     rowStyle = 0;
00991     columns = 1;
00992   }
00993 
00994   kdDebug(30518) << "Reading in rows done" << endl << endl;
00995 
00996   return true;
00997 }
00998 
00999 bool OpenCalcImport::readColLayouts( QDomElement & content, Sheet * table )
01000 {
01001   kdDebug(30518) << endl << "Reading in columns..." << endl;
01002 
01003   QDomNode colLayout = KoDom::namedItemNS( content, ooNS::table, "table-column" );
01004   int column = 1;
01005 
01006   while ( !colLayout.isNull() )
01007   {
01008     if ( colLayout.nodeName() != "table:table-column" )
01009       return true; // all cols read in.
01010 
01011     QDomElement e = colLayout.toElement();
01012 
01013     if ( e.isNull() )
01014       return false; // error, that's it...
01015 
01016     kdDebug(30518) << "New column: " << column << endl;
01017 
01018     int number     = 1;
01019     double width   = colWidth;
01020     bool collapsed = ( e.attributeNS( ooNS::table, "visibility", QString::null ) == "collapse" );
01021     bool insertPageBreak = false;
01022     Format styleLayout( table, table->doc()->styleManager()->defaultStyle() );
01023 
01024     kdDebug(30518) << "Check table:number-columns-repeated" << endl;
01025     if ( e.hasAttributeNS( ooNS::table, "number-columns-repeated" ) )
01026     {
01027       bool ok = true;
01028       number = e.attributeNS( ooNS::table, "number-columns-repeated", QString::null ).toInt( &ok );
01029       if ( !ok )
01030         number = 1;
01031 
01032       kdDebug(30518) << "Repeated: " << number << endl;
01033     }
01034 
01035     kdDebug(30518) << "Checking table:default-cell-style-name" << endl;
01036     if ( e.hasAttributeNS( ooNS::table, "default-cell-style-name" ) )
01037     {
01038       QString n( e.attributeNS( ooNS::table, "default-cell-style-name", QString::null ) );
01039       kdDebug(30518) << "Has attribute default-cell-style-name: " << n << endl;
01040       Format * defaultStyle = m_defaultStyles[ n ];
01041       if ( !defaultStyle )
01042       {
01043         QString name = e.attributeNS( ooNS::table, "default-cell-style-name", QString::null );
01044         QDomElement * st = m_styles[ name ];
01045 
01046         kdDebug(30518) << "Default cell style: " << name << endl;
01047 
01048         if ( st && !st->isNull() )
01049         {
01050           Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() );
01051 
01052           readInStyle( layout, *st );
01053 
01054           m_defaultStyles.insert( name, layout );
01055           kdDebug(30518) << "Insert default cell style: " << name << endl;
01056 
01057           defaultStyle = layout;
01058         }
01059       }
01060 
01061       if ( defaultStyle )
01062       {
01063         //        kdDebug(30518) << "Copying default style, Font: " << defaultStyle->font().toString() << endl;
01064         styleLayout.copy( *defaultStyle );
01065       }
01066     }
01067 
01068     QDomElement * colStyle = 0;
01069     if ( e.hasAttributeNS( ooNS::table, "style-name" ) )
01070     {
01071       QString style = e.attributeNS( ooNS::table, "style-name", QString::null );
01072       colStyle = m_styles[ style ];
01073 
01074       kdDebug(30518) << "Col Style: " << style << endl;
01075     }
01076 
01077     QDomNode node;
01078 
01079     if ( colStyle )
01080       node = colStyle->firstChild();
01081 
01082     while( !node.isNull() )
01083     {
01084       QDomElement property = node.toElement();
01085       if ( !property.isNull() && property.localName() == "properties" && property.namespaceURI() == ooNS::style )
01086       {
01087         if ( property.hasAttributeNS( ooNS::style, "column-width" ) )
01088         {
01089           QString sWidth = property.attributeNS( ooNS::style, "column-width", QString::null );
01090           width = KoUnit::parseValue( property.attributeNS( ooNS::style, "column-width", QString::null ), width );
01091           kdDebug(30518) << "Col Width: " << sWidth << endl;
01092         }
01093 
01094         if ( property.hasAttributeNS( ooNS::fo, "break-before" ) )
01095         {
01096           if ( property.attributeNS( ooNS::fo, "break-before", QString::null ) == "page" )
01097           {
01098             insertPageBreak = true;
01099           }
01100         }
01101 
01102         loadStyleProperties( &styleLayout, property );
01103       }
01104 
01105       node = node.nextSibling();
01106     }
01107 
01108     colLayout = colLayout.nextSibling();
01109 
01110     if ( colLayout.isNull() && ( number > 30 ) )
01111       number = 30;
01112 
01113     for ( int i = 0; i < number; ++i )
01114     {
01115       kdDebug(30518) << "Inserting colLayout: " << column << endl;
01116 
01117       ColumnFormat * col = new ColumnFormat( table, column );
01118       col->copy( styleLayout );
01119       col->setWidth( int( width ) );
01120 
01121       // if ( insertPageBreak )
01122       //   col->setPageBreak( true )
01123 
01124       if ( collapsed )
01125         col->setHide( true );
01126 
01127       table->insertColumnFormat( col );
01128       ++column;
01129     }
01130   }
01131 
01132   return true;
01133 }
01134 
01135 void replaceMacro( QString & text, QString const & old, QString const & newS )
01136 {
01137   int n = text.find( old );
01138   if ( n != -1 )
01139     text = text.replace( n, old.length(), newS );
01140 }
01141 
01142 QString getPart( QDomNode const & part )
01143 {
01144   QString result;
01145   QDomElement e = KoDom::namedItemNS( part, ooNS::text, "p" );
01146   while ( !e.isNull() )
01147   {
01148     QString text = e.text();
01149     kdDebug(30518) << "PART: " << text << endl;
01150 
01151     QDomElement macro = KoDom::namedItemNS( e, ooNS::text, "time" );
01152     if ( !macro.isNull() )
01153       replaceMacro( text, macro.text(), "<time>" );
01154 
01155     macro = KoDom::namedItemNS( e, ooNS::text, "date" );
01156     if ( !macro.isNull() )
01157       replaceMacro( text, macro.text(), "<date>" );
01158 
01159     macro = KoDom::namedItemNS( e, ooNS::text, "page-number" );
01160     if ( !macro.isNull() )
01161       replaceMacro( text, macro.text(), "<page>" );
01162 
01163     macro = KoDom::namedItemNS( e, ooNS::text, "page-count" );
01164     if ( !macro.isNull() )
01165       replaceMacro( text, macro.text(), "<pages>" );
01166 
01167     macro = KoDom::namedItemNS( e, ooNS::text, "sheet-name" );
01168     if ( !macro.isNull() )
01169       replaceMacro( text, macro.text(), "<sheet>" );
01170 
01171     macro = KoDom::namedItemNS( e, ooNS::text, "title" );
01172     if ( !macro.isNull() )
01173       replaceMacro( text, macro.text(), "<name>" );
01174 
01175     macro = KoDom::namedItemNS( e, ooNS::text, "file-name" );
01176     if ( !macro.isNull() )
01177       replaceMacro( text, macro.text(), "<file>" );
01178 
01179     if ( !result.isEmpty() )
01180       result += '\n';
01181     result += text;
01182     e = e.nextSibling().toElement();
01183   }
01184 
01185   return result;
01186 }
01187 
01188 void OpenCalcImport::loadTableMasterStyle( Sheet * table,
01189                                            QString const & stylename )
01190 {
01191   kdDebug(30518) << "Loading table master style: " << stylename << endl;
01192 
01193   QDomElement * style = m_styles[ stylename ];
01194 
01195   if ( !style )
01196   {
01197     kdDebug(30518) << "Master style not found! " << endl;
01198     return;
01199   }
01200 
01201   QDomNode header = KoDom::namedItemNS( *style, ooNS::style, "header" );
01202   kdDebug(30518) << "Style header " << endl;
01203 
01204   QString hleft, hmiddle, hright;
01205   QString fleft, fmiddle, fright;
01206 
01207   if ( !header.isNull() )
01208   {
01209     kdDebug(30518) << "Header exists" << endl;
01210     QDomNode part = KoDom::namedItemNS( header, ooNS::style, "region-left" );
01211     if ( !part.isNull() )
01212     {
01213       hleft = getPart( part );
01214       kdDebug(30518) << "Header left: " << hleft << endl;
01215     }
01216     else
01217       kdDebug(30518) << "Style:region:left doesn't exist!" << endl;
01218     part = KoDom::namedItemNS( header, ooNS::style, "region-center" );
01219     if ( !part.isNull() )
01220     {
01221       hmiddle = getPart( part );
01222       kdDebug(30518) << "Header middle: " << hmiddle << endl;
01223     }
01224     part = KoDom::namedItemNS( header, ooNS::style, "region-right" );
01225     if ( !part.isNull() )
01226     {
01227       hright = getPart( part );
01228       kdDebug(30518) << "Header right: " << hright << endl;
01229     }
01230   }
01231 
01232   QDomNode footer = KoDom::namedItemNS( *style, ooNS::style, "footer" );
01233 
01234   if ( !footer.isNull() )
01235   {
01236     QDomNode part = KoDom::namedItemNS( footer, ooNS::style, "region-left" );
01237     if ( !part.isNull() )
01238     {
01239       fleft = getPart( part );
01240       kdDebug(30518) << "Footer left: " << fleft << endl;
01241     }
01242     part = KoDom::namedItemNS( footer, ooNS::style, "region-center" );
01243     if ( !part.isNull() )
01244     {
01245       fmiddle = getPart( part );
01246       kdDebug(30518) << "Footer middle: " << fmiddle << endl;
01247     }
01248     part = KoDom::namedItemNS( footer, ooNS::style, "region-right" );
01249     if ( !part.isNull() )
01250     {
01251       fright = getPart( part );
01252       kdDebug(30518) << "Footer right: " << fright << endl;
01253     }
01254   }
01255 
01256   table->print()->setHeadFootLine( hleft, hmiddle, hright,
01257                                    fleft, fmiddle, fright );
01258   if ( style->hasAttributeNS( ooNS::style, "page-master-name" ) )
01259   {
01260       QString masterPageLayoutStyleName=style->attributeNS( ooNS::style, "page-master-name", QString::null );
01261       kdDebug(30518)<<"masterPageLayoutStyleName :"<<masterPageLayoutStyleName<<endl;
01262       QDomElement *masterLayoutStyle = m_styles[masterPageLayoutStyleName];
01263       kdDebug(30518)<<"masterLayoutStyle :"<<masterLayoutStyle<<endl;
01264       if ( !masterLayoutStyle )
01265           return;
01266       KoStyleStack styleStack( ooNS::style, ooNS::fo );
01267       styleStack.push( *masterLayoutStyle );
01268       loadOasisMasterLayoutPage( table, styleStack );
01269   }
01270 }
01271 
01272 void OpenCalcImport::loadOasisMasterLayoutPage( Sheet * table,KoStyleStack &styleStack )
01273 {
01274     float left = 0.0;
01275     float right = 0.0;
01276     float top = 0.0;
01277     float bottom = 0.0;
01278     float width = 0.0;
01279     float height = 0.0;
01280     QString orientation = "Portrait";
01281     QString format;
01282 
01283     // Laurent : Why we stored layout information as Millimeter ?!!!!!
01284     // kspread used point for all other attribute
01285     // I don't understand :(
01286     if ( styleStack.hasAttributeNS( ooNS::fo, "page-width" ) )
01287     {
01288         width = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-width" ) ) );
01289     }
01290     if ( styleStack.hasAttributeNS( ooNS::fo, "page-height" ) )
01291     {
01292         height = KoUnit::toMM( KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-height" ) ) );
01293     }
01294     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-top" ) )
01295     {
01296         top = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-top" ) ) );
01297     }
01298     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-bottom" ) )
01299     {
01300         bottom = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-bottom" ) ) );
01301     }
01302     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-left" ) )
01303     {
01304         left = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-left" ) ) );
01305     }
01306     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-right" ) )
01307     {
01308         right = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-right" ) ) );
01309     }
01310     if ( styleStack.hasAttributeNS( ooNS::style, "writing-mode" ) )
01311     {
01312         kdDebug(30518)<<"styleStack.hasAttribute( style:writing-mode ) :"<<styleStack.hasAttributeNS( ooNS::style, "writing-mode" )<<endl;
01313     }
01314     if ( styleStack.hasAttributeNS( ooNS::style, "print-orientation" ) )
01315     {
01316         orientation = ( styleStack.attributeNS( ooNS::style, "print-orientation" )=="landscape" ) ? "Landscape" : "Portrait" ;
01317     }
01318     if ( styleStack.hasAttributeNS( ooNS::style, "num-format" ) )
01319     {
01320         kdDebug(30518)<<" num-format :"<<styleStack.attributeNS( ooNS::style, "num-format" )<<endl;
01321         //todo fixme
01322     }
01323         if ( styleStack.hasAttributeNS( ooNS::fo, "background-color" ) )
01324     {
01325         //todo
01326         kdDebug(30518)<<" fo:background-color :"<<styleStack.attributeNS( ooNS::fo, "background-color" )<<endl;
01327     }
01328     if ( styleStack.hasAttributeNS( ooNS::style, "print" ) )
01329     {
01330         //todo parsing
01331         QString str = styleStack.attributeNS( ooNS::style, "print" );
01332         kdDebug(30518)<<" style:print :"<<str<<endl;
01333 
01334         if (str.contains( "headers" ) )
01335         {
01336             //todo implement it into kspread
01337         }
01338         if ( str.contains( "grid" ) )
01339         {
01340             table->print()->setPrintGrid( true );
01341         }
01342         if ( str.contains( "annotations" ) )
01343         {
01344             //todo it's not implemented
01345         }
01346         if ( str.contains( "objects" ) )
01347         {
01348             //todo it's not implemented
01349         }
01350         if ( str.contains( "charts" ) )
01351         {
01352             //todo it's not implemented
01353         }
01354         if ( str.contains( "drawings" ) )
01355         {
01356             //todo it's not implemented
01357         }
01358         if ( str.contains( "formulas" ) )
01359         {
01360             table->setShowFormula(true);
01361         }
01362         if ( str.contains( "zero-values" ) )
01363         {
01364             //todo it's not implemented
01365         }
01366     }
01367     if ( styleStack.hasAttributeNS( ooNS::style, "table-centering" ) )
01368     {
01369         QString str = styleStack.attributeNS( ooNS::style, "table-centering" );
01370         //not implemented into kspread
01371         kdDebug(30518)<<" styleStack.attribute( style:table-centering ) :"<<str<<endl;
01372 #if 0
01373         if ( str == "horizontal" )
01374         {
01375         }
01376         else if ( str == "vertical" )
01377         {
01378         }
01379         else if ( str == "both" )
01380         {
01381         }
01382         else if ( str == "none" )
01383         {
01384         }
01385         else
01386             kdDebug(30518)<<" table-centering unknown :"<<str<<endl;
01387 #endif
01388     }
01389     format = QString( "%1x%2" ).arg( width ).arg( height );
01390     kdDebug(30518)<<" format : "<<format<<endl;
01391     table->print()->setPaperLayout( left, top, right, bottom, format, orientation );
01392 
01393     kdDebug(30518)<<" left margin :"<<left<<" right :"<<right<<" top :"<<top<<" bottom :"<<bottom<<endl;
01394 //<style:properties fo:page-width="21.8cm" fo:page-height="28.801cm" fo:margin-top="2cm" fo:margin-bottom="2.799cm" fo:margin-left="1.3cm" fo:margin-right="1.3cm" style:writing-mode="lr-tb"/>
01395 //          QString format = paper.attribute( "format" );
01396 //      QString orientation = paper.attribute( "orientation" );
01397 //        m_pPrint->setPaperLayout( left, top, right, bottom, format, orientation );
01398 //      }
01399 }
01400 
01401 
01402 bool OpenCalcImport::parseBody( int numOfTables )
01403 {
01404   QDomElement content = m_content.documentElement();
01405   QDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" );
01406 
01407   if ( body.isNull() )
01408     return false;
01409 
01410   loadOasisAreaName( body.toElement() );
01411   loadOasisCellValidation( body.toElement() );
01412 
01413   Sheet * table;
01414   QDomNode sheet = KoDom::namedItemNS( body, ooNS::table, "table" );
01415 
01416   kdDebug()<<" sheet :"<<sheet.isNull()<<endl;
01417   if ( sheet.isNull() )
01418     return false;
01419 
01420   while ( !sheet.isNull() )
01421   {
01422     QDomElement t = sheet.toElement();
01423     if ( t.isNull() )
01424     {
01425       sheet = sheet.nextSibling();
01426       continue;
01427     }
01428     if ( t.nodeName() != "table:table" )
01429     {
01430       sheet = sheet.nextSibling();
01431       continue;
01432     }
01433 
01434     table = m_doc->map()->addNewSheet();
01435 
01436     table->setSheetName( t.attributeNS( ooNS::table, "name", QString::null ), true, false );
01437     kdDebug()<<" table->name()"<<table->name()<<endl;
01438     sheet = sheet.nextSibling();
01439   }
01440 
01441   sheet = body.firstChild();
01442 
01443   int step = (int) ( 80 / numOfTables );
01444   int progress = 15;
01445 
01446   Format::setGlobalColWidth( MM_TO_POINT( 22.7 ) );
01447   Format::setGlobalRowHeight( MM_TO_POINT( 4.3 ) );
01448   kdDebug(30518) << "Global Height: " << MM_TO_POINT( 4.3 ) << ", Global width: " << MM_TO_POINT( 22.7) << endl;
01449 
01450   while ( !sheet.isNull() )
01451   {
01452     QDomElement t = sheet.toElement();
01453     if ( t.isNull() )
01454     {
01455       KMessageBox::sorry( 0, i18n( "The file seems to be corrupt. Skipping a table." ) );
01456       sheet = sheet.nextSibling();
01457       continue;
01458     }
01459     if ( t.nodeName() != "table:table" )
01460     {
01461       sheet = sheet.nextSibling();
01462       continue;
01463     }
01464 
01465     table = m_doc->map()->findSheet( t.attributeNS( ooNS::table, "name", QString::null ) );
01466     if ( !table )
01467     {
01468       KMessageBox::sorry( 0, i18n( "Skipping a table." ) );
01469       sheet = sheet.nextSibling();
01470       continue;
01471     }
01472 
01473     Format * defaultStyle = m_defaultStyles[ "Default" ];
01474     if ( defaultStyle )
01475     {
01476       Cell* defaultCell = table->defaultCell();
01477       kdDebug(30518) << "Copy default style to default cell" << endl;
01478       defaultCell->format()->copy( *defaultStyle );
01479     }
01480     table->setDefaultHeight( MM_TO_POINT( 4.3 ) );
01481     table->setDefaultWidth( MM_TO_POINT( 22.7 ) );
01482 
01483     kdDebug(30518) << "Added table: " << t.attributeNS( ooNS::table, "name", QString::null ) << endl;
01484 
01485     if ( t.hasAttributeNS( ooNS::table, "style-name" ) )
01486     {
01487       QString style = t.attributeNS( ooNS::table, "style-name", QString::null );
01488       QDomElement * tableStyle = m_styles[ style ];
01489 
01490       QDomNode node;
01491 
01492       if ( tableStyle )
01493         node = tableStyle->firstChild();
01494 
01495       while( !node.isNull() )
01496       {
01497         QDomElement property = node.toElement();
01498         if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
01499         {
01500           if ( property.hasAttributeNS( ooNS::table, "display" ) )
01501           {
01502             bool visible = (property.attributeNS( ooNS::table, "display", QString::null ) == "true" ? true : false );
01503             table->hideSheet( !visible );
01504             kdDebug(30518) << "Table: " << table->tableName() << ", hidden: " << !visible << endl;
01505           }
01506         }
01507 
01508         node = node.nextSibling();
01509       }
01510 
01511       if ( tableStyle && tableStyle->hasAttributeNS( ooNS::style, "master-page-name" ) )
01512       {
01513         QString stylename = "pm" + tableStyle->attributeNS( ooNS::style, "master-page-name", QString::null );
01514 
01515         loadTableMasterStyle( table, stylename );
01516 
01517       }
01518     }
01519     if ( t.hasAttributeNS( ooNS::table, "print-ranges" ) )
01520     {
01521       // e.g.: Sheet4.A1:Sheet4.E28
01522       QString range = t.attributeNS( ooNS::table, "print-ranges", QString::null );
01523       OpenCalcPoint point( range );
01524 
01525       kdDebug(30518) << "Print range: " << point.translation << endl;
01526       KSpread::Range p( point.translation );
01527 
01528       kdDebug(30518) << "Print table: " << p.sheetName() << endl;
01529 
01530       if ( table->sheetName() == p.sheetName() )
01531         table->print()->setPrintRange( p.range() );
01532     }
01533 
01534     if ( !readColLayouts( t, table ) )
01535       return false;
01536 
01537     if ( !readRowsAndCells( t, table ) )
01538       return false;
01539 
01540     if ( t.hasAttributeNS( ooNS::table, "protected" ) )
01541     {
01542       QCString passwd( "" );
01543       if ( t.hasAttributeNS( ooNS::table, "protection-key" ) )
01544       {
01545         QString p = t.attributeNS( ooNS::table, "protection-key", QString::null );
01546         QCString str( p.latin1() );
01547         kdDebug(30518) << "Decoding password: " << str << endl;
01548         passwd = KCodecs::base64Decode( str );
01549       }
01550       kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
01551       table->setProtected( passwd );
01552     }
01553 
01554     progress += step;
01555     emit sigProgress( progress );
01556     sheet = sheet.nextSibling();
01557   }
01558 
01559   QDomElement b = body.toElement();
01560   if ( b.hasAttributeNS( ooNS::table, "structure-protected" ) )
01561   {
01562     QCString passwd( "" );
01563     if ( b.hasAttributeNS( ooNS::table, "protection-key" ) )
01564     {
01565       QString p = b.attributeNS( ooNS::table, "protection-key", QString::null );
01566       QCString str( p.latin1() );
01567       kdDebug(30518) << "Decoding password: " << str << endl;
01568       passwd = KCodecs::base64Decode( str );
01569     }
01570     kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
01571 
01572     m_doc->map()->setProtected( passwd );
01573   }
01574 
01575   emit sigProgress( 98 );
01576 
01577   return true;
01578 }
01579 
01580 void OpenCalcImport::insertStyles( QDomElement const & element )
01581 {
01582   if ( element.isNull() )
01583     return;
01584 
01585   QDomElement e;
01586   forEachElement( e, element )
01587   {
01588     if ( e.isNull() || !e.hasAttributeNS( ooNS::style, "name" ) )
01589     {
01590       continue;
01591     }
01592 
01593     QString name = e.attributeNS( ooNS::style, "name", QString::null );
01594     kdDebug(30518) << "Style: '" << name << "' loaded " << endl;
01595     m_styles.insert( name, new QDomElement( e ) );
01596   }
01597 }
01598 
01599 
01600 void OpenCalcImport::loadOasisAreaName( const QDomElement&body )
01601 {
01602   QDomNode namedAreas = KoDom::namedItemNS( body, ooNS::table, "named-expressions" );
01603   if ( !namedAreas.isNull() )
01604   {
01605     QDomElement e;
01606     forEachElement( e, namedAreas )
01607     {
01608       if ( e.isNull() || !e.hasAttributeNS( ooNS::table, "name" ) || !e.hasAttributeNS( ooNS::table, "cell-range-address" ) )
01609       {
01610         kdDebug(30518) << "Reading in named area failed" << endl;
01611         continue;
01612       }
01613 
01614       // TODO: what is: table:base-cell-address
01615       QString name  = e.attributeNS( ooNS::table, "name", QString::null );
01616       QString areaPoint = e.attributeNS( ooNS::table, "cell-range-address", QString::null );
01617 
01618       m_namedAreas.append( name );
01619       kdDebug(30518) << "Reading in named area, name: " << name << ", area: " << areaPoint << endl;
01620 
01621       OpenCalcPoint point( areaPoint );
01622       kdDebug(30518) << "Area: " << point.translation << endl;
01623 
01624       QString range( point.translation );
01625 
01626       if ( point.translation.find( ':' ) == -1 )
01627       {
01628         Point p( point.translation );
01629 
01630         int n = range.find( '!' );
01631         if ( n > 0 )
01632           range = range + ":" + range.right( range.length() - n - 1);
01633 
01634         kdDebug(30518) << "=> Area: " << range << endl;
01635       }
01636 
01637       KSpread::Range p( range );
01638 
01639       m_doc->addAreaName( p.range(), name, p.sheetName() );
01640       kdDebug(30518) << "Area range: " << p.sheetName() << endl;
01641     }
01642   }
01643 }
01644 
01645 void OpenCalcImport::loadOasisCellValidation( const QDomElement&body )
01646 {
01647     QDomNode validation = KoDom::namedItemNS( body, ooNS::table, "content-validations" );
01648     if ( !validation.isNull() )
01649     {
01650         QDomElement element;
01651         forEachElement( element, validation )
01652         {
01653             if ( element.localName() ==  "content-validation" ) {
01654                 m_validationList.insert( element.attributeNS( ooNS::table, "name", QString::null ), element);
01655                 kdDebug(30518)<<" validation found :"<<element.attributeNS( ooNS::table, "name", QString::null )<<endl;
01656             }
01657             else {
01658                 kdDebug(30518)<<" Tag not recognize :"<<element.tagName()<<endl;
01659             }
01660         }
01661     }
01662 }
01663 
01664 
01665 QString * OpenCalcImport::loadFormat( QDomElement * element,
01666                                       FormatType & formatType,
01667                                       QString name )
01668 {
01669   if ( !element )
01670     return 0;
01671 
01672   int  i;
01673   bool ok;
01674 
01675   QString * format = 0;
01676   QDomElement e = element->firstChild( ).toElement();
01677   int precision = 0;
01678   int leadingZ  = 1;
01679   bool thousandsSep = false;
01680   bool negRed = false;
01681 
01682   if ( element->localName() == "time-style" )
01683     formatType = Custom_format;
01684   else if ( element->localName() == "date-style" )
01685     formatType = Custom_format;
01686   else if ( element->localName() == "percentage-style" )
01687     formatType = Custom_format;
01688   else if ( element->localName() == "number-style" )
01689     formatType = Custom_format;
01690   else if ( element->localName() == "currency-style" )
01691     formatType = Custom_format;
01692   else if ( element->localName() == "boolean-style" )
01693     formatType = Custom_format;
01694 
01695   if ( !e.isNull() )
01696     format = new QString();
01697 
01698   // TODO (element):
01699   // number:automatic-order="true"
01700   // number:truncate-on-overflow="false"
01701   // style:volatile="true"
01702 
01703   while ( !e.isNull() )
01704   {
01705     if ( e.localName() == "properties" && e.namespaceURI() == ooNS::style )
01706     {
01707       if ( e.hasAttributeNS( ooNS::fo, "color" ) )
01708         negRed = true; // we only support red...
01709     }
01710     else if ( e.localName() == "text" && e.namespaceURI()==ooNS::number)
01711     {
01712       if ( negRed && ( e.text() == "-" ) )
01713         ;
01714       else
01715         format->append( e.text() );
01716     }
01717     else if ( e.localName() == "currency-symbol" && e.namespaceURI()==ooNS::number)
01718     {
01719       QString sym( e.text() );
01720       kdDebug(30518) << "Currency: " << sym << endl;
01721       format->append( sym );
01722       // number:language="de" number:country="DE">€</number:currency-symbol>
01723     }
01724     else if ( e.localName() == "day-of-week" && e.namespaceURI()==ooNS::number)
01725     {
01726       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01727       {
01728         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01729           format->append( "dddd" );
01730         else
01731           format->append( "ddd" );
01732       }
01733       else
01734         format->append( "ddd" );
01735     }
01736     else if ( e.localName() == "day" && e.namespaceURI()==ooNS::number)
01737     {
01738       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01739       {
01740         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01741           format->append( "dd" );
01742         else
01743           format->append( "d" );
01744       }
01745       else
01746         format->append( "d" );
01747     }
01748     else if ( e.localName() == "month" && e.namespaceURI()==ooNS::number)
01749     {
01750       if ( e.hasAttributeNS( ooNS::number, "textual" ) )
01751       {
01752         if ( e.attributeNS( ooNS::number, "textual", QString::null ) == "true" )
01753           format->append( "mm" );
01754       }
01755 
01756       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01757       {
01758         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01759           format->append( "mm" );
01760         else
01761           format->append( "m" );
01762       }
01763       else
01764         format->append( "m" );
01765     }
01766     else if ( e.localName() == "year" && e.namespaceURI()==ooNS::number)
01767     {
01768       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01769       {
01770         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01771           format->append( "yyyy" );
01772         else
01773           format->append( "yy" );
01774       }
01775       else
01776         format->append( "yy" );
01777     }
01778     else if ( e.localName() == "hours" && e.namespaceURI()==ooNS::number)
01779     {
01780       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01781       {
01782         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01783           format->append( "hh" );
01784         else
01785           format->append( "h" );
01786       }
01787       else
01788         format->append( "h" );
01789     }
01790     else if ( e.localName() == "minutes" && e.namespaceURI()==ooNS::number)
01791     {
01792       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01793       {
01794         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01795           format->append( "mm" );
01796         else
01797           format->append( "m" );
01798       }
01799       else
01800         format->append( "m" );
01801     }
01802     else if ( e.localName() == "seconds" && e.namespaceURI()==ooNS::number)
01803     {
01804       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01805       {
01806         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01807           format->append( "ss" );
01808         else
01809           format->append( "s" );
01810       }
01811       else
01812         format->append( "s" );
01813     }
01814     else if ( e.localName() == "am-pm" && e.namespaceURI()==ooNS::number)
01815     {
01816       format->append( "AM/PM" );
01817     }
01818     else if ( e.localName() == "number" && e.namespaceURI()==ooNS::number)
01819     {
01820       // TODO: number:grouping="true"
01821 
01822       if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) )
01823       {
01824         int d = e.attributeNS( ooNS::number, "decimal-places", QString::null ).toInt( &ok );
01825         if ( ok )
01826           precision = d;
01827       }
01828 
01829       if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
01830       {
01831         int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok );
01832         if ( ok )
01833           leadingZ = d;
01834       }
01835 
01836       if ( thousandsSep && leadingZ <= 3 )
01837       {
01838         format->append( "#," );
01839         for ( i = leadingZ; i <= 3; ++i )
01840           format->append( '#' );
01841       }
01842 
01843       for ( i = 1; i <= leadingZ; ++i )
01844       {
01845         format->append( '0' );
01846         if ( ( i % 3 == 0 ) && thousandsSep )
01847           format->append( ',' );
01848       }
01849 
01850       format->append( '.' );
01851       for ( i = 0; i < precision; ++i )
01852         format->append( '0' );
01853     }
01854     else if ( e.localName() == "scientific-number" && e.namespaceURI()==ooNS::number)
01855     {
01856       int exp = 2;
01857 
01858       if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) )
01859       {
01860         int d = e.attributeNS( ooNS::number, "decimal-places", QString::null ).toInt( &ok );
01861         if ( ok )
01862           precision = d;
01863       }
01864 
01865       if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
01866       {
01867         int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok );
01868         if ( ok )
01869           leadingZ = d;
01870       }
01871 
01872       if ( e.hasAttributeNS( ooNS::number, "min-exponent-digits" ) )
01873       {
01874         int d = e.attributeNS( ooNS::number, "min-exponent-digits", QString::null ).toInt( &ok );
01875         if ( ok )
01876           exp = d;
01877         if ( exp <= 0 )
01878           exp = 1;
01879       }
01880 
01881       if ( thousandsSep && leadingZ <= 3 )
01882       {
01883         format->append( "#," );
01884         for ( i = leadingZ; i <= 3; ++i )
01885           format->append( '#' );
01886       }
01887 
01888       for ( i = 1; i <= leadingZ; ++i )
01889       {
01890         format->append( '0' );
01891         if ( ( i % 3 == 0 ) && thousandsSep )
01892           format->append( ',' );
01893       }
01894 
01895       format->append( '.' );
01896       for ( i = 0; i < precision; ++i )
01897         format->append( '0' );
01898 
01899       format->append( "E+" );
01900       for ( i = 0; i < exp; ++i )
01901         format->append( '0' );
01902 
01903       formatType = Custom_format;
01904     }
01905     else if ( e.localName() == "fraction" && e.namespaceURI()==ooNS::number)
01906     {
01907       int integer = 0;
01908       int numerator = 1;
01909       int denominator = 1;
01910 
01911       if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
01912       {
01913         int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok );
01914         if ( ok )
01915           integer = d;
01916       }
01917       if ( e.hasAttributeNS( ooNS::number, "min-numerator-digits" ) )
01918       {
01919         int d = e.attributeNS( ooNS::number, "min-numerator-digits", QString::null ).toInt( &ok );
01920         if ( ok )
01921           numerator = d;
01922       }
01923       if ( e.hasAttributeNS( ooNS::number, "min-denominator-digits" ) )
01924       {
01925         int d = e.attributeNS( ooNS::number, "min-denominator-digits", QString::null ).toInt( &ok );
01926         if ( ok )
01927           denominator = d;
01928       }
01929 
01930       for ( i = 0; i <= integer; ++i )
01931         format->append( '#' );
01932 
01933       format->append( ' ' );
01934 
01935       for ( i = 0; i <= numerator; ++i )
01936         format->append( '?' );
01937 
01938       format->append( '/' );
01939 
01940       for ( i = 0; i <= denominator; ++i )
01941         format->append( '?' );
01942     }
01943     // Not needed:
01944     //  <style:map style:condition="value()&gt;=0" style:apply-style-name="N106P0"/>
01945     // we handle painting negative numbers in red differently
01946 
01947     e = e.nextSibling().toElement();
01948   }
01949 
01950   if ( negRed )
01951   {
01952     QString f( *format );
01953     format->append( ";[Red]" );
01954     format->append( f );
01955   }
01956 
01957   kdDebug(30518) << "*** New FormatString: " << *format << endl << endl;
01958 
01959   m_formats.insert( name, format );
01960 
01961   return format;
01962 }
01963 
01964 void OpenCalcImport::loadFontStyle( Format * layout, QDomElement const * font ) const
01965 {
01966   if ( !font || !layout )
01967     return;
01968 
01969   kdDebug(30518) << "Copy font style from the layout " << font->tagName() << ", " << font->nodeName() << endl;
01970 
01971   if ( font->hasAttributeNS( ooNS::fo, "font-family" ) )
01972     layout->setTextFontFamily( font->attributeNS( ooNS::fo, "font-family", QString::null ) );
01973   if ( font->hasAttributeNS( ooNS::fo, "color" ) )
01974     layout->setTextColor( QColor( font->attributeNS( ooNS::fo, "color", QString::null ) ) );
01975   if ( font->hasAttributeNS( ooNS::fo, "font-size" ) )
01976       layout->setTextFontSize( int( KoUnit::parseValue( font->attributeNS( ooNS::fo, "font-size", QString::null ), 10 ) ) );
01977   else
01978     layout->setTextFontSize( 10 );
01979   if ( font->hasAttributeNS( ooNS::fo, "font-style" ) )
01980   {
01981     kdDebug(30518) << "italic" << endl;
01982     layout->setTextFontItalic( true ); // only thing we support
01983   }
01984   if ( font->hasAttributeNS( ooNS::fo, "font-weight" ) )
01985     layout->setTextFontBold( true ); // only thing we support
01986   if ( font->hasAttributeNS( ooNS::fo, "text-underline" ) || font->hasAttributeNS( ooNS::style, "text-underline" ) )
01987     layout->setTextFontUnderline( true ); // only thing we support
01988   if ( font->hasAttributeNS( ooNS::style, "text-crossing-out" ) )
01989     layout->setTextFontStrike( true ); // only thing we support
01990   if ( font->hasAttributeNS( ooNS::style, "font-pitch" ) )
01991   {
01992     // TODO: possible values: fixed, variable
01993   }
01994   // TODO:
01995   // text-underline-color
01996 }
01997 
01998 void OpenCalcImport::loadBorder( Format * layout, QString const & borderDef, bPos pos ) const
01999 {
02000   if ( borderDef == "none" )
02001     return;
02002 
02003   int p = borderDef.find( ' ' );
02004   if ( p < 0 )
02005     return;
02006 
02007   QPen pen;
02008   QString w = borderDef.left( p );
02009   pen.setWidth( (int) KoUnit::parseValue( w ) );
02010 
02011 
02012   ++p;
02013   int p2 = borderDef.find( ' ', p );
02014   QString s = borderDef.mid( p, p2 - p );
02015 
02016   kdDebug(30518) << "Borderstyle: " << s << endl;
02017 
02018   if ( s == "solid" || s == "double" )
02019     pen.setStyle( Qt::SolidLine );
02020   else
02021   {
02022 #if 0
02023     // TODO: not supported by oocalc
02024     pen.setStyle( Qt::DashLine );
02025     pen.setStyle( Qt::DotLine );
02026     pen.setStyle( Qt::DashDotLine );
02027     pen.setStyle( Qt::DashDotDotLine );
02028 #endif
02029     pen.setStyle( Qt::SolidLine ); //default.
02030   }
02031 
02032   ++p2;
02033   p = borderDef.find( ' ', p2 );
02034   if ( p == -1 )
02035     p = borderDef.length();
02036 
02037   pen.setColor( QColor( borderDef.right( p - p2 ) ) );
02038 
02039   if ( pos == Left )
02040     layout->setLeftBorderPen( pen );
02041   else if ( pos == Top )
02042     layout->setTopBorderPen( pen );
02043   else if ( pos == Right )
02044     layout->setRightBorderPen( pen );
02045   else if ( pos == Bottom )
02046     layout->setBottomBorderPen( pen );
02047   else if ( pos == Border )
02048   {
02049     layout->setLeftBorderPen( pen );
02050     layout->setTopBorderPen( pen );
02051     layout->setRightBorderPen( pen );
02052     layout->setBottomBorderPen( pen );
02053   }
02054   // TODO Diagonals not supported by oocalc
02055 }
02056 
02057 void OpenCalcImport::loadStyleProperties( Format * layout, QDomElement const & property ) const
02058 {
02059   kdDebug(30518) << "*** Loading style properties *****" << endl;
02060 
02061   if ( property.hasAttributeNS( ooNS::style, "decimal-places" ) )
02062   {
02063     bool ok = false;
02064     int p = property.attributeNS( ooNS::style, "decimal-places", QString::null ).toInt( &ok );
02065     if (ok )
02066       layout->setPrecision( p );
02067   }
02068 
02069   if ( property.hasAttributeNS( ooNS::style, "font-name" ) )
02070   {
02071     QDomElement * font = m_styles[ property.attributeNS( ooNS::style, "font-name", QString::null ) ];
02072     loadFontStyle( layout, font ); // generell font style
02073   }
02074 
02075   loadFontStyle( layout, &property ); // specific font style
02076 
02077   // TODO:
02078   //   diagonal: fall + goup
02079   //   fo:direction="ltr"
02080   //   style:text-align-source  ("fix")
02081   //   style:shadow
02082   //   style:text-outline
02083   //   indents from right, top, bottom
02084   //   style:condition="cell-content()=15"
02085   //     => style:apply-style-name="Result" style:base-cell-address="Sheet6.A5"/>
02086 
02087   if ( property.hasAttributeNS( ooNS::style, "rotation-angle" ) )
02088   {
02089     bool ok = false;
02090     int a = property.attributeNS( ooNS::style, "rotation-angle", QString::null ).toInt( &ok );
02091     if ( ok )
02092       layout->setAngle( -a + 1 );
02093   }
02094 
02095   if ( property.hasAttributeNS( ooNS::fo, "direction" ) )
02096   {
02097       layout->setVerticalText( true );
02098   }
02099   if ( property.hasAttributeNS( ooNS::fo, "text-align" ) )
02100   {
02101     QString s = property.attributeNS( ooNS::fo, "text-align", QString::null );
02102     if ( s == "center" )
02103       layout->setAlign( Format::Center );
02104     else if ( s == "end" )
02105       layout->setAlign( Format::Right );
02106     else if ( s == "start" )
02107       layout->setAlign( Format::Left );
02108     else if ( s == "justify" ) // TODO in KSpread!
02109       layout->setAlign( Format::Center );
02110   }
02111   if (  property.hasAttributeNS( ooNS::fo, "margin-left" ) )
02112   {
02113       kdDebug(30518)<<"margin-left :"<<KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", QString::null ),0.0 )<<endl;
02114       layout->setIndent( KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", QString::null ),0.0 ) );
02115   }
02116   if ( property.hasAttributeNS( ooNS::fo, "background-color" ) )
02117     layout->setBgColor( QColor( property.attributeNS( ooNS::fo, "background-color", QString::null ) ) );
02118 
02119   if ( property.hasAttributeNS( ooNS::style, "print-content" ) )
02120   {
02121     if ( property.attributeNS( ooNS::style, "print-content", QString::null ) == "false" )
02122       layout->setDontPrintText( false );
02123   }
02124   if ( property.hasAttributeNS( ooNS::style, "cell-protect" ) )
02125   {
02126     QString prot( property.attributeNS( ooNS::style, "cell-protect", QString::null ) );
02127     if ( prot == "none" )
02128     {
02129       layout->setNotProtected( true );
02130       layout->setHideFormula( false );
02131       layout->setHideAll( false );
02132     }
02133     else if ( prot == "formula-hidden" )
02134     {
02135       layout->setNotProtected( true );
02136       layout->setHideFormula( true );
02137       layout->setHideAll( false );
02138     }
02139     else if ( prot == "protected formula-hidden" )
02140     {
02141       layout->setNotProtected( false );
02142       layout->setHideFormula( true );
02143       layout->setHideAll( false );
02144     }
02145     else if ( prot == "hidden-and-protected" )
02146     {
02147       layout->setNotProtected( false );
02148       layout->setHideFormula( false );
02149       layout->setHideAll( true );
02150     }
02151     else if ( prot == "protected" )
02152     {
02153       layout->setNotProtected( false );
02154       layout->setHideFormula( false );
02155       layout->setHideAll( false );
02156     }
02157     kdDebug(30518) << "Cell " << prot << endl;
02158   }
02159 
02160   if ( property.hasAttributeNS( ooNS::fo, "padding-left" ) )
02161     layout->setIndent(  KoUnit::parseValue(property.attributeNS( ooNS::fo, "padding-left", QString::null ) ) );
02162 
02163   if ( property.hasAttributeNS( ooNS::fo, "vertical-align" ) )
02164   {
02165     QString s = property.attributeNS( ooNS::fo, "vertical-align", QString::null );
02166     if ( s == "middle" )
02167       layout->setAlignY( Format::Middle );
02168     else if ( s == "bottom" )
02169       layout->setAlignY( Format::Bottom );
02170     else
02171       layout->setAlignY( Format::Top );
02172   }
02173   else
02174       layout->setAlignY( Format::Bottom );
02175 
02176   if ( property.hasAttributeNS( ooNS::fo, "wrap-option" ) )
02177   {
02178     layout->setMultiRow( true );
02179 
02180     /* we do not support anything else yet
02181       QString s = property.attributeNS( ooNS::fo, "wrap-option", QString::null );
02182       if ( s == "wrap" )
02183       layout->setMultiRow( true );
02184     */
02185   }
02186 
02187   if ( property.hasAttributeNS( ooNS::fo, "border-bottom" ) )
02188   {
02189     loadBorder( layout, property.attributeNS( ooNS::fo, "border-bottom", QString::null ), Bottom );
02190     // TODO: style:border-line-width-bottom if double!
02191   }
02192 
02193   if ( property.hasAttributeNS( ooNS::fo, "border-right" ) )
02194   {
02195     loadBorder( layout, property.attributeNS( ooNS::fo, "border-right", QString::null ), Right );
02196     // TODO: style:border-line-width-right
02197   }
02198 
02199   if ( property.hasAttributeNS( ooNS::fo, "border-top" ) )
02200   {
02201     loadBorder( layout, property.attributeNS( ooNS::fo, "border-top", QString::null ), Top );
02202     // TODO: style:border-line-width-top
02203   }
02204 
02205   if ( property.hasAttributeNS( ooNS::fo, "border-left" ) )
02206   {
02207     loadBorder( layout, property.attributeNS( ooNS::fo, "border-left", QString::null ), Left );
02208     // TODO: style:border-line-width-left
02209   }
02210 
02211   if ( property.hasAttributeNS( ooNS::fo, "border" ) )
02212   {
02213     loadBorder( layout, property.attributeNS( ooNS::fo, "border", QString::null ), Border );
02214     // TODO: style:border-line-width-left
02215   }
02216 }
02217 
02218 void OpenCalcImport::readInStyle( Format * layout, QDomElement const & style )
02219 {
02220   kdDebug(30518) << "** Reading Style: " << style.tagName() << "; " << style.attributeNS( ooNS::style, "name", QString::null) << endl;
02221   if ( style.localName() == "style" && style.namespaceURI()==ooNS::style)
02222   {
02223     if ( style.hasAttributeNS( ooNS::style, "parent-style-name" ) )
02224     {
02225       Format * cp
02226         = m_defaultStyles.find( style.attributeNS( ooNS::style, "parent-style-name", QString::null ) );
02227       kdDebug(30518) << "Copying layout from " << style.attributeNS( ooNS::style, "parent-style-name", QString::null ) << endl;
02228 
02229       if ( cp != 0 )
02230         layout->copy( *cp );
02231     }
02232     else if ( style.hasAttributeNS( ooNS::style, "family") )
02233     {
02234       QString name = style.attribute( "style-family" ) + "default";
02235       Format * cp = m_defaultStyles.find( name );
02236 
02237       kdDebug(30518) << "Copying layout from " << name << ", " << !cp << endl;
02238 
02239       if ( cp != 0 )
02240         layout->copy( *cp );
02241     }
02242 
02243     if ( style.hasAttributeNS( ooNS::style, "data-style-name" ) )
02244     {
02245       QString * format = m_formats[ style.attributeNS( ooNS::style, "data-style-name", QString::null ) ];
02246       FormatType formatType;
02247 
02248       if ( !format )
02249       {
02250         // load and convert it
02251         QString name( style.attributeNS( ooNS::style, "data-style-name", QString::null ) );
02252         format = loadFormat( m_styles[ name ], formatType, name );
02253       }
02254 
02255       if ( format )
02256       {
02257         layout->setFormatString( *format );
02258         layout->setFormatType( formatType );
02259       }
02260 
02261       // <number:currency-symbol number:language="de" number:country="DE">€</number:currency-symbol>
02262     }
02263   }
02264 
02265   QDomElement property;
02266   forEachElement( property, style )
02267   {
02268     if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
02269       loadStyleProperties( layout, property );
02270 
02271     kdDebug(30518) << layout->textFontFamily( 0, 0 ) << endl;
02272   }
02273 }
02274 
02275 bool OpenCalcImport::createStyleMap( QDomDocument const & styles )
02276 {
02277   QDomElement content  = styles.documentElement();
02278   QDomNode docStyles   = KoDom::namedItemNS( content, ooNS::office, "document-styles" );
02279 
02280   if ( content.hasAttributeNS( ooNS::office, "version" ) )
02281   {
02282     bool ok = true;
02283     double d = content.attributeNS( ooNS::office, "version", QString::null ).toDouble( &ok );
02284 
02285     if ( ok )
02286     {
02287       kdDebug(30518) << "OpenCalc version: " << d << endl;
02288       if ( d > 1.0 )
02289       {
02290         QString message( i18n("This document was created with OpenOffice.org version '%1'. This filter was written for version 1.0. Reading this file could cause strange behavior, crashes or incorrect display of the data. Do you want to continue converting the document?") );
02291         message.arg( content.attributeNS( ooNS::office, "version", QString::null ) );
02292         if ( KMessageBox::warningYesNo( 0, message, i18n( "Unsupported document version" ) ) == KMessageBox::No )
02293           return false;
02294       }
02295     }
02296   }
02297 
02298   QDomNode fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" );
02299 
02300   if ( !fontStyles.isNull() )
02301   {
02302     kdDebug(30518) << "Starting reading in font-decl..." << endl;
02303 
02304     insertStyles( fontStyles.toElement() );
02305   }
02306   else
02307     kdDebug(30518) << "No items found" << endl;
02308 
02309   kdDebug(30518) << "Starting reading in auto:styles" << endl;
02310 
02311   QDomNode autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
02312   if ( !autoStyles.isNull() )
02313     insertStyles( autoStyles.toElement() );
02314   else
02315     kdDebug(30518) << "No items found" << endl;
02316 
02317 
02318   kdDebug(30518) << "Reading in master styles" << endl;
02319 
02320   QDomNode masterStyles = KoDom::namedItemNS( content, ooNS::office, "master-styles" );
02321 
02322   if ( masterStyles.isNull() )
02323   {
02324     kdDebug(30518) << "Nothing found " << endl;
02325   }
02326 
02327   QDomElement master = KoDom::namedItemNS( masterStyles, ooNS::style, "master-page");
02328   if ( !master.isNull() )
02329   {
02330     QString name( "pm" );
02331     name += master.attributeNS( ooNS::style, "name", QString::null );
02332     kdDebug(30518) << "Master style: '" << name << "' loaded " << endl;
02333     m_styles.insert( name, new QDomElement( master ) );
02334 
02335     master = master.nextSibling().toElement();
02336   }
02337 
02338 
02339   kdDebug(30518) << "Starting reading in office:styles" << endl;
02340 
02341   QDomNode fixedStyles = KoDom::namedItemNS( content, ooNS::office, "styles" );
02342 
02343   kdDebug(30518) << "Reading in default styles" << endl;
02344 
02345   QDomNode def = KoDom::namedItemNS( fixedStyles, ooNS::style, "default-style" );
02346   kdDebug()<<" def !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<def.isNull()<<endl;
02347   while ( !def.isNull() )
02348   {
02349     QDomElement e = def.toElement();
02350     kdDebug(30518) << "Style found " << e.nodeName() << ", tag: " << e.tagName() << endl;
02351 
02352     if ( e.nodeName() != "style:default-style" )
02353     {
02354       def = def.nextSibling();
02355       continue;
02356     }
02357 
02358     if ( !e.isNull() )
02359     {
02360       Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() );
02361 
02362       readInStyle( layout, e );
02363       kdDebug(30518) << "Default style " << e.attributeNS( ooNS::style, "family", QString::null ) << "default" << " loaded " << endl;
02364 
02365       m_defaultStyles.insert( e.attributeNS( ooNS::style, "family", QString::null ) + "default", layout );
02366       //      QFont font = layout->font();
02367       //      kdDebug(30518) << "Font: " << font.family() << ", " << font.toString() << endl;
02368     }
02369 
02370     def = def.nextSibling();
02371   }
02372 
02373   QDomElement defs = KoDom::namedItemNS( fixedStyles, ooNS::style, "style" );
02374   while ( !defs.isNull() )
02375   {
02376     if ( defs.nodeName() != "style:style" )
02377       break; // done
02378 
02379     if ( !defs.hasAttributeNS( ooNS::style, "name" ) )
02380     {
02381       // ups...
02382       defs = defs.nextSibling().toElement();
02383       continue;
02384     }
02385 
02386     Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() );
02387     readInStyle( layout, defs );
02388     kdDebug(30518) << "Default style " << defs.attributeNS( ooNS::style, "name", QString::null ) << " loaded " << endl;
02389 
02390     m_defaultStyles.insert( defs.attributeNS( ooNS::style, "name", QString::null ), layout );
02391     //    kdDebug(30518) << "Font: " << layout->font().family() << ", " << layout->font().toString() << endl;
02392 
02393     defs = defs.nextSibling().toElement();
02394   }
02395 
02396   if ( !fixedStyles.isNull() )
02397     insertStyles( fixedStyles.toElement() );
02398 
02399   kdDebug(30518) << "Starting reading in automatic styles" << endl;
02400 
02401   content = m_content.documentElement();
02402   autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
02403 
02404   if ( !autoStyles.isNull() )
02405     insertStyles( autoStyles.toElement() );
02406 
02407   fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" );
02408 
02409   if ( !fontStyles.isNull() )
02410   {
02411     kdDebug(30518) << "Starting reading in special font decl" << endl;
02412 
02413     insertStyles( fontStyles.toElement() );
02414   }
02415 
02416   kdDebug(30518) << "Styles read in." << endl;
02417 
02418   return true;
02419 }
02420 
02421 void OpenCalcImport::loadOasisValidation( Validity* val, const QString& validationName )
02422 {
02423     kdDebug(30518)<<"validationName:"<<validationName<<endl;
02424     QDomElement element = m_validationList[validationName];
02425     if ( element.hasAttributeNS( ooNS::table, "condition" ) )
02426     {
02427         QString valExpression = element.attributeNS( ooNS::table, "condition", QString::null );
02428         kdDebug(30518)<<" element.attribute( table:condition ) "<<valExpression<<endl;
02429         //Condition ::= ExtendedTrueCondition | TrueFunction 'and' TrueCondition
02430         //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
02431         //ExtendedTrueCondition ::= ExtendedGetFunction | cell-content-text-length() Operator Value
02432         //TrueCondition ::= GetFunction | cell-content() Operator Value
02433         //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
02434         //ExtendedGetFunction ::= cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value)
02435         //Operator ::= '<' | '>' | '<=' | '>=' | '=' | '!='
02436         //Value ::= NumberValue | String | Formula
02437         //A Formula is a formula without an equals (=) sign at the beginning. See section 8.1.3 for more information.
02438         //A String comprises one or more characters surrounded by quotation marks.
02439         //A NumberValue is a whole or decimal number. It must not contain comma separators for numbers of 1000 or greater.
02440 
02441         //ExtendedTrueCondition
02442         if ( valExpression.contains( "cell-content-text-length()" ) )
02443         {
02444             //"cell-content-text-length()>45"
02445             valExpression = valExpression.remove("cell-content-text-length()" );
02446             kdDebug(30518)<<" valExpression = :"<<valExpression<<endl;
02447             val->m_restriction = Restriction::TextLength;
02448 
02449             loadOasisValidationCondition( val, valExpression );
02450         }
02451         //cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value)
02452         else if ( valExpression.contains( "cell-content-text-length-is-between" ) )
02453         {
02454             val->m_restriction = Restriction::TextLength;
02455             val->m_cond = Conditional::Between;
02456             valExpression = valExpression.remove( "cell-content-text-length-is-between(" );
02457             kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
02458             valExpression = valExpression.remove( ")" );
02459             QStringList listVal = QStringList::split( ",", valExpression );
02460             loadOasisValidationValue( val, listVal );
02461         }
02462         else if ( valExpression.contains( "cell-content-text-length-is-not-between" ) )
02463         {
02464             val->m_restriction = Restriction::TextLength;
02465             val->m_cond = Conditional::Different;
02466             valExpression = valExpression.remove( "cell-content-text-length-is-not-between(" );
02467             kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
02468             valExpression = valExpression.remove( ")" );
02469             kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
02470             QStringList listVal = QStringList::split( ",", valExpression );
02471             loadOasisValidationValue( val, listVal );
02472 
02473         }
02474         //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
02475         else
02476         {
02477             if (valExpression.contains( "cell-content-is-whole-number()" ) )
02478             {
02479                 val->m_restriction =  Restriction::Number;
02480                 valExpression = valExpression.remove( "cell-content-is-whole-number() and " );
02481             }
02482             else if (valExpression.contains( "cell-content-is-decimal-number()" ) )
02483             {
02484                 val->m_restriction = Restriction::Integer;
02485                 valExpression = valExpression.remove( "cell-content-is-decimal-number() and " );
02486             }
02487             else if (valExpression.contains( "cell-content-is-date()" ) )
02488             {
02489                 val->m_restriction = Restriction::Date;
02490                 valExpression = valExpression.remove( "cell-content-is-date() and " );
02491             }
02492             else if (valExpression.contains( "cell-content-is-time()" ) )
02493             {
02494                 val->m_restriction = Restriction::Time;
02495                 valExpression = valExpression.remove( "cell-content-is-time() and " );
02496             }
02497             kdDebug(30518)<<"valExpression :"<<valExpression<<endl;
02498 
02499             if ( valExpression.contains( "cell-content()" ) )
02500             {
02501                 valExpression = valExpression.remove( "cell-content()" );
02502                 loadOasisValidationCondition( val, valExpression );
02503             }
02504             //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
02505             //for the moment we support just int/double value, not text/date/time :(
02506             if ( valExpression.contains( "cell-content-is-between(" ) )
02507             {
02508                 valExpression = valExpression.remove( "cell-content-is-between(" );
02509                 valExpression = valExpression.remove( ")" );
02510                 QStringList listVal = QStringList::split( "," , valExpression );
02511                 loadOasisValidationValue( val, listVal );
02512 
02513                 val->m_cond = Conditional::Between;
02514             }
02515             if ( valExpression.contains( "cell-content-is-not-between(" ) )
02516             {
02517                 valExpression = valExpression.remove( "cell-content-is-not-between(" );
02518                 valExpression = valExpression.remove( ")" );
02519                 QStringList listVal = QStringList::split( ",", valExpression );
02520                 loadOasisValidationValue( val, listVal );
02521                 val->m_cond = Conditional::Different;
02522             }
02523         }
02524     }
02525     if ( element.hasAttributeNS( ooNS::table, "allow-empty-cell" ) )
02526     {
02527         val->allowEmptyCell = ( ( element.attributeNS( ooNS::table, "allow-empty-cell", QString::null )=="true" ) ? true : false );
02528 
02529     }
02530     if ( element.hasAttributeNS( ooNS::table, "base-cell-address" ) )
02531     {
02532         //todo what is it ?
02533     }
02534 
02535     QDomElement help = KoDom::namedItemNS( element, ooNS::table, "help-message" );
02536     if ( !help.isNull() )
02537     {
02538         if ( help.hasAttributeNS( ooNS::table, "title" ) )
02539              val->titleInfo = help.attributeNS( ooNS::table, "title", QString::null );
02540         if ( help.hasAttributeNS( ooNS::table, "display" ) )
02541             val->displayValidationInformation = ( ( help.attributeNS( ooNS::table, "display", QString::null )=="true" ) ? true : false );
02542         QDomElement attrText = KoDom::namedItemNS( help, ooNS::text, "p" );
02543         if ( !attrText.isNull() )
02544             val->messageInfo = attrText.text();
02545     }
02546 
02547     QDomElement error = KoDom::namedItemNS( element, ooNS::table, "error-message" );
02548     if ( !error.isNull() )
02549     {
02550         if ( error.hasAttributeNS( ooNS::table, "title" ) )
02551             val->title = error.attributeNS( ooNS::table, "title", QString::null );
02552         if ( error.hasAttributeNS( ooNS::table, "message-type" ) )
02553         {
02554             QString str = error.attributeNS( ooNS::table, "message-type", QString::null );
02555             if ( str == "warning" )
02556               val->m_action = Action::Warning;
02557             else if ( str == "information" )
02558               val->m_action = Action::Information;
02559             else if ( str == "stop" )
02560               val->m_action = Action::Stop;
02561             else
02562                 kdDebug(30518)<<"validation : message type unknown  :"<<str<<endl;
02563         }
02564 
02565         if ( error.hasAttributeNS( ooNS::table, "display" ) )
02566         {
02567             kdDebug(30518)<<" display message :"<<error.attributeNS( ooNS::table, "display", QString::null )<<endl;
02568             val->displayMessage = (error.attributeNS( ooNS::table, "display", QString::null )=="true");
02569         }
02570         QDomElement attrText = KoDom::namedItemNS( error, ooNS::text, "p" );
02571         if ( !attrText.isNull() )
02572             val->message = attrText.text();
02573     }
02574 }
02575 
02576 void OpenCalcImport::loadOasisValidationValue( Validity* val, const QStringList &listVal )
02577 {
02578     bool ok = false;
02579     kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
02580 
02581     if ( val->m_restriction == Restriction::Date )
02582     {
02583         val->dateMin = QDate::fromString( listVal[0] );
02584         val->dateMax = QDate::fromString( listVal[1] );
02585     }
02586     else if ( val->m_restriction == Restriction::Time )
02587     {
02588         val->timeMin = QTime::fromString( listVal[0] );
02589         val->timeMax = QTime::fromString( listVal[1] );
02590     }
02591     else
02592     {
02593         val->valMin = listVal[0].toDouble(&ok);
02594         if ( !ok )
02595         {
02596             val->valMin = listVal[0].toInt(&ok);
02597             if ( !ok )
02598                 kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl;
02599 
02600 #if 0
02601             if ( !ok )
02602                 val->valMin = listVal[0];
02603 #endif
02604         }
02605         ok=false;
02606         val->valMax = listVal[1].toDouble(&ok);
02607         if ( !ok )
02608         {
02609             val->valMax = listVal[1].toInt(&ok);
02610             if ( !ok )
02611                 kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl;
02612 
02613 #if 0
02614             if ( !ok )
02615                 val->valMax = listVal[1];
02616 #endif
02617         }
02618     }
02619 }
02620 
02621 
02622 void OpenCalcImport::loadOasisValidationCondition( Validity* val,QString &valExpression )
02623 {
02624     QString value;
02625     if (valExpression.contains( "<=" ) )
02626     {
02627         value = valExpression.remove( "<=" );
02628         val->m_cond = Conditional::InferiorEqual;
02629     }
02630     else if (valExpression.contains( ">=" ) )
02631     {
02632         value = valExpression.remove( ">=" );
02633         val->m_cond = Conditional::SuperiorEqual;
02634     }
02635     else if (valExpression.contains( "!=" ) )
02636     {
02637         //add Differentto attribute
02638         value = valExpression.remove( "!=" );
02639         val->m_cond = Conditional::DifferentTo;
02640     }
02641     else if ( valExpression.contains( "<" ) )
02642     {
02643         value = valExpression.remove( "<" );
02644         val->m_cond = Conditional::Inferior;
02645     }
02646     else if(valExpression.contains( ">" ) )
02647     {
02648         value = valExpression.remove( ">" );
02649         val->m_cond = Conditional::Superior;
02650     }
02651     else if (valExpression.contains( "=" ) )
02652     {
02653         value = valExpression.remove( "=" );
02654         val->m_cond = Conditional::Equal;
02655     }
02656     else
02657         kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl;
02658     kdDebug(30518)<<" value :"<<value<<endl;
02659     if ( val->m_restriction == Restriction::Date )
02660     {
02661         val->dateMin = QDate::fromString( value );
02662     }
02663     else if ( val->m_restriction == Restriction::Date )
02664     {
02665         val->timeMin = QTime::fromString( value );
02666     }
02667     else
02668     {
02669         bool ok = false;
02670         val->valMin = value.toDouble(&ok);
02671         if ( !ok )
02672         {
02673             val->valMin = value.toInt(&ok);
02674             if ( !ok )
02675                 kdDebug(30518)<<" Try to parse this value :"<<value<<endl;
02676 
02677 #if 0
02678             if ( !ok )
02679                 val->valMin = value;
02680 #endif
02681         }
02682     }
02683 }
02684 
02685 
02686 int OpenCalcImport::readMetaData()
02687 {
02688   int result = 5;
02689   KoDocumentInfo * docInfo          = m_doc->documentInfo();
02690   KoDocumentInfoAbout  * aboutPage  = static_cast<KoDocumentInfoAbout *>(docInfo->page( "about" ));
02691   KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>(docInfo->page( "author" ));
02692 
02693   QDomNode meta   = KoDom::namedItemNS( m_meta, ooNS::office, "document-meta" );
02694   QDomNode office = KoDom::namedItemNS( meta, ooNS::office, "meta" );
02695 
02696   if ( office.isNull() )
02697     return 2;
02698 
02699   QDomElement e = KoDom::namedItemNS( office, ooNS::dc, "creator" );
02700   if ( !e.isNull() && !e.text().isEmpty() )
02701     authorPage->setFullName( e.text() );
02702 
02703   e = KoDom::namedItemNS( office, ooNS::dc, "title" );
02704   if ( !e.isNull() && !e.text().isEmpty() )
02705     aboutPage->setTitle( e.text() );
02706 
02707   e = KoDom::namedItemNS( office, ooNS::dc, "description" );
02708   if ( !e.isNull() && !e.text().isEmpty() )
02709     aboutPage->setAbstract( e.text() );
02710 
02711   e = KoDom::namedItemNS( office, ooNS::dc, "subject" );
02712   if ( !e.isNull() && !e.text().isEmpty() )
02713     aboutPage->setSubject( e.text() );
02714 
02715   e= KoDom::namedItemNS( office, ooNS::meta, "keywords" );
02716   if ( !e.isNull() )
02717   {
02718       e = KoDom::namedItemNS( e,  ooNS::meta, "keyword" );
02719       if ( !e.isNull() && !e.text().isEmpty() )
02720           aboutPage->setKeywords( e.text() );
02721   }
02722 
02723   e = KoDom::namedItemNS( office, ooNS::meta, "document-statistic" );
02724   if ( !e.isNull() && e.hasAttributeNS( ooNS::meta, "table-count" ) )
02725   {
02726     bool ok = false;
02727     result = e.attributeNS( ooNS::meta, "table-count", QString::null ).toInt( &ok );
02728     if ( !ok )
02729       result = 5;
02730   }
02731 
02732   m_meta.clear(); // not needed anymore
02733 
02734   return result;
02735 }
02736 
02737 KoFilter::ConversionStatus OpenCalcImport::convert( QCString const & from, QCString const & to )
02738 {
02739   kdDebug(30518) << "Entering OpenCalc Import filter: " << from << " - " << to << endl;
02740 
02741   KoDocument * document = m_chain->outputDocument();
02742   if ( !document )
02743     return KoFilter::StupidError;
02744 
02745   if (  !::qt_cast<const KSpread::Doc *>( document ) )  // it's safer that way :)
02746   {
02747     kdWarning(30518) << "document isn't a KSpread::Doc but a " << document->className() << endl;
02748     return KoFilter::NotImplemented;
02749   }
02750 
02751   if ( ( from != "application/vnd.sun.xml.calc" && from != "application/vnd.sun.xml.calc.template") || to != "application/x-kspread" )
02752   {
02753     kdWarning(30518) << "Invalid mimetypes " << from << " " << to << endl;
02754     return KoFilter::NotImplemented;
02755   }
02756 
02757   m_doc = ( Doc * ) document;
02758 
02759   if ( m_doc->mimeType() != "application/x-kspread" )
02760   {
02761     kdWarning(30518) << "Invalid document mimetype " << m_doc->mimeType() << endl;
02762     return KoFilter::NotImplemented;
02763   }
02764 
02765   kdDebug(30518) << "Opening file " << endl;
02766 
02767   KoFilter::ConversionStatus preStatus = openFile();
02768 
02769   if ( preStatus != KoFilter::OK )
02770     return preStatus;
02771 
02772   emit sigProgress( 13 );
02773   int tables = readMetaData();
02774 
02775   emit sigProgress( 15 );
02776 
02777   if ( !parseBody( tables ) )
02778     return KoFilter::StupidError;
02779 
02780   emit sigProgress( 100 );
02781   return KoFilter::OK;
02782 }
02783 
02784 KoFilter::ConversionStatus OpenCalcImport::openFile()
02785 {
02786   KoStore * store = KoStore::createStore( m_chain->inputFile(), KoStore::Read);
02787 
02788   kdDebug(30518) << "Store created" << endl;
02789 
02790   if ( !store )
02791   {
02792     kdWarning(30518) << "Couldn't open the requested file." << endl;
02793     return KoFilter::FileNotFound;
02794   }
02795 
02796   kdDebug(30518) << "Trying to open content.xml" << endl;
02797   QString messageError;
02798   loadAndParse( m_content, "content.xml", store);
02799   kdDebug(30518) << "Opened" << endl;
02800 
02801   QDomDocument styles;
02802   kdDebug(30518) << "file content.xml loaded " << endl;
02803 
02804   loadAndParse( styles, "styles.xml", store);
02805 
02806   loadAndParse( m_meta, "meta.xml", store);
02807   loadAndParse( m_settings, "settings.xml", store);
02808 
02809   delete store;
02810 
02811   emit sigProgress( 10 );
02812 
02813   if ( !createStyleMap( styles ) )
02814     return KoFilter::UserCancelled;
02815 
02816   return KoFilter::OK;
02817 }
02818 
02819 KoFilter::ConversionStatus OpenCalcImport::loadAndParse( QDomDocument& doc, const QString& fileName,KoStore *m_store )
02820 {
02821     return OoUtils::loadAndParse( fileName, doc, m_store);
02822 }
02823 
02824 #include "opencalcimport.moc"
02825 
KDE Home | KDE Accessibility Home | Description of Access Keys