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