filters

ImportFormatting.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, 2002, 2004 Nicolas GOUTTE <goutte@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 as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <kdebug.h>
00021 
00022 #include "ImportFormatting.h"
00023 #include "ImportStyle.h"
00024 
00025 StackItem::StackItem() : fontSize(0), /* No explicit font size */
00026     pos(0), italic(false), bold(false), underline(false), strikeout(false),
00027     textPosition(0)
00028 {
00029 }
00030 
00031 StackItem::~StackItem()
00032 {
00033 }
00034 
00035 void PopulateProperties(StackItem* stackItem, const QString& strStyleProps,
00036     const QXmlAttributes& attributes, AbiPropsMap& abiPropsMap,
00037     const bool allowInit)
00038 // TODO: find a better name for this function
00039 {
00040     if (allowInit)
00041     {
00042         // Initialize the QStrings with the previous values of the properties
00043         // TODO: any others needed?
00044         if (stackItem->italic)
00045         {
00046             abiPropsMap.setProperty("font-style","italic");
00047         }
00048         if (stackItem->bold)
00049         {
00050             abiPropsMap.setProperty("font-weight","bold");
00051         }
00052 
00053         if (stackItem->underline)
00054         {
00055             abiPropsMap.setProperty("text-decoration","underline");
00056         }
00057         else if (stackItem->strikeout)
00058         {
00059             abiPropsMap.setProperty("text-decoration","line-through");
00060         }
00061     }
00062 
00063     // Style goes first
00064     kdDebug(30506)<< "===== from style=\"" << strStyleProps << "\"" << endl;
00065     abiPropsMap.splitAndAddAbiProps(strStyleProps);
00066     // Treat the props attributes in the two available flavors: lower case and upper case.
00067     kdDebug(30506)<< "========== props=\"" << attributes.value("props") << "\"" << endl;
00068     abiPropsMap.splitAndAddAbiProps(attributes.value("props"));
00069     abiPropsMap.splitAndAddAbiProps(attributes.value("PROPS")); // PROPS is deprecated
00070 
00071     stackItem->italic=(abiPropsMap["font-style"].getValue()=="italic");
00072     stackItem->bold=(abiPropsMap["font-weight"].getValue()=="bold");
00073 
00074     QString strDecoration=abiPropsMap["text-decoration"].getValue();
00075     stackItem->underline=(strDecoration=="underline");
00076     stackItem->strikeout=(strDecoration=="line-through");
00077 
00078     QString strTextPosition=abiPropsMap["text-position"].getValue();
00079     if (strTextPosition=="subscript")
00080     {
00081         stackItem->textPosition=1;
00082     }
00083     else if (strTextPosition=="superscript")
00084     {
00085         stackItem->textPosition=2;
00086     }
00087     else if (!strTextPosition.isEmpty())
00088     {
00089         // we have any other new value, assume it means normal!
00090         stackItem->textPosition=0;
00091     }
00092 
00093     QString strColour=abiPropsMap["color"].getValue();
00094     if (!strColour.isEmpty())
00095     {
00096         // The colour information is *not* lead by a hash (#)
00097         stackItem->fgColor.setNamedColor("#"+strColour);
00098    }
00099 
00100     QString strBackgroundTextColor=abiPropsMap["bgcolor"].getValue();
00101     if (strBackgroundTextColor=="transparent")
00102     {
00103         // KWord has no idea what transparency is, so we use white
00104         stackItem->bgColor.setRgb(255,255,255);
00105     }
00106     else if(!strBackgroundTextColor.isEmpty())
00107     {
00108         // The colour information is *not* lead by a hash (#)
00109         stackItem->bgColor.setNamedColor("#"+strBackgroundTextColor);
00110     }
00111 
00112     QString strFontSize=abiPropsMap["font-size"].getValue();
00113     if (!strFontSize.isEmpty())
00114     {
00115         const int size=int(ValueWithLengthUnit(strFontSize));
00116         if (size>0)
00117         {
00118             stackItem->fontSize=size;
00119         }
00120     }
00121 
00122     QString strFontFamily=abiPropsMap["font-family"].getValue();
00123     if (!strFontFamily.isEmpty() && (strFontFamily!="(null)"))
00124     {
00125         // TODO: transform the font-family in a font that we have on the system on which KWord runs.
00126         stackItem->fontName=strFontFamily;
00127     }
00128 }
00129 
00130 void AddFormat(QDomElement& formatElementOut, StackItem* stackItem, QDomDocument& mainDocument)
00131 {
00132     QDomElement element;
00133     if (!stackItem->fontName.isEmpty())
00134     {
00135         element=mainDocument.createElement("FONT");
00136         element.setAttribute("name",stackItem->fontName); // Font name
00137         formatElementOut.appendChild(element); //Append to <FORMAT>
00138     }
00139 
00140     if (stackItem->fontSize>0)
00141     {
00142         element=mainDocument.createElement("SIZE");
00143         element.setAttribute("value",stackItem->fontSize);
00144         formatElementOut.appendChild(element); //Append to <FORMAT>
00145     }
00146 
00147     element=mainDocument.createElement("ITALIC");
00148     element.setAttribute("value",stackItem->italic?1:0);
00149     formatElementOut.appendChild(element); //Append to <FORMAT>
00150 
00151     element=mainDocument.createElement("WEIGHT");
00152     element.setAttribute("value",stackItem->bold?75:50);
00153     formatElementOut.appendChild(element); //Append to <FORMAT>
00154 
00155     element=mainDocument.createElement("UNDERLINE");
00156     element.setAttribute("value",stackItem->underline?1:0);
00157     formatElementOut.appendChild(element); //Append to <FORMAT>
00158 
00159     element=mainDocument.createElement("STRIKEOUT");
00160     element.setAttribute("value",stackItem->strikeout?1:0);
00161     formatElementOut.appendChild(element); //Append to <FORMAT>
00162 
00163     if ((stackItem->textPosition>=0) && (stackItem->textPosition<=2))
00164     {
00165         element=mainDocument.createElement("VERTALIGN");
00166         element.setAttribute("value",stackItem->textPosition);
00167         formatElementOut.appendChild(element); //Append to <FORMAT>
00168     }
00169 
00170     if (stackItem->fgColor.isValid())
00171     {
00172         element=mainDocument.createElement("COLOR");
00173         element.setAttribute("red",  stackItem->fgColor.red());
00174         element.setAttribute("green",stackItem->fgColor.green());
00175         element.setAttribute("blue", stackItem->fgColor.blue());
00176         formatElementOut.appendChild(element); //Append to <FORMAT>
00177     }
00178 
00179     if (stackItem->bgColor.isValid())
00180     {
00181         element=mainDocument.createElement("TEXTBACKGROUNDCOLOR");
00182         element.setAttribute("red",  stackItem->bgColor.red());
00183         element.setAttribute("green",stackItem->bgColor.green());
00184         element.setAttribute("blue", stackItem->bgColor.blue());
00185         formatElementOut.appendChild(element); //Append to <FORMAT>
00186     }
00187 }
00188 
00189 void AddLayout(const QString& strStyleName, QDomElement& layoutElement,
00190     StackItem* stackItem, QDomDocument& mainDocument,
00191     const AbiPropsMap& abiPropsMap, const int level, const bool isStyle)
00192 {
00193     QDomElement element;
00194     element=mainDocument.createElement("NAME");
00195     element.setAttribute("value",strStyleName);
00196     layoutElement.appendChild(element);
00197 
00198     QString strFollowing=abiPropsMap["followedby"].getValue();
00199     QDomElement followingElement=mainDocument.createElement("FOLLOWING");
00200     followingElement.setAttribute("name",strFollowing);
00201     if ((strFollowing.isEmpty())
00202         || (strFollowing=="Current Settings")) // "Current Settings" is only a pseudo-style!
00203     {
00204         // We have no idea what style follows
00205         if (isStyle)
00206         {
00207             // We are a style, so we need a default
00208             followingElement.setAttribute("name","Normal");
00209             layoutElement.appendChild(followingElement);
00210         }
00211         // Else: we are a layout, so we leave the work to KWord (from the style)
00212     }
00213     else
00214     {
00215         // Following style is defined
00216         // TODO: we should be sure that this style is defined!
00217         layoutElement.appendChild(followingElement);
00218     }
00219 
00220     QString strFlow=abiPropsMap["text-align"].getValue();
00221     element=mainDocument.createElement("FLOW");
00222     if ((strFlow=="left") || (strFlow=="center") || (strFlow=="right") || (strFlow=="justify"))
00223     {
00224         element.setAttribute("align",strFlow);
00225     }
00226     else
00227     {
00228         element.setAttribute("align","left");
00229     }
00230     layoutElement.appendChild(element);
00231 
00232     int kwordDepth;
00233     int kwordNumberingType;
00234     int kwordType;
00235     QString kwordRightText;
00236     // level is 1 based like AbiWord, any value lower than 1 means no level!
00237     if ((level<=0) || (level>=15))
00238     {
00239         kwordDepth=0;
00240         kwordNumberingType=2;
00241         kwordType=0;
00242     }
00243     else
00244     {
00245         kwordDepth=level-1;
00246         kwordNumberingType=1;
00247         kwordType=1; // PROVISORY
00248         kwordRightText=".";
00249     }
00250 
00251     element=mainDocument.createElement("COUNTER");
00252     element.setAttribute("type",kwordType);
00253     element.setAttribute("depth",kwordDepth);
00254     element.setAttribute("start",1);
00255     element.setAttribute("numberingtype",kwordNumberingType);
00256     element.setAttribute("lefttext","");
00257     element.setAttribute("righttext",kwordRightText);
00258     element.setAttribute("bullet",64);
00259     element.setAttribute("bulletfont","Symbol");
00260     element.setAttribute("customdef","");
00261     layoutElement.appendChild(element);
00262 
00263     QString strLeftMargin=abiPropsMap["margin-left"].getValue();
00264     QString strRightMargin=abiPropsMap["margin-right"].getValue();
00265     QString strTextIndent=abiPropsMap["text-indent"].getValue();
00266 
00267     if ( !strLeftMargin.isEmpty()
00268         || !strRightMargin.isEmpty()
00269         || !strTextIndent.isEmpty() )
00270     {
00271         element=mainDocument.createElement("INDENTS");
00272         if (!strLeftMargin.isEmpty())
00273             element.setAttribute("left",ValueWithLengthUnit(strLeftMargin));
00274         if (!strRightMargin.isEmpty())
00275             element.setAttribute("right",ValueWithLengthUnit(strRightMargin));
00276         if (!strTextIndent.isEmpty())
00277             element.setAttribute("first",ValueWithLengthUnit(strTextIndent));
00278         layoutElement.appendChild(element);
00279     }
00280 
00281     QString strTopMargin=abiPropsMap["margin-top"].getValue();
00282     QString strBottomMargin=abiPropsMap["margin-bottom"].getValue();
00283     if (!strTopMargin.isEmpty() || !strBottomMargin.isEmpty() )
00284     {
00285         element=mainDocument.createElement("OFFSETS");
00286         const double margin_top=ValueWithLengthUnit(strTopMargin);
00287         const double margin_bottom=ValueWithLengthUnit(strBottomMargin);
00288         // Zero is propably a valid value!
00289         if (!strBottomMargin.isEmpty())
00290             element.setAttribute("after",margin_bottom);
00291         if (!strTopMargin.isEmpty())
00292             element.setAttribute("before",margin_top);
00293         layoutElement.appendChild(element);
00294     }
00295 
00296     QString strLineHeight=abiPropsMap["line-height"].getValue();
00297     if(!strLineHeight.isEmpty())
00298     {
00299         element=mainDocument.createElement("LINESPACING");
00300         double lineHeight;
00301         // Do we have a unit symbol or not?
00302         bool flag=false;
00303         lineHeight=strLineHeight.toDouble(&flag);
00304 
00305         if (flag)
00306         {
00307             if ( lineHeight == 1.0 )
00308             {
00309                 element.setAttribute( "value", "single" );
00310                 element.setAttribute( "type", "single" );
00311             }
00312             else if (lineHeight==1.5)
00313             {
00314                 element.setAttribute( "value", "oneandhalf" );
00315                 element.setAttribute( "type", "oneandhalf" );
00316             }
00317             else if (lineHeight==2.0)
00318             {
00319                 element.setAttribute( "value", "double" );
00320                 element.setAttribute( "type", "double" );
00321             }
00322             else if ( lineHeight > 0.0 )
00323             {
00324                 element.setAttribute( "type", "multiple" );
00325                 element.setAttribute( "spacingvalue", lineHeight );
00326             }
00327             else
00328             {
00329                 kdWarning(30506) << "Unsupported line height " << lineHeight << " (Ignoring !)" << endl;
00330             }
00331         }
00332         else
00333         {
00334             // Something went wrong, so we assume that an unit is specified
00335             bool atleast = false;
00336             lineHeight = ValueWithLengthUnit( strLineHeight, &atleast );
00337             if (lineHeight>1.0)
00338             {
00339                 if ( atleast )
00340                 {
00341                     kdDebug(30506) << "at-least" << endl;
00342                     element.setAttribute( "type", "atleast" );
00343                 }
00344                 else
00345                 {
00346                     element.setAttribute( "type", "exact" );
00347                 }
00348 
00349                 // We have a meaningful value, so use it!
00350                 //element.setAttribute( "value", lineHeight );
00351                 element.setAttribute( "spacingvalue", lineHeight );
00352             }
00353         }
00354         layoutElement.appendChild(element);
00355     }
00356 
00357     QString strTab=abiPropsMap["tabstops"].getValue();
00358     if(!strTab.isEmpty())
00359     {
00360         QStringList listTab=QStringList::split(",",strTab);
00361         for ( QStringList::Iterator it = listTab.begin(); it != listTab.end(); ++it )
00362         {
00363             QStringList tab=QStringList::split("/",*it);
00364             const QChar tabType=tab[1].at(0);
00365             const QChar tabFilling=tab[1].at(1); // Might be empty in old AbiWord files
00366             int type;
00367             if (tabType=='L') // left
00368                 type=0;
00369             else if (tabType=='C') // center
00370                 type=1;
00371             else if (tabType=='R') // right
00372                 type=2;
00373             else if(tabType=='D') // decimal
00374                 type=3;
00375             else if(tabType=='B') // bar (unsupported by KWord)
00376                 type=0;
00377             else
00378             {
00379                 kdWarning(30506)<<"Unknown tabulator type: " << QString(tabType) << endl;
00380                 type=0;
00381             }
00382             int filling;
00383             int width=72; // Any non-null value
00384             if (tabFilling.isNull() || tabFilling=='0') // No filling
00385                 filling=0;
00386             else if (tabFilling=='1') // dot
00387             {
00388                 filling=1;
00389                 width=2;    // TODO: which width?
00390             }
00391             else if (tabFilling=='3') // underline
00392                 filling=2;
00393             else
00394                 filling=0;
00395             element=mainDocument.createElement("TABULATOR");
00396             element.setAttribute("ptpos",ValueWithLengthUnit(tab[0]));
00397             element.setAttribute("type",type);
00398             element.setAttribute("filling",filling);
00399             element.setAttribute("width",width);
00400             layoutElement.appendChild(element);
00401         }
00402     }
00403 
00404     QDomElement formatElementOut=mainDocument.createElement("FORMAT");
00405     layoutElement.appendChild(formatElementOut);
00406 
00407     AddFormat(formatElementOut, stackItem, mainDocument);
00408 }
00409 
00410 void AddStyle(QDomElement& styleElement, const QString& strStyleName,
00411     const StyleData& styleData, QDomDocument& mainDocument)
00412 {
00413     // NOTE; styleElement is <STYLE> (singular), not <STYLES> (plural)
00414 
00415     StackItem stackItem;
00416     QXmlAttributes attributes; // This is just a dummy for reusing already existing functions (TODO)
00417     AbiPropsMap abiPropsMap;
00418 
00419     PopulateProperties(&stackItem, styleData.m_props, attributes, abiPropsMap, false);
00420     AddLayout(strStyleName, styleElement, &stackItem, mainDocument, abiPropsMap, styleData.m_level, true);
00421 }
KDE Home | KDE Accessibility Home | Description of Access Keys