Warning, file /office/calligra/filters/sheets/gnumeric/gnumericexport.cc was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002    Copyright (C) 2000 David Faure <faure@kde.org>
0003    Copyright (C) 2005 Laurent Montel <montel@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 /* Gnumeric export filter by Phillip Ezolt (phillipezolt@hotmail.com)
0022    2004 - Some updates by Tim Beaulen (tbscope@gmail.com) */
0023 
0024 #include <gnumericexport.h>
0025 #include <kdebug.h>
0026 #include <KCompressionDevice>
0027 #include <kpluginfactory.h>
0028 #include <klocale.h>
0029 #include <KoFilterChain.h>
0030 #include <KoZoomHandler.h>
0031 #include <QApplication>
0032 #include <QList>
0033 #include <QFile>
0034 #include <QTextStream>
0035 #include <QPen>
0036 #include <QByteArray>
0037 
0038 // Calligra
0039 #include <KoDocumentInfo.h>
0040 #include <KoUnit.h>
0041 
0042 // Calligra::Sheets
0043 #include <sheets/ApplicationSettings.h>
0044 #include <sheets/part/Canvas.h>
0045 #include <sheets/CellStorage.h>
0046 #include <sheets/Currency.h>
0047 #include <sheets/part/Doc.h>
0048 #include <sheets/HeaderFooter.h>
0049 #include <sheets/Map.h>
0050 #include <sheets/NamedAreaManager.h>
0051 #include <sheets/PrintSettings.h>
0052 #include <sheets/Sheet.h>
0053 #include <sheets/RowColumnFormat.h>
0054 #include <sheets/RowFormatStorage.h>
0055 #include <sheets/Validity.h>
0056 #include <sheets/ValueConverter.h>
0057 #include <sheets/part/View.h>
0058 
0059 using namespace Calligra::Sheets;
0060 
0061 K_PLUGIN_FACTORY_WITH_JSON(GNUMERICExportFactory, "calligra_filter_sheets2gnumeric.json",
0062                            registerPlugin<GNUMERICExport>();)
0063 
0064 GNUMERICExport::GNUMERICExport(QObject* parent, const QVariantList&)
0065         : KoFilter(parent)
0066 {
0067     isLink = false;
0068     isLinkBold = false;
0069     isLinkItalic = false;
0070 }
0071 
0072 /**
0073  * This function will check if a cell has any type of border.
0074  */
0075 bool GNUMERICExport::hasBorder(const Cell& cell, int currentcolumn, int currentrow)
0076 {
0077     Q_UNUSED(currentcolumn);
0078     Q_UNUSED(currentrow);
0079     const Style style = cell.style();
0080     if (((style.leftBorderPen().width() != 0) &&
0081             (style.leftBorderPen().style() != Qt::NoPen)) ||
0082             ((style.rightBorderPen().width() != 0) &&
0083              (style.rightBorderPen().style() != Qt::NoPen)) ||
0084             ((style.topBorderPen().width() != 0) &&
0085              (style.topBorderPen().style() != Qt::NoPen)) ||
0086             ((style.bottomBorderPen().width() != 0) &&
0087              (style.bottomBorderPen().style() != Qt::NoPen)) ||
0088             ((style.fallDiagonalPen().width() != 0) &&
0089              (style.fallDiagonalPen().style() != Qt::NoPen)) ||
0090             ((style.goUpDiagonalPen().width() != 0) &&
0091              (style.goUpDiagonalPen().style() != Qt::NoPen)))
0092         return true;
0093     else
0094         return false;
0095 }
0096 
0097 const QString GNUMERICExport::ColorToString(int red, int green, int blue)
0098 {
0099     return QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16);
0100 }
0101 
0102 QDomElement GNUMERICExport::GetBorderStyle(QDomDocument gnumeric_doc, const Cell& cell, int currentcolumn, int currentrow)
0103 {
0104     Q_UNUSED(currentcolumn);
0105     Q_UNUSED(currentrow);
0106 
0107     QDomElement border_style;
0108     QDomElement border;
0109 
0110     int red, green, blue;
0111     QColor color;
0112 
0113     border_style = gnumeric_doc.createElement("gmr:StyleBorder");
0114     const Style style = cell.style();
0115 
0116     if ((style.leftBorderPen().width() != 0) &&
0117             (style.leftBorderPen().style() != Qt::NoPen)) {
0118         border = gnumeric_doc.createElement("gmr:Left");
0119         border.setAttribute("Style", "1");
0120 
0121         color =  style.leftBorderPen().color();
0122         red = color.red() << 8;
0123         green = color.green() << 8;
0124         blue = color.blue() << 8;
0125 
0126         border.setAttribute("Color", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0127     } else {
0128         border = gnumeric_doc.createElement("gmr:Left");
0129         border.setAttribute("Style", "0");
0130     }
0131 
0132     border_style.appendChild(border);
0133 
0134     if ((style.rightBorderPen().width() != 0) &&
0135             (style.rightBorderPen().style() != Qt::NoPen)) {
0136         border = gnumeric_doc.createElement("gmr:Right");
0137         border.setAttribute("Style", "1");
0138 
0139         color =  style.rightBorderPen().color();
0140         red = color.red() << 8;
0141         green = color.green() << 8;
0142         blue = color.blue() << 8;
0143 
0144         border.setAttribute("Color", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0145     } else {
0146         border = gnumeric_doc.createElement("gmr:Right");
0147         border.setAttribute("Style", "0");
0148     }
0149 
0150     border_style.appendChild(border);
0151 
0152     if ((style.topBorderPen().width() != 0) &&
0153             (style.topBorderPen().style() != Qt::NoPen)) {
0154         border = gnumeric_doc.createElement("gmr:Top");
0155         border.setAttribute("Style", "1");
0156 
0157         color =  style.topBorderPen().color();
0158         red = color.red() << 8;
0159         green = color.green() << 8;
0160         blue = color.blue() << 8;
0161 
0162         border.setAttribute("Color", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0163     } else {
0164         border = gnumeric_doc.createElement("gmr:Top");
0165         border.setAttribute("Style", "0");
0166     }
0167 
0168     border_style.appendChild(border);
0169 
0170     if ((style.bottomBorderPen().width() != 0) &&
0171             (style.bottomBorderPen().style() != Qt::NoPen)) {
0172         border = gnumeric_doc.createElement("gmr:Bottom");
0173         border.setAttribute("Style", "1");
0174 
0175         color =  style.bottomBorderPen().color();
0176         red = color.red() << 8;
0177         green = color.green() << 8;
0178         blue = color.blue() << 8;
0179 
0180         border.setAttribute("Color", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0181     } else {
0182         border = gnumeric_doc.createElement("gmr:Bottom");
0183         border.setAttribute("Style", "0");
0184     }
0185 
0186     border_style.appendChild(border);
0187 
0188     if ((style.fallDiagonalPen().width() != 0) &&
0189             (style.fallDiagonalPen().style() != Qt::NoPen)) {
0190         border = gnumeric_doc.createElement("gmr:Diagonal");
0191         border.setAttribute("Style", "1");
0192 
0193         color =  style.fallDiagonalPen().color();
0194         red = color.red() << 8;
0195         green = color.green() << 8;
0196         blue = color.blue() << 8;
0197 
0198         border.setAttribute("Color", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0199     } else {
0200         border = gnumeric_doc.createElement("gmr:Diagonal");
0201         border.setAttribute("Style", "0");
0202     }
0203 
0204     border_style.appendChild(border);
0205 
0206     if ((style.goUpDiagonalPen().width() != 0) &&
0207             (style.goUpDiagonalPen().style() != Qt::NoPen)) {
0208         border = gnumeric_doc.createElement("gmr:Rev-Diagonal");
0209         border.setAttribute("Style", "1");
0210 
0211         color =  style.goUpDiagonalPen().color();
0212         red = color.red() << 8;
0213         green = color.green() << 8;
0214         blue = color.blue() << 8;
0215 
0216         border.setAttribute("Color", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0217     } else {
0218         border = gnumeric_doc.createElement("gmr:Rev-Diagonal");
0219         border.setAttribute("Style", "0");
0220     }
0221 
0222     border_style.appendChild(border);
0223 
0224     return border_style;
0225 }
0226 
0227 QDomElement GNUMERICExport::GetValidity(QDomDocument gnumeric_doc, const Cell& cell)
0228 {
0229     ValueConverter *const converter = cell.sheet()->map()->converter();
0230 
0231     //<gmr:Validation Style="1" Type="1" Operator="7" AllowBlank="true" UseDropdown="false" Title="ghhg" Message="ghghhhjfhfghjfghj&#10;fg&#10;hjgf&#10;hj">
0232     //        <gmr:Expression0>45</gmr:Expression0>
0233     //      </gmr:Validation>
0234     Validity kspread_validity = cell.validity();
0235     QDomElement val = gnumeric_doc.createElement("gmr:Validation");
0236     val.setAttribute("Title", kspread_validity.title());
0237     val.setAttribute("Message", kspread_validity.message());
0238     val.setAttribute("AllowBlank", kspread_validity.allowEmptyCell() ? "true" : "false");
0239     if (!kspread_validity.displayMessage()) {
0240         val.setAttribute("Style", "0");
0241     } else {
0242         switch (kspread_validity.action()) {
0243         case Validity::Stop:
0244             val.setAttribute("Style", "1");
0245             break;
0246         case Validity::Warning:
0247             val.setAttribute("Style", "2");
0248             break;
0249         case Validity::Information:
0250             val.setAttribute("Style", "3");
0251             break;
0252         }
0253     }
0254 
0255     switch (kspread_validity.condition()) {
0256     case Conditional::None:
0257     case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0258         //Nothing
0259         break;
0260     case Conditional::Equal:
0261         val.setAttribute("Operator", "2");
0262         break;
0263     case Conditional::Superior:
0264         val.setAttribute("Operator", "4");
0265         break;
0266     case Conditional::Inferior:
0267         val.setAttribute("Operator", "5");
0268         break;
0269     case Conditional::SuperiorEqual:
0270         val.setAttribute("Operator", "6");
0271         break;
0272     case Conditional::InferiorEqual:
0273         val.setAttribute("Operator", "7");
0274         break;
0275     case Conditional::Between:
0276         val.setAttribute("Operator", "0");
0277         break;
0278     case Conditional::Different:
0279         val.setAttribute("Operator", "3");
0280         break;
0281     case Conditional::DifferentTo:
0282         val.setAttribute("Operator", "1");
0283         break;
0284     }
0285     switch (kspread_validity.restriction()) {
0286     case Validity::None:
0287         val.setAttribute("Type", "0");
0288         break;
0289     case Validity::Number: {
0290         val.setAttribute("Type", "2");
0291         switch (kspread_validity.condition()) {
0292         case Conditional::None:
0293         case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0294             //Nothing
0295             break;
0296         case Conditional::Equal:
0297         case Conditional::Superior:
0298         case Conditional::Inferior:
0299         case Conditional::SuperiorEqual:
0300         case Conditional::InferiorEqual:
0301         case Conditional::Different: {
0302             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0303             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0304             val.appendChild(tmp);
0305         }
0306         break;
0307         case Conditional::Between:
0308         case Conditional::DifferentTo: {
0309             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0310             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0311             val.appendChild(tmp);
0312             tmp = gnumeric_doc.createElement("gmr:Expression1");
0313             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.maximumValue()).asString()));
0314             val.appendChild(tmp);
0315         }
0316         break;
0317         }
0318 
0319         break;
0320     }
0321     case Validity::Text:
0322         //Not supported into gnumeric
0323         //val.setAttribute("Type", "1" );
0324         break;
0325     case Validity::Time:
0326         val.setAttribute("Type", "5");
0327         switch (kspread_validity.condition()) {
0328         case Conditional::None:
0329         case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0330             //Nothing
0331             break;
0332         case Conditional::Equal:
0333         case Conditional::Superior:
0334         case Conditional::Inferior:
0335         case Conditional::SuperiorEqual:
0336         case Conditional::InferiorEqual:
0337         case Conditional::Different: {
0338             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0339             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0340             val.appendChild(tmp);
0341         }
0342         break;
0343         case Conditional::Between:
0344         case Conditional::DifferentTo: {
0345             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0346             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0347             val.appendChild(tmp);
0348             tmp = gnumeric_doc.createElement("gmr:Expression1");
0349             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.maximumValue()).asString()));
0350             val.appendChild(tmp);
0351         }
0352         break;
0353         }
0354 
0355         break;
0356     case Validity::Date:
0357         val.setAttribute("Type", "4");
0358         switch (kspread_validity.condition()) {
0359         case Conditional::None:
0360         case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0361             //Nothing
0362             break;
0363         case Conditional::Equal:
0364         case Conditional::Superior:
0365         case Conditional::Inferior:
0366         case Conditional::SuperiorEqual:
0367         case Conditional::InferiorEqual:
0368         case Conditional::Different: {
0369             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0370             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0371             val.appendChild(tmp);
0372         }
0373         break;
0374         case Conditional::Between:
0375         case Conditional::DifferentTo: {
0376             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0377             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0378             val.appendChild(tmp);
0379             tmp = gnumeric_doc.createElement("gmr:Expression1");
0380             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.maximumValue()).asString()));
0381             val.appendChild(tmp);
0382         }
0383         break;
0384         }
0385 
0386         break;
0387     case Validity::Integer:
0388         val.setAttribute("Type", "1");
0389         switch (kspread_validity.condition()) {
0390         case Conditional::None:
0391         case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0392             //Nothing
0393             break;
0394         case Conditional::Equal:
0395         case Conditional::Superior:
0396         case Conditional::Inferior:
0397         case Conditional::SuperiorEqual:
0398         case Conditional::InferiorEqual:
0399         case Conditional::Different: {
0400             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0401             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0402             val.appendChild(tmp);
0403         }
0404         break;
0405         case Conditional::Between:
0406         case Conditional::DifferentTo: {
0407             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0408             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0409             val.appendChild(tmp);
0410             tmp = gnumeric_doc.createElement("gmr:Expression1");
0411             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.maximumValue()).asString()));
0412             val.appendChild(tmp);
0413         }
0414         break;
0415         }
0416         break;
0417     case Validity::TextLength:
0418         val.setAttribute("Type", "6");
0419         switch (kspread_validity.condition()) {
0420         case Conditional::None:
0421         case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0422             //Nothing
0423             break;
0424         case Conditional::Equal:
0425         case Conditional::Superior:
0426         case Conditional::Inferior:
0427         case Conditional::SuperiorEqual:
0428         case Conditional::InferiorEqual:
0429         case Conditional::Different: {
0430             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0431             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0432             val.appendChild(tmp);
0433         }
0434         break;
0435         case Conditional::Between:
0436         case Conditional::DifferentTo: {
0437             QDomElement tmp = gnumeric_doc.createElement("gmr:Expression0");
0438             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.minimumValue()).asString()));
0439             val.appendChild(tmp);
0440             tmp = gnumeric_doc.createElement("gmr:Expression1");
0441             tmp.appendChild(gnumeric_doc.createTextNode(converter->asString(kspread_validity.maximumValue()).asString()));
0442             val.appendChild(tmp);
0443         }
0444         break;
0445         }
0446         break;
0447     case Validity::List:
0448         val.setAttribute("Type", "3");
0449         switch (kspread_validity.condition()) {
0450         case Conditional::None:
0451         case Conditional::IsTrueFormula: // FIXME: handle isTrueFormula
0452             //Nothing
0453             break;
0454         case Conditional::Equal:
0455         case Conditional::Superior:
0456         case Conditional::Inferior:
0457         case Conditional::SuperiorEqual:
0458         case Conditional::InferiorEqual:
0459         case Conditional::Different:
0460             break;
0461         case Conditional::Between:
0462         case Conditional::DifferentTo:
0463             break;
0464         }
0465         break;
0466     }
0467 
0468     return val;
0469 }
0470 
0471 QDomElement GNUMERICExport::GetFontStyle(QDomDocument gnumeric_doc, const Cell& cell, int currentcolumn, int currentrow)
0472 {
0473     QDomElement font_style;
0474     const Style style = cell.style();
0475     kDebug(30521) << " currentcolumn :" << currentcolumn << " currentrow :" << currentrow;
0476     font_style = gnumeric_doc.createElement("gmr:Font");
0477     font_style.appendChild(gnumeric_doc.createTextNode(style.fontFamily()));
0478 
0479     if (style.italic() || (isLink && isLinkItalic)) {
0480         font_style.setAttribute("Italic", "1");
0481     }
0482     if (style.bold() || (isLink && isLinkBold)) {
0483         font_style.setAttribute("Bold", "1");
0484     }
0485     if (style.underline()) {
0486         font_style.setAttribute("Underline", "1");
0487     }
0488     if (style.strikeOut()) {
0489         font_style.setAttribute("StrikeThrough", "1");
0490     }
0491     if (style.fontSize()) {
0492         font_style.setAttribute("Unit", QString::number(style.fontSize()));
0493     }
0494 
0495     return font_style;
0496 }
0497 
0498 QDomElement GNUMERICExport::GetLinkStyle(QDomDocument gnumeric_doc)
0499 {
0500     QDomElement link_style;
0501 
0502     link_style = gnumeric_doc.createElement("gmr:HyperLink");
0503 
0504     QString path;
0505 
0506     path = linkUrl;
0507 
0508     if (path.section(":", 0, 0).toLower() == "http")
0509         link_style.setAttribute("type", "GnmHLinkURL");
0510     else if (path.section(":", 0, 0).toLower() == "mailto")
0511         link_style.setAttribute("type", "GnmHLinkEMail");
0512     else if (path.section(":", 0, 0).toLower() == "file")
0513         link_style.setAttribute("type", "GnmHLinkExternal");
0514     else if (path.left(5).toLower() == "sheet")
0515         link_style.setAttribute("type", "GnmHLinkCurWB");
0516     else
0517         link_style.setAttribute("type", "");
0518 
0519     link_style.setAttribute("target", path);
0520 
0521     // Calligra Sheets doesn't support link tips.
0522     link_style.setAttribute("tip", "");
0523 
0524     return link_style;
0525 }
0526 
0527 QDomElement GNUMERICExport::GetCellStyle(QDomDocument gnumeric_doc, const Cell& cell, int currentcolumn, int currentrow)
0528 {
0529     QDomElement cell_style;
0530 
0531     cell_style = gnumeric_doc.createElement("gmr:Style");
0532 
0533     int red, green, blue;
0534 
0535     const Style style = cell.style();
0536     QColor bgColor =  style.backgroundColor();
0537     if (bgColor.isValid()) {
0538         red = bgColor.red() << 8;
0539         green = bgColor.green() << 8;
0540         blue = bgColor.blue() << 8;
0541     } else {
0542         // Let's use white default for background
0543         red = 0xffff;
0544         green = 0xffff;
0545         blue = 0xffff;
0546     }
0547 
0548     switch (style.backgroundBrush().style()) {
0549     case Qt::NoBrush:
0550         cell_style.setAttribute("Shade", "0");
0551         break;
0552     case Qt::SolidPattern:
0553         // 100%
0554         cell_style.setAttribute("Shade", "1");
0555         break;
0556     case Qt::Dense1Pattern:
0557         // 87.5%
0558         cell_style.setAttribute("Shade", "25");
0559         break;
0560     case Qt::Dense2Pattern:
0561         // 75%
0562         cell_style.setAttribute("Shade", "2");
0563         break;
0564     case Qt::Dense3Pattern:
0565         // 62.5%
0566         // Not supported by GNumeric
0567         // Fall back to 50%
0568         cell_style.setAttribute("Shade", "3");
0569         break;
0570     case Qt::Dense4Pattern:
0571         // 50%
0572         cell_style.setAttribute("Shade", "3");
0573         break;
0574     case Qt::Dense5Pattern:
0575         // 25%
0576         cell_style.setAttribute("Shade", "4");
0577         break;
0578     case Qt::Dense6Pattern:
0579         // 12.5%
0580         cell_style.setAttribute("Shade", "5");
0581         break;
0582     case Qt::Dense7Pattern:
0583         // 6.25%
0584         cell_style.setAttribute("Shade", "6");
0585         break;
0586     case Qt::HorPattern:
0587         cell_style.setAttribute("Shade", "13");
0588         break;
0589     case Qt::VerPattern:
0590         cell_style.setAttribute("Shade", "14");
0591         break;
0592     case Qt::CrossPattern:
0593         cell_style.setAttribute("Shade", "17");
0594         break;
0595     case Qt::BDiagPattern:
0596         cell_style.setAttribute("Shade", "16");
0597         break;
0598     case Qt::FDiagPattern:
0599         cell_style.setAttribute("Shade", "15");
0600         break;
0601     case Qt::DiagCrossPattern:
0602         cell_style.setAttribute("Shade", "18");
0603         break;
0604     case Qt::TexturePattern:
0605     default:
0606         // Not supported by Gnumeric
0607         cell_style.setAttribute("Shade", "0");
0608         break;
0609     }
0610 
0611     cell_style.setAttribute("Back", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0612 
0613 
0614     QColor textColor =  style.fontColor();
0615     red = textColor.red() << 8;
0616     green = textColor.green() << 8;
0617     blue = textColor.blue() << 8;
0618 
0619     cell_style.setAttribute("Fore", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0620 
0621     if (style.halign() ==  Style::HAlignUndefined) {
0622         cell_style.setAttribute("HAlign", "1");
0623     } else if (style.halign() ==  Style::Left) {
0624         cell_style.setAttribute("HAlign", "2");
0625     } else if (style.halign() ==  Style::Right) {
0626         cell_style.setAttribute("HAlign", "4");
0627     } else if (style.halign() ==  Style::Center) {
0628         cell_style.setAttribute("HAlign", "8");
0629     }
0630 
0631     if (style.valign() ==  Style::Top) {
0632         cell_style.setAttribute("VAlign", "1");
0633     } else if (style.valign() ==  Style::Bottom) {
0634         cell_style.setAttribute("VAlign", "2");
0635     } else if (style.valign() ==  Style::Middle) {
0636         cell_style.setAttribute("VAlign", "4");
0637     }
0638 
0639     if (style.wrapText())
0640         cell_style.setAttribute("WrapText", "1");
0641     else
0642         cell_style.setAttribute("WrapText", "0");
0643 
0644     // ShrinkToFit not supported by Calligra Sheets (?)
0645     cell_style.setAttribute("ShrinkToFit", "0");
0646 
0647     // I'm not sure about the rotation values.
0648     // I never got it to work in GNumeric.
0649     cell_style.setAttribute("Rotation", QString::number(-1*style.angle()));
0650 
0651     // The indentation in GNumeric is an integer value. In Calligra Sheets, it's a double.
0652     // Save the double anyway, makes it even better when importing the document back in Calligra Sheets.
0653     // TODO verify if it's correct, in import we "* 10.0"
0654     cell_style.setAttribute("Indent", QString::number(style.indentation()));
0655 
0656     cell_style.setAttribute("Locked", QString::number(!style.notProtected()));
0657 
0658     // A Calligra Sheets cell can have two options to hide: only formula hidden, or everything hidden.
0659     // I only consider a cell with everything hidden as hidden.
0660     // Gnumeric hides everything or nothing.
0661     cell_style.setAttribute("Hidden", QString::number(style.hideAll()));
0662 
0663     QColor patColor =  style.backgroundBrush().color();
0664     red = patColor.red() << 8;
0665     green = patColor.green() << 8;
0666     blue = patColor.blue() << 8;
0667 
0668     cell_style.setAttribute("PatternColor", QString::number(red, 16) + ':' + QString::number(green, 16) + ':' + QString::number(blue, 16));
0669 
0670     if (isLink)
0671         cell_style.appendChild(GetLinkStyle(gnumeric_doc));
0672 
0673     cell_style.appendChild(GetFontStyle(gnumeric_doc, cell, currentcolumn, currentrow));
0674 
0675     if (!cell.validity().isEmpty()) {
0676         cell_style.appendChild(GetValidity(gnumeric_doc, cell));
0677     }
0678 
0679     QString stringFormat;
0680 
0681     Currency currency;
0682 
0683     switch (style.formatType()) {
0684     case Format::Generic:
0685         stringFormat = "General";
0686         break;
0687     case Format::Number:
0688         stringFormat = "0.00";
0689         break;
0690     case Format::Text:
0691         stringFormat = "General";
0692         break;
0693     case Format::Money:
0694 
0695         if (!style.hasAttribute(Style::CurrencyFormat)) {
0696             stringFormat = "0.00";
0697             break;
0698         }
0699         currency = style.currency();
0700 
0701         if (currency.code().isEmpty())
0702             stringFormat = "0.00";
0703         else if (currency.code() == "$")
0704             stringFormat = "$0.00";
0705         else if (currency.code() == QString::fromUtf8("€"))
0706             stringFormat = "[$€-2]0.00";
0707         else if (currency.code() == QString::fromUtf8("£"))
0708             stringFormat = "£0.00";
0709         else if (currency.code() == QString::fromUtf8("Â¥"))
0710             stringFormat = "Â¥0.00";
0711         else
0712             stringFormat = "[$" + currency.code() + "]0.00";
0713 
0714         break;
0715     case Format::Percentage:
0716         stringFormat = "0.00%";
0717         break;
0718     case Format::Scientific:
0719         stringFormat = "0.00E+00";
0720         break;
0721     case Format::ShortDate:
0722         stringFormat = cell.locale()->dateFormatShort();
0723         break;
0724     case Format::TextDate:
0725         stringFormat = cell.locale()->dateFormat();
0726         break;
0727     case Format::Date1:
0728         stringFormat = "dd-mmm-yy";
0729         break;
0730     case Format::Date2:
0731         stringFormat = "dd-mmm-yyyy";
0732         break;
0733     case Format::Date3:
0734         stringFormat = "dd-mmm";
0735         break;
0736     case Format::Date4:
0737         stringFormat = "dd-mm";
0738         break;
0739     case Format::Date5:
0740         stringFormat = "dd/mm/yy";
0741         break;
0742     case Format::Date6:
0743         stringFormat = "dd/mm/yyyy";
0744         break;
0745     case Format::Date7:
0746         stringFormat = "mmm-yy";
0747         break;
0748     case Format::Date8:
0749         stringFormat = "mmmm-yy";
0750         break;
0751     case Format::Date9:
0752         stringFormat = "mmmm-yyyy";
0753         break;
0754     case Format::Date10:
0755         stringFormat = "m-yy";
0756         break;
0757     case Format::Date11:
0758         stringFormat = "dd/mmm";
0759         break;
0760     case Format::Date12:
0761         stringFormat = "dd/mm";
0762         break;
0763     case Format::Date13:
0764         stringFormat = "dd/mmm/yyyy";
0765         break;
0766     case Format::Date14:
0767         stringFormat = "yyyy/mmm/dd";
0768         break;
0769     case Format::Date15:
0770         stringFormat = "yyyy-mmm-dd";
0771         break;
0772     case Format::Date16:
0773         stringFormat = "yyyy-mm-dd";
0774         break;
0775     case Format::Date17:
0776         stringFormat = "d mmmm yyyy";
0777         break;
0778     case Format::Date18:
0779         stringFormat = "mm/dd/yyyy";
0780         break;
0781     case Format::Date19:
0782         stringFormat = "mm/dd/yy";
0783         break;
0784     case Format::Date20:
0785         stringFormat = "mmm/dd/yy";
0786         break;
0787     case Format::Date21:
0788         stringFormat = "mmm/dd/yyyy";
0789         break;
0790     case Format::Date22:
0791         stringFormat = "mmm-yyyy";
0792         break;
0793     case Format::Date23:
0794         stringFormat = "yyyy";
0795         break;
0796     case Format::Date24:
0797         stringFormat = "yy";
0798         break;
0799     case Format::Date25:
0800         stringFormat = "yyyy/mm/dd";
0801         break;
0802     case Format::Date26:
0803         stringFormat = "yyyy/mmm/dd";
0804         break;
0805     case Format::Time:
0806     case Format::SecondeTime:
0807         stringFormat = cell.locale()->timeFormat();
0808         break;
0809     case Format::Time1:
0810         stringFormat = "h:mm AM/PM";
0811         break;
0812     case Format::Time2:
0813         stringFormat = "h:mm:ss AM/PM";
0814         break;
0815     case Format::Time3:
0816         stringFormat = "h \"h\" mm \"min\" ss \"s\"";
0817         break;
0818     case Format::Time4:
0819         stringFormat = "h:mm";
0820         break;
0821     case Format::Time5:
0822         stringFormat = "h:mm:ss";
0823         break;
0824     case Format::Time6:
0825         stringFormat = "mm:ss";
0826         break;
0827     case Format::Time7:
0828         stringFormat = "[h]:mm:ss";
0829         break;
0830     case Format::Time8:
0831         stringFormat = "[h]:mm";
0832         break;
0833     case Format::fraction_half:
0834         stringFormat = "# ?/2";
0835         break;
0836     case Format::fraction_quarter:
0837         stringFormat = "# ?/4";
0838         break;
0839     case Format::fraction_eighth:
0840         stringFormat = "# ?/8";
0841         break;
0842     case Format::fraction_sixteenth:
0843         stringFormat = "# ?/16";
0844         break;
0845     case Format::fraction_tenth:
0846         stringFormat = "# ?/10";
0847         break;
0848     case Format::fraction_hundredth:
0849         stringFormat = "# ?/100";
0850         break;
0851     case Format::fraction_one_digit:
0852         stringFormat = "# ?/?";
0853         break;
0854     case Format::fraction_two_digits:
0855         stringFormat = "# ?\?/?\?";
0856         break;
0857     case Format::fraction_three_digits:
0858         stringFormat = "# ?\?\?/?\?\?";
0859         break;
0860     case Format::Custom:
0861         stringFormat = style.customFormat();
0862         break;
0863     default:
0864         // This is a required parameter, so let's write a sane default
0865         kWarning(30521) << "Unhandled Format value, setting 'General' as default: " << style.formatType();
0866         stringFormat = "General";
0867         break;
0868     }
0869     cell_style.setAttribute("Format", stringFormat);
0870 
0871     if (hasBorder(cell, currentcolumn, currentrow))
0872         cell_style.appendChild(GetBorderStyle(gnumeric_doc, cell, currentcolumn, currentrow));
0873 
0874     return cell_style;
0875 }
0876 
0877 
0878 void GNUMERICExport::addAttributeItem(QDomDocument gnumeric_doc, QDomElement attributes, const QString& type, const QString& name, bool value)
0879 {
0880     QDomElement gmr_attribute, gmr_type, gmr_name, gmr_value;
0881 
0882     gmr_attribute = gnumeric_doc.createElement("gmr:Attribute");
0883     attributes.appendChild(gmr_attribute);
0884 
0885     gmr_type = gnumeric_doc.createElement("gmr:type");
0886     gmr_type.appendChild(gnumeric_doc.createTextNode(type));
0887     gmr_attribute.appendChild(gmr_type);
0888 
0889     gmr_name = gnumeric_doc.createElement("gmr:name");
0890     gmr_name.appendChild(gnumeric_doc.createTextNode(name));
0891     gmr_attribute.appendChild(gmr_name);
0892 
0893     QString txtValue;
0894     if (value)
0895         txtValue = "true";
0896     else
0897         txtValue = "false";
0898 
0899     gmr_value = gnumeric_doc.createElement("gmr:value");
0900     gmr_value.appendChild(gnumeric_doc.createTextNode(txtValue));
0901     gmr_attribute.appendChild(gmr_value);
0902 }
0903 
0904 void GNUMERICExport::addSummaryItem(QDomDocument gnumeric_doc, QDomElement summary, const QString& name, const QString& value)
0905 {
0906     if (value.isEmpty())
0907         return;
0908     QDomElement gmr_item, gmr_name, gmr_val_string;
0909 
0910     gmr_item = gnumeric_doc.createElement("gmr:Item");
0911     summary.appendChild(gmr_item);
0912 
0913     gmr_name = gnumeric_doc.createElement("gmr:name");
0914     gmr_name.appendChild(gnumeric_doc.createTextNode(name));
0915     gmr_item.appendChild(gmr_name);
0916 
0917     gmr_val_string = gnumeric_doc.createElement("gmr:val-string");
0918     gmr_val_string.appendChild(gnumeric_doc.createTextNode(value));
0919     gmr_item.appendChild(gmr_val_string);
0920 }
0921 
0922 // The reason why we use the KoDocument* approach and not the QDomDocument
0923 // approach is because we don't want to export formulas but values !
0924 KoFilter::ConversionStatus GNUMERICExport::convert(const QByteArray& from, const QByteArray& to)
0925 {
0926     kDebug(30521) << "Exporting GNUmeric";
0927 
0928     QDomDocument gnumeric_doc = QDomDocument();
0929 
0930     KoDocument* document = m_chain->inputDocument();
0931 
0932     if (!document)
0933         return KoFilter::StupidError;
0934 
0935     if (!qobject_cast<const Calligra::Sheets::Doc *>(document)) {    // it's safer that way :)
0936         kWarning(30521) << "document isn't a Calligra::Sheets::Doc but a " << document->metaObject()->className();
0937         return KoFilter::NotImplemented;
0938     }
0939     if (to != "application/x-gnumeric" || from != "application/x-kspread") {
0940         kWarning(30521) << "Invalid mimetypes " << to << " " << from;
0941         return KoFilter::NotImplemented;
0942     }
0943 
0944     Doc* ksdoc = (Doc*)document;
0945 
0946     if (ksdoc->mimeType() != "application/x-kspread") {
0947         kWarning(30521) << "Invalid document mimetype " << ksdoc->mimeType();
0948         return KoFilter::NotImplemented;
0949     }
0950 
0951     /* This could be Made into a function */
0952 
0953     gnumeric_doc.appendChild(gnumeric_doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
0954 
0955     QDomElement workbook = gnumeric_doc.createElement("gmr:Workbook");
0956     workbook.setAttribute("xmlns:gmr", "http://www.gnumeric.org/v10.dtd");
0957     workbook.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
0958     workbook.setAttribute("xmlns:schemaLocation", "http://www.gnumeric.org/v8.xsd");
0959     gnumeric_doc.appendChild(workbook);
0960 
0961     /* End Made into a function */
0962 
0963     QDomElement sheets, sheet, tmp, cells, selections, cols, rows, styles, merged, margins, topMargin, leftMargin, bottomMargin, rightMargin, orientation, paper, header, footer, customSize, cellComment, objects, repeatColumns, repeatRows;
0964 
0965     KoDocumentInfo *DocumentInfo = document->documentInfo();
0966 
0967     /*
0968      * Attributes
0969      */
0970     QDomElement attributes = gnumeric_doc.createElement("gmr:Attributes");
0971     workbook.appendChild(attributes);
0972 
0973     addAttributeItem(gnumeric_doc, attributes, "4", "WorkbookView::show_horizontal_scrollbar", ksdoc->map()->settings()->showHorizontalScrollBar());
0974     addAttributeItem(gnumeric_doc, attributes, "4", "WorkbookView::show_vertical_scrollbar", ksdoc->map()->settings()->showVerticalScrollBar());
0975     addAttributeItem(gnumeric_doc, attributes, "4", "WorkbookView::show_notebook_tabs", ksdoc->map()->settings()->showTabBar());
0976     if (ksdoc->map()->settings()->completionMode() == KCompletion::CompletionAuto)
0977         addAttributeItem(gnumeric_doc, attributes, "4", "WorkbookView::do_auto_completion", "true");
0978     else
0979         addAttributeItem(gnumeric_doc, attributes, "4", "WorkbookView::do_auto_completion", "false");
0980     addAttributeItem(gnumeric_doc, attributes, "4", "WorkbookView::is_protected", ksdoc->map()->isProtected());
0981 
0982     /*
0983      * Doccument summary
0984      */
0985     QDomElement summary =  gnumeric_doc.createElement("gmr:Summary");
0986     workbook.appendChild(summary);
0987 
0988     addSummaryItem(gnumeric_doc, summary, "title", DocumentInfo->aboutInfo("title"));
0989     addSummaryItem(gnumeric_doc, summary, "company", DocumentInfo->authorInfo("company"));
0990     addSummaryItem(gnumeric_doc, summary, "author", DocumentInfo->authorInfo("creator"));
0991     addSummaryItem(gnumeric_doc, summary, "comments", DocumentInfo->aboutInfo("comments"));
0992     addSummaryItem(gnumeric_doc, summary, "keywords", DocumentInfo->aboutInfo("keyword"));
0993 
0994     addSummaryItem(gnumeric_doc, summary, "application", "KSpread");
0995 
0996     /*
0997      * Sheet name index (necessary for the gnumeric xml_sax importer)
0998      */
0999     QDomElement sheetNameIndex = gnumeric_doc.createElement("gmr:SheetNameIndex");
1000     workbook.appendChild(sheetNameIndex);
1001 
1002     foreach(Sheet* table, ksdoc->map()->sheetList()) {
1003         QDomElement sheetName = gnumeric_doc.createElement("gmr:SheetName");
1004         sheetName.appendChild(gnumeric_doc.createTextNode(table->sheetName()));
1005         sheetNameIndex.appendChild(sheetName);
1006     }
1007 
1008     /*
1009      * Area Names
1010      */
1011     /*
1012     <gmr:Names>
1013     <gmr:Name>
1014       <gmr:name>test</gmr:name>
1015       <gmr:value>Sheet2!$A$2:$D$10</gmr:value>
1016       <gmr:position>A1</gmr:position>
1017     </gmr:Name>
1018     <gmr:Name>
1019       <gmr:name>voiture</gmr:name>
1020       <gmr:value>Sheet2!$A$2:$D$8</gmr:value>
1021       <gmr:position>A1</gmr:position>
1022     </gmr:Name>
1023     </gmr:Names>
1024     */
1025     const QList<QString> namedAreas = ksdoc->map()->namedAreaManager()->areaNames();
1026     if (namedAreas.count() > 0) {
1027         Sheet* sheet = 0;
1028         QRect range;
1029         QDomElement areaNames = gnumeric_doc.createElement("gmr:Names");
1030         for (int i = 0; i < namedAreas.count(); ++i) {
1031             sheet = ksdoc->map()->namedAreaManager()->sheet(namedAreas[i]);
1032             if (!sheet)
1033                 continue;
1034             range = ksdoc->map()->namedAreaManager()->namedArea(namedAreas[i]).firstRange();
1035             QDomElement areaName = gnumeric_doc.createElement("gmr:Name");
1036             QDomElement areaNameElement = gnumeric_doc.createElement("gmr:name");
1037             areaNameElement.appendChild(gnumeric_doc.createTextNode(namedAreas[i]));
1038             areaName.appendChild(areaNameElement);
1039             QDomElement areaNameValue = gnumeric_doc.createElement("gmr:value");
1040             areaNameValue.appendChild(gnumeric_doc.createTextNode(convertRefToRange(sheet->sheetName(), range)));
1041             areaName.appendChild(areaNameValue);
1042             areaNames.appendChild(areaName);
1043             //TODO <gmr:position>A1</gmr:position> I don't know what is it.
1044         }
1045         workbook.appendChild(areaNames);
1046     }
1047 
1048 
1049     /*
1050      * Sheets
1051      */
1052     sheets = gnumeric_doc.createElement("gmr:Sheets");
1053     workbook.appendChild(sheets);
1054 
1055     QString str;
1056 
1057     View *view = ksdoc->documentPart()->views().isEmpty() ? 0 : static_cast<View*>(ksdoc->documentPart()->views().first());
1058     Canvas * canvas = 0L;
1059     QString activeTableName;
1060     if (view) {
1061         canvas = view->canvasWidget();
1062         activeTableName =  canvas->activeSheet()->sheetName();
1063     }
1064     int i = 0;
1065     int indexActiveTable = 0;
1066     foreach(Sheet* table, ksdoc->map()->sheetList()) {
1067         if (table->printSettings()->pageLayout().format == KoPageFormat::CustomSize) {
1068             customSize = gnumeric_doc.createElement("gmr:Geometry");
1069             customSize.setAttribute("Width", QString::number(POINT_TO_MM(table->printSettings()->pageLayout().width)));
1070             customSize.setAttribute("Height", QString::number(POINT_TO_MM(table->printSettings()->pageLayout().width)));
1071             sheets.appendChild(customSize);
1072             //<gmr:Geometry Width="768" Height="365"/>
1073         }
1074 
1075         sheet = gnumeric_doc.createElement("gmr:Sheet");
1076         sheets.appendChild(sheet);
1077 
1078         sheet.setAttribute("DisplayFormulas", table->getShowFormula() ? "true" : "false");
1079         sheet.setAttribute("HideZero", table->getHideZero() ? "true" : "false");
1080         sheet.setAttribute("HideGrid", !table->getShowGrid() ? "true" : "false");
1081         sheet.setAttribute("HideColHeader", (!ksdoc->map()->settings()->showColumnHeader() ? "true" : "false"));
1082         sheet.setAttribute("HideRowHeader", (!ksdoc->map()->settings()->showRowHeader() ? "true" : "false"));
1083         /* Not available in Calligra Sheets ?
1084          * sheet.setAttribute("DisplayOutlines", "true");
1085          * sheet.setAttribute("OutlineSymbolsBelow", "true");
1086          * sheet.setAttribute("OutlineSymbolsRight", "true");
1087          * sheet.setAttribute("TabColor", "");
1088          * sheet.setAttribute("TabTextColor", "");
1089          */
1090 
1091         tmp = gnumeric_doc.createElement("gmr:Name");
1092         if (table->sheetName() == activeTableName)
1093             indexActiveTable = i;
1094 
1095         tmp.appendChild(gnumeric_doc.createTextNode(table->sheetName()));
1096 
1097         sheet.appendChild(tmp);
1098 
1099         tmp = gnumeric_doc.createElement("gmr:MaxCol");
1100         tmp.appendChild(gnumeric_doc.createTextNode(QString::number(table->cellStorage()->columns())));
1101         sheet.appendChild(tmp);
1102 
1103         tmp = gnumeric_doc.createElement("gmr:MaxRow");
1104 
1105         tmp.appendChild(gnumeric_doc.createTextNode(QString::number(table->cellStorage()->rows())));
1106         sheet.appendChild(tmp);
1107 
1108         // Zoom value doesn't appear to be correct
1109         // Calligra Sheets 200% gives zoom() = 2.5, this in GNumeric = 250%
1110         tmp = gnumeric_doc.createElement("gmr:Zoom");
1111         if (view)
1112             tmp.appendChild(gnumeric_doc.createTextNode(QString::number(view->zoomHandler()->zoom())));
1113         else
1114             tmp.appendChild(gnumeric_doc.createTextNode("1.0"));
1115         sheet.appendChild(tmp);
1116 
1117         //Print Info
1118         tmp = gnumeric_doc.createElement("gmr:PrintInformation");
1119         margins = gnumeric_doc.createElement("gmr:Margins");
1120 
1121         topMargin = gnumeric_doc.createElement("gmr:top");
1122         topMargin.setAttribute("Points", QString::number(table->printSettings()->pageLayout().topMargin));
1123         topMargin.setAttribute("PrefUnit", "mm");
1124         margins.appendChild(topMargin);
1125 
1126         bottomMargin = gnumeric_doc.createElement("gmr:bottom");
1127         bottomMargin.setAttribute("Points", QString::number(table->printSettings()->pageLayout().bottomMargin));
1128         bottomMargin.setAttribute("PrefUnit", "mm");
1129         margins.appendChild(bottomMargin);
1130 
1131         leftMargin = gnumeric_doc.createElement("gmr:left");
1132         leftMargin.setAttribute("Points", QString::number(table->printSettings()->pageLayout().leftMargin));
1133         leftMargin.setAttribute("PrefUnit", "mm");
1134         margins.appendChild(leftMargin);
1135 
1136         rightMargin = gnumeric_doc.createElement("gmr:right");
1137         rightMargin.setAttribute("Points", QString::number(table->printSettings()->pageLayout().rightMargin));
1138         rightMargin.setAttribute("PrefUnit", "mm");
1139         margins.appendChild(rightMargin);
1140 
1141         tmp.appendChild(margins);
1142         sheet.appendChild(tmp);
1143 
1144         orientation = gnumeric_doc.createElement("gmr:orientation");
1145         QString orientString = table->printSettings()->pageLayout().orientation == KoPageFormat::Landscape ? "landscape" : "portrait";
1146         orientation.appendChild(gnumeric_doc.createTextNode(orientString));
1147         tmp.appendChild(orientation);
1148 
1149         //TODO for future
1150         //<gmr:repeat_top value="A1:IV5"/>
1151         //<gmr:repeat_left value="B1:D65536"/>
1152 
1153         int _tmpRepeatColumnStart = table->printSettings()->repeatedColumns().first;
1154         int _tmpRepeatColumnEnd = table->printSettings()->repeatedColumns().second;
1155         if (_tmpRepeatColumnStart != 0) {
1156             repeatColumns = gnumeric_doc.createElement("gmr:repeat_left");
1157             QString value = Cell::columnName(_tmpRepeatColumnStart) + "1:" + Cell::columnName(_tmpRepeatColumnEnd) + "65536";
1158             repeatColumns.setAttribute("value", value);
1159             tmp.appendChild(repeatColumns);
1160         }
1161         int _tmpRepeatRowStart = table->printSettings()->repeatedRows().first;
1162         int _tmpRepeatRowEnd = table->printSettings()->repeatedRows().second;
1163         if (_tmpRepeatRowStart != 0) {
1164             repeatRows = gnumeric_doc.createElement("gmr:repeat_top");
1165             QString value = 'A' + QString::number(_tmpRepeatRowStart) + ":IV" + QString::number(_tmpRepeatRowEnd);
1166             repeatRows.setAttribute("value", value);
1167             tmp.appendChild(repeatRows);
1168         }
1169 
1170         const HeaderFooter *const headerFooter = table->headerFooter();
1171         header = gnumeric_doc.createElement("gmr:Header");
1172         header.setAttribute("Left", convertVariable(headerFooter->headLeft()));
1173         header.setAttribute("Middle", convertVariable(headerFooter->headMid()));
1174         header.setAttribute("Right", convertVariable(headerFooter->headRight()));
1175         tmp.appendChild(header);
1176 
1177         footer = gnumeric_doc.createElement("gmr:Footer");
1178         footer.setAttribute("Left", convertVariable(headerFooter->footLeft()));
1179         footer.setAttribute("Middle", convertVariable(headerFooter->footMid()));
1180         footer.setAttribute("Right", convertVariable(headerFooter->footRight()));
1181         tmp.appendChild(footer);
1182 
1183         paper = gnumeric_doc.createElement("gmr:paper");
1184         paper.appendChild(gnumeric_doc.createTextNode(table->printSettings()->paperFormatString()));
1185         tmp.appendChild(paper);
1186 
1187         styles = gnumeric_doc.createElement("gmr:Styles");
1188         sheet.appendChild(styles);
1189 
1190         cells = gnumeric_doc.createElement("gmr:Cells");
1191         sheet.appendChild(cells);
1192 
1193         objects = gnumeric_doc.createElement("gmr:Objects");
1194         sheet.appendChild(objects);
1195 
1196         merged = gnumeric_doc.createElement("gmr:MergedRegions");
1197         bool mergedCells = false; // if there are no merged cells in this sheet, don't write an
1198         // empty mergedRegions to the file.
1199         // So, depending on the value of mergedCells,
1200         // the merged dom element is added or not.
1201 
1202         cols = gnumeric_doc.createElement("gmr:Cols");
1203         sheet.appendChild(cols);
1204 
1205         rows = gnumeric_doc.createElement("gmr:Rows");
1206         sheet.appendChild(rows);
1207 
1208         /*
1209           selections = gnumeric_doc.createElement("gmr:Selections");
1210           sheet.appendChild(selections);
1211         */
1212         // Ah ah ah - the document is const, but the map and table aren't. Safety: 0.
1213         // Either we get hold of Sheet::m_dctCells and apply the old method below
1214         // (for sorting) or, cleaner and already sorted, we use Sheet's API
1215         // (slower probably, though)
1216         int iMaxColumn = table->cellStorage()->columns();
1217         int iMaxRow = table->cellStorage()->rows();
1218 
1219         // this is just a bad approximation which fails for documents with less than 50 rows, but
1220         // we don't need any progress stuff there anyway :) (Werner)
1221         int value = 0;
1222         int step = iMaxRow > 50 ? iMaxRow / 50 : 1;
1223         int i = 1;
1224 
1225         QString emptyLines;
1226 
1227         /* Save selection info. */
1228 
1229         /* can't save selection anymore -- part of the view, not table */
1230         /*
1231           QDomElement selection = gnumeric_doc.createElement("gmr:Selection");
1232           QRect table_selection(table->selection());
1233 
1234           selections.appendChild(selection);
1235         */
1236         /*  <gmr:Selection startCol="3" startRow="2" endCol="3" endRow="2"/>*/
1237         /*
1238           selection.setAttribute("startCol", QString::number(table_selection.left()-1));
1239           selection.setAttribute("startRow", QString::number(table_selection.top()-1));
1240 
1241           selection.setAttribute("endCol", QString::number(table_selection.right()-1));
1242           selection.setAttribute("endRow", QString::number(table_selection.bottom()-1));
1243         */
1244         /* End selection info. */
1245 
1246 
1247         /* Start COLS */
1248         ColumnFormat *cl = table->firstCol();
1249         while (cl) {
1250             QDomElement colinfo = gnumeric_doc.createElement("gmr:ColInfo");
1251             cols.appendChild(colinfo);
1252             colinfo.setAttribute("No", QString::number(cl->column() - 1));
1253             colinfo.setAttribute("Hidden", QString::number(cl->isHidden()));
1254             colinfo.setAttribute("Unit", QString::number(cl->width()));
1255 
1256             cl = cl->next();
1257         }
1258 
1259         /* End COLS */
1260 
1261         //  RowFormat *rl=table->m_cells.firstCell;
1262         //   <gmr:ColInfo No="1" Unit="96.75" MarginA="2" MarginB="2" HardSize="-1" Hidden="0"/>
1263 
1264         /* Start ROWS */
1265         for (int row = 1; row <= table->rowFormats()->lastNonDefaultRow(); ++row) {
1266             int lastRow;
1267             if (table->rowFormats()->isDefaultRow(row, &lastRow)) {
1268                 row = lastRow;
1269                 continue;
1270             }
1271             QDomElement rowinfo = gnumeric_doc.createElement("gmr:RowInfo");
1272             rows.appendChild(rowinfo);
1273             rowinfo.setAttribute("No", QString::number(row - 1));
1274             rowinfo.setAttribute("Hidden", QString::number(table->rowFormats()->isHidden(row)));
1275             rowinfo.setAttribute("Unit", QString::number(table->rowFormats()->rowHeight(row)));
1276         }
1277 
1278         /* End ROWS */
1279 
1280         //rl->setHeight
1281         //  colinfo.info();
1282         /*
1283           <gmr:ColInfo No="1" Unit="96.75" MarginA="2" MarginB="2" HardSize="-1" Hidden="0"/>
1284           <gmr:ColInfo No="3" Unit="113.25" MarginA="2" MarginB="2" HardSize="-1"
1285           Hidden="0"/>
1286         */
1287 
1288         /* End COLS */
1289 
1290         for (int currentrow = 1; currentrow <= iMaxRow; ++currentrow, ++i) {
1291             if (i > step) {
1292                 value += 2;
1293                 emit sigProgress(value);
1294                 i = 0;
1295             }
1296 
1297             QString line;
1298             for (int currentcolumn = 1; currentcolumn <= iMaxColumn; currentcolumn++) {
1299                 QDomElement cell_contents;
1300                 Cell cell(table, currentcolumn, currentrow);
1301 
1302                 QString text, style;
1303                 QDomDocument domLink;
1304                 QDomElement domRoot;
1305                 QDomNode domNode;
1306                 QDomNodeList childNodes;
1307 
1308                 if (!cell.isDefault() && !cell.isEmpty()) {
1309                     if (cell.isFormula()) {
1310                         QString tmp = cell.userInput();
1311                         if (tmp.contains("=="))
1312                             tmp.replace("==", "=");
1313                         text = tmp;
1314                         isLink = false;
1315                     } else if (!cell.link().isEmpty()) {
1316                         isLink = true;
1317                         isLinkBold = false;
1318                         isLinkItalic = false;
1319                         //TODO FIXME
1320                         linkUrl = cell.link();
1321                         linkText = cell.userInput();
1322 
1323                     } else {
1324                         text = cell.userInput();
1325                         isLink = false;
1326                     }
1327 #if 0
1328                     switch (cell.content()) {
1329                     case Cell::Text:
1330                         text = cell.userInput();
1331                         isLink = false;
1332                         break;
1333                     case Cell::RichText:
1334                         // hyperlinks
1335                         // Extract the cell text
1336                         isLink = true;
1337                         isLinkBold = false;
1338                         isLinkItalic = false;
1339                         domLink.setContent(cell.userInput().section("!", 1, 1));
1340 
1341                         domNode = domLink.firstChild();
1342                         domRoot = domNode.toElement();
1343                         text = domNode.toElement().text();
1344 
1345                         while (!domNode.isNull()) {
1346                             style = domNode.toElement().tagName();
1347 
1348                             if (style == "b")
1349                                 isLinkBold = true;
1350 
1351                             if (style == "i")
1352                                 isLinkItalic = true;
1353 
1354                             domNode = domNode.firstChild();
1355                         }
1356 
1357                         //kDebug(30521) <<"---> link, text =" << text;
1358 
1359                         linkUrl = domRoot.attribute("href");
1360                         linkText = text;
1361 
1362                         break;
1363                     case Cell::VisualFormula:
1364                         isLink = false;
1365                         text = cell.userInput(); // untested
1366                         break;
1367                     case Cell::Formula:
1368                         isLink = false;
1369                         QString tmp = cell.userInput();
1370                         if (tmp == "==")
1371                             tmp = replace("==", "=");
1372                         /* cell.calc( true ); // Incredible, cells are not calculated if the document was just opened text = cell.valueString(); */
1373                         text = tmp;
1374                         break;
1375                     }
1376 #endif
1377                 }
1378 
1379                 if (!cell.isDefault()) {
1380 
1381                     // Check if the cell is merged
1382                     // Only cells with content are interesting?
1383                     // Otherwise it can take a while to parse a large sheet
1384 
1385                     if (cell.doesMergeCells()) {
1386                         // The cell is forced to occupy other cells
1387                         QDomElement merge = gnumeric_doc.createElement("gmr:Merge");
1388 
1389                         // Set up the range
1390                         QString fromCol, toCol, fromRow, toRow;
1391                         fromCol = cell.columnName(currentcolumn);
1392                         fromRow = QString::number(currentrow);
1393                         toCol = cell.columnName(currentcolumn + cell.mergedXCells());
1394                         toRow = QString::number(currentrow + cell.mergedYCells());
1395 
1396                         merge.appendChild(gnumeric_doc.createTextNode(fromCol + fromRow + ':' + toCol + toRow));
1397                         mergedCells = true;
1398                         merged.appendChild(merge);
1399                     }
1400                     // ---
1401                     if (!cell.comment().isEmpty()) {
1402                         //<gmr:CellComment Author="" Text="cvbcvbxcvb&#10;cb&#10;xc&#10;vbxcv&#10;" ObjectBound="A1" ObjectOffset="0 0 0 0" ObjectAnchorType="17 16 17 16" Direction="17"/>
1403                         cellComment = gnumeric_doc.createElement("gmr:CellComment");
1404                         cellComment.setAttribute("Text", cell.comment());
1405                         QString sCell = QString("%1%2").arg(Cell::columnName(currentcolumn)).arg(currentrow);
1406 
1407                         cellComment.setAttribute("ObjectBound", sCell);
1408                         objects.appendChild(cellComment);
1409 
1410                     }
1411                     QDomElement gnumeric_cell = gnumeric_doc.createElement("gmr:Cell");
1412                     QDomElement cell_style;
1413 
1414                     QDomElement style_region = gnumeric_doc.createElement("gmr:StyleRegion");
1415 
1416                     cells.appendChild(gnumeric_cell);
1417 
1418                     gnumeric_cell.setAttribute("Col", QString::number(currentcolumn - 1));
1419                     gnumeric_cell.setAttribute("Row", QString::number(currentrow - 1));
1420 
1421                     /* Right now, we create a single region for each cell.. This is inefficient,
1422                      * but the implementation is quicker.. Probably later we will have to
1423                      * consolidate styles into style regions.
1424                      */
1425 
1426                     style_region.setAttribute("startCol", QString::number(currentcolumn - 1));
1427                     style_region.setAttribute("startRow", QString::number(currentrow - 1));
1428                     style_region.setAttribute("endCol", QString::number(currentcolumn - 1));
1429                     style_region.setAttribute("endRow", QString::number(currentrow - 1));
1430 
1431                     cell_style = GetCellStyle(gnumeric_doc, cell, currentcolumn, currentrow);
1432 
1433                     style_region.appendChild(cell_style);
1434 
1435                     styles.appendChild(style_region);
1436 
1437                     //cell_contents = gnumeric_doc.createElement("gmr:Content");
1438                     gnumeric_cell.appendChild(gnumeric_doc.createTextNode(text));
1439                     //gnumeric_cell.appendChild(cell_contents);
1440                 }
1441 
1442                 // Append a delimiter, but in a temp string -> if no other real cell in this line,
1443                 // then those will be dropped
1444             }
1445         }
1446 
1447         if (mergedCells)
1448             sheet.appendChild(merged);
1449     }
1450     QDomElement uidata = gnumeric_doc.createElement("gmr:UIData");
1451     uidata.setAttribute("SelectedTab", QString::number(indexActiveTable));
1452     workbook.appendChild(uidata);
1453 
1454     str = gnumeric_doc.toString();
1455 
1456     emit sigProgress(100);
1457 
1458     // Ok, now write to export file
1459 
1460     QIODevice* out = new KCompressionDevice(m_chain->outputFile(), KCompressionDevice::GZip);
1461 
1462     if (!out) {
1463         kError(30521) << "No output file! Aborting!" << endl;
1464         return KoFilter::FileNotFound;
1465     }
1466 
1467     if (!out->open(QIODevice::WriteOnly)) {
1468         kError(30521) << "Unable to open output file! Aborting!" << endl;
1469         delete out;
1470         return KoFilter::FileNotFound;
1471     }
1472 
1473     QTextStream streamOut(out);
1474 
1475     streamOut << str;
1476     streamOut.flush();
1477 
1478     out->close();
1479     delete out;
1480 
1481     return KoFilter::OK;
1482 }
1483 
1484 
1485 QString GNUMERICExport::convertRefToRange(const QString & table, const QRect & rect)
1486 {
1487     QPoint topLeft(rect.topLeft());
1488     QPoint bottomRight(rect.bottomRight());
1489     if (topLeft == bottomRight)
1490         return convertRefToBase(table, rect);
1491     QString s;
1492     s += table;
1493     s += "!$";
1494     s += Cell::columnName(topLeft.x());
1495     s += '$';
1496     s += QString::number(topLeft.y());
1497     s += ":$";
1498     s += Cell::columnName(bottomRight.x());
1499     s += '$';
1500     s += QString::number(bottomRight.y());
1501 
1502     return s;
1503 }
1504 
1505 
1506 QString GNUMERICExport::convertRefToBase(const QString & table, const QRect & rect)
1507 {
1508     QPoint bottomRight(rect.bottomRight());
1509 
1510     QString s;
1511     s = table;
1512     s += "!$";
1513     s += Cell::columnName(bottomRight.x());
1514     s += '$';
1515     s += QString::number(bottomRight.y());
1516 
1517     return s;
1518 }
1519 
1520 QString GNUMERICExport::convertVariable(QString headerFooter)
1521 {
1522     headerFooter.replace("<sheet>", "&[TAB]");
1523     headerFooter.replace("<date>", "&[DATE]");
1524     headerFooter.replace("<page>", "&[PAGE]");
1525     headerFooter.replace("<pages>", "&[PAGES]");
1526     headerFooter.replace("<time>", "&[TIME]");
1527     headerFooter.replace("<file>", "&[FILE]");
1528 
1529     return headerFooter;
1530 }
1531 
1532 #include "gnumericexport.moc"