lib

KoOasisStyles.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004-2006 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016  * Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "KoOasisStyles.h"
00020 #include <KoXmlWriter.h>
00021 #include <kdebug.h>
00022 #include <qdom.h>
00023 #include "KoDom.h"
00024 #include "KoXmlNS.h"
00025 #include "KoGenStyles.h"
00026 #include <qbuffer.h>
00027 #include <kglobal.h>
00028 #include <klocale.h>
00029 #include <qbrush.h>
00030 #include <KoStyleStack.h>
00031 
00032 class KoOasisStyles::Private
00033 {
00034 public:
00035     // The key of the map is the family
00036     QMap<QString, QDict<QDomElement> > m_styles;
00037     QMap<QString, QDict<QDomElement> > m_stylesAutoStyles;
00038 
00039     NumericFormatsMap numericFormats;
00040 };
00041 
00042 KoOasisStyles::KoOasisStyles()
00043     : d( new Private )
00044 {
00045     m_defaultStyle.setAutoDelete( true );
00046     m_masterPages.setAutoDelete( true );
00047     m_listStyles.setAutoDelete( true );
00048     m_drawStyles.setAutoDelete( true );
00049 }
00050 
00051 KoOasisStyles::~KoOasisStyles()
00052 {
00053     delete d;
00054 }
00055 
00056 void KoOasisStyles::createStyleMap( const QDomDocument& doc, bool stylesDotXml )
00057 {
00058    const QDomElement docElement  = doc.documentElement();
00059     // We used to have the office:version check here, but better let the apps do that
00060     QDomElement fontStyles = KoDom::namedItemNS( docElement, KoXmlNS::office, "font-decls" );
00061 
00062     if ( !fontStyles.isNull() ) {
00063         //kdDebug(30003) << "Starting reading in font-decl..." << endl;
00064         insertStyles( fontStyles, false );
00065     }// else
00066     //   kdDebug(30003) << "No items found" << endl;
00067 
00068     //kdDebug(30003) << "Starting reading in office:automatic-styles. stylesDotXml=" << stylesDotXml << endl;
00069 
00070     QDomElement autoStyles = KoDom::namedItemNS( docElement, KoXmlNS::office, "automatic-styles" );
00071     if ( !autoStyles.isNull() ) {
00072         insertStyles( autoStyles, stylesDotXml );
00073     }// else
00074     //    kdDebug(30003) << "No items found" << endl;
00075 
00076 
00077     //kdDebug(30003) << "Reading in master styles" << endl;
00078 
00079     QDomNode masterStyles = KoDom::namedItemNS( docElement, KoXmlNS::office, "master-styles" );
00080 
00081     if ( !masterStyles.isNull() ) {
00082         QDomElement master;
00083         forEachElement( master, masterStyles )
00084         {
00085             if ( master.localName() == "master-page" &&
00086                  master.namespaceURI() == KoXmlNS::style ) {
00087                 const QString name = master.attributeNS( KoXmlNS::style, "name", QString::null );
00088                 kdDebug(30003) << "Master style: '" << name << "' loaded " << endl;
00089                 m_masterPages.insert( name, new QDomElement( master ) );
00090             } else
00091                 // OASIS docu mentions style:handout-master and draw:layer-set here
00092                 kdWarning(30003) << "Unknown tag " << master.tagName() << " in office:master-styles" << endl;
00093         }
00094     }
00095 
00096 
00097     kdDebug(30003) << "Starting reading in office:styles" << endl;
00098 
00099     const QDomElement officeStyle = KoDom::namedItemNS( docElement, KoXmlNS::office, "styles" );
00100 
00101     if ( !officeStyle.isNull() ) {
00102         m_officeStyle = officeStyle;
00103         insertOfficeStyles( m_officeStyle );
00104 
00105     }
00106 
00107     //kdDebug(30003) << "Styles read in." << endl;
00108 }
00109 
00110 QValueVector<QDomElement> KoOasisStyles::userStyles() const
00111 {
00112     QValueVector<QDomElement> vec;
00113     // Collect user styles
00114     unsigned int i = 0;
00115     QDomElement e;
00116     forEachElement( e, m_officeStyle )
00117     {
00118         if ( e.localName() == "style" &&
00119              e.namespaceURI() == KoXmlNS::style )
00120         {
00121             vec.resize( i+1 );
00122             vec[i++] = e;
00123         }
00124     }
00125     return vec;
00126 }
00127 
00128 const QDict<QDomElement>& KoOasisStyles::styles(const QString& family) const
00129 {
00130     // hmm this can create an empty item in the map, but otherwise we couldn't
00131     // return a const reference.
00132     return d->m_styles[family];
00133 }
00134 
00135 void KoOasisStyles::insertOfficeStyles( const QDomElement& styles )
00136 {
00137     QDomElement e;
00138     forEachElement( e, styles )
00139     {
00140         const QString localName = e.localName();
00141         const QString ns = e.namespaceURI();
00142         if ( ( ns == KoXmlNS::svg && (
00143                    localName == "linearGradient"
00144                    || localName == "radialGradient" ) )
00145              || ( ns == KoXmlNS::draw && (
00146                       localName == "gradient"
00147                       || localName == "hatch"
00148                       || localName == "fill-image"
00149                       || localName == "marker"
00150                       || localName == "stroke-dash"
00151                       || localName == "opacity" ) )
00152              )
00153         {
00154             const QString name = e.attributeNS( KoXmlNS::draw, "name", QString::null );
00155             Q_ASSERT( !name.isEmpty() );
00156             QDomElement* ep = new QDomElement( e );
00157             m_drawStyles.insert( name, ep );
00158         }
00159         else
00160             insertStyle( e, false );
00161     }
00162 }
00163 
00164 
00165 void KoOasisStyles::insertStyles( const QDomElement& styles, bool styleAutoStyles )
00166 {
00167     //kdDebug(30003) << "Inserting styles from " << styles.tagName() << endl;
00168     QDomElement e;
00169     forEachElement( e, styles )
00170         insertStyle( e, styleAutoStyles );
00171 }
00172 
00173 void KoOasisStyles::insertStyle( const QDomElement& e, bool styleAutoStyles )
00174 {
00175     const QString localName = e.localName();
00176     const QString ns = e.namespaceURI();
00177 
00178     const QString name = e.attributeNS( KoXmlNS::style, "name", QString::null );
00179     if ( ns == KoXmlNS::style && localName == "style" ) {
00180         const QString family = e.attributeNS( KoXmlNS::style, "family", QString::null );
00181 
00182         if ( styleAutoStyles ) {
00183             QDict<QDomElement>& dict = d->m_stylesAutoStyles[ family ];
00184             dict.setAutoDelete( true );
00185             if ( dict.find( name ) != 0 )
00186                 kdDebug(30003) << "Auto-style: '" << name << "' already exists" << endl;
00187             dict.insert( name, new QDomElement( e ) );
00188             //kdDebug(30003) << "Style: '" << name << "' loaded as a style auto style" << endl;
00189         } else {
00190             QDict<QDomElement>& dict = d->m_styles[ family ];
00191             dict.setAutoDelete( true );
00192 
00193             if ( dict.find( name ) != 0 )
00194                 kdDebug(30003) << "Style: '" << name << "' already exists" << endl;
00195             dict.insert( name, new QDomElement( e ) );
00196             //kdDebug(30003) << "Style: '" << name << "' loaded " << endl;
00197         }
00198     } else if ( ns == KoXmlNS::style && (
00199                 localName == "page-layout"
00200              || localName == "font-decl"
00201              || localName == "presentation-page-layout" ) )
00202     {
00203         if ( m_styles.find( name ) != 0 )
00204             kdDebug(30003) << "Style: '" << name << "' already exists" << endl;
00205         m_styles.insert( name, new QDomElement( e ) );
00206     } else if ( localName == "default-style" && ns == KoXmlNS::style ) {
00207         const QString family = e.attributeNS( KoXmlNS::style, "family", QString::null );
00208         if ( !family.isEmpty() )
00209             m_defaultStyle.insert( family, new QDomElement( e ) );
00210     } else if ( localName == "list-style" && ns == KoXmlNS::text ) {
00211         m_listStyles.insert( name, new QDomElement( e ) );
00212         //kdDebug(30003) << "List style: '" << name << "' loaded " << endl;
00213     } else if ( ns == KoXmlNS::number && (
00214                    localName == "number-style"
00215                 || localName == "currency-style"
00216                 || localName == "percentage-style"
00217                 || localName == "boolean-style"
00218                 || localName == "text-style"
00219                 || localName == "date-style"
00220                 || localName == "time-style" ) ) {
00221         importDataStyle( e );
00222     }
00223     // The rest (text:*-configuration and text:outline-style) is to be done by the apps.
00224 }
00225 
00226 // OO spec 2.5.4. p68. Conversion to Qt format: see qdate.html
00227 // OpenCalcImport::loadFormat has similar code, but slower, intermixed with other stuff,
00228 // lacking long-textual forms.
00229 void KoOasisStyles::importDataStyle( const QDomElement& parent )
00230 {
00231     KoOasisNumericFormat dataStyle;
00232 
00233     const QString localName = parent.localName();
00234     if (localName == "number-style")
00235       dataStyle.type = KoOasisNumericFormat::Number;
00236     else if (localName == "currency-style")
00237       dataStyle.type = KoOasisNumericFormat::Currency;
00238     else if (localName == "percentage-style")
00239       dataStyle.type = KoOasisNumericFormat::Percentage;
00240     else if (localName == "boolean-style")
00241       dataStyle.type = KoOasisNumericFormat::Boolean;
00242     else if (localName == "text-style")
00243       dataStyle.type = KoOasisNumericFormat::Text;
00244     else if (localName == "date-style")
00245       dataStyle.type = KoOasisNumericFormat::Date;
00246     else if (localName == "time-style")
00247       dataStyle.type = KoOasisNumericFormat::Time;
00248 
00249     QString format;
00250     int precision = -1;
00251     int leadingZ  = 1;
00252     bool thousandsSep = false;
00253     //todo negred
00254     //bool negRed = false;
00255     bool ok = false;
00256     int i = 0;
00257     QDomElement e;
00258     QString prefix;
00259     QString suffix;
00260     forEachElement( e, parent )
00261     {
00262         if ( e.namespaceURI() != KoXmlNS::number )
00263             continue;
00264         QString localName = e.localName();
00265         const QString numberStyle = e.attributeNS( KoXmlNS::number, "style", QString::null );
00266         const bool shortForm = numberStyle == "short" || numberStyle.isEmpty();
00267         if ( localName == "day" ) {
00268             format += shortForm ? "d" : "dd";
00269         } else if ( localName == "day-of-week" ) {
00270             format += shortForm ? "ddd" : "dddd";
00271         } else if ( localName == "month" ) {
00272             if ( e.attributeNS( KoXmlNS::number, "possessive-form", QString::null ) == "true" ) {
00273                 format += shortForm ? "PPP" : "PPPP";
00274             }
00275             // TODO the spec has a strange mention of number:format-source
00276             else if ( e.attributeNS( KoXmlNS::number, "textual", QString::null ) == "true" ) {
00277                 format += shortForm ? "MMM" : "MMMM";
00278             } else { // month number
00279                 format += shortForm ? "M" : "MM";
00280             }
00281         } else if ( localName == "year" ) {
00282             format += shortForm ? "yy" : "yyyy";
00283         } else if ( localName == "era" ) {
00284             //TODO I don't know what is it... (define into oo spec)
00285         } else if ( localName == "week-of-year" || localName == "quarter") {
00286             // ### not supported in Qt
00287         } else if ( localName == "hours" ) {
00288             format += shortForm ? "h" : "hh";
00289         } else if ( localName == "minutes" ) {
00290             format += shortForm ? "m" : "mm";
00291         } else if ( localName == "seconds" ) {
00292             format += shortForm ? "s" : "ss";
00293         } else if ( localName == "am-pm" ) {
00294             format += "ap";
00295         } else if ( localName == "text" ) { // litteral
00296             format += e.text();
00297         } else if ( localName == "suffix" ) {
00298             suffix = e.text();
00299             kdDebug()<<" suffix :"<<suffix<<endl;
00300         } else if ( localName == "prefix" ) {
00301             prefix = e.text();
00302             kdDebug()<<" prefix :"<<prefix<<endl;
00303         } else if ( localName == "currency-symbol" ) {
00304             dataStyle.currencySymbol = e.text();
00305             kdDebug()<<" currency-symbol: "<<dataStyle.currencySymbol<<endl;
00306             format += e.text();
00307             //TODO
00308             // number:language="de" number:country="DE">€</number:currency-symbol>
00309             // Stefan: localization of the symbol?
00310         } else if ( localName == "number" ) {
00311             // TODO: number:grouping="true"
00312             if ( e.hasAttributeNS( KoXmlNS::number, "decimal-places" ) )
00313             {
00314                 int d = e.attributeNS( KoXmlNS::number, "decimal-places", QString::null ).toInt( &ok );
00315                 if ( ok )
00316                     precision = d;
00317             }
00318             if ( e.hasAttributeNS( KoXmlNS::number, "min-integer-digits" ) )
00319             {
00320                 int d = e.attributeNS( KoXmlNS::number, "min-integer-digits", QString::null ).toInt( &ok );
00321                 if ( ok )
00322                     leadingZ = d;
00323             }
00324             if ( thousandsSep && leadingZ <= 3 )
00325             {
00326                 format += "#,";
00327                 for ( i = leadingZ; i <= 3; ++i )
00328                     format += '#';
00329             }
00330             for ( i = 1; i <= leadingZ; ++i )
00331             {
00332                 format +=  '0';
00333                 if ( ( i % 3 == 0 ) && thousandsSep )
00334                     format =+ ',' ;
00335             }
00336             if (precision > -1)
00337             {
00338                 format += '.';
00339                 for ( i = 0; i < precision; ++i )
00340                     format += '0';
00341             }
00342         }
00343         else if ( localName == "scientific-number" ) {
00344             if (dataStyle.type == KoOasisNumericFormat::Number)
00345                 dataStyle.type = KoOasisNumericFormat::Scientific;
00346             int exp = 2;
00347 
00348             if ( e.hasAttributeNS( KoXmlNS::number, "decimal-places" ) )
00349             {
00350                 int d = e.attributeNS( KoXmlNS::number, "decimal-places", QString::null ).toInt( &ok );
00351                 if ( ok )
00352                     precision = d;
00353             }
00354 
00355             if ( e.hasAttributeNS( KoXmlNS::number, "min-integer-digits" ) )
00356             {
00357                 int d = e.attributeNS( KoXmlNS::number, "min-integer-digits", QString::null ).toInt( &ok );
00358                 if ( ok )
00359                     leadingZ = d;
00360             }
00361 
00362             if ( e.hasAttributeNS( KoXmlNS::number, "min-exponent-digits" ) )
00363             {
00364                 int d = e.attributeNS( KoXmlNS::number, "min-exponent-digits", QString::null ).toInt( &ok );
00365                 if ( ok )
00366                     exp = d;
00367                 if ( exp <= 0 )
00368                     exp = 1;
00369             }
00370 
00371             if ( thousandsSep && leadingZ <= 3 )
00372             {
00373                 format += "#,";
00374                 for ( i = leadingZ; i <= 3; ++i )
00375                     format += '#';
00376             }
00377 
00378             for ( i = 1; i <= leadingZ; ++i )
00379             {
00380                 format+='0';
00381                 if ( ( i % 3 == 0 ) && thousandsSep )
00382                     format+=',';
00383             }
00384 
00385             if (precision > -1)
00386             {
00387                 format += '.';
00388                 for ( i = 0; i < precision; ++i )
00389                     format += '0';
00390             }
00391 
00392             format+="E+";
00393             for ( i = 0; i < exp; ++i )
00394                 format+='0';
00395         } else if ( localName == "fraction" ) {
00396                 if (dataStyle.type == KoOasisNumericFormat::Number)
00397                     dataStyle.type = KoOasisNumericFormat::Fraction;
00398                 int integer = 0;
00399                 int numerator = 1;
00400                 int denominator = 1;
00401                 int denominatorValue=0;
00402                 if ( e.hasAttributeNS( KoXmlNS::number, "min-integer-digits" ) )
00403                 {
00404                     int d = e.attributeNS( KoXmlNS::number, "min-integer-digits", QString::null ).toInt( &ok );
00405                     if ( ok )
00406                         integer = d;
00407                 }
00408                 if ( e.hasAttributeNS( KoXmlNS::number, "min-numerator-digits" ) )
00409                 {
00410                     int d = e.attributeNS( KoXmlNS::number, "min-numerator-digits", QString::null ).toInt( &ok );
00411                     if ( ok )
00412                         numerator = d;
00413                 }
00414                 if ( e.hasAttributeNS( KoXmlNS::number, "min-denominator-digits" ) )
00415                 {
00416                     int d = e.attributeNS( KoXmlNS::number, "min-denominator-digits", QString::null ).toInt( &ok );
00417                     if ( ok )
00418                         denominator = d;
00419                 }
00420                 if ( e.hasAttributeNS( KoXmlNS::number, "denominator-value" ) )
00421                 {
00422                     int d = e.attributeNS( KoXmlNS::number, "denominator-value", QString::null ).toInt( &ok );
00423                     if ( ok )
00424                         denominatorValue = d;
00425                 }
00426 
00427                 for ( i = 0; i < integer; ++i )
00428                     format+='#';
00429 
00430                 format+=' ';
00431 
00432                 for ( i = 0; i < numerator; ++i )
00433                     format+='?';
00434 
00435                 format+='/';
00436 
00437                 if ( denominatorValue != 0 )
00438                     format+=QString::number( denominatorValue );
00439                 else
00440                 {
00441                     for ( i = 0; i < denominator; ++i )
00442                         format+='?';
00443                 }
00444             }
00445         // Not needed:
00446         //  <style:map style:condition="value()&gt;=0" style:apply-style-name="N106P0"/>
00447         // we handle painting negative numbers in red differently
00448 
00449     }
00450 
00451     const QString styleName = parent.attributeNS( KoXmlNS::style, "name", QString::null );
00452     kdDebug(30003) << "data style: " << styleName << " qt format=" << format << endl;
00453     if ( !prefix.isEmpty() )
00454     {
00455         kdDebug(30003)<<" format.left( prefix.length() ) :"<<format.left( prefix.length() )<<" prefix :"<<prefix<<endl;
00456         if ( format.left( prefix.length() )==prefix )
00457         {
00458             format = format.right( format.length()-prefix.length() );
00459         }
00460         else
00461             prefix = QString::null;
00462     }
00463     if ( !suffix.isEmpty() )
00464     {
00465         kdDebug(30003)<<"format.right( suffix.length() ) :"<<format.right( suffix.length() )<<" suffix :"<<suffix<<endl;
00466         if ( format.right( suffix.length() )==suffix )
00467         {
00468             format = format.left( format.length()-suffix.length() );
00469         }
00470         else
00471             suffix = QString::null;
00472     }
00473     NumericStyleFormat numeric;
00474     numeric.formatStr=format;
00475     numeric.prefix=prefix;
00476     numeric.suffix=suffix;
00477     kdDebug()<<" finish insert format :"<<format<<" prefix :"<<prefix<<" suffix :"<<suffix<<endl;
00478     m_dataFormats.insert( styleName, numeric );
00479     dataStyle.precision = precision;
00480     d->numericFormats.insert( styleName, dataStyle );
00481 }
00482 
00483 const KoOasisStyles::NumericFormatsMap& KoOasisStyles::numericFormats() const
00484 {
00485     return d->numericFormats;
00486 }
00487 
00488 #define addTextNumber( text, elementWriter ) { \
00489         if ( !text.isEmpty() ) \
00490         { \
00491             elementWriter.startElement( "number:text" ); \
00492             elementWriter.addTextNode( text ); \
00493             elementWriter.endElement(); \
00494             text=""; \
00495         } \
00496 }
00497 
00498 void KoOasisStyles::parseOasisTimeKlocale(KoXmlWriter &elementWriter, QString & format, QString & text )
00499 {
00500     kdDebug(30003)<<"parseOasisTimeKlocale(KoXmlWriter &elementWriter, QString & format, QString & text ) :"<<format<<endl;
00501     do
00502     {
00503         if ( !saveOasisKlocaleTimeFormat( elementWriter, format, text ) )
00504         {
00505             text += format[0];
00506             format = format.remove( 0, 1 );
00507         }
00508     }
00509     while ( format.length() > 0 );
00510     addTextNumber( text, elementWriter );
00511 }
00512 
00513 bool KoOasisStyles::saveOasisKlocaleTimeFormat( KoXmlWriter &elementWriter, QString & format, QString & text )
00514 {
00515     bool changed = false;
00516     if ( format.startsWith( "%H" ) ) //hh
00517     {
00518         //hour in 24h
00519         addTextNumber( text, elementWriter );
00520 
00521         elementWriter.startElement( "number:hours" );
00522         elementWriter.addAttribute( "number:style", "long" );
00523         elementWriter.endElement();
00524         format = format.remove( 0, 2 );
00525         changed = true;
00526     }
00527     else if ( format.startsWith( "%k" ) )//h
00528     {
00529         addTextNumber( text, elementWriter );
00530 
00531         elementWriter.startElement( "number:hours" );
00532         elementWriter.addAttribute( "number:style", "short" );
00533         elementWriter.endElement();
00534         format = format.remove( 0, 2 );
00535         changed = true;
00536     }
00537     else if ( format.startsWith( "%I" ) )// ?????
00538     {
00539         //TODO hour in 12h
00540         changed = true;
00541     }
00542     else if ( format.startsWith( "%l" ) )
00543     {
00544         //TODO hour in 12h with 1 digit
00545         changed = true;
00546     }
00547     else if ( format.startsWith( "%M" ) )// mm
00548     {
00549         addTextNumber( text, elementWriter );
00550 
00551         elementWriter.startElement( "number:minutes" );
00552         elementWriter.addAttribute( "number:style", "long" );
00553         elementWriter.endElement();
00554         format = format.remove( 0, 2 );
00555         changed = true;
00556 
00557     }
00558     else if ( format.startsWith( "%S" ) ) //ss
00559     {
00560         addTextNumber( text, elementWriter );
00561 
00562         elementWriter.startElement( "number:seconds" );
00563         elementWriter.addAttribute( "number:style", "long" );
00564         elementWriter.endElement();
00565         format = format.remove( 0, 2 );
00566         changed = true;
00567     }
00568     else if ( format.startsWith( "%p" ) )
00569     {
00570         //TODO am or pm
00571         addTextNumber( text, elementWriter );
00572 
00573         elementWriter.startElement( "number:am-pm" );
00574         elementWriter.endElement();
00575         format = format.remove( 0, 2 );
00576         changed = true;
00577     }
00578     return changed;
00579 }
00580 
00581 
00582 bool KoOasisStyles::saveOasisTimeFormat( KoXmlWriter &elementWriter, QString & format, QString & text, bool &antislash )
00583 {
00584     bool changed = false;
00585     //we can also add time to date.
00586     if ( antislash )
00587     {
00588         text+=format[0];
00589         format = format.remove( 0, 1 );
00590         antislash = false;
00591         changed = true;
00592     }
00593     else if ( format.startsWith( "hh" ) )
00594     {
00595         addTextNumber( text, elementWriter );
00596 
00597         elementWriter.startElement( "number:hours" );
00598         elementWriter.addAttribute( "number:style", "long" );
00599         elementWriter.endElement();
00600         format = format.remove( 0, 2 );
00601         changed = true;
00602     }
00603     else if ( format.startsWith( "h" ) )
00604     {
00605         addTextNumber( text, elementWriter );
00606 
00607         elementWriter.startElement( "number:hours" );
00608         elementWriter.addAttribute( "number:style", "short" );
00609         elementWriter.endElement();
00610         format = format.remove( 0, 1 );
00611         changed = true;
00612     }
00613     else if ( format.startsWith( "mm" ) )
00614     {
00615         addTextNumber( text, elementWriter );
00616 
00617         elementWriter.startElement( "number:minutes" );
00618         elementWriter.addAttribute( "number:style", "long" );
00619         elementWriter.endElement();
00620         format = format.remove( 0, 2 );
00621         changed = true;
00622     }
00623     else if ( format.startsWith( "m" ) )
00624     {
00625         addTextNumber( text, elementWriter );
00626 
00627         elementWriter.startElement( "number:minutes" );
00628         elementWriter.addAttribute( "number:style", "short" );
00629         elementWriter.endElement();
00630         format = format.remove( 0, 1 );
00631         changed = true;
00632     }
00633     else if ( format.startsWith( "ss" ) )
00634     {
00635         addTextNumber( text, elementWriter );
00636 
00637         elementWriter.startElement( "number:seconds" );
00638         elementWriter.addAttribute( "number:style", "long" );
00639         elementWriter.endElement();
00640         format = format.remove( 0, 2 );
00641         changed = true;
00642     }
00643     else if ( format.startsWith( "s" ) )
00644     {
00645         addTextNumber( text, elementWriter );
00646 
00647         elementWriter.startElement( "number:seconds" );
00648         elementWriter.addAttribute( "number:style", "short" );
00649         elementWriter.endElement();
00650         format = format.remove( 0, 1 );
00651         changed = true;
00652     }
00653     else if ( format.startsWith( "ap" ) )
00654     {
00655         addTextNumber( text, elementWriter );
00656 
00657         elementWriter.startElement( "number:am-pm" );
00658         elementWriter.endElement();
00659         format = format.remove( 0, 2 );
00660         changed = true;
00661     }
00662     return changed;
00663 }
00664 
00665 QString KoOasisStyles::saveOasisTimeStyle( KoGenStyles &mainStyles, const QString & _format, bool klocaleFormat )
00666 {
00667     kdDebug(30003)<<"QString KoOasisStyles::saveOasisTimeStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
00668     QString format( _format );
00669     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_TIME );
00670     QBuffer buffer;
00671     buffer.open( IO_WriteOnly );
00672     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
00673     QString text;
00674     if ( klocaleFormat )
00675     {
00676         parseOasisTimeKlocale( elementWriter, format, text );
00677     }
00678     else
00679     {
00680         bool antislash = false;
00681         do
00682         {
00683             if ( !saveOasisTimeFormat( elementWriter, format, text, antislash ) )
00684             {
00685                 QString elem( format[0] );
00686                 format = format.remove( 0, 1 );
00687                 if ( elem == "\\" )
00688                 {
00689                      antislash = true;
00690                 }
00691                 else
00692                 {
00693                     text += elem;
00694                     antislash = false;
00695                 }
00696             }
00697         }
00698         while ( format.length() > 0 );
00699         addTextNumber( text, elementWriter );
00700     }
00701     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
00702     currentStyle.addChildElement( "number", elementContents );
00703     return mainStyles.lookup( currentStyle, "N" );
00704 }
00705 
00706 //convert klocale string to good format
00707 void KoOasisStyles::parseOasisDateKlocale(KoXmlWriter &elementWriter, QString & format, QString & text )
00708 {
00709     kdDebug(30003)<<"KoOasisStyles::parseOasisDateKlocale(KoXmlWriter &elementWriter, QString & format, QString & text ) :"<<format<<endl;
00710     do
00711     {
00712         if ( format.startsWith( "%Y" ) )
00713         {
00714             addTextNumber( text, elementWriter );
00715             elementWriter.startElement( "number:year" );
00716             elementWriter.addAttribute( "number:style", "long" );
00717             elementWriter.endElement();
00718             format = format.remove( 0, 2 );
00719         }
00720         else if ( format.startsWith( "%y" ) )
00721         {
00722 
00723             addTextNumber( text, elementWriter );
00724 
00725             elementWriter.startElement( "number:year" );
00726             elementWriter.addAttribute( "number:style", "short" );
00727             elementWriter.endElement();
00728             format = format.remove( 0, 2 );
00729         }
00730         else if ( format.startsWith( "%n" ) )
00731         {
00732             addTextNumber( text, elementWriter );
00733             elementWriter.startElement( "number:month" );
00734             elementWriter.addAttribute( "number:style", "short" );
00735             elementWriter.addAttribute( "number:textual", "false");
00736             elementWriter.endElement();
00737             format = format.remove( 0, 2 );
00738         }
00739         else if ( format.startsWith( "%m" ) )
00740         {
00741             addTextNumber( text, elementWriter );
00742             elementWriter.startElement( "number:month" );
00743             elementWriter.addAttribute( "number:style", "long" );
00744             elementWriter.addAttribute( "number:textual", "false"); //not necessary remove it
00745             elementWriter.endElement();
00746             format = format.remove( 0, 2 );
00747         }
00748         else if ( format.startsWith( "%e" ) )
00749         {
00750             addTextNumber( text, elementWriter );
00751 
00752             elementWriter.startElement( "number:day" );
00753             elementWriter.addAttribute( "number:style", "short" );
00754             elementWriter.endElement();
00755             format = format.remove( 0, 2 );
00756         }
00757         else if ( format.startsWith( "%d" ) )
00758         {
00759             addTextNumber( text, elementWriter );
00760 
00761             elementWriter.startElement( "number:day" );
00762             elementWriter.addAttribute( "number:style", "long" );
00763             elementWriter.endElement();
00764             format = format.remove( 0, 2 );
00765         }
00766         else if ( format.startsWith( "%b" ) )
00767         {
00768             addTextNumber( text, elementWriter );
00769             elementWriter.startElement( "number:month" );
00770             elementWriter.addAttribute( "number:style", "short" );
00771             elementWriter.addAttribute( "number:textual", "true");
00772             elementWriter.endElement();
00773             format = format.remove( 0, 2 );
00774         }
00775         else if ( format.startsWith( "%B" ) )
00776         {
00777             addTextNumber( text, elementWriter );
00778             elementWriter.startElement( "number:month" );
00779             elementWriter.addAttribute( "number:style", "long" );
00780             elementWriter.addAttribute( "number:textual", "true");
00781             elementWriter.endElement();
00782             format = format.remove( 0, 2 );
00783         }
00784         else if ( format.startsWith( "%a" ) )
00785         {
00786             addTextNumber( text, elementWriter );
00787             elementWriter.startElement( "number:day-of-week" );
00788             elementWriter.addAttribute( "number:style", "short" );
00789             elementWriter.endElement();
00790 
00791             format = format.remove( 0, 2 );
00792         }
00793         else if ( format.startsWith( "%A" ) )
00794         {
00795             addTextNumber( text, elementWriter );
00796             elementWriter.startElement( "number:day-of-week" );
00797             elementWriter.addAttribute( "number:style", "long" );
00798             elementWriter.endElement();
00799             format = format.remove( 0, 2 );
00800         }
00801         else
00802         {
00803             if ( !saveOasisKlocaleTimeFormat( elementWriter, format, text ) )
00804             {
00805                 text += format[0];
00806                 format = format.remove( 0, 1 );
00807             }
00808         }
00809     }
00810     while ( format.length() > 0 );
00811     addTextNumber( text, elementWriter );
00812 }
00813 
00814 QString KoOasisStyles::saveOasisDateStyle( KoGenStyles &mainStyles, const QString & _format, bool klocaleFormat )
00815 {
00816     kdDebug(30003)<<"QString KoOasisStyles::saveOasisDateStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
00817     QString format( _format );
00818 
00819     // Not supported into Qt: "era" "week-of-year" "quarter"
00820 
00821     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_DATE );
00822     QBuffer buffer;
00823     buffer.open( IO_WriteOnly );
00824     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
00825     QString text;
00826     if ( klocaleFormat )
00827     {
00828         parseOasisDateKlocale( elementWriter, format, text );
00829     }
00830     else
00831     {
00832         bool antislash = false;
00833         do
00834         {
00835             if ( antislash )
00836             {
00837                 text+=format[0];
00838                 format = format.remove( 0, 1 );
00839             }
00840             //TODO implement loading ! What is it ?
00841             else if ( format.startsWith( "MMMMM" ) )
00842             {
00843                 addTextNumber( text, elementWriter );
00844                 elementWriter.startElement( "number:month" );
00845                 elementWriter.addAttribute( "number:textual", "true");
00846                 elementWriter.endElement();
00847                 format = format.remove( 0, 5 );
00848             }
00849             else if ( format.startsWith( "MMMM" ) )
00850             {
00851                 addTextNumber( text, elementWriter );
00852                 elementWriter.startElement( "number:month" );
00853                 elementWriter.addAttribute( "number:style", "long" );
00854                 elementWriter.addAttribute( "number:textual", "true");
00855                 elementWriter.endElement();
00856                 format = format.remove( 0, 4 );
00857             }
00858             else if ( format.startsWith( "MMM" ) )
00859             {
00860                 addTextNumber( text, elementWriter );
00861                 elementWriter.startElement( "number:month" );
00862                 elementWriter.addAttribute( "number:style", "short" );
00863                 elementWriter.addAttribute( "number:textual", "true");
00864                 elementWriter.endElement();
00865                 format = format.remove( 0, 3 );
00866             }
00867             else if ( format.startsWith( "MM" ) )
00868             {
00869                 addTextNumber( text, elementWriter );
00870                 elementWriter.startElement( "number:month" );
00871                 elementWriter.addAttribute( "number:style", "long" );
00872                 elementWriter.addAttribute( "number:textual", "false"); //not necessary remove it
00873                 elementWriter.endElement();
00874                 format = format.remove( 0, 2 );
00875             }
00876             else if ( format.startsWith( "M" ) )
00877             {
00878                 addTextNumber( text, elementWriter );
00879                 elementWriter.startElement( "number:month" );
00880                 elementWriter.addAttribute( "number:style", "short" );
00881                 elementWriter.addAttribute( "number:textual", "false");
00882                 elementWriter.endElement();
00883                 format = format.remove( 0, 1 );
00884             }
00885             else if ( format.startsWith( "PPPP" ) )
00886             {
00887                 addTextNumber( text, elementWriter );
00888                 //<number:month number:possessive-form="true" number:textual="true" number:style="long"/>
00889                 elementWriter.startElement( "number:month" );
00890                 elementWriter.addAttribute( "number:style", "short" );
00891                 elementWriter.addAttribute( "number:textual", "false");
00892                 elementWriter.addAttribute( "number:possessive-form", "true" );
00893                 elementWriter.endElement();
00894                 format = format.remove( 0, 4 );
00895             }
00896             else if ( format.startsWith( "PPP" ) )
00897             {
00898                 addTextNumber( text, elementWriter );
00899                 //<number:month number:possessive-form="true" number:textual="true" number:style="short"/>
00900                 elementWriter.startElement( "number:month" );
00901                 elementWriter.addAttribute( "number:possessive-form", "true" );
00902 
00903                 elementWriter.addAttribute( "number:style", "short" );
00904                 elementWriter.addAttribute( "number:textual", "false");
00905                 elementWriter.endElement();
00906                 format = format.remove( 0, 3 );
00907             }
00908             else if ( format.startsWith( "dddd" ) )
00909             {
00910                 addTextNumber( text, elementWriter );
00911 
00912                 elementWriter.startElement( "number:day-of-week" );
00913                 elementWriter.addAttribute( "number:style", "long" );
00914                 elementWriter.endElement();
00915                 format = format.remove( 0, 4 );
00916             }
00917             else if ( format.startsWith( "ddd" ) )
00918             {
00919                 addTextNumber( text, elementWriter );
00920 
00921                 elementWriter.startElement( "number:day-of-week" );
00922                 elementWriter.addAttribute( "number:style", "short" );
00923                 elementWriter.endElement();
00924                 format = format.remove( 0, 3 );
00925             }
00926             else if ( format.startsWith( "dd" ) )
00927             {
00928                 addTextNumber( text, elementWriter );
00929 
00930                 elementWriter.startElement( "number:day" );
00931                 elementWriter.addAttribute( "number:style", "long" );
00932                 elementWriter.endElement();
00933                 format = format.remove( 0, 2 );
00934             }
00935             else if ( format.startsWith( "d" ) )
00936             {
00937                 addTextNumber( text, elementWriter );
00938 
00939                 elementWriter.startElement( "number:day" );
00940                 elementWriter.addAttribute( "number:style", "short" );
00941                 elementWriter.endElement();
00942                 format = format.remove( 0, 1 );
00943             }
00944             else if ( format.startsWith( "yyyy" ) )
00945             {
00946                 addTextNumber( text, elementWriter );
00947 
00948                 elementWriter.startElement( "number:year" );
00949                 elementWriter.addAttribute( "number:style", "long" );
00950                 elementWriter.endElement();
00951                 format = format.remove( 0, 4 );
00952             }
00953             else if ( format.startsWith( "yy" ) )
00954             {
00955                 addTextNumber( text, elementWriter );
00956 
00957                 elementWriter.startElement( "number:year" );
00958                 elementWriter.addAttribute( "number:style", "short" );
00959                 elementWriter.endElement();
00960                 format = format.remove( 0, 2 );
00961             }
00962             else
00963             {
00964                 if ( !saveOasisTimeFormat( elementWriter, format, text,antislash ) )
00965                 {
00966                     QString elem( format[0] );
00967                     format = format.remove( 0, 1 );
00968                     if ( elem == "\\" )
00969                     {
00970                         antislash = true;
00971                     }
00972                     else
00973                     {
00974                         text += elem;
00975                         antislash = false;
00976                     }
00977                 }
00978             }
00979         }
00980         while ( format.length() > 0 );
00981         addTextNumber( text, elementWriter );
00982     }
00983 
00984     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
00985     currentStyle.addChildElement( "number", elementContents );
00986     return mainStyles.lookup( currentStyle, "N" );
00987 }
00988 
00989 
00990 QString KoOasisStyles::saveOasisFractionStyle( KoGenStyles &mainStyles, const QString & _format, const QString &_prefix, const QString &_suffix )
00991 {
00992     kdDebug(30003)<<"QString saveOasisFractionStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
00993     QString format( _format );
00994 
00995     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_FRACTION );
00996     QBuffer buffer;
00997     buffer.open( IO_WriteOnly );
00998     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
00999     QString text;
01000     int integer = 0;
01001     int numerator = 0;
01002     int denominator = 0;
01003     int denominatorValue = 0;
01004     bool beforeSlash = true;
01005     do
01006     {
01007         if ( format[0]=='#' )
01008             integer++;
01009         else if ( format[0]=='/' )
01010             beforeSlash = false;
01011         else if ( format[0]=='?' )
01012         {
01013             if ( beforeSlash )
01014                 numerator++;
01015             else
01016                 denominator++;
01017         }
01018         else
01019         {
01020             bool ok;
01021             int value = format.toInt( &ok );
01022             if ( ok )
01023             {
01024                 denominatorValue=value;
01025                 break;
01026             }
01027         }
01028         format.remove( 0,1 );
01029     }
01030     while ( format.length() > 0 );
01031 
01032     text= _prefix;
01033     addTextNumber(text, elementWriter );
01034 
01035     elementWriter.startElement( "number:fraction" );
01036     elementWriter.addAttribute( "number:min-integer-digits", integer );
01037     elementWriter.addAttribute( "number:min-numerator-digits",numerator );
01038     elementWriter.addAttribute( "number:min-denominator-digits",denominator );
01039     if ( denominatorValue != 0 )
01040         elementWriter.addAttribute( "number:denominator-value",denominatorValue );
01041     elementWriter.endElement();
01042 
01043     addKofficeNumericStyleExtension( elementWriter, _suffix, _prefix );
01044 
01045     text=_suffix;
01046     addTextNumber(text, elementWriter );
01047 
01048     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
01049     currentStyle.addChildElement( "number", elementContents );
01050     return mainStyles.lookup( currentStyle, "N" );
01051 }
01052 
01053 
01054 QString KoOasisStyles::saveOasisNumberStyle( KoGenStyles &mainStyles, const QString & _format, const QString &_prefix, const QString &_suffix )
01055 {
01056     kdDebug(30003)<<"QString saveOasisNumberStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
01057     QString format( _format );
01058 
01059     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_NUMBER );
01060     QBuffer buffer;
01061     buffer.open( IO_WriteOnly );
01062     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
01063     QString text;
01064     int decimalplaces = 0;
01065     int integerdigits = 0;
01066     bool beforeSeparator = true;
01067     do
01068     {
01069         if ( format[0]=='.' || format[0]==',' )
01070             beforeSeparator = false;
01071         else if ( format[0]=='0' && beforeSeparator )
01072             integerdigits++;
01073         else if ( format[0]=='0' && !beforeSeparator )
01074             decimalplaces++;
01075         else
01076             kdDebug(30003)<<" error format 0 \n";
01077         format.remove( 0,1 );
01078     }
01079     while ( format.length() > 0 );
01080     text= _prefix ;
01081     addTextNumber(text, elementWriter );
01082     elementWriter.startElement( "number:number" );
01083     kdDebug(30003)<<" decimalplaces :"<<decimalplaces<<" integerdigits :"<<integerdigits<<endl;
01084     if (!beforeSeparator)
01085         elementWriter.addAttribute( "number:decimal-places", decimalplaces );
01086     elementWriter.addAttribute( "number:min-integer-digits", integerdigits );
01087     elementWriter.endElement();
01088 
01089     text =_suffix ;
01090     addTextNumber(text, elementWriter );
01091     addKofficeNumericStyleExtension( elementWriter, _suffix,_prefix );
01092 
01093     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
01094     currentStyle.addChildElement( "number", elementContents );
01095     return mainStyles.lookup( currentStyle, "N" );
01096 }
01097 
01098 QString KoOasisStyles::saveOasisPercentageStyle( KoGenStyles &mainStyles, const QString & _format, const QString &_prefix, const QString &_suffix )
01099 {
01100     //<number:percentage-style style:name="N11">
01101     //<number:number number:decimal-places="2" number:min-integer-digits="1"/>
01102     //<number:text>%</number:text>
01103     //</number:percentage-style>
01104 
01105     kdDebug(30003)<<"QString saveOasisPercentageStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
01106     QString format( _format );
01107 
01108     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_PERCENTAGE );
01109     QBuffer buffer;
01110     buffer.open( IO_WriteOnly );
01111     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
01112     QString text;
01113     int decimalplaces = 0;
01114     int integerdigits = 0;
01115     bool beforeSeparator = true;
01116     do
01117     {
01118         if ( format[0]=='.' || format[0]==',' )
01119             beforeSeparator = false;
01120         else if ( format[0]=='0' && beforeSeparator )
01121             integerdigits++;
01122         else if ( format[0]=='0' && !beforeSeparator )
01123             decimalplaces++;
01124         else
01125             kdDebug(30003)<<" error format 0 \n";
01126         format.remove( 0,1 );
01127     }
01128     while ( format.length() > 0 );
01129     text= _prefix ;
01130     addTextNumber(text, elementWriter );
01131     elementWriter.startElement( "number:number" );
01132     if (!beforeSeparator)
01133         elementWriter.addAttribute( "number:decimal-places", decimalplaces );
01134     elementWriter.addAttribute( "number:min-integer-digits", integerdigits );
01135     elementWriter.endElement();
01136 
01137     addTextNumber(QString( "%" ), elementWriter );
01138 
01139     text =_suffix ;
01140     addTextNumber(text, elementWriter );
01141     addKofficeNumericStyleExtension( elementWriter, _suffix,_prefix );
01142 
01143     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
01144     currentStyle.addChildElement( "number", elementContents );
01145     return mainStyles.lookup( currentStyle, "N" );
01146 
01147 }
01148 
01149 QString KoOasisStyles::saveOasisScientificStyle( KoGenStyles &mainStyles, const QString & _format, const QString &_prefix, const QString &_suffix )
01150 {
01151     //<number:number-style style:name="N60">
01152     //<number:scientific-number number:decimal-places="2" number:min-integer-digits="1" number:min-exponent-digits="3"/>
01153     //</number:number-style>
01154 
01155     //example 000,000e+0000
01156     kdDebug(30003)<<"QString saveOasisScientificStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
01157     QString format( _format );
01158 
01159     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_SCIENTIFIC );
01160     QBuffer buffer;
01161     buffer.open( IO_WriteOnly );
01162     int decimalplace = 0;
01163     int integerdigits = 0;
01164     int exponentdigits = 0;
01165     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
01166     QString text;
01167     bool beforeSeparator = true;
01168     bool exponential = false;
01169     bool positive = true;
01170     do
01171     {
01172         if ( !exponential )
01173         {
01174             if ( format[0]=='0' && beforeSeparator )
01175                 integerdigits++;
01176             else if ( format[0]==',' || format[0]=='.' )
01177                 beforeSeparator = false;
01178             else if (  format[0]=='0' && !beforeSeparator )
01179                 decimalplace++;
01180             else if ( format[0].lower()=='e' )
01181             {
01182                 format.remove( 0, 1 );
01183                 if ( format[0]=='+' )
01184                     positive = true;
01185                 else if ( format[0]=='-' )
01186                     positive = false;
01187                 else
01188                     kdDebug(30003)<<"Error into scientific number\n";
01189                 exponential = true;
01190             }
01191         }
01192         else
01193         {
01194             if ( format[0]=='0' && positive )
01195                 exponentdigits++;
01196             else if ( format[0]=='0' && !positive )
01197                 exponentdigits--;
01198             else
01199                 kdDebug(30003)<<" error into scientific number exponential value\n";
01200         }
01201         format.remove( 0,1 );
01202     }
01203     while ( format.length() > 0 );
01204     text =  _prefix ;
01205     addTextNumber(text, elementWriter );
01206 
01207     elementWriter.startElement( "number:scientific-number" );
01208     kdDebug(30003)<<" decimalplace :"<<decimalplace<<" integerdigits :"<<integerdigits<<" exponentdigits :"<<exponentdigits<<endl;
01209     if (!beforeSeparator)
01210         elementWriter.addAttribute( "number:decimal-places", decimalplace );
01211     elementWriter.addAttribute( "number:min-integer-digits",integerdigits );
01212     elementWriter.addAttribute( "number:min-exponent-digits",exponentdigits );
01213     elementWriter.endElement();
01214 
01215     text = _suffix;
01216     addTextNumber(text, elementWriter );
01217     addKofficeNumericStyleExtension( elementWriter, _suffix,_prefix );
01218 
01219     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
01220     currentStyle.addChildElement( "number", elementContents );
01221     return mainStyles.lookup( currentStyle, "N" );
01222 }
01223 
01224 QString KoOasisStyles::saveOasisCurrencyStyle( KoGenStyles &mainStyles, const QString & _format, const QString &_prefix, const QString &_suffix )
01225 {
01226 
01227     //<number:currency-style style:name="N107P0" style:volatile="true">
01228     //<number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
01229     //<number:text> </number:text>
01230     //<number:currency-symbol>VEB</number:currency-symbol>
01231     //</number:currency-style>
01232 
01233     kdDebug(30003)<<"QString saveOasisCurrencyStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
01234     QString format( _format );
01235 
01236     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_CURRENCY );
01237     QBuffer buffer;
01238     buffer.open( IO_WriteOnly );
01239     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
01240     QString text;
01241     int decimalplaces = 0;
01242     int integerdigits = 0;
01243     bool beforeSeparator = true;
01244     do
01245     {
01246         if ( format[0]=='.' || format[0]==',' )
01247             beforeSeparator = false;
01248         else if ( format[0]=='0' && beforeSeparator )
01249             integerdigits++;
01250         else if ( format[0]=='0' && !beforeSeparator )
01251             decimalplaces++;
01252         else
01253             kdDebug(30003)<<" error format 0 \n";
01254         format.remove( 0,1 );
01255     }
01256     while ( format.length() > 0 );
01257 
01258     // NOTE Stefan: Misusing the prefix for the currency symbol.
01259     //              It was not used before. If somebody complains about missing
01260     //              prefixes for the currency in the 1.5 series, we've got a
01261     //              probably a problem. For KOffice 2.0 I added a separate arg.
01262     text =  QString::null; // _prefix ;
01263     addTextNumber(text, elementWriter );
01264 
01265     elementWriter.startElement( "number:number" );
01266     kdDebug(30003)<<" decimalplaces :"<<decimalplaces<<" integerdigits :"<<integerdigits<<endl;
01267     if (!beforeSeparator)
01268       elementWriter.addAttribute( "number:decimal-places", decimalplaces );
01269     elementWriter.addAttribute( "number:min-integer-digits", integerdigits );
01270     elementWriter.endElement();
01271 
01272     text =  _suffix ;
01273     addTextNumber(text, elementWriter );
01274     addKofficeNumericStyleExtension( elementWriter, _suffix,_prefix );
01275 
01276     elementWriter.startElement( "number:currency-symbol" );
01277     kdDebug(30003)<<" currency-symbol: "<<_prefix<<endl;
01278     elementWriter.addTextNode( _prefix );
01279     elementWriter.endElement();
01280 
01281     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
01282     currentStyle.addChildElement( "number", elementContents );
01283     return mainStyles.lookup( currentStyle, "N" );
01284 }
01285 
01286 QString KoOasisStyles::saveOasisTextStyle( KoGenStyles &mainStyles, const QString & _format, const QString &_prefix, const QString &_suffix )
01287 {
01288 
01289     //<number:text-style style:name="N100">
01290     //<number:text-content/>
01292 
01293     kdDebug(30003)<<"QString saveOasisTextStyle( KoGenStyles &mainStyles, const QString & _format ) :"<<_format<<endl;
01294     QString format( _format );
01295 
01296     KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_TEXT );
01297     QBuffer buffer;
01298     buffer.open( IO_WriteOnly );
01299     KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
01300     QString text;
01301     do
01302     {
01303         format.remove( 0,1 );
01304     }
01305     while ( format.length() > 0 );
01306     text =  _prefix ;
01307     addTextNumber(text, elementWriter );
01308 
01309     elementWriter.startElement( "number:text-style" );
01310 
01311     text =  _suffix ;
01312     addTextNumber(text, elementWriter );
01313     addKofficeNumericStyleExtension( elementWriter, _suffix,_prefix );
01314     elementWriter.endElement();
01315 
01316     QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
01317     currentStyle.addChildElement( "number", elementContents );
01318     return mainStyles.lookup( currentStyle, "N" );
01319 }
01320 
01321 //This is an extension of numeric style. For the moment we used namespace of oasis format for specific koffice extention. change it for the futur.
01322 void KoOasisStyles::addKofficeNumericStyleExtension( KoXmlWriter & elementWriter, const QString &_suffix, const QString &_prefix )
01323  {
01324      if ( !_suffix.isEmpty() )
01325      {
01326          elementWriter.startElement( "number:suffix" );
01327          elementWriter.addTextNode( _suffix );
01328          elementWriter.endElement();
01329      }
01330      if ( !_prefix.isEmpty() )
01331      {
01332          elementWriter.startElement( "number:prefix" );
01333          elementWriter.addTextNode( _prefix );
01334          elementWriter.endElement();
01335      }
01336 }
01337 
01338 void KoOasisStyles::saveOasisFillStyle( KoGenStyle &styleFill, KoGenStyles& mainStyles, const QBrush & brush )
01339 {
01340     if ( brush.style() == Qt::SolidPattern )
01341     {
01342         styleFill.addProperty( "draw:fill","solid" );
01343         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01344     }
01345     else if ( brush.style() == Qt::Dense1Pattern )
01346     {
01347         styleFill.addProperty( "draw:transparency", "94%" );
01348         styleFill.addProperty( "draw:fill","solid" );
01349         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01350     }
01351     else if ( brush.style() == Qt::Dense2Pattern )
01352     {
01353         styleFill.addProperty( "draw:transparency", "88%" );
01354         styleFill.addProperty( "draw:fill","solid" );
01355         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01356     }
01357     else if ( brush.style() == Qt::Dense3Pattern )
01358     {
01359         styleFill.addProperty( "draw:transparency", "63%" );
01360         styleFill.addProperty( "draw:fill","solid" );
01361         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01362     }
01363     else if ( brush.style() == Qt::Dense4Pattern )
01364     {
01365         styleFill.addProperty( "draw:transparency", "50%" );
01366         styleFill.addProperty( "draw:fill","solid" );
01367         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01368     }
01369     else if ( brush.style() == Qt::Dense5Pattern )
01370     {
01371         styleFill.addProperty( "draw:transparency", "37%" );
01372         styleFill.addProperty( "draw:fill","solid" );
01373         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01374     }
01375     else if ( brush.style() == Qt::Dense6Pattern )
01376     {
01377         styleFill.addProperty( "draw:transparency", "12%" );
01378         styleFill.addProperty( "draw:fill","solid" );
01379         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01380     }
01381     else if ( brush.style() == Qt::Dense7Pattern )
01382     {
01383         styleFill.addProperty( "draw:transparency", "6%" );
01384         styleFill.addProperty( "draw:fill","solid" );
01385         styleFill.addProperty( "draw:fill-color", brush.color().name() );
01386     }
01387     else //otherstyle
01388     {
01389         styleFill.addProperty( "draw:fill","hatch" );
01390         styleFill.addProperty( "draw:fill-hatch-name", saveOasisHatchStyle( mainStyles,brush ) );
01391     }
01392 
01393 }
01394 
01395 QString KoOasisStyles::saveOasisHatchStyle( KoGenStyles& mainStyles, const QBrush &brush )
01396 {
01397     KoGenStyle hatchStyle( KoGenStyle::STYLE_HATCH /*no family name*/);
01398     hatchStyle.addAttribute( "draw:color", brush.color().name() );
01399     //hatchStyle.addAttribute( "draw:distance", m_distance ); not implemented into kpresenter
01400     switch( brush.style() )
01401     {
01402     case Qt::HorPattern:
01403         hatchStyle.addAttribute( "draw:style", "single" );
01404         hatchStyle.addAttribute( "draw:rotation", 0);
01405         break;
01406     case Qt::BDiagPattern:
01407         hatchStyle.addAttribute( "draw:style", "single" );
01408         hatchStyle.addAttribute( "draw:rotation", 450);
01409         break;
01410     case Qt::VerPattern:
01411         hatchStyle.addAttribute( "draw:style", "single" );
01412         hatchStyle.addAttribute( "draw:rotation", 900);
01413         break;
01414     case Qt::FDiagPattern:
01415         hatchStyle.addAttribute( "draw:style", "single" );
01416         hatchStyle.addAttribute( "draw:rotation", 1350);
01417         break;
01418     case Qt::CrossPattern:
01419         hatchStyle.addAttribute( "draw:style", "double" );
01420         hatchStyle.addAttribute( "draw:rotation", 0);
01421         break;
01422     case Qt::DiagCrossPattern:
01423         hatchStyle.addAttribute( "draw:style", "double" );
01424         hatchStyle.addAttribute( "draw:rotation", 450);
01425         break;
01426     default:
01427         break;
01428     }
01429 
01430     return mainStyles.lookup( hatchStyle, "hatch" );
01431 }
01432 
01433 QBrush KoOasisStyles::loadOasisFillStyle( const KoStyleStack &styleStack, const QString & fill, const KoOasisStyles & oasisStyles )
01434 {
01435     QBrush tmpBrush;
01436     if ( fill == "solid" )
01437     {
01438         tmpBrush.setStyle(static_cast<Qt::BrushStyle>( 1 ) );
01439         if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill-color" ) )
01440             tmpBrush.setColor(styleStack.attributeNS( KoXmlNS::draw, "fill-color" ) );
01441         if ( styleStack.hasAttributeNS( KoXmlNS::draw, "transparency" ) )
01442         {
01443             QString transparency = styleStack.attributeNS( KoXmlNS::draw, "transparency" );
01444             if ( transparency == "94%" )
01445             {
01446                 tmpBrush.setStyle(Qt::Dense1Pattern);
01447             }
01448             else if ( transparency == "88%" )
01449             {
01450                 tmpBrush.setStyle(Qt::Dense2Pattern);
01451             }
01452             else if ( transparency == "63%" )
01453             {
01454                 tmpBrush.setStyle(Qt::Dense3Pattern);
01455 
01456             }
01457             else if ( transparency == "50%" )
01458             {
01459                 tmpBrush.setStyle(Qt::Dense4Pattern);
01460 
01461             }
01462             else if ( transparency == "37%" )
01463             {
01464                 tmpBrush.setStyle(Qt::Dense5Pattern);
01465 
01466             }
01467             else if ( transparency == "12%" )
01468             {
01469                 tmpBrush.setStyle(Qt::Dense6Pattern);
01470 
01471             }
01472             else if ( transparency == "6%" )
01473             {
01474                 tmpBrush.setStyle(Qt::Dense7Pattern);
01475 
01476             }
01477             else
01478                 kdDebug()<<" transparency is not defined into kpresenter :"<<transparency<<endl;
01479         }
01480     }
01481     else if ( fill == "hatch" )
01482     {
01483         QString style = styleStack.attributeNS( KoXmlNS::draw, "fill-hatch-name" );
01484         kdDebug()<<" hatch style is  : "<<style<<endl;
01485 
01486         //type not defined by default
01487         //try to use style.
01488         QDomElement* draw = oasisStyles.drawStyles()[style];
01489         if ( draw)
01490         {
01491             kdDebug()<<"We have a style\n";
01492             int angle = 0;
01493             if( draw->hasAttributeNS( KoXmlNS::draw, "rotation" ))
01494             {
01495                 angle = (draw->attributeNS( KoXmlNS::draw, "rotation", QString::null ).toInt())/10;
01496                 kdDebug()<<"angle :"<<angle<<endl;
01497             }
01498             if(draw->hasAttributeNS( KoXmlNS::draw, "color" ) )
01499             {
01500                 //kdDebug()<<" draw:color :"<<draw->attributeNS( KoXmlNS::draw, "color", QString::null )<<endl;
01501                 tmpBrush.setColor(draw->attributeNS( KoXmlNS::draw, "color", QString::null ) );
01502             }
01503             if( draw->hasAttributeNS( KoXmlNS::draw, "distance" ))
01504             {
01505                 //todo implemente it into kpresenter
01506             }
01507             if( draw->hasAttributeNS( KoXmlNS::draw, "display-name"))
01508             {
01509                 //todo implement it into kpresenter
01510             }
01511             if( draw->hasAttributeNS( KoXmlNS::draw, "style" ))
01512             {
01513                 //todo implemente it into kpresenter
01514                 QString styleHash = draw->attributeNS( KoXmlNS::draw, "style", QString::null );
01515                 if( styleHash == "single")
01516                 {
01517                     switch( angle )
01518                     {
01519                     case 0:
01520                     case 180:
01521                         tmpBrush.setStyle(Qt::HorPattern );
01522                         break;
01523                     case 45:
01524                     case 225:
01525                         tmpBrush.setStyle(Qt::BDiagPattern );
01526                         break;
01527                     case 90:
01528                     case 270:
01529                         tmpBrush.setStyle(Qt::VerPattern );
01530                         break;
01531                     case 135:
01532                     case 315:
01533                         tmpBrush.setStyle(Qt::FDiagPattern );
01534                         break;
01535                     default:
01536                         //todo fixme when we will have a kopaint
01537                         kdDebug()<<" draw:rotation 'angle' : "<<angle<<endl;
01538                         break;
01539                     }
01540                 }
01541                 else if( styleHash == "double")
01542                 {
01543                     switch( angle )
01544                     {
01545                     case 0:
01546                     case 180:
01547                     case 90:
01548                     case 270:
01549                         tmpBrush.setStyle(Qt::CrossPattern );
01550                         break;
01551                     case 45:
01552                     case 135:
01553                     case 225:
01554                     case 315:
01555                         tmpBrush.setStyle(Qt::DiagCrossPattern );
01556                         break;
01557                     default:
01558                         //todo fixme when we will have a kopaint
01559                         kdDebug()<<" draw:rotation 'angle' : "<<angle<<endl;
01560                         break;
01561                     }
01562 
01563                 }
01564                 else if( styleHash == "triple")
01565                 {
01566                     kdDebug()<<" it is not implemented :( \n";
01567                 }
01568             }
01569         }
01570     }
01571     return tmpBrush;
01572 }
01573 
01574 const QDomElement* KoOasisStyles::defaultStyle( const QString& family ) const
01575 {
01576     return m_defaultStyle[family];
01577 }
01578 
01579 const QDomElement* KoOasisStyles::findStyle( const QString& name ) const
01580 {
01581     return m_styles[ name ];
01582 }
01583 
01584 const QDomElement* KoOasisStyles::findStyle( const QString& styleName, const QString& family ) const
01585 {
01586     const QDomElement* style = d->m_styles[ family ][ styleName ];
01587     if ( style && !family.isEmpty() ) {
01588         const QString styleFamily = style->attributeNS( KoXmlNS::style, "family", QString::null );
01589         if ( styleFamily != family ) {
01590             kdWarning() << "KoOasisStyles: was looking for style " << styleName
01591                         << " in family " << family << " but got " << styleFamily << endl;
01592         }
01593     }
01594     return style;
01595 }
01596 
01597 const QDomElement* KoOasisStyles::findStyleAutoStyle( const QString& styleName, const QString& family ) const
01598 {
01599     const QDomElement* style = d->m_stylesAutoStyles[ family ][ styleName ];
01600     if ( style ) {
01601         const QString styleFamily = style->attributeNS( KoXmlNS::style, "family", QString::null );
01602         if ( styleFamily != family ) {
01603             kdWarning() << "KoOasisStyles: was looking for style " << styleName
01604                         << " in family " << family << " but got " << styleFamily << endl;
01605         }
01606     }
01607     return style;
01608 }
KDE Home | KDE Accessibility Home | Description of Access Keys