Warning, file /office/calligra/filters/sheets/gnumeric/gnumericimport.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) 1999 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 import filter by Phillip Ezolt 6-2-2001 */
0022 /*                        phillipezolt@hotmail.com  */
0023 /* additions: Norbert Andres nandres@web.de         */
0024 #include "gnumericimport.h"
0025 
0026 #include <QMap>
0027 #include <QFile>
0028 #include <QStringList>
0029 #include <QByteArray>
0030 #include <QPen>
0031 #include <QDomDocument>
0032 
0033 #include <KCompressionDevice>
0034 #include <kdebug.h>
0035 #include <kpluginfactory.h>
0036 
0037 #include <KoFilterChain.h>
0038 #include <KoDocumentInfo.h>
0039 #include <KoUnit.h>
0040 
0041 // Calligra Sheets
0042 #include <sheets/ApplicationSettings.h>
0043 #include <sheets/Cell.h>
0044 #include <sheets/part/Doc.h>
0045 #include <sheets/HeaderFooter.h>
0046 #include <sheets/LoadingInfo.h>
0047 #include <sheets/Map.h>
0048 #include <sheets/NamedAreaManager.h>
0049 #include <sheets/PrintSettings.h>
0050 #include <sheets/Region.h>
0051 #include <sheets/RowColumnFormat.h>
0052 #include <sheets/Sheet.h>
0053 #include <sheets/Util.h>
0054 #include <sheets/Validity.h>
0055 #include <sheets/ValueParser.h>
0056 
0057 #include <math.h>
0058 
0059 #define SECS_PER_DAY 86400
0060 #define HALF_SEC (0.5 / SECS_PER_DAY)
0061 
0062 using namespace Calligra::Sheets;
0063 
0064 // copied from gnumeric: src/format.c:
0065 static const int g_dateSerial_19000228 = 59;
0066 /* One less that the Julian day number of 19000101.  */
0067 static int g_dateOrigin = 0;
0068 
0069 // copied from gnumeric: src/formats.c:
0070 static char const * const cell_date_format [] = {
0071     "m/d/yy",  /* 0 Cell::Format::Date5*/
0072     "m/d/yyyy",  /* 1 Cell::Format::Date6*/
0073     "d-mmm-yy",  /* 2 Cell::Format::Date1 18-Feb-99 */
0074     "d-mmm-yyyy",  /* 3 Cell::Format::Date2 18-Feb-1999 */
0075     "d-mmm",  /* 4 Cell::Format::Date3 18-Feb */
0076     "d-mm",   /* 5 Cell::Format::Date4 18-05 */
0077     "mmm/d",  /* 6 Cell::Format::Date11*/
0078     "mm/d",   /* 7 Cell::Format::Date12*/
0079     "mm/dd/yy",  /* 8 Cell::Format::Date19*/
0080     "mm/dd/yyyy",  /* 9 Cell::Format::Date18*/
0081     "mmm/dd/yy",  /* 10 Cell::Format::Date20*/
0082     "mmm/dd/yyyy",  /* 11 Cell::Format::Date21*/
0083     "mmm/ddd/yy",  /* 12 */
0084     "mmm/ddd/yyyy",  /* 13 */
0085     "mm/ddd/yy",  /* 14 */
0086     "mm/ddd/yyyy",  /* 15 */
0087     "mmm-yy",  /* 16 Cell::Format::Date7*/
0088     "mmm-yyyy",  /* 17 Cell::Format::Date22*/
0089     "mmmm-yy",  /* 18 Cell::Format::Date8*/
0090     "mmmm-yyyy",  /* 19 Cell::Format::Date9*/
0091     "m/d/yy h:mm",  /* 20 */
0092     "m/d/yyyy h:mm", /* 21 */
0093     "yyyy/mm/d",  /* 22 Cell::Format::Date25*/
0094     "yyyy/mmm/d",  /* 23 Cell::Format::Date14*/
0095     "yyyy/mm/dd",  /* 24 Cell::Format::Date25*/
0096     "yyyy/mmm/dd",  /* 25 Cell::Format::Date26*/
0097     "yyyy-mm-d",  /* 26 Cell::Format::Date16*/
0098     "yyyy-mmm-d",  /* 27 Cell::Format::Date15*/
0099     "yyyy-mm-dd",  /* 28 Cell::Format::Date16*/
0100     "yyyy-mmm-dd",  /* 29 Cell::Format::Date15*/
0101     "yy",   /* 30 Cell::Format::Date24*/
0102     "yyyy",   /* 31 Cell::Format::Date23*/
0103     nullptr
0104 };
0105 
0106 // copied from gnumeric: src/formats.c:
0107 static char const * const cell_time_format [] = {
0108     "h:mm AM/PM",    // Cell::Format::Time1 9 : 01 AM
0109     "h:mm:ss AM/PM", // Cell::Format::Time2 9:01:05 AM
0110     "h:mm",          // Cell::Format::Time4 9:01
0111     "h:mm:ss",       // Cell::Format::Time5 9:01:12
0112     "m/d/yy h:mm",
0113     "mm:ss",         // Cell::Format::Time6 01:12
0114     "mm:ss.0",       // Cell::Format::Time6 01:12
0115     "[h]:mm:ss",
0116     "[h]:mm",
0117     "[mm]:ss",
0118     "[ss]",
0119     nullptr
0120 };
0121 
0122 namespace gnumeric_import_LNS
0123 {
0124 QStringList list1;
0125 QStringList list2;
0126 }
0127 
0128 using namespace gnumeric_import_LNS;
0129 
0130 void GNUMERICFilter::dateInit()
0131 {
0132     // idea copied form gnumeric src/format.c:
0133     /* Day 1 means 1st of January of 1900 */
0134     g_dateOrigin = GnumericDate::greg2jul(1900, 1, 1) - 1;
0135 }
0136 
0137 uint GNUMERICFilter::GnumericDate::greg2jul(int y, int m, int d)
0138 {
0139     return QDate(y, m, d).toJulianDay();
0140 }
0141 
0142 void GNUMERICFilter::GnumericDate::jul2greg(double num, int & y, int & m, int & d)
0143 {
0144     int i = (int) floor(num + HALF_SEC);
0145     if (i > g_dateSerial_19000228)
0146         --i;
0147     else if (i == g_dateSerial_19000228 + 1)
0148         kWarning(30521) << "Request for date 02/29/1900.";
0149 
0150     kDebug(30521) << "***** Num:" << num << ", i:" << i;
0151 
0152     QDate::fromJulianDay(i + g_dateOrigin).getDate(&y, &m, &d);
0153     kDebug(30521) << "y:" << y << ", m:" << m << ", d:" << d;
0154 }
0155 
0156 QTime GNUMERICFilter::GnumericDate::getTime(double num)
0157 {
0158     // idea copied from gnumeric: src/datetime.c
0159     num += HALF_SEC;
0160     int secs = qRound((num - floor(num)) * SECS_PER_DAY);
0161 
0162     kDebug(30521) << "***** Num:" << num << ", secs" << secs;
0163 
0164     const int h = secs / 3600;
0165     secs -= h * 3600;
0166     const int m = secs / 60;
0167     secs -= h * 60;
0168 
0169     kDebug(30521) << "****** h:" << h << ", m:" << m << ", secs:" << secs;
0170     const QTime time(h, m, (secs < 0 || secs > 59 ? 0 : secs));
0171 
0172     return time;
0173 }
0174 
0175 K_PLUGIN_FACTORY_WITH_JSON(GNUMERICFilterFactory, "calligra_filter_gnumeric2sheets.json",
0176                            registerPlugin<GNUMERICFilter>();)
0177 
0178 GNUMERICFilter::GNUMERICFilter(QObject* parent, const QVariantList &)
0179         : KoFilter(parent)
0180 {
0181 }
0182 
0183 /* This converts GNUmeric's color string "0:0:0" to a QColor. */
0184 void  convert_string_to_qcolor(const QString &color_string, QColor * color)
0185 {
0186     int red, green, blue, first_col_pos, second_col_pos;
0187 
0188     bool number_ok;
0189 
0190     first_col_pos  = color_string.indexOf(':', 0);
0191     second_col_pos = color_string.indexOf(':', first_col_pos + 1);
0192 
0193     /* Fore="0:0:FF00" */
0194     /* If GNUmeric kicks out some invalid colors, we could crash. */
0195     /* GNUmeric gives us two bytes of color data per element. */
0196     /* We only care about the top byte. */
0197 
0198     red   = color_string.mid(0, first_col_pos).toInt(&number_ok, 16) >> 8;
0199     green = color_string.mid(first_col_pos + 1,
0200                              (second_col_pos - first_col_pos) - 1).toInt(&number_ok, 16) >> 8;
0201     blue  = color_string.mid(second_col_pos + 1,
0202                              (color_string.length() - first_col_pos) - 1).toInt(&number_ok, 16) >> 8;
0203     color->setRgb(red, green, blue);
0204 }
0205 
0206 void areaNames(Doc * ksdoc, const QString &_name, QString _zone)
0207 {
0208 //Sheet2!$A$2:$D$8
0209     QString tableName;
0210     int pos = _zone.indexOf('!');
0211     if (pos != -1) {
0212         tableName = _zone.left(pos);
0213         _zone = _zone.right(_zone.length() - pos - 1);
0214         pos = _zone.indexOf(':');
0215         QRect rect;
0216         if (pos != -1) {
0217             QString left = _zone.mid(1, pos - 1);
0218             QString right = _zone.mid(pos + 2, _zone.length() - pos - 2);
0219             int pos = left.indexOf('$');
0220 
0221             rect.setLeft(Util::decodeColumnLabelText(left.left(pos)));
0222             rect.setTop(left.right(left.length() - pos - 1).toInt());
0223 
0224             pos = right.indexOf('$');
0225             rect.setRight(Util::decodeColumnLabelText(right.left(pos)));
0226             rect.setBottom(right.right(right.length() - pos - 1).toInt());
0227         } else {
0228             QString left = _zone;
0229             int pos = left.indexOf('$');
0230             int leftPos = Util::decodeColumnLabelText(left.left(pos));
0231             rect.setLeft(leftPos);
0232             rect.setRight(leftPos);
0233 
0234             int top = left.right(left.length() - pos - 1).toInt();
0235             rect.setTop(top);
0236             rect.setBottom(top);
0237         }
0238         ksdoc->map()->namedAreaManager()->insert(Calligra::Sheets::Region(rect, ksdoc->map()->findSheet(tableName)), _name);
0239     }
0240 }
0241 
0242 
0243 void set_document_area_names(Doc * ksdoc, QDomElement * docElem)
0244 {
0245     QDomNode areaNamesElement = docElem->namedItem("Names");
0246     if (areaNamesElement.isNull())
0247         return;
0248     QDomNode areaNameItem = areaNamesElement.namedItem("Name");
0249     while (!areaNameItem.isNull()) {
0250         QDomNode gmr_name  = areaNameItem.namedItem("name");
0251         QDomNode gmr_value = areaNameItem.namedItem("value");
0252         QString name = gmr_name.toElement().text();
0253         areaNames(ksdoc, name, gmr_value.toElement().text());
0254         areaNameItem = areaNameItem.nextSibling();
0255     }
0256 }
0257 
0258 
0259 
0260 void set_document_attributes(Doc * ksdoc, QDomElement * docElem)
0261 {
0262     ksdoc->loadConfigFromFile();
0263     QDomNode attributes  = docElem->namedItem("Attributes");
0264     if (attributes.isNull())
0265         return;
0266 
0267     QDomNode attributeItem = attributes.namedItem("Attribute");
0268     while (!attributeItem.isNull()) {
0269         QDomNode gmr_name  = attributeItem.namedItem("name");
0270         QDomNode gmr_value = attributeItem.namedItem("value");
0271         if (gmr_name.toElement().text() == "WorkbookView::show_horizontal_scrollbar") {
0272             ksdoc->map()->settings()->setShowHorizontalScrollBar(gmr_value.toElement().text().toLower() == "true" ? true : false);
0273         } else if (gmr_name.toElement().text() == "WorkbookView::show_vertical_scrollbar") {
0274             ksdoc->map()->settings()->setShowVerticalScrollBar(gmr_value.toElement().text().toLower() == "true" ? true : false);
0275         } else if (gmr_name.toElement().text() == "WorkbookView::show_notebook_tabs") {
0276             ksdoc->map()->settings()->setShowTabBar(gmr_value.toElement().text().toLower() == "true" ? true : false);
0277         } else if (gmr_name.toElement().text() == "WorkbookView::do_auto_completion") {
0278             ksdoc->map()->settings()->setCompletionMode(KCompletion::CompletionAuto);
0279         } else if (gmr_name.toElement().text() == "WorkbookView::is_protected") {
0280             //TODO protect document ???
0281             //ksdoc->map()->isProtected()
0282         }
0283 
0284         attributeItem = attributeItem.nextSibling();
0285     }
0286 }
0287 
0288 /* This sets the documentation information from the information stored in
0289    the GNUmeric file. Particularly in the "Summary" subcategory.
0290 */
0291 void set_document_info(KoDocument * document, QDomElement * docElem)
0292 {
0293     /* Summary Handling START */
0294     QDomNode summary  = docElem->namedItem("Summary");
0295     QDomNode gmr_item = summary.namedItem("Item");
0296 
0297     while (!gmr_item.isNull()) {
0298         QDomNode gmr_name  = gmr_item.namedItem("name");
0299         QDomNode gmr_value = gmr_item.namedItem("val-string");
0300 
0301         KoDocumentInfo * DocumentInfo     = document->documentInfo();
0302 
0303         if (gmr_name.toElement().text() == "title") {
0304             DocumentInfo->setAboutInfo("title", gmr_value.toElement().text());
0305         } else if (gmr_name.toElement().text() == "keywords") {
0306             DocumentInfo->setAboutInfo("keyword", gmr_value.toElement().text());
0307         } else if (gmr_name.toElement().text() == "comments") {
0308             DocumentInfo->setAboutInfo("comments", gmr_value.toElement().text());
0309         } else if (gmr_name.toElement().text() == "category") {
0310             /* Not supported by Calligra::Sheets */
0311         } else if (gmr_name.toElement().text() == "manager") {
0312             /* Not supported by Calligra::Sheets */
0313         } else if (gmr_name.toElement().text() == "application") {
0314             /* Not supported by Calligra::Sheets */
0315         } else if (gmr_name.toElement().text() == "author") {
0316             DocumentInfo->setAuthorInfo("creator", gmr_value.toElement().text());
0317         } else if (gmr_name.toElement().text() == "company") {
0318             DocumentInfo->setAuthorInfo("company", gmr_value.toElement().text());
0319         }
0320 
0321         gmr_item = gmr_item.nextSibling();
0322     }
0323 
0324     /* Summany Handling STOP */
0325 }
0326 
0327 
0328 void setColInfo(QDomNode * sheet, Sheet * table)
0329 {
0330     QDomNode columns =  sheet->namedItem("Cols");
0331     QDomNode columninfo = columns.namedItem("ColInfo");
0332 
0333     double defaultWidth = 0.0;
0334     bool defaultWidthOk = false;
0335 
0336     QDomElement def = columns.toElement();
0337     if (def.hasAttribute("DefaultSizePts")) {
0338         defaultWidth = def.attribute("DefaultSizePts").toDouble(&defaultWidthOk);
0339     }
0340 
0341     while (!columninfo.isNull()) {
0342         QDomElement e = columninfo.toElement(); // try to convert the node to an element.
0343         int column_number;
0344 
0345         column_number = e.attribute("No").toInt() + 1;
0346         ColumnFormat *cl = new ColumnFormat();
0347         cl->setSheet(table);
0348         cl->setColumn(column_number);
0349         if (e.hasAttribute("Hidden")) {
0350             if (e.attribute("Hidden") == "1") {
0351                 cl->setHidden(true);
0352             }
0353         }
0354         if (e.hasAttribute("Unit")) {
0355             //  xmm = (x_points) * (1 inch / 72 points) * (25.4 mm/ 1 inch)
0356             bool ok = false;
0357             double dbl = e.attribute("Unit").toDouble(&ok);
0358             if (ok)
0359                 cl->setWidth(dbl);
0360             else if (defaultWidthOk)
0361                 cl->setWidth(defaultWidth);
0362         }
0363         table->insertColumnFormat(cl);
0364         columninfo = columninfo.nextSibling();
0365     }
0366 }
0367 
0368 void setRowInfo(QDomNode *sheet, Sheet *table)
0369 {
0370     QDomNode rows =  sheet->namedItem("Rows");
0371     QDomNode rowinfo = rows.namedItem("RowInfo");
0372 
0373     double defaultHeight = 0.0;
0374     bool defaultHeightOk = false;
0375 
0376     QDomElement def = rows.toElement();
0377     if (def.hasAttribute("DefaultSizePts")) {
0378         defaultHeight = def.attribute("DefaultSizePts").toDouble(&defaultHeightOk);
0379     }
0380 
0381     while (!rowinfo.isNull()) {
0382         QDomElement e = rowinfo.toElement(); // try to convert the node to an element.
0383         int row_number;
0384         row_number = e.attribute("No").toInt() + 1;
0385         RowFormat *rl = new RowFormat();
0386         rl->setSheet(table);
0387         rl->setRow(row_number);
0388 
0389         if (e.hasAttribute("Hidden")) {
0390             if (e.attribute("Hidden") == "1") {
0391                 rl->setHidden(true);
0392             }
0393         }
0394         if (e.hasAttribute("Unit")) {
0395             bool ok = false;
0396             double dbl = e.attribute("Unit").toDouble(&ok);
0397             if (ok)
0398                 rl->setHeight(dbl);
0399             else if (defaultHeightOk)
0400                 rl->setHeight(defaultHeight);
0401         }
0402         table->insertRowFormat(rl);
0403         rowinfo = rowinfo.nextSibling();
0404     }
0405 }
0406 
0407 void setSelectionInfo(QDomNode * sheet, Sheet * /* table */)
0408 {
0409     QDomNode selections =  sheet->namedItem("Selections");
0410     QDomNode selection = selections.namedItem("Selection");
0411 
0412     /* Calligra Sheets does not support multiple selections.. */
0413     /* This code will set the selection to the last one GNUmeric's multiple
0414        selections. */
0415     while (!selection.isNull()) {
0416         QDomElement e = selection.toElement(); // try to convert the node to an element.
0417         QRect kspread_selection;
0418 
0419         kspread_selection.setLeft((e.attribute("startCol").toInt() + 1));
0420         kspread_selection.setTop((e.attribute("startRow").toInt() + 1));
0421         kspread_selection.setRight((e.attribute("endCol").toInt() + 1));
0422         kspread_selection.setBottom((e.attribute("endRow").toInt() + 1));
0423 
0424         /* can't set it in the table -- must set it to a view */
0425         //   table->setSelection(kspread_selection);
0426 
0427         selection = selection.nextSibling();
0428     }
0429 }
0430 
0431 
0432 void setObjectInfo(QDomNode * sheet, Sheet * table)
0433 {
0434     QDomNode gmr_objects =  sheet->namedItem("Objects");
0435     QDomNode gmr_cellcomment = gmr_objects.namedItem("CellComment");
0436     while (!gmr_cellcomment.isNull()) {
0437         QDomElement e = gmr_cellcomment.toElement(); // try to convert the node to an element.
0438         if (e.hasAttribute("Text")) {
0439             if (e.hasAttribute("ObjectBound")) {
0440                 const Calligra::Sheets::Region region(e.attribute("ObjectBound"));
0441                 Cell cell = Cell(table, region.firstRange().topLeft());
0442                 cell.setComment(e.attribute("Text"));
0443             }
0444         }
0445 
0446         gmr_cellcomment  = gmr_cellcomment.nextSibling();
0447     }
0448 }
0449 
0450 void convertToPen(QPen & pen, int style)
0451 {
0452     switch (style) {
0453     case 0:
0454         break;
0455     case 1:
0456         pen.setStyle(Qt::SolidLine);
0457         pen.setWidth(1);
0458         break;
0459     case 2:
0460         pen.setStyle(Qt::SolidLine);
0461         pen.setWidth(2);
0462         break;
0463     case 3:
0464         pen.setStyle(Qt::DashLine);
0465         pen.setWidth(1);
0466         break;
0467     case 4:
0468         // width should be 1 but otherwise it would be the same as 7
0469         pen.setStyle(Qt::DotLine);
0470         pen.setWidth(2);
0471         break;
0472     case 5:
0473         pen.setStyle(Qt::SolidLine);
0474         pen.setWidth(3);
0475         break;
0476     case 6:
0477         // TODO should be double
0478         pen.setStyle(Qt::SolidLine);
0479         pen.setWidth(1);
0480         break;
0481     case 7:
0482         // very thin dots => no match in Calligra::Sheets
0483         pen.setStyle(Qt::DotLine);
0484         pen.setWidth(1);
0485         break;
0486     case 8:
0487         pen.setStyle(Qt::DashLine);
0488         pen.setWidth(2);
0489         break;
0490     case 9:
0491         pen.setStyle(Qt::DashDotLine);
0492         pen.setWidth(1);
0493         break;
0494     case 10:
0495         pen.setStyle(Qt::DashDotLine);
0496         pen.setWidth(2);
0497         break;
0498     case 11:
0499         pen.setStyle(Qt::DashDotDotLine);
0500         pen.setWidth(1);
0501         break;
0502     case 12:
0503         pen.setStyle(Qt::DashDotDotLine);
0504         pen.setWidth(2);
0505         break;
0506     case 13:
0507         // TODO: long dash, short dash, long dash,...
0508         pen.setStyle(Qt::DashDotLine);
0509         pen.setWidth(3);
0510         break;
0511     default:
0512         pen.setStyle(Qt::SolidLine);
0513         pen.setWidth(1);
0514     }
0515 }
0516 
0517 void GNUMERICFilter::ParseBorder(QDomElement & gmr_styleborder, const Cell& kspread_cell)
0518 {
0519     QDomNode gmr_diagonal = gmr_styleborder.namedItem("Diagonal");
0520     QDomNode gmr_rev_diagonal = gmr_styleborder.namedItem("Rev-Diagonal");
0521     QDomNode gmr_top = gmr_styleborder.namedItem("Top");
0522     QDomNode gmr_bottom = gmr_styleborder.namedItem("Bottom");
0523     QDomNode gmr_left = gmr_styleborder.namedItem("Left");
0524     QDomNode gmr_right = gmr_styleborder.namedItem("Right");
0525 
0526     // NoPen - no line at all. For example,
0527     // QPainter::drawRect() fills but does not
0528     // draw any explicit boundary
0529     // line. SolidLine - a simple line. DashLine
0530     // - dashes, separated by a few
0531     // pixels. DotLine - dots, separated by a
0532     // few pixels. DashDotLine - alternately
0533     // dots and dashes. DashDotDotLine - one dash, two dots, one dash, two dots...
0534 
0535     if (!gmr_left.isNull()) {
0536         QDomElement e = gmr_left.toElement(); // try to convert the node to an element.
0537         importBorder(e, Left, kspread_cell);
0538     }
0539 
0540     if (!gmr_right.isNull()) {
0541         QDomElement e = gmr_right.toElement(); // try to convert the node to an element.
0542         importBorder(e, Right, kspread_cell);
0543     }
0544 
0545     if (!gmr_top.isNull()) {
0546         QDomElement e = gmr_top.toElement(); // try to convert the node to an element.
0547         importBorder(e, Top,  kspread_cell);
0548     }
0549 
0550     if (!gmr_bottom.isNull()) {
0551         QDomElement e = gmr_bottom.toElement(); // try to convert the node to an element.
0552         importBorder(e, Bottom, kspread_cell);
0553     }
0554 
0555     if (!gmr_diagonal.isNull()) {
0556         QDomElement e = gmr_diagonal.toElement(); // try to convert the node to an element.
0557         importBorder(e, Diagonal, kspread_cell);
0558     }
0559 
0560     if (!gmr_rev_diagonal.isNull()) {
0561         QDomElement e = gmr_rev_diagonal.toElement(); // try to convert the node to an element.
0562         importBorder(e, Revdiagonal, kspread_cell);
0563     }
0564 
0565     //  QDomElement gmr_styleborder_element = gmr_styleborder.toElement();
0566 }
0567 
0568 
0569 void GNUMERICFilter::importBorder(QDomElement border, borderStyle _style, const Calligra::Sheets::Cell& cell)
0570 {
0571     if (!border.isNull()) {
0572         QDomElement e = border.toElement(); // try to convert the node to an element.
0573         if (e.hasAttribute("Style")) {
0574             Style style;
0575             int penStyle = e.attribute("Style").toInt();
0576 
0577             QPen pen;
0578             convertToPen(pen, penStyle);
0579             QPen leftPen(Qt::NoPen);
0580             QPen rightPen(Qt::NoPen);
0581             QPen topPen(Qt::NoPen);
0582             QPen bottomPen(Qt::NoPen);
0583             QPen fallPen(Qt::NoPen);
0584             QPen goUpPen(Qt::NoPen);
0585 
0586             if (penStyle > 0) {
0587                 switch (_style) {
0588                 case Left:
0589                     leftPen = pen;
0590                     break;
0591                 case Right:
0592                     rightPen = pen;
0593                     break;
0594                 case Top:
0595                     topPen = pen;
0596                     break;
0597                 case Bottom:
0598                     bottomPen = pen;
0599                     break;
0600                 case Diagonal:
0601                     fallPen = pen;
0602                     break;
0603                 case Revdiagonal:
0604                     goUpPen = pen;
0605                     break;
0606                 }
0607             }
0608             if (e.hasAttribute("Color")) {
0609                 QColor color;
0610                 QString colorString = e.attribute("Color");
0611                 convert_string_to_qcolor(colorString, &color);
0612                 {
0613                     switch (_style) {
0614                     case Left:
0615                         leftPen.setColor(color);
0616                         break;
0617                     case Right:
0618                         rightPen.setColor(color);
0619                         break;
0620                     case Top:
0621                         topPen.setColor(color);
0622                         break;
0623                     case Bottom:
0624                         bottomPen.setColor(color);
0625                         break;
0626                     case Diagonal:
0627                         fallPen.setColor(color);
0628                         break;
0629                     case Revdiagonal:
0630                         goUpPen.setColor(color);
0631                         break;
0632                     }
0633                 }
0634             }
0635             if (leftPen.style() != Qt::NoPen) style.setLeftBorderPen(leftPen);
0636             if (rightPen.style() != Qt::NoPen) style.setRightBorderPen(rightPen);
0637             if (topPen.style() != Qt::NoPen) style.setTopBorderPen(topPen);
0638             if (bottomPen.style() != Qt::NoPen) style.setBottomBorderPen(bottomPen);
0639             if (fallPen.style() != Qt::NoPen) style.setFallDiagonalPen(fallPen);
0640             if (goUpPen.style() != Qt::NoPen) style.setGoUpDiagonalPen(goUpPen);
0641             Cell(cell).setStyle(style);
0642         }
0643     }
0644 }
0645 
0646 bool GNUMERICFilter::setType(const Cell& kspread_cell,
0647                              QString const & formatString,
0648                              QString & cell_content)
0649 {
0650     int i = 0;
0651     for (i = 0; cell_date_format[i] ; ++i) {
0652         kDebug(30521) << "Format::Cell:" << cell_date_format[i] << ", FormatString:" << formatString;
0653         if ((formatString == "d/m/yy") || (formatString == cell_date_format[i])) {
0654             kDebug(30521) << "   FormatString: Date:" << formatString << ", CellContent:" << cell_content;
0655             QDate date;
0656             if (!kspread_cell.isDate()) {
0657                 // convert cell_content to date
0658                 int y, m, d;
0659                 bool ok = true;
0660                 int val  = cell_content.toInt(&ok);
0661 
0662                 kDebug(30521) << "!!!   FormatString: Date:" << formatString << ", CellContent:" << cell_content
0663                 << ", Double: " << val << endl;
0664                 if (!ok)
0665                     return false;
0666 
0667                 GnumericDate::jul2greg(val, y, m, d);
0668                 kDebug(30521) << "     num:" << val << ", y:" << y << ", m:" << m << ", d:" << d;
0669 
0670                 date.setYMD(y, m, d);
0671             } else
0672                 date = kspread_cell.value().asDate(kspread_cell.sheet()->map()->calculationSettings());
0673 
0674             Format::Type type;
0675             switch (i) {
0676             case 0:  type = Format::Date5;  break;
0677             case 1:  type = Format::Date6;  break;
0678             case 2:  type = Format::Date1;  break;
0679             case 3:  type = Format::Date2;  break;
0680             case 4:  type = Format::Date3;  break;
0681             case 5:  type = Format::Date4;  break;
0682             case 6:  type = Format::Date11; break;
0683             case 7:  type = Format::Date12; break;
0684             case 8:  type = Format::Date19; break;
0685             case 9:  type = Format::Date18; break;
0686             case 10: type = Format::Date20; break;
0687             case 11: type = Format::Date21; break;
0688             case 16: type = Format::Date7;  break;
0689             case 17: type = Format::Date22; break;
0690             case 18: type = Format::Date8;  break;
0691             case 19: type = Format::Date9;  break;
0692             case 22: type = Format::Date25; break;
0693             case 23: type = Format::Date14; break;
0694             case 24: type = Format::Date25; break;
0695             case 25: type = Format::Date26; break;
0696             case 26: type = Format::Date16; break;
0697             case 27: type = Format::Date15; break;
0698             case 28: type = Format::Date16; break;
0699             case 29: type = Format::Date15; break;
0700             case 30: type = Format::Date24; break;
0701             case 31: type = Format::Date23; break;
0702             default:
0703                 type = Format::ShortDate;
0704                 break;
0705                 /* 12, 13, 14, 15, 20, 21 */
0706             }
0707 
0708             kDebug(30521) << "i:" << i << ", Type:" << type << ", Date:" << date.toString();
0709 
0710             Cell cell(kspread_cell);
0711             cell.setValue(Value(date, kspread_cell.sheet()->map()->calculationSettings()));
0712             Style style;
0713             style.setFormatType(type);
0714             cell.setStyle(style);
0715 
0716             return true;
0717         }
0718     }
0719 
0720     for (i = 0; cell_time_format[i] ; ++i) {
0721         if (formatString == cell_time_format[i]) {
0722             QTime time;
0723 
0724             if (!kspread_cell.isTime()) {
0725                 bool ok = true;
0726                 double content = cell_content.toDouble(&ok);
0727 
0728                 kDebug(30521) << "   FormatString: Time:" << formatString << ", CellContent:" << cell_content
0729                 << ", Double: " << content << endl;
0730 
0731                 if (!ok)
0732                     return false;
0733 
0734                 time = GnumericDate::getTime(content);
0735             } else
0736                 time = kspread_cell.value().asTime();
0737 
0738             Format::Type type;
0739             switch (i) {
0740             case 0: type = Format::Time1; break;
0741             case 1: type = Format::Time2; break;
0742             case 2: type = Format::Time4; break;
0743             case 3: type = Format::Time5; break;
0744             case 5: type = Format::Time6; break;
0745             case 6: type = Format::Time6; break;
0746             default:
0747                 type = Format::Time1; break;
0748             }
0749 
0750             kDebug(30521) << "i:" << i << ", Type:" << type;
0751             Cell cell(kspread_cell);
0752             cell.setValue(Value(time));
0753             Style style;
0754             style.setFormatType(type);
0755             cell.setStyle(style);
0756 
0757             return true;
0758         }
0759     }
0760 
0761     return false; // no date or time
0762 }
0763 
0764 QString GNUMERICFilter::convertVars(QString const & str, Sheet * table) const
0765 {
0766     QString result(str);
0767     uint count = list1.count();
0768     if (count == 0) {
0769         list1 << "&[TAB]" << "&[DATE]" << "&[PAGE]"
0770         << "&[PAGES]" << "&[TIME]" << "&[FILE]";
0771         list2 << "<sheet>" << "<date>" << "<page>"
0772         << "<pages>" << "<time>" << "<file>";
0773         count = list1.count();
0774     }
0775 
0776     for (uint i = 0; i < count; ++i) {
0777         int n = result.indexOf(list1[i]);
0778 
0779         if (n != -1) {
0780             kDebug(30521) << "Found var:" << list1[i];
0781             if (i == 0)
0782                 result.replace(list1[i], table->sheetName());
0783             else
0784                 result.replace(list1[i], list2[i]);
0785         }
0786     }
0787 
0788     return result;
0789 }
0790 
0791 double GNUMERICFilter::parseAttribute(const QDomElement &_element)
0792 {
0793     QString unit = _element.attribute("PrefUnit");
0794     bool ok;
0795     double value = _element.attribute("Points").toFloat(&ok);
0796     if (!ok)
0797         value = 2.0;
0798     if (unit == "mm")
0799         return POINT_TO_MM(value);
0800     else if (unit == "cm")
0801         return (POINT_TO_MM(value) / 10.0);
0802     else if (unit == "in")
0803         return POINT_TO_INCH(value);
0804     else if (unit == "Pt" || unit == "Px" || unit == "points")
0805         return value;
0806     else
0807         return value;
0808 }
0809 
0810 void GNUMERICFilter::ParsePrintInfo(QDomNode const & printInfo, Sheet * table)
0811 {
0812     kDebug(30521) << "Parsing print info";
0813 
0814     float fleft = 2.0;
0815     float fright = 2.0;
0816     float ftop = 2.0;
0817     float fbottom = 2.0;
0818 
0819     QString paperSize("A4");
0820     QString orientation("Portrait");
0821     QString footLeft, footMiddle, footRight;
0822     QString headLeft, headMiddle, headRight; // no we are zombies :-)
0823 
0824     QDomNode margins(printInfo.namedItem("Margins"));
0825     if (!margins.isNull()) {
0826         QDomElement top(margins.namedItem("top").toElement());
0827         if (!top.isNull())
0828             ftop = parseAttribute(top);
0829 
0830         QDomElement bottom(margins.namedItem("bottom").toElement());
0831         if (!bottom.isNull())
0832             fbottom = parseAttribute(bottom);
0833 
0834         QDomElement left(margins.namedItem("left").toElement());
0835         if (!left.isNull())
0836             fleft = parseAttribute(left);
0837 
0838         QDomElement right(margins.namedItem("right").toElement());
0839         if (!right.isNull())
0840             fright = parseAttribute(right);
0841     }
0842 
0843     QDomElement foot(printInfo.namedItem("Footer").toElement());
0844     if (!foot.isNull()) {
0845         kDebug(30521) << "Parsing footer:" << foot.attribute("Left") << "," << foot.attribute("Middle") << ","
0846         << foot.attribute("Right") << ", " << endl;
0847         if (foot.hasAttribute("Left"))
0848             footLeft = convertVars(foot.attribute("Left"), table);
0849         if (foot.hasAttribute("Middle"))
0850             footMiddle = convertVars(foot.attribute("Middle"), table);
0851         if (foot.hasAttribute("Right"))
0852             footRight = convertVars(foot.attribute("Right"), table);
0853     }
0854 
0855     QDomElement head(printInfo.namedItem("Header").toElement());
0856     if (!head.isNull()) {
0857         kDebug(30521) << "Parsing header:" << head.attribute("Left") << "," << head.attribute("Middle") << "," << head.attribute("Right") << ",";
0858         if (head.hasAttribute("Left"))
0859             headLeft = convertVars(head.attribute("Left"), table);
0860         if (head.hasAttribute("Middle"))
0861             headMiddle = convertVars(head.attribute("Middle"), table);
0862         if (head.hasAttribute("Right"))
0863             headRight = convertVars(head.attribute("Right"), table);
0864     }
0865 
0866     QDomElement repeateColumn(printInfo.namedItem("repeat_top").toElement());
0867     if (!repeateColumn.isNull()) {
0868         QString repeate = repeateColumn.attribute("value");
0869         if (!repeate.isEmpty()) {
0870             const Calligra::Sheets::Region region(repeate);
0871             //kDebug()<<" repeate :"<<repeate<<"range. ::start row :"<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ();
0872             table->printSettings()->setRepeatedRows(qMakePair(region.firstRange().top(), region.firstRange().bottom()));
0873         }
0874     }
0875 
0876     QDomElement repeateRow(printInfo.namedItem("repeat_left").toElement());
0877     if (!repeateRow.isNull()) {
0878         QString repeate = repeateRow.attribute("value");
0879         if (!repeate.isEmpty()) {
0880             //fix row too high
0881             repeate.replace("65536", "32500");
0882             const Calligra::Sheets::Region region(repeate);
0883             //kDebug()<<" repeate :"<<repeate<<"range. ::start row :"<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ();
0884             table->printSettings()->setRepeatedColumns(qMakePair(region.firstRange().left(), region.firstRange().right()));
0885         }
0886     }
0887 
0888     QDomElement orient(printInfo.namedItem("orientation").toElement());
0889     if (!orient.isNull())
0890         orientation = orient.text();
0891 
0892     QDomElement size(printInfo.namedItem("paper").toElement());
0893     if (!size.isNull())
0894         paperSize = size.text();
0895 
0896     KoPageLayout pageLayout;
0897     pageLayout.format = KoPageFormat::formatFromString(paperSize);
0898     pageLayout.orientation = (orientation == "Portrait")
0899                              ? KoPageFormat::Portrait : KoPageFormat::Landscape;
0900     pageLayout.leftMargin   = fleft;
0901     pageLayout.rightMargin  = fright;
0902     pageLayout.topMargin    = ftop;
0903     pageLayout.bottomMargin = fbottom;
0904     table->printSettings()->setPageLayout(pageLayout);
0905 
0906     table->headerFooter()->setHeadFootLine(headLeft, headMiddle, headRight,
0907                                            footLeft, footMiddle, footRight);
0908 }
0909 
0910 void GNUMERICFilter::ParseFormat(QString const & formatString, const Cell& kspread_cell)
0911 {
0912     int l = formatString.length();
0913     int lastPos = 0;
0914 
0915     if (l == 0) return;
0916 
0917     Style style;
0918 
0919     if (l == 0 || formatString == "General") {
0920         style.setFormatType(Format::Generic);
0921     } else if (formatString[l - 1] == '%') {
0922         style.setFormatType(Format::Percentage);
0923     } else if (formatString[0] == '$') { // dollar
0924         style.setFormatType(Format::Money);
0925         Currency currency("$");
0926         style.setCurrency(currency);
0927         lastPos = 1;
0928     } else if (formatString.startsWith("£")) { // pound
0929         style.setFormatType(Format::Money);
0930         Currency currency("£");
0931         style.setCurrency(currency);
0932         lastPos = 1;
0933     } else if (formatString.startsWith("Â¥")) { // yen
0934         style.setFormatType(Format::Money);
0935         Currency currency("Â¥");
0936         style.setCurrency(currency);
0937         lastPos = 1;
0938     } else if (formatString.startsWith("€")) { // euro
0939         style.setFormatType(Format::Money);
0940         Currency currency("€");
0941         style.setCurrency(currency);
0942         lastPos = 1;
0943     } else if (l > 1) {
0944         if ((formatString[0] == '[') && (formatString[1] == '$')) {
0945             int n = formatString.indexOf(']');
0946             if (n != -1) {
0947                 style.setFormatType(Format::Money);
0948                 Currency currency(formatString.mid(2, n - 2));
0949                 style.setCurrency(currency);
0950             }
0951             lastPos = ++n;
0952         } else if (formatString.indexOf("E+0") != -1) {
0953             style.setFormatType(Format::Scientific);
0954         } else {
0955             // do pattern matching with gnumeric formats
0956             QString content(kspread_cell.value().asString());
0957 
0958             if (setType(kspread_cell, formatString, content))
0959                 return;
0960 
0961             if (formatString.indexOf("?/?") != -1) {
0962                 // TODO: fixme!
0963                 style.setFormatType(Format::fraction_three_digits);
0964                 Cell(kspread_cell).setStyle(style);
0965                 return;
0966             }
0967             // so it's nothing we want to understand:-)
0968             return;
0969         }
0970     }
0971 
0972     while (formatString[lastPos] == ' ')
0973         ++lastPos;
0974 
0975     // GetPrecision and decimal point, format of negative items...
0976 
0977     // thousands separator
0978     if (formatString[lastPos] == '#') {
0979         if (formatString[lastPos + 1] == ',')
0980             lastPos += 2;
0981         // since KSpread 1.3
0982         // kspread_cell.setThousandsSeparator( sep );
0983     }
0984 
0985     while (formatString[lastPos] == ' ')
0986         ++lastPos;
0987 
0988     int n = formatString.indexOf('.', lastPos);
0989     if (n != -1) {
0990         lastPos = n + 1;
0991         int precision = lastPos;
0992         while (formatString[precision] == '0')
0993             ++precision;
0994 
0995         int tmp = lastPos;
0996         lastPos = precision;
0997         precision -= tmp;
0998 
0999         style.setPrecision(precision);
1000     }
1001 
1002     bool red = false;
1003     if (formatString.indexOf("[RED]", lastPos) != -1) {
1004         red = true;
1005         style.setFloatColor(Style::NegRed);
1006     }
1007     if (formatString.indexOf('(', lastPos) != -1) {
1008         if (red)
1009             style.setFloatColor(Style::NegRedBrackets);
1010         else
1011             style.setFloatColor(Style::NegBrackets);
1012     }
1013     Cell(kspread_cell).setStyle(style);
1014 }
1015 
1016 void GNUMERICFilter::convertFormula(QString & formula) const
1017 {
1018     int n = formula.indexOf('=', 1);
1019 
1020     // TODO: check if we do not screw something up here...
1021     if (n != -1)
1022         formula.replace(n, 1, "==");
1023 
1024     bool inQuote1 = false;
1025     bool inQuote2 = false;
1026     int l = formula.length();
1027     for (int i = 0; i < l; ++i) {
1028         if (formula[i] == '\'')
1029             inQuote1 = !inQuote1;
1030         else if (formula[i] == '"')
1031             inQuote2 = !inQuote2;
1032         else if (formula[i] == ',' && !inQuote1 && !inQuote2)
1033             formula.replace(i, 1, ';');
1034     }
1035 }
1036 
1037 void GNUMERICFilter::setStyleInfo(QDomNode * sheet, Sheet * table)
1038 {
1039     kDebug(30521) << "SetStyleInfo entered";
1040     ValueParser *const parser = table->map()->parser();
1041 
1042     int row, column;
1043     QDomNode styles =  sheet->namedItem("Styles");
1044     if (!styles.isNull()) {
1045         // Get a style region within that sheet.
1046         QDomNode style_region =  styles.namedItem("StyleRegion");
1047 
1048         while (!style_region.isNull()) {
1049             QDomElement e = style_region.toElement(); // try to convert the node to an element.
1050 
1051             QDomNode gnumericStyle = style_region.namedItem("Style");
1052             QDomNode font = gnumericStyle.namedItem("Font");
1053             QDomNode validation = gnumericStyle.namedItem("Validation");
1054             QDomNode gmr_styleborder = gnumericStyle.namedItem("StyleBorder");
1055             QDomNode hyperlink = gnumericStyle.namedItem("HyperLink");
1056             int startCol = e.attribute("startCol").toInt() + 1;
1057             int endCol   = e.attribute("endCol").toInt() + 1;
1058             int startRow = e.attribute("startRow").toInt() + 1;
1059             int endRow   = e.attribute("endRow").toInt() + 1;
1060 
1061             kDebug(30521) << "------Style:" << startCol << ","
1062             << startRow << " - " << endCol << ", " << endRow << endl;
1063 
1064             if (endCol - startCol > 200 || endRow - startRow > 200) {
1065                 style_region = style_region.nextSibling();
1066                 continue;
1067             }
1068 
1069             for (column = startCol; column <= endCol; ++column) {
1070                 for (row = startRow; row <= endRow; ++row) {
1071                     kDebug(30521) << "Cell:" << column << "," << row;
1072                     Cell kspread_cell(table, column, row);
1073                     Style style;
1074 
1075                     // don't create new cells -> don't apply format on empty cells, if bigger region
1076                     if ((kspread_cell.isDefault() || kspread_cell.isEmpty())
1077                             && ((endCol - startCol > 2) || (endRow - startRow > 2))) {
1078                         kDebug(30521) << "CELL EMPTY OR RANGE TOO BIG";
1079                         continue;
1080                     }
1081 
1082                     QDomElement style_element = gnumericStyle.toElement(); // try to convert the node to an element.
1083 
1084                     kDebug(30521) << "Style valid for Calligra Sheets";
1085                     kspread_cell = Cell(table, column, row);
1086 
1087                     if (style_element.hasAttribute("Fore")) {
1088                         QString color_string = style_element.attribute("Fore");
1089                         QColor color;
1090                         convert_string_to_qcolor(color_string, &color);
1091                         style.setFontColor(color);
1092                     }
1093 
1094                     if (style_element.hasAttribute("Back")) {
1095                         QString color_string = style_element.attribute("Back");
1096                         QColor color;
1097                         convert_string_to_qcolor(color_string, &color);
1098                         style.setBackgroundColor(color);
1099                     }
1100 
1101                     QBrush backgroundBrush;
1102                     if (style_element.hasAttribute("PatternColor")) {
1103                         QString color_string = style_element.attribute("PatternColor");
1104                         QColor color;
1105                         convert_string_to_qcolor(color_string, &color);
1106                         backgroundBrush.setColor(color);
1107                     }
1108 
1109                     if (style_element.hasAttribute("Shade")) {
1110                         /* Pattern's taken from: gnumeric's pattern.c */
1111                         /* if "TODO" added: doesn't match exactly the gnumeric one */
1112 
1113                         QString shade = style_element.attribute("Shade");
1114                         if (shade == "0") {
1115                             // nothing to do
1116                         } else if (shade == "1") {
1117                             /* 1 Solid */
1118                             //backgroundBrush.setStyle(Qt::SolidPattern);
1119                             //This is as empty
1120                             /* What should this be? */
1121 
1122                         } else if (shade == "2") {
1123                             /* 2 75% */
1124                             backgroundBrush.setStyle(Qt::Dense2Pattern);
1125                         } else if (shade == "3") {
1126                             /* 3 50% */
1127                             backgroundBrush.setStyle(Qt::Dense4Pattern);
1128                         } else if (shade == "4") {
1129                             backgroundBrush.setStyle(Qt::Dense5Pattern);
1130                             /* This should be 25%... All qt has is 37% */
1131 
1132                             /* 4 25% */
1133                         } else if (shade == "5") {
1134                             backgroundBrush.setStyle(Qt::Dense6Pattern);
1135                             /* 5 12.5% */
1136                         } else if (shade == "6") {
1137                             backgroundBrush.setStyle(Qt::Dense7Pattern);
1138                             /* 6 6.25% */
1139 
1140                         } else if (shade == "7") {
1141                             backgroundBrush.setStyle(Qt::HorPattern);
1142                             /* 7 Horizontal Stripe */
1143                         } else if (shade == "8") {
1144                             backgroundBrush.setStyle(Qt::VerPattern);
1145                             /* 8 Vertical Stripe */
1146                         } else if (shade == "9") {
1147                             backgroundBrush.setStyle(Qt::BDiagPattern);
1148                             /* 9 Reverse Diagonal Stripe */
1149                         } else if (shade == "10") {
1150                             /* 10 Diagonal Stripe */
1151                             backgroundBrush.setStyle(Qt::FDiagPattern);
1152                         } else if (shade == "11") {
1153                             /* 11 Diagonal Crosshatch */
1154                             backgroundBrush.setStyle(Qt::DiagCrossPattern);
1155                         } else if (shade == "12") {
1156                             /* 12 Thick Diagonal Crosshatch TODO!*/
1157                             backgroundBrush.setStyle(Qt::DiagCrossPattern);
1158                         } else if (shade == "13") {
1159                             /* 13 Thin Horizontal Stripe TODO: wrong: this is thick!*/
1160                             backgroundBrush.setStyle(Qt::HorPattern);
1161                         } else if (shade == "14") {
1162                             backgroundBrush.setStyle(Qt::VerPattern);
1163                         } else if (shade == "15") {
1164                             backgroundBrush.setStyle(Qt::FDiagPattern);
1165                         } else if (shade == "16") {
1166                             /* 16 Thick Reverse Stripe TODO:*/
1167                             backgroundBrush.setStyle(Qt::BDiagPattern);
1168                         } else if (shade == "17") {
1169                             backgroundBrush.setStyle(Qt::DiagCrossPattern);
1170                         } else if (shade == "18") {
1171                             backgroundBrush.setStyle(Qt::DiagCrossPattern);
1172                         } else if (shade == "19") {
1173                             /* 19 Applix small circle */
1174                         } else if (shade == "20") {
1175                             /* 20 Applix semicircle */
1176                         } else if (shade == "21") {
1177                             /* 21 Applix small thatch */
1178                         } else if (shade == "22") {
1179                             /* 22 Applix round thatch */
1180                         } else if (shade == "23") {
1181                             /* 23 Applix Brick */
1182                         } else if (shade == "24") {
1183                             /* 24 100% */
1184                             backgroundBrush.setStyle(Qt::SolidPattern);
1185                         } else if (shade == "25") {
1186                             /* 25 87.5% */
1187                             backgroundBrush.setStyle(Qt::Dense2Pattern);
1188                         }
1189                     }
1190                     style.setBackgroundBrush(backgroundBrush);
1191 
1192                     if (style_element.hasAttribute("Rotation")) {
1193                         int rot = style_element.attribute("Rotation").toInt();
1194                         style.setAngle(-1* rot);
1195                     }
1196                     if (style_element.hasAttribute("Indent")) {
1197                         double indent = style_element.attribute("Indent").toDouble();
1198                         // gnumeric saves indent in characters, we in points:
1199                         style.setIndentation(indent * 10.0);
1200                     }
1201 
1202                     if (style_element.hasAttribute("HAlign")) {
1203                         QString halign_string = style_element.attribute("HAlign");
1204 
1205                         if (halign_string == "1") {
1206                             /* General: No equivalent in Calligra Sheets. */
1207                         } else if (halign_string == "2") {
1208                             style.setHAlign(Style::Left);
1209                         } else if (halign_string == "4") {
1210                             style.setHAlign(Style::Right);
1211                         } else if (halign_string == "8") {
1212                             style.setHAlign(Style::Center);
1213                         } else if (halign_string == "16") {
1214                             /* Fill: No equivalent in Calligra Sheets. */
1215                         } else if (halign_string == "32") {
1216                             /* Justify: No equivalent in Calligra Sheets */
1217                         } else if (halign_string == "64") {
1218                             /* Centered across selection*/
1219                         }
1220 
1221                     }
1222 
1223                     if (style_element.hasAttribute("VAlign")) {
1224                         QString valign_string = style_element.attribute("VAlign");
1225 
1226                         if (valign_string == "1") {
1227                             /* General: No equivalent in Calligra Sheets. */
1228                             style.setVAlign(Style::Top);
1229                         } else if (valign_string == "2") {
1230                             style.setVAlign(Style::Bottom);
1231                         } else if (valign_string == "4") {
1232                             style.setVAlign(Style::Middle);
1233                         } else if (valign_string == "8") {
1234                             /* Justify: No equivalent in Calligra Sheets */
1235                         }
1236                     }
1237 
1238                     if (style_element.hasAttribute("WrapText")) {
1239                         QString multiRow = style_element.attribute("WrapText");
1240 
1241                         if (multiRow == "1")
1242                             style.setWrapText(true);
1243                     }
1244 
1245                     if (style_element.hasAttribute("Format")) {
1246                         QString formatString = style_element.attribute("Format");
1247 
1248                         kDebug(30521) << "Format:" << formatString;
1249                         ParseFormat(formatString, kspread_cell);
1250 
1251                     } // End "Format"
1252 
1253                     if (!gmr_styleborder.isNull()) {
1254                         QDomElement style_element = gmr_styleborder.toElement(); // try to convert the node to an element.
1255                         ParseBorder(style_element, kspread_cell);
1256                     }
1257                     if (!validation.isNull()) {
1258                         QDomElement validation_element = validation.toElement();
1259                         if (!validation_element.isNull()) {
1260                             kDebug(30521) << " Cell validation";
1261                             Validity kspread_validity = kspread_cell.validity();
1262                             if (validation_element.hasAttribute("AllowBlank") && validation_element.attribute("AllowBlank") == "true") {
1263                                 kspread_validity.setAllowEmptyCell(true);
1264                             }
1265                             if (validation_element.hasAttribute("Title")) {
1266                                 kspread_validity.setTitle(validation_element.attribute("Title"));
1267                             }
1268                             if (validation_element.hasAttribute("Message")) {
1269                                 kspread_validity.setMessage(validation_element.attribute("Message"));
1270                             }
1271                             if (validation_element.hasAttribute("Style")) {
1272                                 int value = validation_element.attribute("Style").toInt();
1273                                 switch (value) {
1274                                 case 0:
1275                                     kspread_validity.setDisplayMessage(false);
1276                                     break;
1277                                 case 1:
1278                                     kspread_validity.setAction(Validity::Stop);
1279                                     break;
1280                                 case 2:
1281                                     kspread_validity.setAction(Validity::Warning);
1282                                     break;
1283                                 case 3:
1284                                     kspread_validity.setAction(Validity::Information);
1285                                     break;
1286                                 default:
1287                                     kDebug() << " Error in validation style :" << value;
1288                                     break;
1289                                 }
1290                             }
1291                             QDomNode expression0 = validation_element.namedItem("Expression0");
1292                             QDomNode expression1 = validation_element.namedItem("Expression1");
1293                             //kDebug()<<" expression0.isNull()"<<expression0.isNull();
1294                             //kDebug()<<" expression1.isNull()"<<expression1.isNull();
1295                             if (validation_element.hasAttribute("Type")) {
1296                                 int valueOp = validation_element.attribute("Type").toInt();
1297                                 switch (valueOp) {
1298                                 case 0:
1299                                     kspread_validity.setRestriction(Validity::None);
1300                                     break;
1301                                 case 1: {
1302                                     kspread_validity.setRestriction(Validity::Integer);
1303                                     if (validation_element.hasAttribute("Operator")) {
1304                                         const Value value1(expression0.toElement().text().toInt());
1305                                         const Value value2(expression1.toElement().text().toInt());
1306                                         int value = validation_element.attribute("Operator").toInt();
1307                                         switch (value) {
1308                                         case 0:
1309                                             kspread_validity.setCondition(Conditional::Between);
1310                                             if (!expression0.isNull())
1311                                                 kspread_validity.setMinimumValue(value1);
1312                                             if (!expression1.isNull())
1313                                                 kspread_validity.setMaximumValue(value2);
1314                                             break;
1315                                         case 1:
1316                                             kspread_validity.setCondition(Conditional::DifferentTo);
1317                                             if (!expression0.isNull())
1318                                                 kspread_validity.setMinimumValue(value1);
1319                                             if (!expression1.isNull())
1320                                                 kspread_validity.setMaximumValue(value2);
1321                                             break;
1322                                         case 2:
1323                                             kspread_validity.setCondition(Conditional::Equal);
1324                                             if (!expression0.isNull())
1325                                                 kspread_validity.setMinimumValue(value1);
1326                                             break;
1327                                         case 3:
1328                                             kspread_validity.setCondition(Conditional::Different);
1329                                             if (!expression0.isNull())
1330                                                 kspread_validity.setMinimumValue(value1);
1331                                             break;
1332                                         case 4:
1333                                             kspread_validity.setCondition(Conditional::Superior);
1334                                             if (!expression0.isNull())
1335                                                 kspread_validity.setMinimumValue(value1);
1336                                             break;
1337                                         case 5:
1338                                             kspread_validity.setCondition(Conditional::Inferior);
1339                                             if (!expression0.isNull())
1340                                                 kspread_validity.setMinimumValue(value1);
1341                                             break;
1342                                         case 6:
1343                                             kspread_validity.setCondition(Conditional::SuperiorEqual);
1344                                             if (!expression0.isNull())
1345                                                 kspread_validity.setMinimumValue(value1);
1346                                             break;
1347                                         case 7:
1348                                             kspread_validity.setCondition(Conditional::InferiorEqual);
1349                                             if (!expression0.isNull())
1350                                                 kspread_validity.setMinimumValue(value1);
1351                                             break;
1352                                         default:
1353                                             kDebug() << " Error in validation Operator :" << value;
1354                                             break;
1355                                         }
1356                                     }
1357                                 }
1358                                 break;
1359                                 case 2:
1360                                     kspread_validity.setRestriction(Validity::Number);
1361                                     if (validation_element.hasAttribute("Operator")) {
1362                                         const Value value1(expression0.toElement().text().toInt());
1363                                         const Value value2(expression1.toElement().text().toInt());
1364                                         int value = validation_element.attribute("Operator").toInt();
1365                                         switch (value) {
1366                                         case 0:
1367                                             kspread_validity.setCondition(Conditional::Between);
1368                                             if (!expression0.isNull())
1369                                                 kspread_validity.setMinimumValue(value1);
1370                                             if (!expression1.isNull())
1371                                                 kspread_validity.setMaximumValue(value2);
1372                                             break;
1373                                         case 1:
1374                                             kspread_validity.setCondition(Conditional::DifferentTo);
1375                                             if (!expression0.isNull())
1376                                                 kspread_validity.setMinimumValue(value1);
1377                                             if (!expression1.isNull())
1378                                                 kspread_validity.setMaximumValue(value2);
1379                                             break;
1380                                         case 2:
1381                                             kspread_validity.setCondition(Conditional::Equal);
1382                                             if (!expression0.isNull())
1383                                                 kspread_validity.setMinimumValue(value1);
1384                                             break;
1385                                         case 3:
1386                                             kspread_validity.setCondition(Conditional::Different);
1387                                             if (!expression0.isNull())
1388                                                 kspread_validity.setMinimumValue(value1);
1389                                             break;
1390                                         case 4:
1391                                             kspread_validity.setCondition(Conditional::Superior);
1392                                             if (!expression0.isNull())
1393                                                 kspread_validity.setMinimumValue(value1);
1394                                             break;
1395                                         case 5:
1396                                             if (!expression0.isNull())
1397                                                 kspread_validity.setMinimumValue(value1);
1398                                             kspread_validity.setCondition(Conditional::Inferior);
1399                                             break;
1400                                         case 6:
1401                                             kspread_validity.setCondition(Conditional::SuperiorEqual);
1402                                             if (!expression0.isNull())
1403                                                 kspread_validity.setMinimumValue(value1);
1404                                             break;
1405                                         case 7:
1406                                             kspread_validity.setCondition(Conditional::InferiorEqual);
1407                                             if (!expression0.isNull())
1408                                                 kspread_validity.setMinimumValue(value1);
1409                                             break;
1410                                         default:
1411                                             kDebug() << " Error in validation Operator :" << value;
1412                                             break;
1413                                         }
1414                                     }
1415                                     break;
1416                                 case 3:
1417                                     kspread_validity.setRestriction(Validity::List);
1418                                     break;
1419                                 case 4:
1420                                     kspread_validity.setRestriction(Validity::Date);
1421                                     if (validation_element.hasAttribute("Operator")) {
1422                                         const Value value1 = parser->tryParseDate(expression0.toElement().text());
1423                                         const Value value2 = parser->tryParseDate(expression1.toElement().text());
1424                                         int value = validation_element.attribute("Operator").toInt();
1425                                         switch (value) {
1426                                         case 0:
1427                                             kspread_validity.setCondition(Conditional::Between);
1428                                             if (!expression0.isNull())
1429                                                 kspread_validity.setMinimumValue(value1);
1430                                             if (!expression1.isNull())
1431                                                 kspread_validity.setMaximumValue(value2);
1432 
1433                                             break;
1434                                         case 1:
1435                                             if (!expression0.isNull())
1436                                                 kspread_validity.setMinimumValue(value1);
1437                                             if (!expression1.isNull())
1438                                                 kspread_validity.setMaximumValue(value2);
1439                                             kspread_validity.setCondition(Conditional::DifferentTo);
1440                                             break;
1441                                         case 2:
1442                                             if (!expression0.isNull())
1443                                                 kspread_validity.setMinimumValue(value1);
1444                                             kspread_validity.setCondition(Conditional::Equal);
1445                                             break;
1446                                         case 3:
1447                                             if (!expression0.isNull())
1448                                                 kspread_validity.setMinimumValue(value1);
1449                                             kspread_validity.setCondition(Conditional::Different);
1450                                             break;
1451                                         case 4:
1452                                             if (!expression0.isNull())
1453                                                 kspread_validity.setMinimumValue(value1);
1454                                             kspread_validity.setCondition(Conditional::Superior);
1455                                             break;
1456                                         case 5:
1457                                             if (!expression0.isNull())
1458                                                 kspread_validity.setMinimumValue(value1);
1459                                             kspread_validity.setCondition(Conditional::Inferior);
1460                                             break;
1461                                         case 6:
1462                                             if (!expression0.isNull())
1463                                                 kspread_validity.setMinimumValue(value1);
1464                                             kspread_validity.setCondition(Conditional::SuperiorEqual);
1465                                             break;
1466                                         case 7:
1467                                             if (!expression0.isNull())
1468                                                 kspread_validity.setMinimumValue(value1);
1469                                             kspread_validity.setCondition(Conditional::InferiorEqual);
1470                                             break;
1471                                         default:
1472                                             kDebug() << " Error in validation Operator :" << value;
1473                                             break;
1474                                         }
1475                                     }
1476                                     break;
1477                                 case 5:
1478                                     kspread_validity.setRestriction(Validity::Time);
1479                                     if (validation_element.hasAttribute("Operator")) {
1480                                         const Value value1 = parser->tryParseTime(expression0.toElement().text());
1481                                         const Value value2 = parser->tryParseTime(expression1.toElement().text());
1482                                         int value = validation_element.attribute("Operator").toInt();
1483                                         switch (value) {
1484                                         case 0:
1485                                             kspread_validity.setCondition(Conditional::Between);
1486                                             if (!expression0.isNull())
1487                                                 kspread_validity.setMinimumValue(value1);
1488                                             if (!expression1.isNull())
1489                                                 kspread_validity.setMaximumValue(value2);
1490                                             break;
1491                                         case 1:
1492                                             if (!expression0.isNull())
1493                                                 kspread_validity.setMinimumValue(value1);
1494                                             if (!expression1.isNull())
1495                                                 kspread_validity.setMaximumValue(value2);
1496                                             kspread_validity.setCondition(Conditional::DifferentTo);
1497                                             break;
1498                                         case 2:
1499                                             if (!expression0.isNull())
1500                                                 kspread_validity.setMinimumValue(value1);
1501                                             kspread_validity.setCondition(Conditional::Equal);
1502                                             break;
1503                                         case 3:
1504                                             kspread_validity.setCondition(Conditional::Different);
1505                                             break;
1506                                         case 4:
1507                                             if (!expression0.isNull())
1508                                                 kspread_validity.setMinimumValue(value1);
1509                                             kspread_validity.setCondition(Conditional::Superior);
1510                                             break;
1511                                         case 5:
1512                                             kspread_validity.setCondition(Conditional::Inferior);
1513                                             if (!expression0.isNull())
1514                                                 kspread_validity.setMinimumValue(value1);
1515                                             break;
1516                                         case 6:
1517                                             kspread_validity.setCondition(Conditional::SuperiorEqual);
1518                                             if (!expression0.isNull())
1519                                                 kspread_validity.setMinimumValue(value1);
1520                                             break;
1521                                         case 7:
1522                                             if (!expression0.isNull())
1523                                                 kspread_validity.setMinimumValue(value1);
1524                                             kspread_validity.setCondition(Conditional::InferiorEqual);
1525                                             break;
1526                                         default:
1527                                             kDebug() << " Error in validation Operator :" << value;
1528                                             break;
1529                                         }
1530                                     }
1531                                     break;
1532                                 case 6:
1533                                     kspread_validity.setRestriction(Validity::TextLength);
1534                                     if (validation_element.hasAttribute("Operator")) {
1535                                         const Value value1(expression0.toElement().text().toInt());
1536                                         const Value value2(expression1.toElement().text().toInt());
1537                                         int value = validation_element.attribute("Operator").toInt();
1538                                         switch (value) {
1539                                         case 0:
1540                                             kspread_validity.setCondition(Conditional::Between);
1541                                             if (!expression0.isNull())
1542                                                 kspread_validity.setMinimumValue(value1);
1543                                             if (!expression1.isNull())
1544                                                 kspread_validity.setMaximumValue(value2);
1545                                             break;
1546                                         case 1:
1547                                             kspread_validity.setCondition(Conditional::DifferentTo);
1548                                             if (!expression0.isNull())
1549                                                 kspread_validity.setMinimumValue(value1);
1550                                             if (!expression1.isNull())
1551                                                 kspread_validity.setMaximumValue(value2);
1552                                             break;
1553                                         case 2:
1554                                             kspread_validity.setCondition(Conditional::Equal);
1555                                             if (!expression0.isNull())
1556                                                 kspread_validity.setMinimumValue(value1);
1557                                             break;
1558                                         case 3:
1559                                             kspread_validity.setCondition(Conditional::Different);
1560                                             if (!expression0.isNull())
1561                                                 kspread_validity.setMinimumValue(value1);
1562                                             break;
1563                                         case 4:
1564                                             if (!expression0.isNull())
1565                                                 kspread_validity.setMinimumValue(value1);
1566                                             kspread_validity.setCondition(Conditional::Superior);
1567                                             break;
1568                                         case 5:
1569                                             if (!expression0.isNull())
1570                                                 kspread_validity.setMinimumValue(value1);
1571                                             kspread_validity.setCondition(Conditional::Inferior);
1572                                             break;
1573                                         case 6:
1574                                             if (!expression0.isNull())
1575                                                 kspread_validity.setMinimumValue(value1);
1576                                             kspread_validity.setCondition(Conditional::SuperiorEqual);
1577                                             break;
1578                                         case 7:
1579                                             if (!expression0.isNull())
1580                                                 kspread_validity.setMinimumValue(value1);
1581                                             kspread_validity.setCondition(Conditional::InferiorEqual);
1582                                             break;
1583                                         default:
1584                                             kDebug() << " Error in validation Operator :" << value;
1585                                             break;
1586                                         }
1587                                     }
1588                                     break;
1589                                 default:
1590                                     kDebug() << " Error in Type element :" << valueOp;
1591                                 }
1592 
1593                             }
1594                             //<Validation Style="0" Type="1" Operator="0" AllowBlank="true" UseDropdown="false">
1595                             //<Expression0>745</Expression0>
1596                             //<Expression1>4546</Expression1>
1597                         }
1598                     }
1599                     if (!font.isNull()) {
1600                         QDomElement font_element = font.toElement();
1601 
1602                         style.setFontFamily(font_element.text());
1603 
1604                         if (!font_element.isNull()) {
1605                             if (font_element.attribute("Italic") == "1") {
1606                                 style.setFontItalic(true);
1607                             }
1608 
1609                             if (font_element.attribute("Bold") == "1") {
1610                                 style.setFontBold(true);
1611                             }
1612 
1613                             if (font_element.hasAttribute("Underline") && (font_element.attribute("Underline") != "0")) {
1614                                 style.setFontUnderline(true);
1615                             }
1616 
1617                             if (font_element.hasAttribute("StrikeThrough") && (font_element.attribute("StrikeThrough") != "0")) {
1618                                 style.setFontStrikeOut(true);
1619                             }
1620 
1621                             if (font_element.hasAttribute("Unit")) {
1622                                 style.setFontSize(font_element.attribute("Unit").toInt());
1623                             }
1624 
1625                         }
1626                         if (!hyperlink.isNull()) {
1627                             //<HyperLink type="GnmHLinkURL" target="www.kde.org"/>
1628                             if (hyperlink.toElement().hasAttribute("type")) {
1629                                 QString linkType = hyperlink.toElement().attribute("type");
1630                                 QString target = hyperlink.toElement().attribute("target");
1631                                 QString tip = hyperlink.toElement().attribute("tip");
1632                                 if (!tip.isEmpty()) {
1633                                     kspread_cell.setUserInput(tip);
1634                                     kspread_cell.setValue(Value(tip));
1635                                 }
1636                                 if (linkType == "GnmHLinkURL") {
1637                                     if (!target.startsWith("http://"))
1638                                         target = "http://" + target;
1639                                     kspread_cell.setLink(target);
1640                                 } else if (linkType == "GnmHLinkEMail") {
1641                                     if (!target.startsWith("mailto:/"))
1642                                         target = "mailto:/" + target;
1643                                     kspread_cell.setLink(target);
1644                                 } else if (linkType == "GnmHLinkExternal") {
1645                                     if (!target.startsWith("file://"))
1646                                         target = "file://" + target;
1647 
1648                                     kspread_cell.setLink(target);
1649                                 } else if (linkType == "GnmHLinkCurWB") {
1650                                     kspread_cell.setLink(target);
1651                                 } else
1652                                     kDebug() << " linkType not defined :" << linkType;
1653                             }
1654                         }
1655                     }
1656                     kspread_cell.setStyle(style);
1657                 }
1658             }
1659             style_region = style_region.nextSibling();
1660         }
1661 
1662     }
1663 }
1664 
1665 /* NOTE: As of now everything is in a single huge function.  This is
1666          very ugly.  It should all be broken up into smaller
1667          functions, probably one for each GNUMeric section.  It kind
1668          of grew out of control.  It could probably be cleaned up in
1669          an hour or so. --PGE
1670   */
1671 
1672 
1673 KoFilter::ConversionStatus GNUMERICFilter::convert(const QByteArray & from, const QByteArray & to)
1674 {
1675     dateInit();
1676     bool bSuccess = true;
1677 
1678     kDebug(30521) << "Entering GNUmeric Import filter.";
1679 
1680     KoDocument * document = m_chain->outputDocument();
1681     if (!document)
1682         return KoFilter::StupidError;
1683 
1684     kDebug(30521) << "here we go..." << document->metaObject()->className();
1685 
1686     if (!qobject_cast<const Calligra::Sheets::Doc *>(document)) {    // it's safer that way :)
1687         kWarning(30521) << "document isn't a Calligra::Sheets::Doc but a " << document->metaObject()->className();
1688         return KoFilter::NotImplemented;
1689     }
1690     if (from != "application/x-gnumeric" || to != "application/x-kspread") {
1691         kWarning(30521) << "Invalid mimetypes " << from << " " << to;
1692         return KoFilter::NotImplemented;
1693     }
1694 
1695     kDebug(30521) << "...still here...";
1696 
1697     // No need for a dynamic cast here, since we use Qt's moc magic
1698     Doc * ksdoc = (Doc *) document;
1699 
1700     if (ksdoc->mimeType() != "application/x-kspread") {
1701         kWarning(30521) << "Invalid document mimetype " << ksdoc->mimeType();
1702         return KoFilter::NotImplemented;
1703     }
1704 
1705 
1706     QIODevice* in = new KCompressionDevice(m_chain->inputFile(), KCompressionDevice::GZip);
1707 
1708     if (!in) {
1709         kError(30521) << "Cannot create device for uncompressing! Aborting!" << endl;
1710         return KoFilter::FileNotFound;
1711     }
1712 
1713     if (!in->open(QIODevice::ReadOnly)) {
1714         kError(30521) << "Cannot open file for uncompressing! Aborting!" << endl;
1715         delete in;
1716         return KoFilter::FileNotFound;
1717     }
1718 
1719     QDomDocument doc;
1720     QString errorMsg;
1721     int errorLine, errorColumn;
1722     if (!doc.setContent(in, true, &errorMsg, &errorLine, &errorColumn)) {
1723         kError(30521) << "Parsing error in " << from << "! Aborting!" << endl
1724         << " In line: " << errorLine << ", column: " << errorColumn << endl
1725         << " Error message: " << errorMsg << endl;
1726         in->close();
1727         return KoFilter::ParsingError;
1728     }
1729 
1730     in->close();
1731     delete in;
1732 
1733     int row, column;
1734     int value = 0;
1735     int currentTab = -1;
1736     int selectedTab = 0;
1737     Sheet * selTable = 0;
1738 
1739     QDomElement docElem = doc.documentElement();
1740     QDomElement uiData  = docElem.namedItem("UIData").toElement();
1741     if (!uiData.isNull()) {
1742         if (uiData.hasAttribute("SelectedTab")) {
1743             bool ok = false;
1744             int n = uiData.attribute("SelectedTab").toInt(&ok);
1745             if (ok) {
1746                 selectedTab = n;
1747             }
1748         }
1749     }
1750     QDomNode sheets = docElem.namedItem("Sheets");
1751     if (sheets.isNull()) {
1752         //avoid crash with new file format.
1753         //TODO allow to load new file format
1754         return KoFilter::ParsingError;
1755     }
1756     QDomNode sheet =  sheets.namedItem("Sheet");
1757 
1758     /* This sets the Document information. */
1759     set_document_info(document, &docElem);
1760 
1761     /* This sets the Document attributes */
1762     set_document_attributes(ksdoc, &docElem);
1763 
1764     /* This sets the Area Names */
1765     set_document_area_names(ksdoc, &docElem);
1766 
1767     Sheet * table;
1768 
1769     // This is a mapping of exprID to expressions.
1770 
1771     QMap<QString, char*> exprID_dict;
1772     int num = 1;
1773 
1774     while (!sheet.isNull()) {
1775         ++currentTab;
1776         table = ksdoc->map()->addNewSheet();
1777 
1778         if (currentTab == selectedTab)
1779             selTable = table;
1780 
1781         QDomElement name = sheet.namedItem("Name").toElement();
1782         QDomElement sheetElement = sheet.toElement();
1783 
1784         if (!name.isNull())
1785             table->setSheetName(name.text(), true);
1786         else
1787             table->setSheetName("Sheet" + QString::number(num), true);
1788 
1789         //kDebug()<<" sheetElement.hasAttribute( DisplayFormulas ) :"<<sheetElement.hasAttribute("DisplayFormulas" );
1790         QString tmp;
1791         if (sheetElement.hasAttribute("DisplayFormulas")) {
1792             tmp = sheetElement.attribute("DisplayFormulas");
1793             table->setShowFormula((tmp == "true") || (tmp == "1"));
1794         }
1795         if (sheetElement.hasAttribute("HideZero")) {
1796             tmp = sheetElement.attribute("HideZero");
1797             table->setHideZero((tmp == "true") || (tmp == "1"));
1798         }
1799         if (sheetElement.hasAttribute("HideGrid")) {
1800             tmp = sheetElement.attribute("HideGrid");
1801             table->setShowGrid((tmp == "false") || (tmp == "0"));
1802         }
1803         if (sheetElement.hasAttribute("HideColHeader")) {
1804             tmp = sheetElement.attribute("HideColHeader");
1805             ksdoc->map()->settings()->setShowColumnHeader((tmp == "false") || (tmp == "0"));
1806         }
1807         if (sheetElement.hasAttribute("HideRowHeader")) {
1808             tmp = sheetElement.attribute("HideRowHeader");
1809             ksdoc->map()->settings()->setShowRowHeader((tmp == "false") || (tmp == "0"));
1810         }
1811 
1812 
1813         setObjectInfo(&sheet, table);
1814         setColInfo(&sheet, table);
1815         setRowInfo(&sheet, table);
1816         setSelectionInfo(&sheet, table);
1817 
1818         /* handling print information */
1819         QDomNode printInfo = sheet.namedItem("PrintInformation");
1820         if (!printInfo.isNull())
1821             ParsePrintInfo(printInfo, table);
1822 
1823         kDebug(30521) << "Reading in cells";
1824 
1825         /* CELL handling START */
1826         QDomNode cells = sheet.namedItem("Cells");
1827         QDomNode cell  = cells.namedItem("Cell");
1828         QDomNode mergedCells = sheet.namedItem("MergedRegions");
1829         QDomNode mergedRegion = mergedCells.namedItem("Merge");
1830         if (cell.isNull()) {
1831             kWarning(30521) << "No cells";
1832         }
1833 
1834         while (!cell.isNull()) {
1835             value += 2;
1836             emit sigProgress(value);
1837 
1838             QDomElement e = cell.toElement(); // try to convert the node to an element.
1839             if (!e.isNull()) { // the node was really an element.
1840                 kDebug(30521) << "New Cell";
1841                 QDomNode content_node = cell.namedItem("Content");
1842 
1843                 if (!content_node.isNull()) {
1844                     QDomElement content = content_node.toElement();
1845 
1846                     if (!content.isNull()) { // the node was really an element.
1847                         column = e.attribute("Col").toInt() + 1;
1848                         row    = e.attribute("Row").toInt() + 1;
1849 
1850                         QString cell_content(content.text());
1851                         //kDebug()<<"cell_content :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<cell_content;
1852                         if (cell_content[0] == '=')
1853                             convertFormula(cell_content);
1854 
1855                         Cell kspread_cell = Cell(table, column, row);
1856                         Style style;
1857 
1858                         if (e.hasAttribute("ValueType")) {
1859                             // TODO: what is this for?
1860                             // <xsd:enumeration value="10"/> <!-- empty     -->
1861                             // <xsd:enumeration value="20"/> <!-- boolean   -->
1862                             // <xsd:enumeration value="30"/> <!-- integer   -->
1863                             // <xsd:enumeration value="40"/> <!-- float     -->
1864                             // <xsd:enumeration value="50"/> <!-- error     -->
1865                             // <xsd:enumeration value="60"/> <!-- string    -->
1866                             // <xsd:enumeration value="70"/> <!-- cellrange -->
1867                             // <xsd:enumeration value="80"/> <!-- array     -->
1868                             QString valuetype = e.attribute("ValueType");
1869                             if (valuetype == "40") { //percentage
1870                                 style.setFormatType(Format::Percentage);
1871                                 kspread_cell.setValue(Value(cell_content));
1872                             } else if (valuetype == "60") { //string
1873                                 style.setFormatType(Format::Text);
1874                                 kspread_cell.setValue(Value(cell_content));
1875                             }
1876                         }
1877 
1878                         if (e.hasAttribute("ValueFormat")) {
1879                             QString formatString = e.attribute("ValueFormat");
1880                             if (!setType(kspread_cell, formatString, cell_content))
1881                                 setText(table, row, column, cell_content, false);
1882                         } else
1883                             setText(table, row, column, cell_content, false);
1884 
1885                         if (e.hasAttribute("ExprID")) {
1886                             // QString encoded_string( Cell( table, column, row ).encodeFormula( row, column ).utf8());
1887                             QString encoded_string(Cell(table, column, row).encodeFormula().toLatin1());
1888 
1889 
1890                             char * tmp_string = (char *) malloc(strlen(encoded_string.toLatin1()));
1891                             strcpy(tmp_string, encoded_string.toLatin1());
1892 
1893                             kDebug(30521) << encoded_string.toLatin1();
1894 
1895                             exprID_dict.insert(e.attribute("ExprID").toLower(), tmp_string);
1896 
1897                             kDebug(30521) << exprID_dict[e.attribute(QString("ExprID").toLower())];
1898                             kDebug(30521) << exprID_dict[QString("1")];
1899                             kDebug(30521) << e.attribute("ExprID");
1900 
1901                         }
1902                         kspread_cell.setStyle(style);
1903                     }
1904                 } else {
1905 
1906                     column = e.attribute("Col").toInt() + 1;
1907                     row    = e.attribute("Row").toInt() + 1;
1908 
1909                     QString cell_content(e.text());
1910                     //kDebug()<<"cell_content :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<cell_content;
1911                     if (cell_content[0] == '=')
1912                         convertFormula(cell_content);
1913 
1914                     Cell kspread_cell = Cell(table, column, row);
1915                     Style style;
1916 
1917                     if (e.hasAttribute("ValueType")) {
1918                         // TODO: Defined type of cell
1919                         //<xsd:enumeration value="10"/> <!-- empty     -->
1920                         //<xsd:enumeration value="20"/> <!-- boolean   -->
1921                         //<xsd:enumeration value="30"/> <!-- integer   -->
1922                         //<xsd:enumeration value="40"/> <!-- float     -->
1923                         //<xsd:enumeration value="50"/> <!-- error     -->
1924                         //<xsd:enumeration value="60"/> <!-- string    -->
1925                         //<xsd:enumeration value="70"/> <!-- cellrange -->
1926                         //<xsd:enumeration value="80"/> <!-- array     -->
1927                         //kspread_cell.setValue( date );
1928                         //style.setFormatType( type );
1929                         QString valuetype = e.attribute("ValueType");
1930                         if (valuetype == "40") { //percentage
1931                             style.setFormatType(Format::Percentage);
1932                             kspread_cell.setValue(Value(cell_content));
1933                         } else if (valuetype == "60") { //string
1934                             style.setFormatType(Format::Text);
1935                             kspread_cell.setValue(Value(cell_content));
1936                         }
1937 
1938                     }
1939 
1940                     if (e.hasAttribute("ValueFormat")) {
1941                         QString formatString = e.attribute("ValueFormat");
1942                         if (!setType(kspread_cell, formatString, cell_content))
1943                             setText(table, row, column, cell_content, false);
1944                     } else
1945                         setText(table, row, column, cell_content, false);
1946 
1947 
1948                     if (e.hasAttribute("ExprID")) {
1949                         column = e.attribute("Col").toInt() + 1;
1950                         row    = e.attribute("Row").toInt() + 1;
1951                         char * expr;
1952                         expr = exprID_dict[e.attribute("ExprID").toLower()];
1953                         // expr = exprID_dict[QString("1")];
1954 
1955                         kDebug(30521) << "FOO:" << column << row;
1956                         kDebug(30521) <<
1957                         Cell(table, column, row).decodeFormula(expr).toLatin1() << endl;
1958                         kDebug(30521) << expr;
1959 
1960                         setText(table, row, column, Cell(table, column, row).decodeFormula(expr), false);
1961                     }
1962                     kspread_cell.setStyle(style);
1963                 }
1964             }
1965             cell = cell.nextSibling();
1966         }
1967 
1968         kDebug(30521) << "Reading in cells done";
1969 
1970         if (mergedRegion.isNull()) {
1971             kWarning(30521) << "No cells merged !";
1972         }
1973         while (!mergedRegion.isNull()) {
1974             QDomElement e = mergedRegion.toElement(); // try to convert the node to an element.
1975             QString cell_merge_area(e.text());
1976             const Calligra::Sheets::Region region(cell_merge_area);
1977             //kDebug()<<"text !!! :"<<cell_merge_area<<"range :start row :"<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ();
1978             Cell cell = Cell(table, region.firstRange().left(), region.firstRange().top());
1979             cell.mergeCells(region.firstRange().left(), region.firstRange().top(),
1980                             region.firstRange().width() - 1, region.firstRange().height() - 1);
1981             mergedRegion = mergedRegion.nextSibling();
1982         }
1983 #ifdef __GNUC__
1984 #warning "The strings in the exprID_dict have been allocated, but they have not been freed: there is a memory leak here"
1985 #endif
1986         /* exprID_dict.statistics(); */
1987 
1988         /* CELL handling STOP */
1989 
1990         /* STYLE handling START */
1991         //Laurent - 2001-12-07  desactivate this code : otherwise we
1992         //create 65535*255 cells (Styleregion is define for a area and
1993         //not for cell, so gnumeric define a style as : col start=0 col end=255
1994         //rowstart=0 rowend=255 => we create 255*255 cells
1995         //and gnumeric stocke all area and not just modify area
1996         //=> not good for Calligra Sheets.
1997         // Norbert: activated again, only cells with texts get modified, nothing else created
1998         setStyleInfo(&sheet, table);
1999 
2000         sheet = sheet.nextSibling();
2001         ++num;
2002     }
2003 
2004     if (selTable) {
2005         ksdoc->map()->loadingInfo()->setFileFormat(LoadingInfo::Gnumeric);
2006         ksdoc->map()->loadingInfo()->setInitialActiveSheet(selTable);
2007     }
2008 
2009     emit sigProgress(100);
2010     if (bSuccess)
2011         return KoFilter::OK;
2012     else
2013         return KoFilter::StupidError;
2014 }
2015 
2016 void GNUMERICFilter::setText(Calligra::Sheets::Sheet* sheet, int _row, int _column, const QString& _text,
2017                              bool asString)
2018 {
2019     Cell cell(sheet, _column, _row);
2020     if (asString) {
2021         cell.setUserInput(_text);
2022         cell.setValue(Value(_text));
2023     } else {
2024         cell.parseUserInput(_text);
2025     }
2026 }
2027 
2028 #include <gnumericimport.moc>