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   = -1.0;
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       if ( width != -1.0 )
01120         col->setWidth( int( width ) );
01121 
01122       // if ( insertPageBreak )
01123       //   col->setPageBreak( true )
01124 
01125       if ( collapsed )
01126         col->setHide( true );
01127 
01128       table->insertColumnFormat( col );
01129       ++column;
01130     }
01131   }
01132 
01133   return true;
01134 }
01135 
01136 void replaceMacro( QString & text, QString const & old, QString const & newS )
01137 {
01138   int n = text.find( old );
01139   if ( n != -1 )
01140     text = text.replace( n, old.length(), newS );
01141 }
01142 
01143 QString getPart( QDomNode const & part )
01144 {
01145   QString result;
01146   QDomElement e = KoDom::namedItemNS( part, ooNS::text, "p" );
01147   while ( !e.isNull() )
01148   {
01149     QString text = e.text();
01150     kdDebug(30518) << "PART: " << text << endl;
01151 
01152     QDomElement macro = KoDom::namedItemNS( e, ooNS::text, "time" );
01153     if ( !macro.isNull() )
01154       replaceMacro( text, macro.text(), "<time>" );
01155 
01156     macro = KoDom::namedItemNS( e, ooNS::text, "date" );
01157     if ( !macro.isNull() )
01158       replaceMacro( text, macro.text(), "<date>" );
01159 
01160     macro = KoDom::namedItemNS( e, ooNS::text, "page-number" );
01161     if ( !macro.isNull() )
01162       replaceMacro( text, macro.text(), "<page>" );
01163 
01164     macro = KoDom::namedItemNS( e, ooNS::text, "page-count" );
01165     if ( !macro.isNull() )
01166       replaceMacro( text, macro.text(), "<pages>" );
01167 
01168     macro = KoDom::namedItemNS( e, ooNS::text, "sheet-name" );
01169     if ( !macro.isNull() )
01170       replaceMacro( text, macro.text(), "<sheet>" );
01171 
01172     macro = KoDom::namedItemNS( e, ooNS::text, "title" );
01173     if ( !macro.isNull() )
01174       replaceMacro( text, macro.text(), "<name>" );
01175 
01176     macro = KoDom::namedItemNS( e, ooNS::text, "file-name" );
01177     if ( !macro.isNull() )
01178       replaceMacro( text, macro.text(), "<file>" );
01179 
01180     if ( !result.isEmpty() )
01181       result += '\n';
01182     result += text;
01183     e = e.nextSibling().toElement();
01184   }
01185 
01186   return result;
01187 }
01188 
01189 void OpenCalcImport::loadTableMasterStyle( Sheet * table,
01190                                            QString const & stylename )
01191 {
01192   kdDebug(30518) << "Loading table master style: " << stylename << endl;
01193 
01194   QDomElement * style = m_styles[ stylename ];
01195 
01196   if ( !style )
01197   {
01198     kdDebug(30518) << "Master style not found! " << endl;
01199     return;
01200   }
01201 
01202   QDomNode header = KoDom::namedItemNS( *style, ooNS::style, "header" );
01203   kdDebug(30518) << "Style header " << endl;
01204 
01205   QString hleft, hmiddle, hright;
01206   QString fleft, fmiddle, fright;
01207 
01208   if ( !header.isNull() )
01209   {
01210     kdDebug(30518) << "Header exists" << endl;
01211     QDomNode part = KoDom::namedItemNS( header, ooNS::style, "region-left" );
01212     if ( !part.isNull() )
01213     {
01214       hleft = getPart( part );
01215       kdDebug(30518) << "Header left: " << hleft << endl;
01216     }
01217     else
01218       kdDebug(30518) << "Style:region:left doesn't exist!" << endl;
01219     part = KoDom::namedItemNS( header, ooNS::style, "region-center" );
01220     if ( !part.isNull() )
01221     {
01222       hmiddle = getPart( part );
01223       kdDebug(30518) << "Header middle: " << hmiddle << endl;
01224     }
01225     part = KoDom::namedItemNS( header, ooNS::style, "region-right" );
01226     if ( !part.isNull() )
01227     {
01228       hright = getPart( part );
01229       kdDebug(30518) << "Header right: " << hright << endl;
01230     }
01231   }
01232 
01233   QDomNode footer = KoDom::namedItemNS( *style, ooNS::style, "footer" );
01234 
01235   if ( !footer.isNull() )
01236   {
01237     QDomNode part = KoDom::namedItemNS( footer, ooNS::style, "region-left" );
01238     if ( !part.isNull() )
01239     {
01240       fleft = getPart( part );
01241       kdDebug(30518) << "Footer left: " << fleft << endl;
01242     }
01243     part = KoDom::namedItemNS( footer, ooNS::style, "region-center" );
01244     if ( !part.isNull() )
01245     {
01246       fmiddle = getPart( part );
01247       kdDebug(30518) << "Footer middle: " << fmiddle << endl;
01248     }
01249     part = KoDom::namedItemNS( footer, ooNS::style, "region-right" );
01250     if ( !part.isNull() )
01251     {
01252       fright = getPart( part );
01253       kdDebug(30518) << "Footer right: " << fright << endl;
01254     }
01255   }
01256 
01257   table->print()->setHeadFootLine( hleft, hmiddle, hright,
01258                                    fleft, fmiddle, fright );
01259   if ( style->hasAttributeNS( ooNS::style, "page-master-name" ) )
01260   {
01261       QString masterPageLayoutStyleName=style->attributeNS( ooNS::style, "page-master-name", QString::null );
01262       kdDebug(30518)<<"masterPageLayoutStyleName :"<<masterPageLayoutStyleName<<endl;
01263       QDomElement *masterLayoutStyle = m_styles[masterPageLayoutStyleName];
01264       kdDebug(30518)<<"masterLayoutStyle :"<<masterLayoutStyle<<endl;
01265       if ( !masterLayoutStyle )
01266           return;
01267       KoStyleStack styleStack( ooNS::style, ooNS::fo );
01268       styleStack.push( *masterLayoutStyle );
01269       loadOasisMasterLayoutPage( table, styleStack );
01270   }
01271 }
01272 
01273 void OpenCalcImport::loadOasisMasterLayoutPage( Sheet * table,KoStyleStack &styleStack )
01274 {
01275     float left = 0.0;
01276     float right = 0.0;
01277     float top = 0.0;
01278     float bottom = 0.0;
01279     float width = 0.0;
01280     float height = 0.0;
01281     QString orientation = "Portrait";
01282     QString format;
01283 
01284     // Laurent : Why we stored layout information as Millimeter ?!!!!!
01285     // kspread used point for all other attribute
01286     // I don't understand :(
01287     if ( styleStack.hasAttributeNS( ooNS::fo, "page-width" ) )
01288     {
01289         width = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-width" ) ) );
01290     }
01291     if ( styleStack.hasAttributeNS( ooNS::fo, "page-height" ) )
01292     {
01293         height = KoUnit::toMM( KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-height" ) ) );
01294     }
01295     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-top" ) )
01296     {
01297         top = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-top" ) ) );
01298     }
01299     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-bottom" ) )
01300     {
01301         bottom = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-bottom" ) ) );
01302     }
01303     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-left" ) )
01304     {
01305         left = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-left" ) ) );
01306     }
01307     if ( styleStack.hasAttributeNS( ooNS::fo, "margin-right" ) )
01308     {
01309         right = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-right" ) ) );
01310     }
01311     if ( styleStack.hasAttributeNS( ooNS::style, "writing-mode" ) )
01312     {
01313         kdDebug(30518)<<"styleStack.hasAttribute( style:writing-mode ) :"<<styleStack.hasAttributeNS( ooNS::style, "writing-mode" )<<endl;
01314     }
01315     if ( styleStack.hasAttributeNS( ooNS::style, "print-orientation" ) )
01316     {
01317         orientation = ( styleStack.attributeNS( ooNS::style, "print-orientation" )=="landscape" ) ? "Landscape" : "Portrait" ;
01318     }
01319     if ( styleStack.hasAttributeNS( ooNS::style, "num-format" ) )
01320     {
01321         kdDebug(30518)<<" num-format :"<<styleStack.attributeNS( ooNS::style, "num-format" )<<endl;
01322         //todo fixme
01323     }
01324         if ( styleStack.hasAttributeNS( ooNS::fo, "background-color" ) )
01325     {
01326         //todo
01327         kdDebug(30518)<<" fo:background-color :"<<styleStack.attributeNS( ooNS::fo, "background-color" )<<endl;
01328     }
01329     if ( styleStack.hasAttributeNS( ooNS::style, "print" ) )
01330     {
01331         //todo parsing
01332         QString str = styleStack.attributeNS( ooNS::style, "print" );
01333         kdDebug(30518)<<" style:print :"<<str<<endl;
01334 
01335         if (str.contains( "headers" ) )
01336         {
01337             //todo implement it into kspread
01338         }
01339         if ( str.contains( "grid" ) )
01340         {
01341             table->print()->setPrintGrid( true );
01342         }
01343         if ( str.contains( "annotations" ) )
01344         {
01345             //todo it's not implemented
01346         }
01347         if ( str.contains( "objects" ) )
01348         {
01349             //todo it's not implemented
01350         }
01351         if ( str.contains( "charts" ) )
01352         {
01353             //todo it's not implemented
01354         }
01355         if ( str.contains( "drawings" ) )
01356         {
01357             //todo it's not implemented
01358         }
01359         if ( str.contains( "formulas" ) )
01360         {
01361             table->setShowFormula(true);
01362         }
01363         if ( str.contains( "zero-values" ) )
01364         {
01365             //todo it's not implemented
01366         }
01367     }
01368     if ( styleStack.hasAttributeNS( ooNS::style, "table-centering" ) )
01369     {
01370         QString str = styleStack.attributeNS( ooNS::style, "table-centering" );
01371         //not implemented into kspread
01372         kdDebug(30518)<<" styleStack.attribute( style:table-centering ) :"<<str<<endl;
01373 #if 0
01374         if ( str == "horizontal" )
01375         {
01376         }
01377         else if ( str == "vertical" )
01378         {
01379         }
01380         else if ( str == "both" )
01381         {
01382         }
01383         else if ( str == "none" )
01384         {
01385         }
01386         else
01387             kdDebug(30518)<<" table-centering unknown :"<<str<<endl;
01388 #endif
01389     }
01390     format = QString( "%1x%2" ).arg( width ).arg( height );
01391     kdDebug(30518)<<" format : "<<format<<endl;
01392     table->print()->setPaperLayout( left, top, right, bottom, format, orientation );
01393 
01394     kdDebug(30518)<<" left margin :"<<left<<" right :"<<right<<" top :"<<top<<" bottom :"<<bottom<<endl;
01395 //<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"/>
01396 //          QString format = paper.attribute( "format" );
01397 //      QString orientation = paper.attribute( "orientation" );
01398 //        m_pPrint->setPaperLayout( left, top, right, bottom, format, orientation );
01399 //      }
01400 }
01401 
01402 
01403 bool OpenCalcImport::parseBody( int numOfTables )
01404 {
01405   QDomElement content = m_content.documentElement();
01406   QDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" );
01407 
01408   if ( body.isNull() )
01409     return false;
01410 
01411   loadOasisAreaName( body.toElement() );
01412   loadOasisCellValidation( body.toElement() );
01413 
01414   Sheet * table;
01415   QDomNode sheet = KoDom::namedItemNS( body, ooNS::table, "table" );
01416 
01417   kdDebug()<<" sheet :"<<sheet.isNull()<<endl;
01418   if ( sheet.isNull() )
01419     return false;
01420 
01421   while ( !sheet.isNull() )
01422   {
01423     QDomElement t = sheet.toElement();
01424     if ( t.isNull() )
01425     {
01426       sheet = sheet.nextSibling();
01427       continue;
01428     }
01429     if ( t.nodeName() != "table:table" )
01430     {
01431       sheet = sheet.nextSibling();
01432       continue;
01433     }
01434 
01435     table = m_doc->map()->addNewSheet();
01436 
01437     table->setSheetName( t.attributeNS( ooNS::table, "name", QString::null ), true, false );
01438     kdDebug()<<" table->name()"<<table->name()<<endl;
01439     sheet = sheet.nextSibling();
01440   }
01441 
01442   sheet = body.firstChild();
01443 
01444   int step = (int) ( 80 / numOfTables );
01445   int progress = 15;
01446 
01447   Format::setGlobalColWidth( MM_TO_POINT( 22.7 ) );
01448   Format::setGlobalRowHeight( MM_TO_POINT( 4.3 ) );
01449   kdDebug(30518) << "Global Height: " << MM_TO_POINT( 4.3 ) << ", Global width: " << MM_TO_POINT( 22.7) << endl;
01450 
01451   while ( !sheet.isNull() )
01452   {
01453     QDomElement t = sheet.toElement();
01454     if ( t.isNull() )
01455     {
01456       KMessageBox::sorry( 0, i18n( "The file seems to be corrupt. Skipping a table." ) );
01457       sheet = sheet.nextSibling();
01458       continue;
01459     }
01460     if ( t.nodeName() != "table:table" )
01461     {
01462       sheet = sheet.nextSibling();
01463       continue;
01464     }
01465 
01466     table = m_doc->map()->findSheet( t.attributeNS( ooNS::table, "name", QString::null ) );
01467     if ( !table )
01468     {
01469       KMessageBox::sorry( 0, i18n( "Skipping a table." ) );
01470       sheet = sheet.nextSibling();
01471       continue;
01472     }
01473 
01474     Format * defaultStyle = m_defaultStyles[ "Default" ];
01475     if ( defaultStyle )
01476     {
01477       Cell* defaultCell = table->defaultCell();
01478       kdDebug(30518) << "Copy default style to default cell" << endl;
01479       defaultCell->format()->copy( *defaultStyle );
01480     }
01481     table->setDefaultHeight( MM_TO_POINT( 4.3 ) );
01482     table->setDefaultWidth( MM_TO_POINT( 22.7 ) );
01483 
01484     kdDebug(30518) << "Added table: " << t.attributeNS( ooNS::table, "name", QString::null ) << endl;
01485 
01486     if ( t.hasAttributeNS( ooNS::table, "style-name" ) )
01487     {
01488       QString style = t.attributeNS( ooNS::table, "style-name", QString::null );
01489       QDomElement * tableStyle = m_styles[ style ];
01490 
01491       QDomNode node;
01492 
01493       if ( tableStyle )
01494         node = tableStyle->firstChild();
01495 
01496       while( !node.isNull() )
01497       {
01498         QDomElement property = node.toElement();
01499         if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
01500         {
01501           if ( property.hasAttributeNS( ooNS::table, "display" ) )
01502           {
01503             bool visible = (property.attributeNS( ooNS::table, "display", QString::null ) == "true" ? true : false );
01504             table->hideSheet( !visible );
01505             kdDebug(30518) << "Table: " << table->tableName() << ", hidden: " << !visible << endl;
01506           }
01507         }
01508 
01509         node = node.nextSibling();
01510       }
01511 
01512       if ( tableStyle && tableStyle->hasAttributeNS( ooNS::style, "master-page-name" ) )
01513       {
01514         QString stylename = "pm" + tableStyle->attributeNS( ooNS::style, "master-page-name", QString::null );
01515 
01516         loadTableMasterStyle( table, stylename );
01517 
01518       }
01519     }
01520     if ( t.hasAttributeNS( ooNS::table, "print-ranges" ) )
01521     {
01522       // e.g.: Sheet4.A1:Sheet4.E28
01523       QString range = t.attributeNS( ooNS::table, "print-ranges", QString::null );
01524       OpenCalcPoint point( range );
01525 
01526       kdDebug(30518) << "Print range: " << point.translation << endl;
01527       KSpread::Range p( point.translation );
01528 
01529       kdDebug(30518) << "Print table: " << p.sheetName() << endl;
01530 
01531       if ( table->sheetName() == p.sheetName() )
01532         table->print()->setPrintRange( p.range() );
01533     }
01534 
01535     if ( !readColLayouts( t, table ) )
01536       return false;
01537 
01538     if ( !readRowsAndCells( t, table ) )
01539       return false;
01540 
01541     if ( t.hasAttributeNS( ooNS::table, "protected" ) )
01542     {
01543       QCString passwd( "" );
01544       if ( t.hasAttributeNS( ooNS::table, "protection-key" ) )
01545       {
01546         QString p = t.attributeNS( ooNS::table, "protection-key", QString::null );
01547         QCString str( p.latin1() );
01548         kdDebug(30518) << "Decoding password: " << str << endl;
01549         passwd = KCodecs::base64Decode( str );
01550       }
01551       kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
01552       table->setProtected( passwd );
01553     }
01554 
01555     progress += step;
01556     emit sigProgress( progress );
01557     sheet = sheet.nextSibling();
01558   }
01559 
01560   QDomElement b = body.toElement();
01561   if ( b.hasAttributeNS( ooNS::table, "structure-protected" ) )
01562   {
01563     QCString passwd( "" );
01564     if ( b.hasAttributeNS( ooNS::table, "protection-key" ) )
01565     {
01566       QString p = b.attributeNS( ooNS::table, "protection-key", QString::null );
01567       QCString str( p.latin1() );
01568       kdDebug(30518) << "Decoding password: " << str << endl;
01569       passwd = KCodecs::base64Decode( str );
01570     }
01571     kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
01572 
01573     m_doc->map()->setProtected( passwd );
01574   }
01575 
01576   emit sigProgress( 98 );
01577 
01578   return true;
01579 }
01580 
01581 void OpenCalcImport::insertStyles( QDomElement const & element )
01582 {
01583   if ( element.isNull() )
01584     return;
01585 
01586   QDomElement e;
01587   forEachElement( e, element )
01588   {
01589     if ( e.isNull() || !e.hasAttributeNS( ooNS::style, "name" ) )
01590     {
01591       continue;
01592     }
01593 
01594     QString name = e.attributeNS( ooNS::style, "name", QString::null );
01595     kdDebug(30518) << "Style: '" << name << "' loaded " << endl;
01596     m_styles.insert( name, new QDomElement( e ) );
01597   }
01598 }
01599 
01600 
01601 void OpenCalcImport::loadOasisAreaName( const QDomElement&body )
01602 {
01603   QDomNode namedAreas = KoDom::namedItemNS( body, ooNS::table, "named-expressions" );
01604   if ( !namedAreas.isNull() )
01605   {
01606     QDomElement e;
01607     forEachElement( e, namedAreas )
01608     {
01609       if ( e.isNull() || !e.hasAttributeNS( ooNS::table, "name" ) || !e.hasAttributeNS( ooNS::table, "cell-range-address" ) )
01610       {
01611         kdDebug(30518) << "Reading in named area failed" << endl;
01612         continue;
01613       }
01614 
01615       // TODO: what is: table:base-cell-address
01616       QString name  = e.attributeNS( ooNS::table, "name", QString::null );
01617       QString areaPoint = e.attributeNS( ooNS::table, "cell-range-address", QString::null );
01618 
01619       m_namedAreas.append( name );
01620       kdDebug(30518) << "Reading in named area, name: " << name << ", area: " << areaPoint << endl;
01621 
01622       OpenCalcPoint point( areaPoint );
01623       kdDebug(30518) << "Area: " << point.translation << endl;
01624 
01625       QString range( point.translation );
01626 
01627       if ( point.translation.find( ':' ) == -1 )
01628       {
01629         Point p( point.translation );
01630 
01631         int n = range.find( '!' );
01632         if ( n > 0 )
01633           range = range + ":" + range.right( range.length() - n - 1);
01634 
01635         kdDebug(30518) << "=> Area: " << range << endl;
01636       }
01637 
01638       KSpread::Range p( range );
01639 
01640       m_doc->addAreaName( p.range(), name, p.sheetName() );
01641       kdDebug(30518) << "Area range: " << p.sheetName() << endl;
01642     }
01643   }
01644 }
01645 
01646 void OpenCalcImport::loadOasisCellValidation( const QDomElement&body )
01647 {
01648     QDomNode validation = KoDom::namedItemNS( body, ooNS::table, "content-validations" );
01649     if ( !validation.isNull() )
01650     {
01651         QDomElement element;
01652         forEachElement( element, validation )
01653         {
01654             if ( element.localName() ==  "content-validation" ) {
01655                 m_validationList.insert( element.attributeNS( ooNS::table, "name", QString::null ), element);
01656                 kdDebug(30518)<<" validation found :"<<element.attributeNS( ooNS::table, "name", QString::null )<<endl;
01657             }
01658             else {
01659                 kdDebug(30518)<<" Tag not recognize :"<<element.tagName()<<endl;
01660             }
01661         }
01662     }
01663 }
01664 
01665 
01666 QString * OpenCalcImport::loadFormat( QDomElement * element,
01667                                       FormatType & formatType,
01668                                       QString name )
01669 {
01670   if ( !element )
01671     return 0;
01672 
01673   int  i;
01674   bool ok;
01675 
01676   QString * format = 0;
01677   QDomElement e = element->firstChild( ).toElement();
01678   int precision = 0;
01679   int leadingZ  = 1;
01680   bool thousandsSep = false;
01681   bool negRed = false;
01682 
01683   if ( element->localName() == "time-style" )
01684     formatType = Custom_format;
01685   else if ( element->localName() == "date-style" )
01686     formatType = Custom_format;
01687   else if ( element->localName() == "percentage-style" )
01688     formatType = Custom_format;
01689   else if ( element->localName() == "number-style" )
01690     formatType = Custom_format;
01691   else if ( element->localName() == "currency-style" )
01692     formatType = Custom_format;
01693   else if ( element->localName() == "boolean-style" )
01694     formatType = Custom_format;
01695 
01696   if ( !e.isNull() )
01697     format = new QString();
01698 
01699   // TODO (element):
01700   // number:automatic-order="true"
01701   // number:truncate-on-overflow="false"
01702   // style:volatile="true"
01703 
01704   while ( !e.isNull() )
01705   {
01706     if ( e.localName() == "properties" && e.namespaceURI() == ooNS::style )
01707     {
01708       if ( e.hasAttributeNS( ooNS::fo, "color" ) )
01709         negRed = true; // we only support red...
01710     }
01711     else if ( e.localName() == "text" && e.namespaceURI()==ooNS::number)
01712     {
01713       if ( negRed && ( e.text() == "-" ) )
01714         ;
01715       else
01716         format->append( e.text() );
01717     }
01718     else if ( e.localName() == "currency-symbol" && e.namespaceURI()==ooNS::number)
01719     {
01720       QString sym( e.text() );
01721       kdDebug(30518) << "Currency: " << sym << endl;
01722       format->append( sym );
01723       // number:language="de" number:country="DE">€</number:currency-symbol>
01724     }
01725     else if ( e.localName() == "day-of-week" && e.namespaceURI()==ooNS::number)
01726     {
01727       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01728       {
01729         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01730           format->append( "dddd" );
01731         else
01732           format->append( "ddd" );
01733       }
01734       else
01735         format->append( "ddd" );
01736     }
01737     else if ( e.localName() == "day" && e.namespaceURI()==ooNS::number)
01738     {
01739       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01740       {
01741         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01742           format->append( "dd" );
01743         else
01744           format->append( "d" );
01745       }
01746       else
01747         format->append( "d" );
01748     }
01749     else if ( e.localName() == "month" && e.namespaceURI()==ooNS::number)
01750     {
01751       if ( e.hasAttributeNS( ooNS::number, "textual" ) )
01752       {
01753         if ( e.attributeNS( ooNS::number, "textual", QString::null ) == "true" )
01754           format->append( "mm" );
01755       }
01756 
01757       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01758       {
01759         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01760           format->append( "mm" );
01761         else
01762           format->append( "m" );
01763       }
01764       else
01765         format->append( "m" );
01766     }
01767     else if ( e.localName() == "year" && e.namespaceURI()==ooNS::number)
01768     {
01769       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01770       {
01771         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01772           format->append( "yyyy" );
01773         else
01774           format->append( "yy" );
01775       }
01776       else
01777         format->append( "yy" );
01778     }
01779     else if ( e.localName() == "hours" && e.namespaceURI()==ooNS::number)
01780     {
01781       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01782       {
01783         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01784           format->append( "hh" );
01785         else
01786           format->append( "h" );
01787       }
01788       else
01789         format->append( "h" );
01790     }
01791     else if ( e.localName() == "minutes" && e.namespaceURI()==ooNS::number)
01792     {
01793       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01794       {
01795         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01796           format->append( "mm" );
01797         else
01798           format->append( "m" );
01799       }
01800       else
01801         format->append( "m" );
01802     }
01803     else if ( e.localName() == "seconds" && e.namespaceURI()==ooNS::number)
01804     {
01805       if ( e.hasAttributeNS( ooNS::number, "style" ) )
01806       {
01807         if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" )
01808           format->append( "ss" );
01809         else
01810           format->append( "s" );
01811       }
01812       else
01813         format->append( "s" );
01814     }
01815     else if ( e.localName() == "am-pm" && e.namespaceURI()==ooNS::number)
01816     {
01817       format->append( "AM/PM" );
01818     }
01819     else if ( e.localName() == "number" && e.namespaceURI()==ooNS::number)
01820     {
01821       // TODO: number:grouping="true"
01822 
01823       if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) )
01824       {
01825         int d = e.attributeNS( ooNS::number, "decimal-places", QString::null ).toInt( &ok );
01826         if ( ok )
01827           precision = d;
01828       }
01829 
01830       if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
01831       {
01832         int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok );
01833         if ( ok )
01834           leadingZ = d;
01835       }
01836 
01837       if ( thousandsSep && leadingZ <= 3 )
01838       {
01839         format->append( "#," );
01840         for ( i = leadingZ; i <= 3; ++i )
01841           format->append( '#' );
01842       }
01843 
01844       for ( i = 1; i <= leadingZ; ++i )
01845       {
01846         format->append( '0' );
01847         if ( ( i % 3 == 0 ) && thousandsSep )
01848           format->append( ',' );
01849       }
01850 
01851       format->append( '.' );
01852       for ( i = 0; i < precision; ++i )
01853         format->append( '0' );
01854     }
01855     else if ( e.localName() == "scientific-number" && e.namespaceURI()==ooNS::number)
01856     {
01857       int exp = 2;
01858 
01859       if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) )
01860       {
01861         int d = e.attributeNS( ooNS::number, "decimal-places", QString::null ).toInt( &ok );
01862         if ( ok )
01863           precision = d;
01864       }
01865 
01866       if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
01867       {
01868         int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok );
01869         if ( ok )
01870           leadingZ = d;
01871       }
01872 
01873       if ( e.hasAttributeNS( ooNS::number, "min-exponent-digits" ) )
01874       {
01875         int d = e.attributeNS( ooNS::number, "min-exponent-digits", QString::null ).toInt( &ok );
01876         if ( ok )
01877           exp = d;
01878         if ( exp <= 0 )
01879           exp = 1;
01880       }
01881 
01882       if ( thousandsSep && leadingZ <= 3 )
01883       {
01884         format->append( "#," );
01885         for ( i = leadingZ; i <= 3; ++i )
01886           format->append( '#' );
01887       }
01888 
01889       for ( i = 1; i <= leadingZ; ++i )
01890       {
01891         format->append( '0' );
01892         if ( ( i % 3 == 0 ) && thousandsSep )
01893           format->append( ',' );
01894       }
01895 
01896       format->append( '.' );
01897       for ( i = 0; i < precision; ++i )
01898         format->append( '0' );
01899 
01900       format->append( "E+" );
01901       for ( i = 0; i < exp; ++i )
01902         format->append( '0' );
01903 
01904       formatType = Custom_format;
01905     }
01906     else if ( e.localName() == "fraction" && e.namespaceURI()==ooNS::number)
01907     {
01908       int integer = 0;
01909       int numerator = 1;
01910       int denominator = 1;
01911 
01912       if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
01913       {
01914         int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok );
01915         if ( ok )
01916           integer = d;
01917       }
01918       if ( e.hasAttributeNS( ooNS::number, "min-numerator-digits" ) )
01919       {
01920         int d = e.attributeNS( ooNS::number, "min-numerator-digits", QString::null ).toInt( &ok );
01921         if ( ok )
01922           numerator = d;
01923       }
01924       if ( e.hasAttributeNS( ooNS::number, "min-denominator-digits" ) )
01925       {
01926         int d = e.attributeNS( ooNS::number, "min-denominator-digits", QString::null ).toInt( &ok );
01927         if ( ok )
01928           denominator = d;
01929       }
01930 
01931       for ( i = 0; i <= integer; ++i )
01932         format->append( '#' );
01933 
01934       format->append( ' ' );
01935 
01936       for ( i = 0; i <= numerator; ++i )
01937         format->append( '?' );
01938 
01939       format->append( '/' );
01940 
01941       for ( i = 0; i <= denominator; ++i )
01942         format->append( '?' );
01943     }
01944     // Not needed:
01945     //  <style:map style:condition="value()&gt;=0" style:apply-style-name="N106P0"/>
01946     // we handle painting negative numbers in red differently
01947 
01948     e = e.nextSibling().toElement();
01949   }
01950 
01951   if ( negRed )
01952   {
01953     QString f( *format );
01954     format->append( ";[Red]" );
01955     format->append( f );
01956   }
01957 
01958   kdDebug(30518) << "*** New FormatString: " << *format << endl << endl;
01959 
01960   m_formats.insert( name, format );
01961 
01962   return format;
01963 }
01964 
01965 void OpenCalcImport::loadFontStyle( Format * layout, QDomElement const * font ) const
01966 {
01967   if ( !font || !layout )
01968     return;
01969 
01970   kdDebug(30518) << "Copy font style from the layout " << font->tagName() << ", " << font->nodeName() << endl;
01971 
01972   if ( font->hasAttributeNS( ooNS::fo, "font-family" ) )
01973     layout->setTextFontFamily( font->attributeNS( ooNS::fo, "font-family", QString::null ) );
01974   if ( font->hasAttributeNS( ooNS::fo, "color" ) )
01975     layout->setTextColor( QColor( font->attributeNS( ooNS::fo, "color", QString::null ) ) );
01976   if ( font->hasAttributeNS( ooNS::fo, "font-size" ) )
01977       layout->setTextFontSize( int( KoUnit::parseValue( font->attributeNS( ooNS::fo, "font-size", QString::null ), 10 ) ) );
01978   else
01979     layout->setTextFontSize( 10 );
01980   if ( font->hasAttributeNS( ooNS::fo, "font-style" ) )
01981   {
01982     kdDebug(30518) << "italic" << endl;
01983     layout->setTextFontItalic( true ); // only thing we support
01984   }
01985   if ( font->hasAttributeNS( ooNS::fo, "font-weight" ) )
01986     layout->setTextFontBold( true ); // only thing we support
01987   if ( font->hasAttributeNS( ooNS::fo, "text-underline" ) || font->hasAttributeNS( ooNS::style, "text-underline" ) )
01988     layout->setTextFontUnderline( true ); // only thing we support
01989   if ( font->hasAttributeNS( ooNS::style, "text-crossing-out" ) )
01990     layout->setTextFontStrike( true ); // only thing we support
01991   if ( font->hasAttributeNS( ooNS::style, "font-pitch" ) )
01992   {
01993     // TODO: possible values: fixed, variable
01994   }
01995   // TODO:
01996   // text-underline-color
01997 }
01998 
01999 void OpenCalcImport::loadBorder( Format * layout, QString const & borderDef, bPos pos ) const
02000 {
02001   if ( borderDef == "none" )
02002     return;
02003 
02004   int p = borderDef.find( ' ' );
02005   if ( p < 0 )
02006     return;
02007 
02008   QPen pen;
02009   QString w = borderDef.left( p );
02010   pen.setWidth( (int) KoUnit::parseValue( w ) );
02011 
02012 
02013   ++p;
02014   int p2 = borderDef.find( ' ', p );
02015   QString s = borderDef.mid( p, p2 - p );
02016 
02017   kdDebug(30518) << "Borderstyle: " << s << endl;
02018 
02019   if ( s == "solid" || s == "double" )
02020     pen.setStyle( Qt::SolidLine );
02021   else
02022   {
02023 #if 0
02024     // TODO: not supported by oocalc
02025     pen.setStyle( Qt::DashLine );
02026     pen.setStyle( Qt::DotLine );
02027     pen.setStyle( Qt::DashDotLine );
02028     pen.setStyle( Qt::DashDotDotLine );
02029 #endif
02030     pen.setStyle( Qt::SolidLine ); //default.
02031   }
02032 
02033   ++p2;
02034   p = borderDef.find( ' ', p2 );
02035   if ( p == -1 )
02036     p = borderDef.length();
02037 
02038   pen.setColor( QColor( borderDef.right( p - p2 ) ) );
02039 
02040   if ( pos == Left )
02041     layout->setLeftBorderPen( pen );
02042   else if ( pos == Top )
02043     layout->setTopBorderPen( pen );
02044   else if ( pos == Right )
02045     layout->setRightBorderPen( pen );
02046   else if ( pos == Bottom )
02047     layout->setBottomBorderPen( pen );
02048   else if ( pos == Border )
02049   {
02050     layout->setLeftBorderPen( pen );
02051     layout->setTopBorderPen( pen );
02052     layout->setRightBorderPen( pen );
02053     layout->setBottomBorderPen( pen );
02054   }
02055   // TODO Diagonals not supported by oocalc
02056 }
02057 
02058 void OpenCalcImport::loadStyleProperties( Format * layout, QDomElement const & property ) const
02059 {
02060   kdDebug(30518) << "*** Loading style properties *****" << endl;
02061 
02062   if ( property.hasAttributeNS( ooNS::style, "decimal-places" ) )
02063   {
02064     bool ok = false;
02065     int p = property.attributeNS( ooNS::style, "decimal-places", QString::null ).toInt( &ok );
02066     if (ok )
02067       layout->setPrecision( p );
02068   }
02069 
02070   if ( property.hasAttributeNS( ooNS::style, "font-name" ) )
02071   {
02072     QDomElement * font = m_styles[ property.attributeNS( ooNS::style, "font-name", QString::null ) ];
02073     loadFontStyle( layout, font ); // generell font style
02074   }
02075 
02076   loadFontStyle( layout, &property ); // specific font style
02077 
02078   // TODO:
02079   //   diagonal: fall + goup
02080   //   fo:direction="ltr"
02081   //   style:text-align-source  ("fix")
02082   //   style:shadow
02083   //   style:text-outline
02084   //   indents from right, top, bottom
02085   //   style:condition="cell-content()=15"
02086   //     => style:apply-style-name="Result" style:base-cell-address="Sheet6.A5"/>
02087 
02088   if ( property.hasAttributeNS( ooNS::style, "rotation-angle" ) )
02089   {
02090     bool ok = false;
02091     int a = property.attributeNS( ooNS::style, "rotation-angle", QString::null ).toInt( &ok );
02092     if ( ok )
02093       layout->setAngle( -a + 1 );
02094   }
02095 
02096   if ( property.hasAttributeNS( ooNS::fo, "direction" ) )
02097   {
02098       layout->setVerticalText( true );
02099   }
02100   if ( property.hasAttributeNS( ooNS::fo, "text-align" ) )
02101   {
02102     QString s = property.attributeNS( ooNS::fo, "text-align", QString::null );
02103     if ( s == "center" )
02104       layout->setAlign( Format::Center );
02105     else if ( s == "end" )
02106       layout->setAlign( Format::Right );
02107     else if ( s == "start" )
02108       layout->setAlign( Format::Left );
02109     else if ( s == "justify" ) // TODO in KSpread!
02110       layout->setAlign( Format::Center );
02111   }
02112   if (  property.hasAttributeNS( ooNS::fo, "margin-left" ) )
02113   {
02114       kdDebug(30518)<<"margin-left :"<<KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", QString::null ),0.0 )<<endl;
02115       layout->setIndent( KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", QString::null ),0.0 ) );
02116   }
02117   if ( property.hasAttributeNS( ooNS::fo, "background-color" ) )
02118     layout->setBgColor( QColor( property.attributeNS( ooNS::fo, "background-color", QString::null ) ) );
02119 
02120   if ( property.hasAttributeNS( ooNS::style, "print-content" ) )
02121   {
02122     if ( property.attributeNS( ooNS::style, "print-content", QString::null ) == "false" )
02123       layout->setDontPrintText( false );
02124   }
02125   if ( property.hasAttributeNS( ooNS::style, "cell-protect" ) )
02126   {
02127     QString prot( property.attributeNS( ooNS::style, "cell-protect", QString::null ) );
02128     if ( prot == "none" )
02129     {
02130       layout->setNotProtected( true );
02131       layout->setHideFormula( false );
02132       layout->setHideAll( false );
02133     }
02134     else if ( prot == "formula-hidden" )
02135     {
02136       layout->setNotProtected( true );
02137       layout->setHideFormula( true );
02138       layout->setHideAll( false );
02139     }
02140     else if ( prot == "protected formula-hidden" )
02141     {
02142       layout->setNotProtected( false );
02143       layout->setHideFormula( true );
02144       layout->setHideAll( false );
02145     }
02146     else if ( prot == "hidden-and-protected" )
02147     {
02148       layout->setNotProtected( false );
02149       layout->setHideFormula( false );
02150       layout->setHideAll( true );
02151     }
02152     else if ( prot == "protected" )
02153     {
02154       layout->setNotProtected( false );
02155       layout->setHideFormula( false );
02156       layout->setHideAll( false );
02157     }
02158     kdDebug(30518) << "Cell " << prot << endl;
02159   }
02160 
02161   if ( property.hasAttributeNS( ooNS::fo, "padding-left" ) )
02162     layout->setIndent(  KoUnit::parseValue(property.attributeNS( ooNS::fo, "padding-left", QString::null ) ) );
02163 
02164   if ( property.hasAttributeNS( ooNS::fo, "vertical-align" ) )
02165   {
02166     QString s = property.attributeNS( ooNS::fo, "vertical-align", QString::null );
02167     if ( s == "middle" )
02168       layout->setAlignY( Format::Middle );
02169     else if ( s == "bottom" )
02170       layout->setAlignY( Format::Bottom );
02171     else
02172       layout->setAlignY( Format::Top );
02173   }
02174   else
02175       layout->setAlignY( Format::Bottom );
02176 
02177   if ( property.hasAttributeNS( ooNS::fo, "wrap-option" ) )
02178   {
02179     layout->setMultiRow( true );
02180 
02181     /* we do not support anything else yet
02182       QString s = property.attributeNS( ooNS::fo, "wrap-option", QString::null );
02183       if ( s == "wrap" )
02184       layout->setMultiRow( true );
02185     */
02186   }
02187 
02188   if ( property.hasAttributeNS( ooNS::fo, "border-bottom" ) )
02189   {
02190     loadBorder( layout, property.attributeNS( ooNS::fo, "border-bottom", QString::null ), Bottom );
02191     // TODO: style:border-line-width-bottom if double!
02192   }
02193 
02194   if ( property.hasAttributeNS( ooNS::fo, "border-right" ) )
02195   {
02196     loadBorder( layout, property.attributeNS( ooNS::fo, "border-right", QString::null ), Right );
02197     // TODO: style:border-line-width-right
02198   }
02199 
02200   if ( property.hasAttributeNS( ooNS::fo, "border-top" ) )
02201   {
02202     loadBorder( layout, property.attributeNS( ooNS::fo, "border-top", QString::null ), Top );
02203     // TODO: style:border-line-width-top
02204   }
02205 
02206   if ( property.hasAttributeNS( ooNS::fo, "border-left" ) )
02207   {
02208     loadBorder( layout, property.attributeNS( ooNS::fo, "border-left", QString::null ), Left );
02209     // TODO: style:border-line-width-left
02210   }
02211 
02212   if ( property.hasAttributeNS( ooNS::fo, "border" ) )
02213   {
02214     loadBorder( layout, property.attributeNS( ooNS::fo, "border", QString::null ), Border );
02215     // TODO: style:border-line-width-left
02216   }
02217 }
02218 
02219 void OpenCalcImport::readInStyle( Format * layout, QDomElement const & style )
02220 {
02221   kdDebug(30518) << "** Reading Style: " << style.tagName() << "; " << style.attributeNS( ooNS::style, "name", QString::null) << endl;
02222   if ( style.localName() == "style" && style.namespaceURI()==ooNS::style)
02223   {
02224     if ( style.hasAttributeNS( ooNS::style, "parent-style-name" ) )
02225     {
02226       Format * cp
02227         = m_defaultStyles.find( style.attributeNS( ooNS::style, "parent-style-name", QString::null ) );
02228       kdDebug(30518) << "Copying layout from " << style.attributeNS( ooNS::style, "parent-style-name", QString::null ) << endl;
02229 
02230       if ( cp != 0 )
02231         layout->copy( *cp );
02232     }
02233     else if ( style.hasAttributeNS( ooNS::style, "family") )
02234     {
02235       QString name = style.attribute( "style-family" ) + "default";
02236       Format * cp = m_defaultStyles.find( name );
02237 
02238       kdDebug(30518) << "Copying layout from " << name << ", " << !cp << endl;
02239 
02240       if ( cp != 0 )
02241         layout->copy( *cp );
02242     }
02243 
02244     if ( style.hasAttributeNS( ooNS::style, "data-style-name" ) )
02245     {
02246       QString * format = m_formats[ style.attributeNS( ooNS::style, "data-style-name", QString::null ) ];
02247       FormatType formatType;
02248 
02249       if ( !format )
02250       {
02251         // load and convert it
02252         QString name( style.attributeNS( ooNS::style, "data-style-name", QString::null ) );
02253         format = loadFormat( m_styles[ name ], formatType, name );
02254       }
02255 
02256       if ( format )
02257       {
02258         layout->setFormatString( *format );
02259         layout->setFormatType( formatType );
02260       }
02261 
02262       // <number:currency-symbol number:language="de" number:country="DE">€</number:currency-symbol>
02263     }
02264   }
02265 
02266   QDomElement property;
02267   forEachElement( property, style )
02268   {
02269     if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
02270       loadStyleProperties( layout, property );
02271 
02272     kdDebug(30518) << layout->textFontFamily( 0, 0 ) << endl;
02273   }
02274 }
02275 
02276 bool OpenCalcImport::createStyleMap( QDomDocument const & styles )
02277 {
02278   QDomElement content  = styles.documentElement();
02279   QDomNode docStyles   = KoDom::namedItemNS( content, ooNS::office, "document-styles" );
02280 
02281   if ( content.hasAttributeNS( ooNS::office, "version" ) )
02282   {
02283     bool ok = true;
02284     double d = content.attributeNS( ooNS::office, "version", QString::null ).toDouble( &ok );
02285 
02286     if ( ok )
02287     {
02288       kdDebug(30518) << "OpenCalc version: " << d << endl;
02289       if ( d > 1.0 )
02290       {
02291         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?") );
02292         message.arg( content.attributeNS( ooNS::office, "version", QString::null ) );
02293         if ( KMessageBox::warningYesNo( 0, message, i18n( "Unsupported document version" ) ) == KMessageBox::No )
02294           return false;
02295       }
02296     }
02297   }
02298 
02299   QDomNode fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" );
02300 
02301   if ( !fontStyles.isNull() )
02302   {
02303     kdDebug(30518) << "Starting reading in font-decl..." << endl;
02304 
02305     insertStyles( fontStyles.toElement() );
02306   }
02307   else
02308     kdDebug(30518) << "No items found" << endl;
02309 
02310   kdDebug(30518) << "Starting reading in auto:styles" << endl;
02311 
02312   QDomNode autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
02313   if ( !autoStyles.isNull() )
02314     insertStyles( autoStyles.toElement() );
02315   else
02316     kdDebug(30518) << "No items found" << endl;
02317 
02318 
02319   kdDebug(30518) << "Reading in master styles" << endl;
02320 
02321   QDomNode masterStyles = KoDom::namedItemNS( content, ooNS::office, "master-styles" );
02322 
02323   if ( masterStyles.isNull() )
02324   {
02325     kdDebug(30518) << "Nothing found " << endl;
02326   }
02327 
02328   QDomElement master = KoDom::namedItemNS( masterStyles, ooNS::style, "master-page");
02329   if ( !master.isNull() )
02330   {
02331     QString name( "pm" );
02332     name += master.attributeNS( ooNS::style, "name", QString::null );
02333     kdDebug(30518) << "Master style: '" << name << "' loaded " << endl;
02334     m_styles.insert( name, new QDomElement( master ) );
02335 
02336     master = master.nextSibling().toElement();
02337   }
02338 
02339 
02340   kdDebug(30518) << "Starting reading in office:styles" << endl;
02341 
02342   QDomNode fixedStyles = KoDom::namedItemNS( content, ooNS::office, "styles" );
02343 
02344   kdDebug(30518) << "Reading in default styles" << endl;
02345 
02346   QDomNode def = KoDom::namedItemNS( fixedStyles, ooNS::style, "default-style" );
02347   kdDebug()<<" def !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<def.isNull()<<endl;
02348   while ( !def.isNull() )
02349   {
02350     QDomElement e = def.toElement();
02351     kdDebug(30518) << "Style found " << e.nodeName() << ", tag: " << e.tagName() << endl;
02352 
02353     if ( e.nodeName() != "style:default-style" )
02354     {
02355       def = def.nextSibling();
02356       continue;
02357     }
02358 
02359     if ( !e.isNull() )
02360     {
02361       Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() );
02362 
02363       readInStyle( layout, e );
02364       kdDebug(30518) << "Default style " << e.attributeNS( ooNS::style, "family", QString::null ) << "default" << " loaded " << endl;
02365 
02366       m_defaultStyles.insert( e.attributeNS( ooNS::style, "family", QString::null ) + "default", layout );
02367       //      QFont font = layout->font();
02368       //      kdDebug(30518) << "Font: " << font.family() << ", " << font.toString() << endl;
02369     }
02370 
02371     def = def.nextSibling();
02372   }
02373 
02374   QDomElement defs = KoDom::namedItemNS( fixedStyles, ooNS::style, "style" );
02375   while ( !defs.isNull() )
02376   {
02377     if ( defs.nodeName() != "style:style" )
02378       break; // done
02379 
02380     if ( !defs.hasAttributeNS( ooNS::style, "name" ) )
02381     {
02382       // ups...
02383       defs = defs.nextSibling().toElement();
02384       continue;
02385     }
02386 
02387     Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() );
02388     readInStyle( layout, defs );
02389     kdDebug(30518) << "Default style " << defs.attributeNS( ooNS::style, "name", QString::null ) << " loaded " << endl;
02390 
02391     m_defaultStyles.insert( defs.attributeNS( ooNS::style, "name", QString::null ), layout );
02392     //    kdDebug(30518) << "Font: " << layout->font().family() << ", " << layout->font().toString() << endl;
02393 
02394     defs = defs.nextSibling().toElement();
02395   }
02396 
02397   if ( !fixedStyles.isNull() )
02398     insertStyles( fixedStyles.toElement() );
02399 
02400   kdDebug(30518) << "Starting reading in automatic styles" << endl;
02401 
02402   content = m_content.documentElement();
02403   autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
02404 
02405   if ( !autoStyles.isNull() )
02406     insertStyles( autoStyles.toElement() );
02407 
02408   fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" );
02409 
02410   if ( !fontStyles.isNull() )
02411   {
02412     kdDebug(30518) << "Starting reading in special font decl" << endl;
02413 
02414     insertStyles( fontStyles.toElement() );
02415   }
02416 
02417   kdDebug(30518) << "Styles read in." << endl;
02418 
02419   return true;
02420 }
02421 
02422 void OpenCalcImport::loadOasisValidation( Validity* val, const QString& validationName )
02423 {
02424     kdDebug(30518)<<"validationName:"<<validationName<<endl;
02425     QDomElement element = m_validationList[validationName];
02426     if ( element.hasAttributeNS( ooNS::table, "condition" ) )
02427     {
02428         QString valExpression = element.attributeNS( ooNS::table, "condition", QString::null );
02429         kdDebug(30518)<<" element.attribute( table:condition ) "<<valExpression<<endl;
02430         //Condition ::= ExtendedTrueCondition | TrueFunction 'and' TrueCondition
02431         //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
02432         //ExtendedTrueCondition ::= ExtendedGetFunction | cell-content-text-length() Operator Value
02433         //TrueCondition ::= GetFunction | cell-content() Operator Value
02434         //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
02435         //ExtendedGetFunction ::= cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value)
02436         //Operator ::= '<' | '>' | '<=' | '>=' | '=' | '!='
02437         //Value ::= NumberValue | String | Formula
02438         //A Formula is a formula without an equals (=) sign at the beginning. See section 8.1.3 for more information.
02439         //A String comprises one or more characters surrounded by quotation marks.
02440         //A NumberValue is a whole or decimal number. It must not contain comma separators for numbers of 1000 or greater.
02441 
02442         //ExtendedTrueCondition
02443         if ( valExpression.contains( "cell-content-text-length()" ) )
02444         {
02445             //"cell-content-text-length()>45"
02446             valExpression = valExpression.remove("cell-content-text-length()" );
02447             kdDebug(30518)<<" valExpression = :"<<valExpression<<endl;
02448             val->m_restriction = Restriction::TextLength;
02449 
02450             loadOasisValidationCondition( val, valExpression );
02451         }
02452         //cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value)
02453         else if ( valExpression.contains( "cell-content-text-length-is-between" ) )
02454         {
02455             val->m_restriction = Restriction::TextLength;
02456             val->m_cond = Conditional::Between;
02457             valExpression = valExpression.remove( "cell-content-text-length-is-between(" );
02458             kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
02459             valExpression = valExpression.remove( ")" );
02460             QStringList listVal = QStringList::split( ",", valExpression );
02461             loadOasisValidationValue( val, listVal );
02462         }
02463         else if ( valExpression.contains( "cell-content-text-length-is-not-between" ) )
02464         {
02465             val->m_restriction = Restriction::TextLength;
02466             val->m_cond = Conditional::Different;
02467             valExpression = valExpression.remove( "cell-content-text-length-is-not-between(" );
02468             kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
02469             valExpression = valExpression.remove( ")" );
02470             kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
02471             QStringList listVal = QStringList::split( ",", valExpression );
02472             loadOasisValidationValue( val, listVal );
02473 
02474         }
02475         //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
02476         else
02477         {
02478             if (valExpression.contains( "cell-content-is-whole-number()" ) )
02479             {
02480                 val->m_restriction =  Restriction::Number;
02481                 valExpression = valExpression.remove( "cell-content-is-whole-number() and " );
02482             }
02483             else if (valExpression.contains( "cell-content-is-decimal-number()" ) )
02484             {
02485                 val->m_restriction = Restriction::Integer;
02486                 valExpression = valExpression.remove( "cell-content-is-decimal-number() and " );
02487             }
02488             else if (valExpression.contains( "cell-content-is-date()" ) )
02489             {
02490                 val->m_restriction = Restriction::Date;
02491                 valExpression = valExpression.remove( "cell-content-is-date() and " );
02492             }
02493             else if (valExpression.contains( "cell-content-is-time()" ) )
02494             {
02495                 val->m_restriction = Restriction::Time;
02496                 valExpression = valExpression.remove( "cell-content-is-time() and " );
02497             }
02498             kdDebug(30518)<<"valExpression :"<<valExpression<<endl;
02499 
02500             if ( valExpression.contains( "cell-content()" ) )
02501             {
02502                 valExpression = valExpression.remove( "cell-content()" );
02503                 loadOasisValidationCondition( val, valExpression );
02504             }
02505             //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
02506             //for the moment we support just int/double value, not text/date/time :(
02507             if ( valExpression.contains( "cell-content-is-between(" ) )
02508             {
02509                 valExpression = valExpression.remove( "cell-content-is-between(" );
02510                 valExpression = valExpression.remove( ")" );
02511                 QStringList listVal = QStringList::split( "," , valExpression );
02512                 loadOasisValidationValue( val, listVal );
02513 
02514                 val->m_cond = Conditional::Between;
02515             }
02516             if ( valExpression.contains( "cell-content-is-not-between(" ) )
02517             {
02518                 valExpression = valExpression.remove( "cell-content-is-not-between(" );
02519                 valExpression = valExpression.remove( ")" );
02520                 QStringList listVal = QStringList::split( ",", valExpression );
02521                 loadOasisValidationValue( val, listVal );
02522                 val->m_cond = Conditional::Different;
02523             }
02524         }
02525     }
02526     if ( element.hasAttributeNS( ooNS::table, "allow-empty-cell" ) )
02527     {
02528         val->allowEmptyCell = ( ( element.attributeNS( ooNS::table, "allow-empty-cell", QString::null )=="true" ) ? true : false );
02529 
02530     }
02531     if ( element.hasAttributeNS( ooNS::table, "base-cell-address" ) )
02532     {
02533         //todo what is it ?
02534     }
02535 
02536     QDomElement help = KoDom::namedItemNS( element, ooNS::table, "help-message" );
02537     if ( !help.isNull() )
02538     {
02539         if ( help.hasAttributeNS( ooNS::table, "title" ) )
02540              val->titleInfo = help.attributeNS( ooNS::table, "title", QString::null );
02541         if ( help.hasAttributeNS( ooNS::table, "display" ) )
02542             val->displayValidationInformation = ( ( help.attributeNS( ooNS::table, "display", QString::null )=="true" ) ? true : false );
02543         QDomElement attrText = KoDom::namedItemNS( help, ooNS::text, "p" );
02544         if ( !attrText.isNull() )
02545             val->messageInfo = attrText.text();
02546     }
02547 
02548     QDomElement error = KoDom::namedItemNS( element, ooNS::table, "error-message" );
02549     if ( !error.isNull() )
02550     {
02551         if ( error.hasAttributeNS( ooNS::table, "title" ) )
02552             val->title = error.attributeNS( ooNS::table, "title", QString::null );
02553         if ( error.hasAttributeNS( ooNS::table, "message-type" ) )
02554         {
02555             QString str = error.attributeNS( ooNS::table, "message-type", QString::null );
02556             if ( str == "warning" )
02557               val->m_action = Action::Warning;
02558             else if ( str == "information" )
02559               val->m_action = Action::Information;
02560             else if ( str == "stop" )
02561               val->m_action = Action::Stop;
02562             else
02563                 kdDebug(30518)<<"validation : message type unknown  :"<<str<<endl;
02564         }
02565 
02566         if ( error.hasAttributeNS( ooNS::table, "display" ) )
02567         {
02568             kdDebug(30518)<<" display message :"<<error.attributeNS( ooNS::table, "display", QString::null )<<endl;
02569             val->displayMessage = (error.attributeNS( ooNS::table, "display", QString::null )=="true");
02570         }
02571         QDomElement attrText = KoDom::namedItemNS( error, ooNS::text, "p" );
02572         if ( !attrText.isNull() )
02573             val->message = attrText.text();
02574     }
02575 }
02576 
02577 void OpenCalcImport::loadOasisValidationValue( Validity* val, const QStringList &listVal )
02578 {
02579     bool ok = false;
02580     kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
02581 
02582     if ( val->m_restriction == Restriction::Date )
02583     {
02584         val->dateMin = QDate::fromString( listVal[0] );
02585         val->dateMax = QDate::fromString( listVal[1] );
02586     }
02587     else if ( val->m_restriction == Restriction::Time )
02588     {
02589         val->timeMin = QTime::fromString( listVal[0] );
02590         val->timeMax = QTime::fromString( listVal[1] );
02591     }
02592     else
02593     {
02594         val->valMin = listVal[0].toDouble(&ok);
02595         if ( !ok )
02596         {
02597             val->valMin = listVal[0].toInt(&ok);
02598             if ( !ok )
02599                 kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl;
02600 
02601 #if 0
02602             if ( !ok )
02603                 val->valMin = listVal[0];
02604 #endif
02605         }
02606         ok=false;
02607         val->valMax = listVal[1].toDouble(&ok);
02608         if ( !ok )
02609         {
02610             val->valMax = listVal[1].toInt(&ok);
02611             if ( !ok )
02612                 kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl;
02613 
02614 #if 0
02615             if ( !ok )
02616                 val->valMax = listVal[1];
02617 #endif
02618         }
02619     }
02620 }
02621 
02622 
02623 void OpenCalcImport::loadOasisValidationCondition( Validity* val,QString &valExpression )
02624 {
02625     QString value;
02626     if (valExpression.contains( "<=" ) )
02627     {
02628         value = valExpression.remove( "<=" );
02629         val->m_cond = Conditional::InferiorEqual;
02630     }
02631     else if (valExpression.contains( ">=" ) )
02632     {
02633         value = valExpression.remove( ">=" );
02634         val->m_cond = Conditional::SuperiorEqual;
02635     }
02636     else if (valExpression.contains( "!=" ) )
02637     {
02638         //add Differentto attribute
02639         value = valExpression.remove( "!=" );
02640         val->m_cond = Conditional::DifferentTo;
02641     }
02642     else if ( valExpression.contains( "<" ) )
02643     {
02644         value = valExpression.remove( "<" );
02645         val->m_cond = Conditional::Inferior;
02646     }
02647     else if(valExpression.contains( ">" ) )
02648     {
02649         value = valExpression.remove( ">" );
02650         val->m_cond = Conditional::Superior;
02651     }
02652     else if (valExpression.contains( "=" ) )
02653     {
02654         value = valExpression.remove( "=" );
02655         val->m_cond = Conditional::Equal;
02656     }
02657     else
02658         kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl;
02659     kdDebug(30518)<<" value :"<<value<<endl;
02660     if ( val->m_restriction == Restriction::Date )
02661     {
02662         val->dateMin = QDate::fromString( value );
02663     }
02664     else if ( val->m_restriction == Restriction::Date )
02665     {
02666         val->timeMin = QTime::fromString( value );
02667     }
02668     else
02669     {
02670         bool ok = false;
02671         val->valMin = value.toDouble(&ok);
02672         if ( !ok )
02673         {
02674             val->valMin = value.toInt(&ok);
02675             if ( !ok )
02676                 kdDebug(30518)<<" Try to parse this value :"<<value<<endl;
02677 
02678 #if 0
02679             if ( !ok )
02680                 val->valMin = value;
02681 #endif
02682         }
02683     }
02684 }
02685 
02686 
02687 int OpenCalcImport::readMetaData()
02688 {
02689   int result = 5;
02690   KoDocumentInfo * docInfo          = m_doc->documentInfo();
02691   KoDocumentInfoAbout  * aboutPage  = static_cast<KoDocumentInfoAbout *>(docInfo->page( "about" ));
02692   KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>(docInfo->page( "author" ));
02693 
02694   QDomNode meta   = KoDom::namedItemNS( m_meta, ooNS::office, "document-meta" );
02695   QDomNode office = KoDom::namedItemNS( meta, ooNS::office, "meta" );
02696 
02697   if ( office.isNull() )
02698     return 2;
02699 
02700   QDomElement e = KoDom::namedItemNS( office, ooNS::dc, "creator" );
02701   if ( !e.isNull() && !e.text().isEmpty() )
02702     authorPage->setFullName( e.text() );
02703 
02704   e = KoDom::namedItemNS( office, ooNS::dc, "title" );
02705   if ( !e.isNull() && !e.text().isEmpty() )
02706     aboutPage->setTitle( e.text() );
02707 
02708   e = KoDom::namedItemNS( office, ooNS::dc, "description" );
02709   if ( !e.isNull() && !e.text().isEmpty() )
02710     aboutPage->setAbstract( e.text() );
02711 
02712   e = KoDom::namedItemNS( office, ooNS::dc, "subject" );
02713   if ( !e.isNull() && !e.text().isEmpty() )
02714     aboutPage->setSubject( e.text() );
02715 
02716   e= KoDom::namedItemNS( office, ooNS::meta, "keywords" );
02717   if ( !e.isNull() )
02718   {
02719       e = KoDom::namedItemNS( e,  ooNS::meta, "keyword" );
02720       if ( !e.isNull() && !e.text().isEmpty() )
02721           aboutPage->setKeywords( e.text() );
02722   }
02723 
02724   e = KoDom::namedItemNS( office, ooNS::meta, "document-statistic" );
02725   if ( !e.isNull() && e.hasAttributeNS( ooNS::meta, "table-count" ) )
02726   {
02727     bool ok = false;
02728     result = e.attributeNS( ooNS::meta, "table-count", QString::null ).toInt( &ok );
02729     if ( !ok )
02730       result = 5;
02731   }
02732 
02733   m_meta.clear(); // not needed anymore
02734 
02735   return result;
02736 }
02737 
02738 KoFilter::ConversionStatus OpenCalcImport::convert( QCString const & from, QCString const & to )
02739 {
02740   kdDebug(30518) << "Entering OpenCalc Import filter: " << from << " - " << to << endl;
02741 
02742   KoDocument * document = m_chain->outputDocument();
02743   if ( !document )
02744     return KoFilter::StupidError;
02745 
02746   if (  !::qt_cast<const KSpread::Doc *>( document ) )  // it's safer that way :)
02747   {
02748     kdWarning(30518) << "document isn't a KSpread::Doc but a " << document->className() << endl;
02749     return KoFilter::NotImplemented;
02750   }
02751 
02752   if ( ( from != "application/vnd.sun.xml.calc" && from != "application/vnd.sun.xml.calc.template") || to != "application/x-kspread" )
02753   {
02754     kdWarning(30518) << "Invalid mimetypes " << from << " " << to << endl;
02755     return KoFilter::NotImplemented;
02756   }
02757 
02758   m_doc = ( Doc * ) document;
02759 
02760   if ( m_doc->mimeType() != "application/x-kspread" )
02761   {
02762     kdWarning(30518) << "Invalid document mimetype " << m_doc->mimeType() << endl;
02763     return KoFilter::NotImplemented;
02764   }
02765 
02766   kdDebug(30518) << "Opening file " << endl;
02767 
02768   KoFilter::ConversionStatus preStatus = openFile();
02769 
02770   if ( preStatus != KoFilter::OK )
02771     return preStatus;
02772 
02773   emit sigProgress( 13 );
02774   int tables = readMetaData();
02775 
02776   emit sigProgress( 15 );
02777 
02778   if ( !parseBody( tables ) )
02779     return KoFilter::StupidError;
02780 
02781   emit sigProgress( 100 );
02782   return KoFilter::OK;
02783 }
02784 
02785 KoFilter::ConversionStatus OpenCalcImport::openFile()
02786 {
02787   KoStore * store = KoStore::createStore( m_chain->inputFile(), KoStore::Read);
02788 
02789   kdDebug(30518) << "Store created" << endl;
02790 
02791   if ( !store )
02792   {
02793     kdWarning(30518) << "Couldn't open the requested file." << endl;
02794     return KoFilter::FileNotFound;
02795   }
02796 
02797   kdDebug(30518) << "Trying to open content.xml" << endl;
02798   QString messageError;
02799   loadAndParse( m_content, "content.xml", store);
02800   kdDebug(30518) << "Opened" << endl;
02801 
02802   QDomDocument styles;
02803   kdDebug(30518) << "file content.xml loaded " << endl;
02804 
02805   loadAndParse( styles, "styles.xml", store);
02806 
02807   loadAndParse( m_meta, "meta.xml", store);
02808   loadAndParse( m_settings, "settings.xml", store);
02809 
02810   delete store;
02811 
02812   emit sigProgress( 10 );
02813 
02814   if ( !createStyleMap( styles ) )
02815     return KoFilter::UserCancelled;
02816 
02817   return KoFilter::OK;
02818 }
02819 
02820 KoFilter::ConversionStatus OpenCalcImport::loadAndParse( QDomDocument& doc, const QString& fileName,KoStore *m_store )
02821 {
02822     return OoUtils::loadAndParse( fileName, doc, m_store);
02823 }
02824 
02825 #include "opencalcimport.moc"
02826 
KDE Home | KDE Accessibility Home | Description of Access Keys