[prev in list] [next in list] [prev in thread] [next in thread] 

List:       koffice-devel
Subject:    Re: precision in OpenDocument
From:       "Ariya Hidayat" <ariya () kde ! org>
Date:       2006-04-19 20:02:39
Message-ID: ba035dd10604191302v304dfbbfl35cc209820ba5548 () mail ! gmail ! com
[Download RAW message or body]

Second try. This hopefully preserves BC (thanks to dfaure for noticing
the problem in my previous patch).

A big part of this patch also comes from Stefan. This is supposed to
fix bug 125520 and 118331. Some problem still remains, e.g. saving
6.234 with precision=3D1 and loading it again will give 6.2 as displayed
(correct) BUT the value also becomes 6.2 (which is wrong because there
will be loss of data). Stefan: could you look into this?

Also, I don't know if finding precision from the format string is
reliable enough. That's why I include my previous patch (which works
directly from within KoOasisStyles). IMHO we should  do that way for
other format options as well, rather than doing round trip stuff
(Oasis format elements to format string, and then to get parsed
again).

Comments?

["precision.patch" (text/x-patch)]

Index: lib/kofficecore/KoGenStyles.h
===================================================================
--- lib/kofficecore/KoGenStyles.h	(revision 531652)
+++ lib/kofficecore/KoGenStyles.h	(working copy)
@@ -195,7 +195,7 @@
            STYLE_MASTER = 3,
            STYLE_LIST = 4,
            STYLE_AUTO_LIST = 5,
-           // 6 is available
+           STYLE_NUMERIC_NUMBER = 6,
            STYLE_NUMERIC_DATE = 7,
            STYLE_NUMERIC_TIME = 8,
            STYLE_NUMERIC_FRACTION = 9,
Index: lib/kofficecore/KoOasisStyles.cpp
===================================================================
--- lib/kofficecore/KoOasisStyles.cpp	(revision 531652)
+++ lib/kofficecore/KoOasisStyles.cpp	(working copy)
@@ -35,6 +35,8 @@
     // The key of the map is the family
     QMap<QString, QDict<QDomElement> > m_styles;
     QMap<QString, QDict<QDomElement> > m_stylesAutoStyles;
+
+    NumericFormatsMap numericFormats;
 };
 
 KoOasisStyles::KoOasisStyles()
@@ -227,7 +229,7 @@
 void KoOasisStyles::importDataStyle( const QDomElement& parent )
 {
     QString format;
-    int precision = 0;
+    int precision = -1;
     int leadingZ  = 1;
     bool thousandsSep = false;
     //todo negred
@@ -310,9 +312,12 @@
                 if ( ( i % 3 == 0 ) && thousandsSep )
                     format =+ ',' ;
             }
-            format += '.';
-            for ( i = 0; i < precision; ++i )
-                format += '0';
+            if (precision > -1)
+            {
+                format += '.';
+                for ( i = 0; i < precision; ++i )
+                    format += '0';
+            }
         }
         else if ( localName == "scientific-number" ) {
             int exp = 2;
@@ -354,9 +359,12 @@
                     format+=',';
             }
 
-            format+='.';
-            for ( i = 0; i < precision; ++i )
-                format+='0';
+            if (precision > -1)
+            {
+                format += '.';
+                for ( i = 0; i < precision; ++i )
+                    format += '0';
+            }
 
             format+="E+";
             for ( i = 0; i < exp; ++i )
@@ -445,6 +453,11 @@
     m_dataFormats.insert( styleName, numeric );
 }
 
+const KoOasisStyles::NumericFormatsMap& KoOasisStyles::numericFormats() const
+{
+    return d->numericFormats;
+}
+
 #define addTextNumber( text, elementWriter ) { \
         if ( !text.isEmpty() ) \
         { \
@@ -1011,6 +1024,50 @@
 }
 
 
+QString KoOasisStyles::saveOasisNumberStyle( KoGenStyles &mainStyles, const QString \
& _format, const QString &_prefix, const QString &_suffix ) +{
+    kdDebug(30003)<<"QString saveOasisNumberStyle( KoGenStyles &mainStyles, const \
QString & _format ) :"<<_format<<endl; +    QString format( _format );
+
+    KoGenStyle currentStyle( KoGenStyle::STYLE_NUMERIC_NUMBER );
+    QBuffer buffer;
+    buffer.open( IO_WriteOnly );
+    KoXmlWriter elementWriter( &buffer );  // TODO pass indentation level
+    QString text;
+    int decimalplaces = 0;
+    int integerdigits = 0;
+    bool beforeSeparator = true;
+    do
+    {
+        if ( format[0]=='.' || format[0]==',' )
+            beforeSeparator = false;
+        else if ( format[0]=='0' && beforeSeparator )
+            integerdigits++;
+        else if ( format[0]=='0' && !beforeSeparator )
+            decimalplaces++;
+        else
+            kdDebug(30003)<<" error format 0 \n";
+        format.remove( 0,1 );
+    }
+    while ( format.length() > 0 );
+    text= _prefix ;
+    addTextNumber(text, elementWriter );
+    elementWriter.startElement( "number:number" );
+    kdDebug(30003)<<" decimalplaces :"<<decimalplaces<<" integerdigits \
:"<<integerdigits<<endl; +    if (!beforeSeparator)
+        elementWriter.addAttribute( "number:decimal-places", decimalplaces );
+    elementWriter.addAttribute( "number:min-integer-digits", integerdigits );
+    elementWriter.endElement();
+
+    text =_suffix ;
+    addTextNumber(text, elementWriter );
+    addKofficeNumericStyleExtension( elementWriter, _suffix,_prefix );
+
+    QString elementContents = QString::fromUtf8( buffer.buffer(), \
buffer.buffer().size() ); +    currentStyle.addChildElement( "number", \
elementContents ); +    return mainStyles.lookup( currentStyle, "N" );
+}
+
 QString KoOasisStyles::saveOasisPercentageStyle( KoGenStyles &mainStyles, const \
QString & _format, const QString &_prefix, const QString &_suffix )  {
     //<number:percentage-style style:name="N11">
@@ -1045,7 +1102,8 @@
     text= _prefix ;
     addTextNumber(text, elementWriter );
     elementWriter.startElement( "number:number" );
-    elementWriter.addAttribute( "number:decimal-places", decimalplaces );
+    if (!beforeSeparator)
+        elementWriter.addAttribute( "number:decimal-places", decimalplaces );
     elementWriter.addAttribute( "number:min-integer-digits", integerdigits );
     elementWriter.endElement();
 
@@ -1121,7 +1179,8 @@
 
     elementWriter.startElement( "number:scientific-number" );
     kdDebug(30003)<<" decimalplace :"<<decimalplace<<" integerdigits \
                :"<<integerdigits<<" exponentdigits :"<<exponentdigits<<endl;
-    elementWriter.addAttribute( "number:decimal-places", decimalplace );
+    if (!beforeSeparator)
+        elementWriter.addAttribute( "number:decimal-places", decimalplace );
     elementWriter.addAttribute( "number:min-integer-digits",integerdigits );
     elementWriter.addAttribute( "number:min-exponent-digits",exponentdigits );
     elementWriter.endElement();
Index: lib/kofficecore/KoOasisStyles.h
===================================================================
--- lib/kofficecore/KoOasisStyles.h	(revision 531652)
+++ lib/kofficecore/KoOasisStyles.h	(working copy)
@@ -31,6 +31,13 @@
 class KoGenStyle;
 class KoStyleStack;
 
+// FIXME this is to maintain binary compatibility of KoOasisStyles in 1.5.x
+// TODO merge with KoOasisStyles::NumericStyleFormat in KOffice 2.0
+struct KOFFICECORE_EXPORT KoOasisNumericFormat
+{
+    int precision;
+};
+
 /**
  * Repository of styles used during loading of OASIS/OOo file
  */
@@ -104,10 +111,14 @@
     /// Key: format name. Value:
     const DataFormatsMap& dataFormats() const { return m_dataFormats; }
 
+    typedef QMap<QString, KoOasisNumericFormat> NumericFormatsMap;
+    const NumericFormatsMap& numericFormats() const;
+
     static QString saveOasisDateStyle( KoGenStyles &mainStyles, const QString & \
                _format, bool klocaleFormat );
     static QString saveOasisTimeStyle( KoGenStyles &mainStyles, const QString & \
_format, bool klocaleFormat );  static QString saveOasisFractionStyle( KoGenStyles \
&mainStyles, const QString & _format, const QString &_prefix = QString::null , const \
QString &_suffix= QString::null );  static QString saveOasisScientificStyle( \
KoGenStyles &mainStyles, const QString & _format, const QString &_prefix = \
QString::null , const QString &_suffix= QString::null ); +    static QString \
saveOasisNumberStyle( KoGenStyles &mainStyles, const QString & _format, const QString \
&_prefix = QString::null , const QString &_suffix= QString::null );  static QString \
saveOasisPercentageStyle( KoGenStyles &mainStyles, const QString & _format, const \
QString &_prefix = QString::null , const QString &_suffix= QString::null );  static \
QString saveOasisCurrencyStyle( KoGenStyles &mainStyles, const QString & _format, \
const QString &_prefix = QString::null , const QString &_suffix= QString::null );  \
static QString saveOasisTextStyle( KoGenStyles &mainStyles, const QString & _format, \
                const QString &_prefix = QString::null , const QString &_suffix= \
                QString::null );
Index: kspread/kspread_doc.cc
===================================================================
--- kspread/kspread_doc.cc	(revision 531643)
+++ kspread/kspread_doc.cc	(working copy)
@@ -703,6 +703,12 @@
         (*it).style->writeStyle( contentWriter, mainStyles, "style:style", \
(*it).name, "style:table-cell-properties" );  }
 
+    styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_NUMBER );
+    it = styles.begin();
+    for ( ; it != styles.end() ; ++it ) {
+      (*it).style->writeStyle( contentWriter, mainStyles, "number:number-style", \
(*it).name, 0 /*TODO ????*/  ); +    }
+
     //TODO FIXME !!!!
     styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE );
     it = styles.begin();
Index: kspread/kspread_style.cc
===================================================================
--- kspread/kspread_style.cc	(revision 531649)
+++ kspread/kspread_style.cc	(working copy)
@@ -177,26 +177,70 @@
         //kdDebug()<< " oasisStyles.dataFormats()[...] prefix :"<< \
oasisStyles.dataFormats()[element.attributeNS( KoXmlNS::style, "data-style-name" , \
QString::null)].prefix<<endl;  //kdDebug()<< " oasisStyles.dataFormats()[...] suffix \
:"<< oasisStyles.dataFormats()[element.attributeNS( KoXmlNS::style, "data-style-name" \
, QString::null)].suffix<<endl;  
-        str = element.attributeNS( KoXmlNS::style, "data-style-name" , \
QString::null); +        QString styleName = element.attributeNS( KoXmlNS::style, \
"data-style-name" , QString::null); +        if ( \
oasisStyles.dataFormats().contains(styleName) ) +        {
+          KoOasisStyles::NumericStyleFormat dataStyle = \
oasisStyles.dataFormats()[styleName];  
-        QString tmp = oasisStyles.dataFormats()[str].prefix;
-        if ( !tmp.isEmpty() )
-        {
+          QString tmp = dataStyle.prefix;
+          if ( !tmp.isEmpty() )
+          {
             m_prefix = tmp;
             m_featuresSet |= SPrefix;
-        }
-        tmp = oasisStyles.dataFormats()[str].suffix;
-        if ( !tmp.isEmpty() )
-        {
+          }
+          tmp = dataStyle.suffix;
+          if ( !tmp.isEmpty() )
+          {
             m_postfix = tmp;
             m_featuresSet |= SPostfix;
-        }
-        tmp = oasisStyles.dataFormats()[str].formatStr;
-        if ( !tmp.isEmpty() )
-        {
+          }
+          m_formatType = Number_format;
+          tmp = dataStyle.formatStr;
+          if ( !tmp.isEmpty() )
+          {
             m_formatType = Style::formatType( tmp );
             m_featuresSet |= SFormatType;
+
+            // determine precision for numeric values
+            QString numericFormat;
+            if (m_formatType == Number_format)
+            {
+              numericFormat = tmp;
+            }
+            else if (m_formatType == Scientific_format)
+            {
+              numericFormat = tmp.section("E+",0,0);
+            }
+            else if (m_formatType == Percentage_format)
+            {
+              numericFormat = tmp.section("%",0,0);
+            }
+            if (!numericFormat.isNull())
+            {
+              // (Ariya) is this reliable? 
+              int decimalPlaces = -1;
+              int pos = numericFormat.findRev('.');
+              if (pos > -1)
+              {
+                int len = numericFormat.length();
+                for (; pos < len; ++pos)
+                  ++decimalPlaces;
+                m_precision = decimalPlaces;
+                m_featuresSet |= SPrecision;
+              }
+            }
+          }
         }
+
+        bool hasNumericFormat = oasisStyles.numericFormats().contains(styleName);
+        const KoOasisNumericFormat& numFormat = \
oasisStyles.numericFormats()[styleName]; +
+        if ( hasNumericFormat )
+        {
+            m_precision = numFormat.precision;
+            m_featuresSet |= SPrecision;
+        }
+
     }
 
     styleStack.setTypeProperties( "text" );
@@ -298,6 +342,10 @@
             m_alignX = Format::Undefined;
         m_featuresSet |= SAlignX;
     }
+
+// NOTE Stefan: IMHO the formatting of numbers is always done
+//              by evaluating OASIS data styles
+#if 0
     if ( styleStack.hasAttributeNS( KoXmlNS::office, "value-type" ) )
     {
       m_formatType = Generic_format;
@@ -322,6 +370,7 @@
       if ( m_formatType != Generic_format )
         m_featuresSet |= SFormatType;
     }
+#endif
 
     styleStack.setTypeProperties( "table-cell" );
     if ( styleStack.hasAttributeNS( KoXmlNS::style, "vertical-align" ) )
@@ -704,6 +753,10 @@
         return Time_format7;
     else if ( _format == "h:mm" )
         return Time_format8;
+    else if ( _format.contains("E+0") )
+        return Scientific_format;
+    else if ( _format.contains("%") )
+        return Percentage_format;
     else
         return Number_format;
 }
@@ -802,6 +855,11 @@
         break;
     case Generic_format:
     case No_format:
+      if (_precision > -1 || !_prefix.isEmpty() || !_postfix.isEmpty())
+      {
+        styleName = saveOasisStyleNumericNumber( mainStyles, _style, _precision );
+        valueType = "float";
+      }
       break;
     }
     if ( !valueType.isEmpty() )
@@ -817,9 +875,22 @@
     return styleName;
 }
 
-QString Style::saveOasisStyleNumericNumber( KoGenStyles& /*mainStyles*/, FormatType \
/*_style*/, int /*_precision*/ ) +QString Style::saveOasisStyleNumericNumber( \
KoGenStyles& mainStyles, FormatType /*_style*/, int _precision )  {
-    return "";
+  QString format;
+  if ( _precision == -1 )
+    format="0";
+  else
+  {
+    QString tmp;
+    for ( int i = 0; i <_precision; i++ )
+    {
+      tmp+="0";
+    }
+    format = "0."+tmp;
+  }
+  kdDebug() << format << endl;
+  return KoOasisStyles::saveOasisNumberStyle( mainStyles, format );
 }
 
 QString Style::saveOasisStyleNumericText( KoGenStyles& /*mainStyles*/, FormatType \
/*_style*/, int /*_precision*/ ) @@ -842,7 +913,7 @@
     //TODO add decimal etc.
     QString format;
     if ( _precision == -1 )
-        format="0.00";
+        format="0";
     else
     {
         QString tmp;
@@ -863,7 +934,7 @@
     //</number:number-style>
     QString format;
     if ( _precision == -1 )
-        format="0.0E+00";
+        format="0E+00";
     else
     {
         QString tmp;



_______________________________________________
koffice-devel mailing list
koffice-devel@kde.org
https://mail.kde.org/mailman/listinfo/koffice-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic