diff options
Diffstat (limited to 'filters/kspread/gnumeric/gnumericimport.cpp')
-rw-r--r-- | filters/kspread/gnumeric/gnumericimport.cpp | 2207 |
1 files changed, 2207 insertions, 0 deletions
diff --git a/filters/kspread/gnumeric/gnumericimport.cpp b/filters/kspread/gnumeric/gnumericimport.cpp new file mode 100644 index 000000000..f437aad00 --- /dev/null +++ b/filters/kspread/gnumeric/gnumericimport.cpp @@ -0,0 +1,2207 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <faure@kde.org> + Copyright (C) 2005 Laurent Montel <montel@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +/* GNUmeric import filter by Phillip Ezolt 6-2-2001 */ +/* phillipezolt@hotmail.com */ +/* additions: Norbert Andres nandres@web.de */ + +#include <tqdict.h> +#include <tqfile.h> +#include <tqstringlist.h> + +#include <gnumericimport.h> +#include <tdemessagebox.h> +#include <kfilterdev.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <KoFilterChain.h> +#include <KoGlobal.h> + +// hehe >:-> +#include <kspread_doc.h> +#include <kspread_map.h> +#include <kspread_sheet.h> +#include <kspread_sheetprint.h> +#include <kspread_cell.h> +#include <kspread_util.h> +#include <KoDocumentInfo.h> + +#include <math.h> + +#define SECS_PER_DAY 86400 +#define HALF_SEC (0.5 / SECS_PER_DAY) + +using namespace KSpread; + +// copied from gnumeric: src/format.c: +static const int g_dateSerial_19000228 = 59; +/* One less that the Julian day number of 19000101. */ +static int g_dateOrigin = 0; + +// copied from gnumeric: src/formats.c: +static char const * cell_format_date [] = { + "m/d/yy", /* 0 Cell::date_format5*/ + "m/d/yyyy", /* 1 Cell::date_format6*/ + "d-mmm-yy", /* 2 Cell::date_format1 18-Feb-99 */ + "d-mmm-yyyy", /* 3 Cell::date_format2 18-Feb-1999 */ + "d-mmm", /* 4 Cell::date_format3 18-Feb */ + "d-mm", /* 5 Cell::date_format4 18-05 */ + "mmm/d", /* 6 Cell::date_format11*/ + "mm/d", /* 7 Cell::date_format12*/ + "mm/dd/yy", /* 8 Cell::date_format19*/ + "mm/dd/yyyy", /* 9 Cell::date_format18*/ + "mmm/dd/yy", /* 10 Cell::date_format20*/ + "mmm/dd/yyyy", /* 11 Cell::date_format21*/ + "mmm/ddd/yy", /* 12 */ + "mmm/ddd/yyyy", /* 13 */ + "mm/ddd/yy", /* 14 */ + "mm/ddd/yyyy", /* 15 */ + "mmm-yy", /* 16 Cell::date_format7*/ + "mmm-yyyy", /* 17 Cell::date_format22*/ + "mmmm-yy", /* 18 Cell::date_format8*/ + "mmmm-yyyy", /* 19 Cell::date_format9*/ + "m/d/yy h:mm", /* 20 */ + "m/d/yyyy h:mm", /* 21 */ + "yyyy/mm/d", /* 22 Cell::date_format25*/ + "yyyy/mmm/d", /* 23 Cell::date_format14*/ + "yyyy/mm/dd", /* 24 Cell::date_format25*/ + "yyyy/mmm/dd", /* 25 Cell::date_format26*/ + "yyyy-mm-d", /* 26 Cell::date_format16*/ + "yyyy-mmm-d", /* 27 Cell::date_format15*/ + "yyyy-mm-dd", /* 28 Cell::date_format16*/ + "yyyy-mmm-dd", /* 29 Cell::date_format15*/ + "yy", /* 30 Cell::date_format24*/ + "yyyy", /* 31 Cell::date_format23*/ + NULL +}; + +// copied from gnumeric: src/formats.c: +static char const * cell_format_time [] = { + "h:mm AM/PM", // Cell::Time_format1 9 : 01 AM + "h:mm:ss AM/PM", // Cell::Time_format2 9:01:05 AM + "h:mm", // Cell::Time_format4 9:01 + "h:mm:ss", // Cell::Time_format5 9:01:12 + "m/d/yy h:mm", + "mm:ss", // Cell::Time_format6 01:12 + "mm:ss.0", // Cell::Time_format6 01:12 + "[h]:mm:ss", + "[h]:mm", + "[mm]:ss", + "[ss]", + NULL +}; + +namespace gnumeric_import_LNS +{ + TQStringList list1; + TQStringList list2; +} + +using namespace gnumeric_import_LNS; + +void GNUMERICFilter::dateInit() +{ + // idea copied form gnumeric src/format.c: + /* Day 1 means 1st of January of 1900 */ + g_dateOrigin = GnumericDate::greg2jul( 1900, 1, 1 ) - 1; +} + +uint GNUMERICFilter::GnumericDate::greg2jul( int y, int m, int d ) +{ + return TQDate::gregorianToJulian( y, m, d ); +} + +void GNUMERICFilter::GnumericDate::jul2greg( double num, int & y, int & m, int & d ) +{ + int i = (int) floor( num + HALF_SEC ); + if (i > g_dateSerial_19000228) + --i; + else if (i == g_dateSerial_19000228 + 1) + kdWarning(30521) << "Request for date 02/29/1900." << endl; + + kdDebug(30521) << "***** Num: " << num << ", i: " << i << endl; + + TQDate::julianToGregorian( i + g_dateOrigin, y, m, d ); + kdDebug(30521) << "y: " << y << ", m: " << m << ", d: " << d << endl; +} + +TQTime GNUMERICFilter::GnumericDate::getTime( double num ) +{ + // idea copied from gnumeric: src/datetime.c + num += HALF_SEC; + int secs = tqRound( (num - floor(num)) * SECS_PER_DAY ); + + kdDebug(30521) << "***** Num: " << num << ", secs " << secs << endl; + + const int h = secs / 3600; + secs -= h * 3600; + const int m = secs / 60; + secs -= h * 60; + + kdDebug(30521) << "****** h: " << h << ", m: " << m << ", secs: " << secs << endl; + const TQTime time( h, m, ( secs < 0 || secs > 59 ? 0 : secs ) ); + + return time; +} + +typedef KGenericFactory<GNUMERICFilter, KoFilter> GNUMERICFilterFactory; +K_EXPORT_COMPONENT_FACTORY( libgnumericimport, GNUMERICFilterFactory( "kofficefilters" ) ) + +GNUMERICFilter::GNUMERICFilter( KoFilter *, const char *, const TQStringList & ) + : KoFilter() +{ +} + +/* This converts GNUmeric's color string "0:0:0" to a TQColor. */ +void convert_string_to_qcolor(TQString color_string, TQColor * color) +{ + int red, green, blue, first_col_pos, second_col_pos; + + bool number_ok; + + first_col_pos = color_string.find(":", 0); + second_col_pos = color_string.find(":", first_col_pos + 1); + + /* Fore="0:0:FF00" */ + /* If GNUmeric kicks out some invalid colors, we could crash. */ + /* GNUmeric gives us two bytes of color data per element. */ + /* We only care about the top byte. */ + + red = color_string.mid( 0, first_col_pos).toInt( &number_ok, 16 ) >> 8; + green = color_string.mid(first_col_pos + 1, + (second_col_pos-first_col_pos) - 1).toInt( &number_ok, 16) >> 8; + blue = color_string.mid(second_col_pos + 1, + (color_string.length() - first_col_pos) - 1).toInt( &number_ok, 16) >> 8; + color->setRgb(red, green, blue); +} + +void areaNames( Doc * ksdoc, const TQString &_name, TQString _zone ) +{ +//Sheet2!$A$2:$D$8 + TQString tableName; + int pos = _zone.find( '!' ); + if ( pos != -1 ) + { + tableName = _zone.left( pos ); + _zone = _zone.right( _zone.length()-pos-1 ); + pos = _zone.find( ':' ); + TQRect rect; + if ( pos != -1 ) + { + TQString left = _zone.mid( 1, pos-1 ); + TQString right = _zone.mid( pos+2, _zone.length()-pos-2 ); + int pos = left.find( '$' ); + + rect.setLeft( util_decodeColumnLabelText(left.left(pos ) ) ); + rect.setTop( left.right( left.length()-pos-1 ).toInt() ); + + pos = right.find( '$' ); + rect.setRight( util_decodeColumnLabelText(right.left(pos ) ) ); + rect.setBottom( right.right( right.length()-pos-1 ).toInt() ); + } + else + { + TQString left = _zone; + int pos = left.find( '$' ); + int leftPos = util_decodeColumnLabelText(left.left(pos ) ); + rect.setLeft( leftPos ); + rect.setRight( leftPos ); + + int top = left.right( left.length()-pos-1 ).toInt(); + rect.setTop( top ); + rect.setBottom( top ); + } + ksdoc->addAreaName( rect, _name ,tableName); + } +} + + +void set_document_area_names( Doc * ksdoc, TQDomElement * docElem ) +{ + TQDomNode areaNamesElement = docElem->namedItem( "gmr:Names" ); + if ( areaNamesElement.isNull() ) + return; + TQDomNode areaNameItem = areaNamesElement.namedItem( "gmr:Name" ); + while ( !areaNameItem.isNull() ) + { + TQDomNode gmr_name = areaNameItem.namedItem("gmr:name"); + TQDomNode gmr_value = areaNameItem.namedItem("gmr:value"); + TQString name = gmr_name.toElement().text(); + areaNames( ksdoc, name, gmr_value.toElement().text() ); + areaNameItem = areaNameItem.nextSibling(); + } +} + + + +void set_document_attributes( Doc * ksdoc, TQDomElement * docElem) +{ + ksdoc->loadConfigFromFile(); + TQDomNode attributes = docElem->namedItem("gmr:Attributes"); + if ( attributes.isNull() ) + return; + + TQDomNode attributeItem = attributes.namedItem("gmr:Attribute"); + while( !attributeItem.isNull() ) + { + TQDomNode gmr_name = attributeItem.namedItem("gmr:name"); + TQDomNode gmr_value = attributeItem.namedItem("gmr:value"); + if (gmr_name.toElement().text() == "WorkbookView::show_horizontal_scrollbar") + { + ksdoc->setShowHorizontalScrollBar( gmr_value.toElement().text().lower()=="true"? true : false ); + } + else if ( gmr_name.toElement().text() == "WorkbookView::show_vertical_scrollbar") + { + ksdoc->setShowVerticalScrollBar( gmr_value.toElement().text().lower()=="true"? true : false ); + } + else if ( gmr_name.toElement().text() == "WorkbookView::show_notebook_tabs") + { + ksdoc->setShowTabBar(gmr_value.toElement().text().lower()=="true"? true : false ); + } + else if ( gmr_name.toElement().text() == "WorkbookView::do_auto_completion") + { + ksdoc->setCompletionMode( TDEGlobalSettings::CompletionAuto); + } + else if ( gmr_name.toElement().text() == "WorkbookView::is_protected") + { + //TODO protect document ??? + //ksdoc->map()->isProtected() + } + + attributeItem = attributeItem.nextSibling(); + } +} + +/* This sets the documentation information from the information stored in + the GNUmeric file. Particularly in the "gmr:Summary" subcategory. +*/ +void set_document_info(KoDocument * document, TQDomElement * docElem) +{ + /* Summary Handling START */ + TQDomNode summary = docElem->namedItem("gmr:Summary"); + TQDomNode gmr_item = summary.namedItem("gmr:Item"); + + while( !gmr_item.isNull() ) + { + TQDomNode gmr_name = gmr_item.namedItem("gmr:name"); + TQDomNode gmr_value = gmr_item.namedItem("gmr:val-string"); + + KoDocumentInfo * DocumentInfo = document->documentInfo(); + KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(DocumentInfo->page( "about" )); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>(DocumentInfo->page( "author" )); + + + if (gmr_name.toElement().text() == "title") + { + aboutPage->setTitle(gmr_value.toElement().text()); + } + else if (gmr_name.toElement().text() == "keywords") + { + aboutPage->setKeywords( gmr_value.toElement().text()); + } + else if (gmr_name.toElement().text() == "comments") + { + aboutPage->setAbstract(gmr_value.toElement().text()); + } + else if (gmr_name.toElement().text() == "category") + { + /* Not supported by KSpread */ + } + else if (gmr_name.toElement().text() == "manager") + { + /* Not supported by KSpread */ + } + else if (gmr_name.toElement().text() == "application") + { + /* Not supported by KSpread */ + } + else if (gmr_name.toElement().text() == "author") + { + authorPage->setFullName(gmr_value.toElement().text()); + } + else if (gmr_name.toElement().text() == "company") + { + authorPage->setCompany(gmr_value.toElement().text()); + } + + gmr_item = gmr_item.nextSibling(); + } + + /* Summany Handling STOP */ +} + + +void setColInfo(TQDomNode * sheet, Sheet * table) +{ + TQDomNode columns = sheet->namedItem("gmr:Cols"); + TQDomNode columninfo = columns.namedItem("gmr:ColInfo"); + + TQDomElement def = columns.toElement(); + if ( def.hasAttribute( "DefaultSizePts" ) ) + { + bool ok = false; + double d = def.attribute( "DefaultSizePts" ).toDouble( &ok ); + if ( ok ) + { + Format::setGlobalColWidth( d ); + table->setDefaultWidth( d ); + } + } + + while( !columninfo.isNull() ) + { + TQDomElement e = columninfo.toElement(); // try to convert the node to an element. + int column_number; + + column_number = e.attribute("No").toInt()+1; + ColumnFormat *cl = new ColumnFormat(table, column_number); + if (e.hasAttribute("Hidden")) + { + if (e.attribute("Hidden")=="1") + { + cl->setHide(true); + } + } + if (e.hasAttribute("Unit")) + { + // xmm = (x_points) * (1 inch / 72 points) * (25.4 mm/ 1 inch) + cl->setDblWidth(e.attribute("Unit").toDouble()); + //cl->setWidth(e.attribute("Unit").toInt()); + } + table->insertColumnFormat(cl); + columninfo = columninfo.nextSibling(); + } +} + +void setRowInfo(TQDomNode *sheet, Sheet *table) +{ + TQDomNode rows = sheet->namedItem("gmr:Rows"); + TQDomNode rowinfo = rows.namedItem("gmr:RowInfo"); + + double d; + bool ok = false; + + TQDomElement def = rows.toElement(); + if ( def.hasAttribute( "DefaultSizePts" ) ) + { + d = def.attribute( "DefaultSizePts" ).toDouble( &ok ); + if ( ok ) + { + Format::setGlobalRowHeight( d ); + table->setDefaultHeight( d ); + } + } + + while( !rowinfo.isNull() ) + { + TQDomElement e = rowinfo.toElement(); // try to convert the node to an element. + int row_number; + row_number = e.attribute("No").toInt() + 1; + RowFormat *rl = new RowFormat(table, row_number); + + if (e.hasAttribute("Hidden")) + { + if (e.attribute("Hidden") == "1") + { + rl->setHide(true); + } + } + if (e.hasAttribute("Unit")) + { + double dbl = e.attribute( "Unit" ).toDouble( &ok ); + if ( ok ) + rl->setDblHeight( dbl ); + } + table->insertRowFormat(rl); + rowinfo = rowinfo.nextSibling(); + } +} + +void setSelectionInfo( TQDomNode * sheet, Sheet * /* table */ ) +{ + TQDomNode selections = sheet->namedItem("gmr:Selections"); + TQDomNode selection = selections.namedItem("gmr:Selection"); + + /* Kspread does not support mutiple selections.. */ + /* This code will set the selection to the last one GNUmeric's multiple + selections. */ + while( !selection.isNull() ) + { + TQDomElement e = selection.toElement(); // try to convert the node to an element. + TQRect kspread_selection; + + kspread_selection.setLeft((e.attribute("startCol").toInt() + 1)); + kspread_selection.setTop((e.attribute("startRow").toInt() + 1)); + kspread_selection.setRight((e.attribute("endCol").toInt() + 1)); + kspread_selection.setBottom((e.attribute("endRow").toInt() + 1)); + + /* can't set it in the table -- must set it to a view */ + // table->setSelection(kspread_selection); + + selection = selection.nextSibling(); + } +} + + +void setObjectInfo(TQDomNode * sheet, Sheet * table) +{ + TQDomNode gmr_objects = sheet->namedItem("gmr:Objects"); + TQDomNode gmr_cellcomment = gmr_objects.namedItem("gmr:CellComment"); + while( !gmr_cellcomment.isNull() ) + { + TQDomElement e = gmr_cellcomment.toElement(); // try to convert the node to an element. + if (e.hasAttribute("Text")) + { + if (e.hasAttribute("ObjectBound")) + { + Point point(e.attribute("ObjectBound")); + Cell * cell = table->nonDefaultCell( point.pos().x(), point.pos().y() ); + cell->format()->setComment(e.attribute("Text")); + } + } + + gmr_cellcomment = gmr_cellcomment.nextSibling(); + } +} + +void convertToPen( TQPen & pen, int style ) +{ + switch( style ) + { + case 0: + break; + case 1: + pen.setStyle( Qt::SolidLine ); + pen.setWidth( 1 ); + break; + case 2: + pen.setStyle( Qt::SolidLine ); + pen.setWidth( 2 ); + break; + case 3: + pen.setStyle( Qt::DashLine ); + pen.setWidth( 1 ); + break; + case 4: + // width should be 1 but otherwise it would be the same as 7 + pen.setStyle( Qt::DotLine ); + pen.setWidth( 2 ); + break; + case 5: + pen.setStyle( Qt::SolidLine ); + pen.setWidth( 3 ); + break; + case 6: + // TODO should be double + pen.setStyle( Qt::SolidLine ); + pen.setWidth( 1 ); + break; + case 7: + // very thin dots => no match in KSpread + pen.setStyle( Qt::DotLine ); + pen.setWidth( 1 ); + break; + case 8: + pen.setStyle( Qt::DashLine ); + pen.setWidth( 2 ); + break; + case 9: + pen.setStyle( Qt::DashDotLine ); + pen.setWidth( 1 ); + break; + case 10: + pen.setStyle( Qt::DashDotLine ); + pen.setWidth( 2 ); + break; + case 11: + pen.setStyle( Qt::DashDotDotLine ); + pen.setWidth( 1 ); + break; + case 12: + pen.setStyle( Qt::DashDotDotLine ); + pen.setWidth( 2 ); + break; + case 13: + // TODO: long dash, short dash, long dash,... + pen.setStyle( Qt::DashDotLine ); + pen.setWidth( 3 ); + break; + default: + pen.setStyle( Qt::SolidLine ); + pen.setWidth( 1 ); + } +} + +void GNUMERICFilter::ParseBorder( TQDomElement & gmr_styleborder, Cell * kspread_cell ) +{ + TQDomNode gmr_diagonal = gmr_styleborder.namedItem("gmr:Diagonal"); + TQDomNode gmr_rev_diagonal = gmr_styleborder.namedItem("gmr:Rev-Diagonal"); + TQDomNode gmr_top = gmr_styleborder.namedItem("gmr:Top"); + TQDomNode gmr_bottom = gmr_styleborder.namedItem("gmr:Bottom"); + TQDomNode gmr_left = gmr_styleborder.namedItem("gmr:Left"); + TQDomNode gmr_right = gmr_styleborder.namedItem("gmr:Right"); + + // NoPen - no line at all. For example, + // TQPainter::drawRect() fills but does not + // draw any explicit boundary + // line. SolidLine - a simple line. DashLine + // - dashes, separated by a few + // pixels. DotLine - dots, separated by a + // few pixels. DashDotLine - alternately + // dots and dashes. DashDotDotLine - one dash, two dots, one dash, two dots... + + if ( !gmr_left.isNull() ) + { + TQDomElement e = gmr_left.toElement(); // try to convert the node to an element. + importBorder( e, Left, kspread_cell); + } + + if ( !gmr_right.isNull() ) + { + TQDomElement e = gmr_right.toElement(); // try to convert the node to an element. + importBorder( e, Right, kspread_cell); + } + + if ( !gmr_top.isNull() ) + { + TQDomElement e = gmr_top.toElement(); // try to convert the node to an element. + importBorder( e, Top, kspread_cell); + } + + if ( !gmr_bottom.isNull() ) + { + TQDomElement e = gmr_bottom.toElement(); // try to convert the node to an element. + importBorder( e, Bottom, kspread_cell); + } + + if ( !gmr_diagonal.isNull() ) + { + TQDomElement e = gmr_diagonal.toElement(); // try to convert the node to an element. + importBorder( e, Diagonal, kspread_cell); + } + + if ( !gmr_rev_diagonal.isNull() ) + { + TQDomElement e = gmr_rev_diagonal.toElement(); // try to convert the node to an element. + importBorder( e, Revdiagonal, kspread_cell); + } + + // TQDomElement gmr_styleborder_element = gmr_styleborder.toElement(); +} + + +void GNUMERICFilter::importBorder( TQDomElement border, borderStyle _style, Cell *cell) +{ + if ( !border.isNull() ) + { + TQDomElement e = border.toElement(); // try to convert the node to an element. + if ( e.hasAttribute( "Style" ) ) + { + int style = e.attribute( "Style" ).toInt(); + + TQPen pen; + convertToPen( pen, style ); + + if ( style > 0 ) + { + switch( _style ) + { + case Left: + cell->setLeftBorderPen( pen ); + break; + case Right: + cell->setRightBorderPen( pen ); + break; + case Top: + cell->setTopBorderPen( pen ); + break; + case Bottom: + cell->setBottomBorderPen( pen ); + break; + case Diagonal: + cell->format()->setFallDiagonalPen( pen ); // check if this is really Fall border + break; + case Revdiagonal: + cell->format()->setGoUpDiagonalPen( pen ); // check if this is really GoUp + break; + } + } + if ( e.hasAttribute( "Color" ) ) + { + TQColor color; + TQString colorString = e.attribute( "Color" ); + convert_string_to_qcolor( colorString, &color ); + { + switch( _style ) + { + case Left: + cell->format()->setLeftBorderColor( color ); + break; + case Right: + cell->format()->setRightBorderColor( color ); + break; + case Top: + cell->format()->setTopBorderColor( color ); + break; + case Bottom: + cell->format()->setBottomBorderColor( color ); + break; + case Diagonal: + cell->format()->setFallDiagonalColor( color ); + break; + case Revdiagonal: + cell->format()->setGoUpDiagonalPen( color ); + break; + } + } + } + } + } + +} + +bool GNUMERICFilter::setType( Cell * kspread_cell, + TQString const & formatString, + TQString & cell_content ) +{ + int i = 0; + for ( i = 0; cell_format_date[i] ; ++i ) + { + kdDebug(30521) << "Cell_format: " << cell_format_date[i] << ", FormatString: " << formatString << endl; + if ( ( formatString == "d/m/yy" ) || ( formatString == cell_format_date[i] ) ) + { + kdDebug(30521) << " FormatString: Date: " << formatString << ", CellContent: " << cell_content << endl; + TQDate date; + if ( !kspread_cell->isDate() ) + { + // convert cell_content to date + int y, m, d; + bool ok = true; + int val = cell_content.toInt( &ok ); + + kdDebug(30521) << "!!! FormatString: Date: " << formatString << ", CellContent: " << cell_content + << ", Double: " << val << endl; + if ( !ok ) + return false; + + GnumericDate::jul2greg( val, y, m, d ); + kdDebug(30521) << " num: " << val << ", y: " << y << ", m: " << m << ", d: " << d << endl; + + date.setYMD( y, m, d ); + } + else + date = kspread_cell->value().asDate(); + + FormatType type; + switch( i ) + { + case 0: type = date_format5; break; + case 1: type = date_format6; break; + case 2: type = date_format1; break; + case 3: type = date_format2; break; + case 4: type = date_format3; break; + case 5: type = date_format4; break; + case 6: type = date_format11; break; + case 7: type = date_format12; break; + case 8: type = date_format19; break; + case 9: type = date_format18; break; + case 10: type = date_format20; break; + case 11: type = date_format21; break; + case 16: type = date_format7; break; + case 17: type = date_format22; break; + case 18: type = date_format8; break; + case 19: type = date_format9; break; + case 22: type = date_format25; break; + case 23: type = date_format14; break; + case 24: type = date_format25; break; + case 25: type = date_format26; break; + case 26: type = date_format16; break; + case 27: type = date_format15; break; + case 28: type = date_format16; break; + case 29: type = date_format15; break; + case 30: type = date_format24; break; + case 31: type = date_format23; break; + default: + type = ShortDate_format; + break; + /* 12, 13, 14, 15, 20, 21 */ + } + + kdDebug(30521) << "i: " << i << ", Type: " << type << ", Date: " << TQString(date.toString()) << endl; + + kspread_cell->setValue( date ); + kspread_cell->format()->setFormatType( type ); + + return true; + } + } + + for ( i = 0; cell_format_time[i] ; ++i ) + { + if (formatString == cell_format_time[i]) + { + TQTime time; + + if ( !kspread_cell->isTime() ) + { + bool ok = true; + double content = cell_content.toDouble( &ok ); + + kdDebug(30521) << " FormatString: Time: " << formatString << ", CellContent: " << cell_content + << ", Double: " << content << endl; + + if ( !ok ) + return false; + + time = GnumericDate::getTime( content ); + } + else + time = kspread_cell->value().asTime(); + + FormatType type; + switch( i ) + { + case 0: type = Time_format1; break; + case 1: type = Time_format2; break; + case 2: type = Time_format4; break; + case 3: type = Time_format5; break; + case 5: type = Time_format6; break; + case 6: type = Time_format6; break; + default: + type = Time_format1; break; + } + + kdDebug(30521) << "i: " << i << ", Type: " << type << endl; + kspread_cell->setValue( time ); + kspread_cell->format()->setFormatType( type ); + + return true; + } + } + + return false; // no date or time +} + +TQString GNUMERICFilter::convertVars( TQString const & str, Sheet * table ) const +{ + TQString result( str ); + uint count = list1.count(); + if ( count == 0 ) + { + list1 << "&[TAB]" << "&[DATE]" << "&[PAGE]" + << "&[PAGES]"<<"&[TIME]" << "&[FILE]"; + list2 << "<sheet>" << "<date>" << "<page>" + << "<pages>" << "<time>" << "<file>"; + count = list1.count(); + } + + for ( uint i = 0; i < count; ++i ) + { + int n = result.find( list1[i] ); + + if ( n != -1 ) + { + kdDebug(30521) << "Found var: " << list1[i] << endl; + if ( i == 0 ) + result = result.replace( list1[i], table->tableName() ); + else + result = result.replace( list1[i], list2[i] ); + } + } + + return result; +} + +double GNUMERICFilter::parseAttribute( const TQDomElement &_element ) +{ + TQString unit = _element.attribute( "PrefUnit" ); + bool ok; + double value = _element.attribute("Points").toFloat( &ok ); + if ( !ok ) + value = 2.0; + if ( unit == "mm" ) + return value; + else if ( unit == "cm" ) + return ( value/10.0 ); + else if ( unit == "in" ) + return MM_TO_INCH( value ); + else if ( unit == "Pt" || unit == "Px" || unit == "points" ) + return MM_TO_POINT( value ); + else + return value; +} + +void GNUMERICFilter::ParsePrintInfo( TQDomNode const & printInfo, Sheet * table ) +{ + kdDebug(30521) << "Parsing print info " << endl; + + float fleft = 2.0; + float fright = 2.0; + float ftop = 2.0; + float fbottom = 2.0; + + TQString paperSize("A4"); + TQString orientation("Portrait"); + TQString footLeft, footMiddle, footRight; + TQString headLeft, headMiddle, headRight; // no we are zombies :-) + + TQDomNode margins( printInfo.namedItem("gmr:Margins") ); + if ( !margins.isNull() ) + { + TQDomElement top( margins.namedItem( "gmr:top" ).toElement() ); + if ( !top.isNull() ) + ftop = parseAttribute( top ); + + TQDomElement bottom( margins.namedItem( "gmr:bottom" ).toElement() ); + if ( !bottom.isNull() ) + fbottom= parseAttribute( bottom ); + + TQDomElement left( margins.namedItem( "gmr:left" ).toElement() ); + if ( !left.isNull() ) + fleft = parseAttribute( left ); + + TQDomElement right( margins.namedItem( "gmr:right" ).toElement() ); + if ( !right.isNull() ) + fright = parseAttribute( right ); + } + + TQDomElement foot( printInfo.namedItem("gmr:Footer").toElement() ); + if ( !foot.isNull() ) + { + kdDebug(30521) << "Parsing footer: " << foot.attribute("Left") << ", " << foot.attribute("Middle") << ", " + << foot.attribute("Right") << ", " <<endl; + if ( foot.hasAttribute("Left") ) + footLeft = convertVars( foot.attribute("Left"), table ); + if ( foot.hasAttribute("Middle") ) + footMiddle = convertVars( foot.attribute("Middle"), table ); + if ( foot.hasAttribute("Right") ) + footRight = convertVars( foot.attribute("Right"), table ); + } + + TQDomElement head( printInfo.namedItem("gmr:Header").toElement() ); + if ( !head.isNull() ) + { + kdDebug(30521) << "Parsing header: " << head.attribute("Left") << ", " << head.attribute("Middle") << ", " << head.attribute("Right") << ", "<< endl; + if ( head.hasAttribute("Left") ) + headLeft = convertVars( head.attribute("Left"), table ); + if ( head.hasAttribute("Middle") ) + headMiddle = convertVars( head.attribute("Middle"), table ); + if ( head.hasAttribute("Right") ) + headRight = convertVars( head.attribute("Right"), table ); + } + + TQDomElement repeateColumn( printInfo.namedItem("gmr:repeat_top").toElement() ); + if ( !repeateColumn.isNull() ) + { + TQString repeate = repeateColumn.attribute( "value" ); + if ( !repeate.isEmpty() ) + { + Range range(repeate); + //kdDebug()<<" repeate :"<<repeate<<"range. ::start row : "<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ()<<endl; + table->print()->setPrintRepeatRows( tqMakePair( range.startRow (),range.endRow ()) ); + } + } + + TQDomElement repeateRow( printInfo.namedItem("gmr:repeat_left").toElement() ); + if ( !repeateRow.isNull() ) + { + TQString repeate = repeateRow.attribute( "value" ); + if ( !repeate.isEmpty() ) + { + //fix row too high + repeate = repeate.replace( "65536", "32500" ); + Range range(repeate); + //kdDebug()<<" repeate :"<<repeate<<"range. ::start row : "<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ()<<endl; + table->print()->setPrintRepeatColumns( tqMakePair( range.startCol (),range.endCol ()) ); + } + } + + TQDomElement orient( printInfo.namedItem("gmr:orientation").toElement() ); + if ( !orient.isNull() ) + orientation = orient.text(); + + TQDomElement size( printInfo.namedItem("gmr:paper").toElement() ); + if ( !size.isNull() ) + paperSize = size.text(); + + table->print()->setPaperLayout( fleft, ftop, fright, fbottom, + paperSize, orientation ); + + table->print()->setHeadFootLine( headLeft, headMiddle, headRight, + footLeft, footMiddle, footRight ); +} + +void GNUMERICFilter::ParseFormat(TQString const & formatString, Cell * kspread_cell) +{ + int l = formatString.length(); + int lastPos = 0; + + if (formatString[l - 1] == '%') + kspread_cell->format()->setFormatType(Percentage_format); + else if (formatString[0] == '$') + { + kspread_cell->format()->setFormatType(Money_format); + kspread_cell->format()->setCurrency( 1, "$" ); + lastPos = 1; + } + else if (formatString[0] == '£') + { + kspread_cell->format()->setFormatType(Money_format); + kspread_cell->format()->setCurrency( 1, "£" ); + lastPos = 1; + } + else if (formatString[0] == '¥') + { + kspread_cell->format()->setFormatType(Money_format); + kspread_cell->format()->setCurrency( 1, "¥" ); + lastPos = 1; + } + else if (formatString[0] == '¤') + { + kspread_cell->format()->setFormatType(Money_format); + kspread_cell->format()->setCurrency( 1, "¤" ); + lastPos = 1; + } + else if (l > 1) + { + if ((formatString[0] == '[') && (formatString[1] == '$')) + { + int n = formatString.find(']'); + if (n != -1) + { + TQString currency = formatString.mid(2, n - 2); + kspread_cell->format()->setFormatType(Money_format); + kspread_cell->format()->setCurrency( 1, currency ); + } + lastPos = ++n; + } + else if (formatString.find("E+0") != -1) + { + kspread_cell->format()->setFormatType(Scientific_format); + } + else + { + // do pattern matching with gnumeric formats + TQString content(kspread_cell->value().asString()); + + if ( setType(kspread_cell, formatString, content) ) + return; + + if (formatString.find("?/?") != -1) + { + // TODO: fixme! + kspread_cell->format()->setFormatType( fraction_three_digits ); + return; + } + // so it's nothing we want to understand:-) + return; + } + } + + while (formatString[lastPos] == ' ') + ++lastPos; + + // GetPrecision and decimal point, format of negative items... + + // thousands separator + if (formatString[lastPos] == '#') + { + bool sep = true; + if (formatString[lastPos + 1] == ',') + lastPos += 2; + else + sep = false; + // since KSpread 1.3 + // kspread_cell->setThousandsSeparator( sep ); + } + + while (formatString[lastPos] == ' ') + ++lastPos; + + int n = formatString.find( '.', lastPos ); + if ( n != -1) + { + lastPos = n + 1; + int precision = lastPos; + while (formatString[precision] == '0') + ++precision; + + int tmp = lastPos; + lastPos = precision; + precision -= tmp; + + kspread_cell->format()->setPrecision( precision ); + } + + bool red = false; + if (formatString.find("[RED]", lastPos) != -1) + { + red = true; + kspread_cell->format()->setFloatColor( Format::NegRed ); + } + if ( formatString.find('(', lastPos) != -1 ) + { + if ( red ) + kspread_cell->format()->setFloatColor( Format::NegRedBrackets ); + else + kspread_cell->format()->setFloatColor( Format::NegBrackets ); + } +} + +void GNUMERICFilter::convertFormula( TQString & formula ) const +{ + int n = formula.find( '=', 1 ); + + // TODO: check if we do not screw something up here... + if ( n != -1 ) + formula = formula.replace( n, 1, "==" ); + + bool inQuote1 = false; + bool inQuote2 = false; + int l = formula.length(); + for ( int i = 0; i < l; ++i ) + { + if ( formula[i] == '\'' ) + inQuote1 = !inQuote1; + else if ( formula[i] == '"' ) + inQuote2 = !inQuote2; + else if ( formula[i] == ',' && !inQuote1 && !inQuote2 ) + formula = formula.replace( i, 1, ";" ); + } +} + +void GNUMERICFilter::setStyleInfo(TQDomNode * sheet, Sheet * table) +{ + kdDebug(30521) << "SetStyleInfo entered " << endl; + + int row, column; + TQDomNode styles = sheet->namedItem( "gmr:Styles" ); + if ( !styles.isNull() ) + { + // Get a style region within that sheet. + TQDomNode style_region = styles.namedItem( "gmr:StyleRegion" ); + + while ( !style_region.isNull() ) + { + TQDomElement e = style_region.toElement(); // try to convert the node to an element. + + TQDomNode style = style_region.namedItem( "gmr:Style" ); + TQDomNode font = style.namedItem( "gmr:Font" ); + TQDomNode validation = style.namedItem( "gmr:Validation" ); + TQDomNode gmr_styleborder = style.namedItem( "gmr:StyleBorder" ); + TQDomNode hyperlink = style.namedItem( "gmr:HyperLink" ); + int startCol = e.attribute( "startCol" ).toInt() + 1; + int endCol = e.attribute( "endCol" ).toInt() + 1; + int startRow = e.attribute( "startRow" ).toInt() + 1; + int endRow = e.attribute( "endRow" ).toInt() + 1; + + kdDebug(30521) << "------Style: " << startCol << ", " + << startRow << " - " << endCol << ", " << endRow << endl; + + if ( endCol - startCol > 200 || endRow - startRow > 200 ) + { + style_region = style_region.nextSibling(); + continue; + } + + for ( column = startCol; column <= endCol; ++column ) + { + for ( row = startRow; row <= endRow; ++row ) + { + kdDebug(30521) << "Cell: " << column << ", " << row << endl; + Cell * kspread_cell = table->cellAt( column, row, false ); + + // don't create new cells -> don't apply format on empty cells, if bigger region + if ( ( kspread_cell->isDefault() || kspread_cell->isEmpty() ) + && ( ( endCol - startCol > 2 ) || ( endRow - startRow > 2 ) ) ) + { + kdDebug(30521) << "CELL EMPTY OR RANGE TOO BIG " << endl; + continue; + } + + TQDomElement style_element = style.toElement(); // try to convert the node to an element. + + kdDebug(30521) << "Style valid for kspread" << endl; + kspread_cell = table->nonDefaultCell( column, row, false ); + + if (style_element.hasAttribute("Fore")) + { + TQString color_string = style_element.attribute("Fore"); + TQColor color; + convert_string_to_qcolor(color_string, &color); + kspread_cell->format()->setTextColor(color); + } + + if (style_element.hasAttribute("Back")) + { + TQString color_string = style_element.attribute("Back"); + TQColor color; + convert_string_to_qcolor(color_string, &color); + kspread_cell->format()->setBgColor(color); + } + + if (style_element.hasAttribute("PatternColor")) + { + TQString color_string = style_element.attribute("PatternColor"); + TQColor color; + convert_string_to_qcolor(color_string, &color); + kspread_cell->format()->setBackGroundBrushColor( color ); + } + + if (style_element.hasAttribute("Shade")) + { + /* Pattern's taken from: gnumeric's pattern.c */ + /* if "TODO" added: doesn't match exactly the gnumeric one */ + + TQString shade = style_element.attribute("Shade"); + if (shade == "0") + { + // nothing to do + } + else if (shade == "1") + { + /* 1 Solid */ + //kspread_cell->format()->setBackGroundBrushStyle(Qt::SolidPattern); + //This is as empty + /* What should this be? */ + + } + else if (shade == "2") + { + /* 2 75% */ + kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense2Pattern); + } + else if (shade == "3") + { + /* 3 50% */ + kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense4Pattern); + } + else if (shade == "4") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense5Pattern); + /* This should be 25%... All qt has is 37% */ + + /* 4 25% */ + } + else if (shade == "5") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense6Pattern); + /* 5 12.5% */ + } + else if (shade == "6") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense7Pattern); + /* 6 6.25% */ + + } + else if (shade == "7") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::HorPattern); + /* 7 Horizontal Stripe */ + } + else if (shade == "8") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::VerPattern); + /* 8 Vertical Stripe */ + } + else if (shade == "9") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::BDiagPattern); + /* 9 Reverse Diagonal Stripe */ + } + else if (shade == "10") + { + /* 10 Diagonal Stripe */ + kspread_cell->format()->setBackGroundBrushStyle(Qt::FDiagPattern); + } + else if (shade == "11") + { + /* 11 Diagonal Crosshatch */ + kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern); + } + else if (shade == "12") + { + /* 12 Thick Diagonal Crosshatch TODO!*/ + kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern); + } + else if (shade == "13") + { + /* 13 Thin Horizontal Stripe TODO: wrong: this is thick!*/ + kspread_cell->format()->setBackGroundBrushStyle(Qt::HorPattern); + } + else if (shade == "14") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::VerPattern); + } + else if (shade == "15") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::FDiagPattern); + } + else if (shade == "16") + { + /* 16 Thick Reverse Stripe TODO:*/ + kspread_cell->format()->setBackGroundBrushStyle(Qt::BDiagPattern); + } + else if (shade == "17") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern); + } + else if (shade == "18") + { + kspread_cell->format()->setBackGroundBrushStyle(Qt::DiagCrossPattern); + } + else if (shade == "19") + { + /* 19 Applix small circle */ + } + else if (shade == "20") + { + /* 20 Applix semicircle */ + } + else if (shade == "21") + { + /* 21 Applix small thatch */ + } + else if (shade == "22") + { + /* 22 Applix round thatch */ + } + else if (shade == "23") + { + /* 23 Applix Brick */ + } + else if (shade == "24") + { + /* 24 100% */ + kspread_cell->format()->setBackGroundBrushStyle(Qt::SolidPattern); + } + else if (shade == "25") + { + /* 25 87.5% */ + kspread_cell->format()->setBackGroundBrushStyle(Qt::Dense2Pattern); + } + } + + if ( style_element.hasAttribute( "Rotation" ) ) + { + int rot = style_element.attribute( "Rotation" ).toInt(); + kspread_cell->format()->setAngle( -1* rot ); + } + if (style_element.hasAttribute("Indent")) + { + double indent = style_element.attribute("Indent").toDouble(); + // gnumeric saves indent in characters, we in points: + kspread_cell->format()->setIndent( indent * 10.0 ); + } + + if (style_element.hasAttribute("HAlign")) + { + TQString halign_string=style_element.attribute("HAlign"); + + if (halign_string == "1") + { + /* General: No equivalent in Kspread. */ + } + else if (halign_string == "2") + { + kspread_cell->format()->setAlign(Format::Left); + } + else if (halign_string == "4") + { + kspread_cell->format()->setAlign(Format::Right); + } + else if (halign_string == "8") + { + kspread_cell->format()->setAlign(Format::Center); + } + else if (halign_string == "16") + { + /* Fill: No equivalent in Kspread. */ + } + else if (halign_string == "32") + { + /* Justify: No equivalent in Kspread */ + } + else if (halign_string == "64") + { + /* Centered across selection*/ + } + + } + + if (style_element.hasAttribute("VAlign")) + { + TQString valign_string=style_element.attribute("VAlign"); + + if (valign_string == "1") + { + /* General: No equivalent in Kspread. */ + kspread_cell->format()->setAlignY(Format::Top); + } + else if (valign_string == "2") + { + kspread_cell->format()->setAlignY(Format::Bottom); + } + else if (valign_string == "4") + { + kspread_cell->format()->setAlignY(Format::Middle); + } + else if (valign_string == "8") + { + /* Justify: No equivalent in Kspread */ + } + } + + if (style_element.hasAttribute("WrapText")) + { + TQString multiRow = style_element.attribute("WrapText"); + + if ( multiRow == "1" ) + kspread_cell->format()->setMultiRow( true ); + } + + if (style_element.hasAttribute("Format")) + { + TQString formatString = style_element.attribute("Format"); + + kdDebug(30521) << "Format: " << formatString << endl; + ParseFormat(formatString, kspread_cell); + + } // End "Format" + + if (!gmr_styleborder.isNull()) + { + TQDomElement style_element = gmr_styleborder.toElement(); // try to convert the node to an element. + ParseBorder( style_element, kspread_cell ); + } + if ( !validation.isNull() ) + { + TQDomElement validation_element = validation.toElement(); + if ( !validation_element.isNull() ) + { + kdDebug(30521)<<" Cell validation \n"; + Validity* kspread_validity = kspread_cell->getValidity(); + if ( validation_element.hasAttribute( "AllowBlank" ) && validation_element.attribute( "AllowBlank" )=="true" ) + { + kspread_validity->allowEmptyCell=true; + } + if ( validation_element.hasAttribute( "Title" )) + { + kspread_validity->title=validation_element.attribute( "Title" ); + } + if ( validation_element.hasAttribute( "Message" )) + { + kspread_validity->message=validation_element.attribute( "Message" ); + } + if ( validation_element.hasAttribute( "Style" ) ) + { + int value = validation_element.attribute( "Style" ).toInt(); + switch( value ) + { + case 0: + kspread_validity->displayMessage=false; + break; + case 1: + kspread_validity->m_action=Action::Stop; + break; + case 2: + kspread_validity->m_action=Action::Warning; + break; + case 3: + kspread_validity->m_action=Action::Information; + break; + default: + kdDebug()<<" Error in validation style :"<<value<<endl; + break; + } + } + TQDomNode expression0 = validation_element.namedItem( "gmr:Expression0" ); + TQDomNode expression1 = validation_element.namedItem( "gmr:Expression1" ); + //kdDebug()<<" expression0.isNull() "<<expression0.isNull()<<endl; + //kdDebug()<<" expression1.isNull() "<<expression1.isNull()<<endl; + if ( validation_element.hasAttribute( "Type" ) ) + { + int valueOp = validation_element.attribute( "Type" ).toInt(); + switch( valueOp ) + { + case 0: + kspread_validity->m_restriction=Restriction::None; + break; + case 1: + { + kspread_validity->m_restriction=Restriction::Integer; + if ( validation_element.hasAttribute( "Operator" ) ) + { + int value = validation_element.attribute( "Operator" ).toInt(); + + switch( value ) + { + case 0: + kspread_validity->m_cond=Conditional::Between; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + if ( !expression1.isNull() ) + kspread_validity->valMax=expression1.toElement().text().toInt(); + break; + case 1: + kspread_validity->m_cond=Conditional::DifferentTo; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + if ( !expression1.isNull() ) + kspread_validity->valMax=expression1.toElement().text().toInt(); + break; + case 2: + kspread_validity->m_cond=Conditional::Equal; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 3: + kspread_validity->m_cond=Conditional::Different; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 4: + kspread_validity->m_cond=Conditional::Superior; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 5: + kspread_validity->m_cond=Conditional::Inferior; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 6: + kspread_validity->m_cond=Conditional::SuperiorEqual; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 7: + kspread_validity->m_cond=Conditional::InferiorEqual; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + default: + kdDebug()<<" Error in validation Operator :"<<value<<endl; + break; + } + } + } + break; + case 2: + kspread_validity->m_restriction=Restriction::Number; + if ( validation_element.hasAttribute( "Operator" ) ) + { + int value = validation_element.attribute( "Operator" ).toInt(); + switch( value ) + { + case 0: + kspread_validity->m_cond=Conditional::Between; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + if ( !expression1.isNull() ) + kspread_validity->valMax=expression1.toElement().text().toInt(); + break; + case 1: + kspread_validity->m_cond=Conditional::DifferentTo; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + if ( !expression1.isNull() ) + kspread_validity->valMax=expression1.toElement().text().toInt(); + break; + case 2: + kspread_validity->m_cond=Conditional::Equal; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 3: + kspread_validity->m_cond=Conditional::Different; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 4: + kspread_validity->m_cond=Conditional::Superior; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 5: + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + kspread_validity->m_cond=Conditional::Inferior; + break; + case 6: + kspread_validity->m_cond=Conditional::SuperiorEqual; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 7: + kspread_validity->m_cond=Conditional::InferiorEqual; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + default: + kdDebug()<<" Error in validation Operator :"<<value<<endl; + break; + } + } + break; + case 3: + kspread_validity->m_restriction=Restriction::List; + break; + case 4: + kspread_validity->m_restriction=Restriction::Date; + if ( validation_element.hasAttribute( "Operator" ) ) + { + int value = validation_element.attribute( "Operator" ).toInt(); + switch( value ) + { + case 0: + kspread_validity->m_cond=Conditional::Between; + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + if ( !expression1.isNull() ) + kspread_validity->dateMax=TQDate::fromString( expression1.toElement().text() ); + + break; + case 1: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + if ( !expression1.isNull() ) + kspread_validity->dateMax=TQDate::fromString( expression1.toElement().text() ); + kspread_validity->m_cond=Conditional::DifferentTo; + break; + case 2: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::Equal; + break; + case 3: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::Different; + break; + case 4: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::Superior; + break; + case 5: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::Inferior; + break; + case 6: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::SuperiorEqual; + break; + case 7: + if ( !expression0.isNull() ) + kspread_validity->dateMin=TQDate::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::InferiorEqual; + break; + default: + kdDebug()<<" Error in validation Operator :"<<value<<endl; + break; + } + } + break; + case 5: + kspread_validity->m_restriction=Restriction::Time; + if ( validation_element.hasAttribute( "Operator" ) ) + { + int value = validation_element.attribute( "Operator" ).toInt(); + switch( value ) + { + case 0: + kspread_validity->m_cond=Conditional::Between; + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + if ( !expression1.isNull() ) + kspread_validity->timeMax=TQTime::fromString( expression1.toElement().text() ); + break; + case 1: + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + if ( !expression1.isNull() ) + kspread_validity->timeMax=TQTime::fromString( expression1.toElement().text() ); + kspread_validity->m_cond=Conditional::DifferentTo; + break; + case 2: + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::Equal; + break; + case 3: + kspread_validity->m_cond=Conditional::Different; + break; + case 4: + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::Superior; + break; + case 5: + kspread_validity->m_cond=Conditional::Inferior; + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + break; + case 6: + kspread_validity->m_cond=Conditional::SuperiorEqual; + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + break; + case 7: + if ( !expression0.isNull() ) + kspread_validity->timeMin=TQTime::fromString( expression0.toElement().text() ); + kspread_validity->m_cond=Conditional::InferiorEqual; + break; + default: + kdDebug()<<" Error in validation Operator :"<<value<<endl; + break; + } + } + break; + case 6: + kspread_validity->m_restriction=Restriction::TextLength; + if ( validation_element.hasAttribute( "Operator" ) ) + { + int value = validation_element.attribute( "Operator" ).toInt(); + switch( value ) + { + case 0: + kspread_validity->m_cond=Conditional::Between; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + if ( !expression1.isNull() ) + kspread_validity->valMax=expression1.toElement().text().toInt(); + break; + case 1: + kspread_validity->m_cond=Conditional::DifferentTo; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + if ( !expression1.isNull() ) + kspread_validity->valMax=expression1.toElement().text().toInt(); + break; + case 2: + kspread_validity->m_cond=Conditional::Equal; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 3: + kspread_validity->m_cond=Conditional::Different; + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + break; + case 4: + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + kspread_validity->m_cond=Conditional::Superior; + break; + case 5: + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + kspread_validity->m_cond=Conditional::Inferior; + break; + case 6: + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + kspread_validity->m_cond=Conditional::SuperiorEqual; + break; + case 7: + if ( !expression0.isNull() ) + kspread_validity->valMin=expression0.toElement().text().toInt(); + kspread_validity->m_cond=Conditional::InferiorEqual; + break; + default: + kdDebug()<<" Error in validation Operator :"<<value<<endl; + break; + } + } + break; + default: + kdDebug()<<" Error in Type element : "<<valueOp<<endl; + } + + } + //<gmr:Validation Style="0" Type="1" Operator="0" AllowBlank="true" UseDropdown="false"> + //<gmr:Expression0>745</gmr:Expression0> + //<gmr:Expression1>4546</gmr:Expression1> + } + } + if (!font.isNull()) + { + TQDomElement font_element = font.toElement(); + + kspread_cell->format()->setTextFontFamily( font_element.text() ); + + if (!font_element.isNull()) + { + if (font_element.attribute("Italic") == "1") + { kspread_cell->format()->setTextFontItalic(true); } + + if (font_element.attribute("Bold") == "1") + { kspread_cell->format()->setTextFontBold(true); } + + if (font_element.hasAttribute("Underline") && ( font_element.attribute("Underline") != "0") ) + { kspread_cell->format()->setTextFontUnderline(true); } + + if (font_element.hasAttribute("StrikeThrough" ) && ( font_element.attribute("StrikeThrough") != "0") ) + { kspread_cell->format()->setTextFontStrike(true); } + + if (font_element.hasAttribute("Unit")) + { kspread_cell->format()->setTextFontSize(font_element.attribute("Unit").toInt()); } + + } + if ( !hyperlink.isNull() ) + { + //<gmr:HyperLink type="GnmHLinkURL" target="www.kde.org"/> + if ( hyperlink.toElement().hasAttribute( "type" ) ) + { + TQString linkType= hyperlink.toElement().attribute( "type" ); + TQString target = hyperlink.toElement().attribute( "target" ); + TQString tip = hyperlink.toElement().attribute( "tip" ); + if ( !tip.isEmpty() ) + kspread_cell->setCellText( tip ); + if ( linkType=="GnmHLinkURL" ) + { + if ( !target.startsWith( "http://" ) ) + target="http://"+target; + kspread_cell->setLink( target ); + } + else if ( linkType=="GnmHLinkEMail" ) + { + if ( !target.startsWith( "mailto:/" ) ) + target="mailto:/"+target; + kspread_cell->setLink( target ); + } + else if ( linkType=="GnmHLinkExternal" ) + { + if ( !target.startsWith( "file://" ) ) + target="file://"+target; + + kspread_cell->setLink( target ); + } + else if ( linkType=="GnmHLinkCurWB" ) + { + kspread_cell->setLink( target ); + } + else + kdDebug()<<" linkType not defined : "<<linkType<<endl; + } + } + } + } + } + style_region = style_region.nextSibling(); + } + + } +} + +/* NOTE: As of now everything is in a single huge function. This is + very ugly. It should all be broken up into smaller + functions, probably one for each GNUMeric section. It kind + of grew out of control. It could probably be cleaned up in + an hour or so. --PGE + */ + + +KoFilter::ConversionStatus GNUMERICFilter::convert( const TQCString & from, const TQCString & to ) +{ + dateInit(); + bool bSuccess=true; + + kdDebug(30521) << "Entering GNUmeric Import filter." << endl; + + KoDocument * document = m_chain->outputDocument(); + if ( !document ) + return KoFilter::StupidError; + + kdDebug(30521) << "here we go... " << document->className() << endl; + + if ( !::tqqt_cast<const KSpread::Doc *>( document ) ) // it's safer that way :) + { + kdWarning(30521) << "document isn't a KSpread::Doc but a " << document->className() << endl; + return KoFilter::NotImplemented; + } + if ( from != "application/x-gnumeric" || to != "application/x-kspread" ) + { + kdWarning(30521) << "Invalid mimetypes " << from << " " << to << endl; + return KoFilter::NotImplemented; + } + + kdDebug(30521) << "...still here..." << endl; + + // No need for a dynamic cast here, since we use TQt's moc magic + Doc * ksdoc = ( Doc * ) document; + + if ( ksdoc->mimeType() != "application/x-kspread" ) + { + kdWarning(30521) << "Invalid document mimetype " << ksdoc->mimeType() << endl; + return KoFilter::NotImplemented; + } + + + TQIODevice* in = KFilterDev::deviceForFile(m_chain->inputFile(),"application/x-gzip"); + + if ( !in ) + { + kdError(30521) << "Cannot create device for uncompressing! Aborting!" << endl; + return KoFilter::FileNotFound; + } + + if (!in->open(IO_ReadOnly)) + { + kdError(30521) << "Cannot open file for uncompressing! Aborting!" << endl; + delete in; + return KoFilter::FileNotFound; + } + + TQDomDocument doc; + TQString errorMsg; + int errorLine, errorColumn; + if ( !doc.setContent(in, &errorMsg, &errorLine, &errorColumn) ) + { + kdError(30521) << "Parsing error in " << from << "! Aborting!" << endl + << " In line: " << errorLine << ", column: " << errorColumn << endl + << " Error message: " << errorMsg << endl; + in->close(); + return KoFilter::ParsingError; + } + + in->close(); + delete in; + + int row, column; + int value = 0; + int currentTab = -1; + int selectedTab = 0; + Sheet * selTable = 0; + + TQDomElement docElem = doc.documentElement(); + TQDomElement uiData = docElem.namedItem("gmr:UIData").toElement(); + if ( !uiData.isNull() ) + { + if ( uiData.hasAttribute( "SelectedTab" ) ) + { + bool ok = false; + int n = uiData.attribute( "SelectedTab" ).toInt( &ok ); + if ( ok ) + { + selectedTab = n; + } + } + } + TQDomNode sheets = docElem.namedItem("gmr:Sheets"); + if ( sheets.isNull() ) + { + //avoid crash with new file format. + //TODO allow to load new file format + return KoFilter::ParsingError; + } + TQDomNode sheet = sheets.namedItem("gmr:Sheet"); + + /* This sets the Document information. */ + set_document_info( document, &docElem ); + + /* This sets the Document attributes */ + set_document_attributes( ksdoc, &docElem ); + + /* This sets the Area Names */ + set_document_area_names( ksdoc, &docElem ); + + Sheet * table; + + // This is a mapping of exprID to expressions. + + TQDict<char> exprID_dict( 17, FALSE ); + int num = 1; + + while (!sheet.isNull()) + { + ++currentTab; + table = ksdoc->map()->addNewSheet(); + + if ( currentTab == selectedTab ) + selTable = table; + + TQDomElement name = sheet.namedItem( "gmr:Name" ).toElement(); + TQDomElement sheetElement = sheet.toElement(); + + if ( !name.isNull() ) + table->setSheetName( name.text(), false, false ); + else + table->setSheetName( "Sheet" + TQString::number( num ), false, false ); + table->enableScrollBarUpdates( false ); + + //kdDebug()<<" sheetElement.hasAttribute( DisplayFormulas ) :"<<sheetElement.hasAttribute( "DisplayFormulas" )<<endl; + TQString tmp; + if ( sheetElement.hasAttribute( "DisplayFormulas" ) ) + { + tmp=sheetElement.attribute( "DisplayFormulas"); + table->setShowFormula( ( tmp=="true" )||( tmp=="1" ) ); + } + if ( sheetElement.hasAttribute( "HideZero" ) ) + { + tmp = sheetElement.attribute( "HideZero" ); + table->setHideZero( ( tmp=="true" )||( tmp=="1" ) ); + } + if ( sheetElement.hasAttribute( "HideGrid" ) ) + { + tmp = sheetElement.attribute( "HideGrid" ); + table->setShowGrid( ( tmp=="false" )||( tmp=="0" ) ); + } + if ( sheetElement.hasAttribute( "HideColHeader" ) ) + { + tmp = sheetElement.attribute( "HideColHeader" ); + ksdoc->setShowColumnHeader( ( tmp=="false" )||( tmp=="0" ) ); + } + if ( sheetElement.hasAttribute( "HideRowHeader" ) ) + { + tmp =sheetElement.attribute( "HideRowHeader" ); + ksdoc->setShowRowHeader( ( tmp=="false" )||( tmp=="0" ) ); + } + + + setObjectInfo(&sheet, table); + setColInfo(&sheet, table); + setRowInfo(&sheet, table); + setSelectionInfo(&sheet, table); + + /* handling print information */ + TQDomNode printInfo = sheet.namedItem("gmr:PrintInformation"); + if ( !printInfo.isNull() ) + ParsePrintInfo( printInfo, table ); + + kdDebug(30521) << "Reading in cells" << endl; + + /* CELL handling START */ + TQDomNode cells = sheet.namedItem( "gmr:Cells" ); + TQDomNode cell = cells.namedItem( "gmr:Cell" ); + TQDomNode mergedCells = sheet.namedItem( "gmr:MergedRegions" ); + TQDomNode mergedRegion = mergedCells.namedItem( "gmr:Merge" ); + if ( cell.isNull() ) + { + kdWarning(30521) << "No cells" << endl; + } + + while ( !cell.isNull() ) + { + value += 2; + emit sigProgress(value); + + TQDomElement e = cell.toElement(); // try to convert the node to an element. + if ( !e.isNull() ) + { // the node was really an element. + kdDebug(30521) << "New Cell " << endl; + TQDomNode content_node = cell.namedItem("gmr:Content"); + + if (!content_node.isNull()) + { + TQDomElement content = content_node.toElement(); + + if( !content.isNull() ) + { // the node was really an element. + column = e.attribute( "Col" ).toInt() + 1; + row = e.attribute( "Row" ).toInt() + 1; + + TQString cell_content( content.text() ); + //kdDebug()<<"cell_content :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<cell_content<<endl; + if ( cell_content[0] == '=' ) + convertFormula( cell_content ); + + Cell * kspread_cell = table->nonDefaultCell( column, row ); + + if (e.hasAttribute("ValueType")) + { + // TODO: what is this for? + // <xsd:enumeration value="10"/> <!-- empty --> + // <xsd:enumeration value="20"/> <!-- boolean --> + // <xsd:enumeration value="30"/> <!-- integer --> + // <xsd:enumeration value="40"/> <!-- float --> + // <xsd:enumeration value="50"/> <!-- error --> + // <xsd:enumeration value="60"/> <!-- string --> + // <xsd:enumeration value="70"/> <!-- cellrange --> + // <xsd:enumeration value="80"/> <!-- array --> + TQString valuetype = e.attribute( "ValueType" ); + if ( valuetype == "40" )//percentage + { + kspread_cell->format()->setFormatType( Percentage_format ); + kspread_cell->setValue( cell_content ); + } + else if ( valuetype =="60" )//string + { + kspread_cell->format()->setFormatType( Text_format ); + kspread_cell->setValue( cell_content ); + } + } + + if (e.hasAttribute( "ValueFormat" )) + { + TQString formatString = e.attribute( "ValueFormat" ); + if ( !setType( kspread_cell, formatString, cell_content ) ) + table->setText(row, column, cell_content, false); + } + else + table->setText(row, column, cell_content, false); + + if (e.hasAttribute("ExprID")) + { + // TQString encoded_string(table->cellAt( column, row, false)->encodeFormula( row, column ).utf8()); + TQString encoded_string(table->cellAt( column, row, false )->encodeFormula().latin1()); + + + char * tmp_string = ( char * ) malloc( strlen( encoded_string.latin1() ) ); + strcpy( tmp_string, encoded_string.latin1() ); + + kdDebug(30521) << encoded_string.latin1() << endl; + + exprID_dict.insert(e.attribute("ExprID"), tmp_string); + + kdDebug(30521) << exprID_dict[e.attribute("ExprID")] << endl; + kdDebug(30521) << exprID_dict[TQString("1")] << endl; + kdDebug(30521) << e.attribute("ExprID") << endl; + + } + } + } + else + { + + column = e.attribute( "Col" ).toInt() + 1; + row = e.attribute( "Row" ).toInt() + 1; + + TQString cell_content( e.text() ); + //kdDebug()<<"cell_content :!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<cell_content<<endl; + if ( cell_content[0] == '=' ) + convertFormula( cell_content ); + + Cell * kspread_cell = table->nonDefaultCell( column, row ); + + if (e.hasAttribute("ValueType")) + { + // TODO: Defined type of cell + //<xsd:enumeration value="10"/> <!-- empty --> + //<xsd:enumeration value="20"/> <!-- boolean --> + //<xsd:enumeration value="30"/> <!-- integer --> + //<xsd:enumeration value="40"/> <!-- float --> + //<xsd:enumeration value="50"/> <!-- error --> + //<xsd:enumeration value="60"/> <!-- string --> + //<xsd:enumeration value="70"/> <!-- cellrange --> + //<xsd:enumeration value="80"/> <!-- array --> + //kspread_cell->setValue( date ); + //kspread_cell->format()->setFormatType( type ); + TQString valuetype = e.attribute( "ValueType" ); + if ( valuetype == "40" )//percentage + { + kspread_cell->format()->setFormatType( Percentage_format ); + kspread_cell->setValue( cell_content ); + } + else if ( valuetype =="60" )//string + { + kspread_cell->format()->setFormatType( Text_format ); + kspread_cell->setValue( cell_content ); + } + + } + + if (e.hasAttribute( "ValueFormat" )) + { + TQString formatString = e.attribute( "ValueFormat" ); + if ( !setType( kspread_cell, formatString, cell_content ) ) + table->setText(row, column, cell_content, false); + } + else + table->setText(row, column, cell_content, false); + + + if (e.hasAttribute("ExprID")) + { + column = e.attribute("Col").toInt() + 1; + row = e.attribute("Row").toInt() + 1; + char * expr; + expr = exprID_dict[e.attribute("ExprID")]; + // expr = exprID_dict[TQString("1")]; + + kdDebug(30521) << "FOO:" << column << row << endl; + kdDebug(30521) << + table->cellAt( column, row, false )->decodeFormula( expr, column, row ).latin1() << endl; + kdDebug(30521) << expr << endl; + + table->setText(row, column, + table->cellAt( column, row, false )->decodeFormula( expr, column, row ), + false); + } + } + } + cell = cell.nextSibling(); + } + + kdDebug(30521) << "Reading in cells done" << endl; + + if ( mergedRegion.isNull() ) + { + kdWarning(30521) << "No cells merged !" << endl; + } + while ( !mergedRegion.isNull() ) + { + TQDomElement e = mergedRegion.toElement(); // try to convert the node to an element. + TQString cell_merge_area( e.text() ); + Range range(cell_merge_area); + //kdDebug()<<"text !!! :"<<cell_merge_area<< "range :start row : "<<range.startRow ()<<" start col :"<<range.startCol ()<<" end row :"<<range.endRow ()<<" end col :"<<range.endCol ()<<endl; + Cell * cell = table->nonDefaultCell( range.startCol (), range.startRow () ); + cell->mergeCells( range.startCol (), range.startRow (), range.endCol ()-range.startCol (), range.endRow ()-range.startRow ()); + mergedRegion = mergedRegion.nextSibling(); + } + /* There is a memory leak here... + * The strings in the exprID_dict have been allocated, but they have not been freed. + */ + + /* exprID_dict.statistics(); */ + + /* CELL handling STOP */ + + /* STYLE handling START */ + //Laurent - 2001-12-07 desactivate this code : otherwise we + //create 65535*255 cells (Styleregion is define for a area and + //not for cell, so gnumeric define a style as : col start=0 col end=255 + //rowstart=0 rowend=255 => we create 255*255 cells + //and gnumeric stocke all area and not just modify area + //=> not good for kspread. + // Norbert: activated again, only cells with texts get modified, nothing else created + setStyleInfo(&sheet, table); + + /* STYLE handling STOP */ + table->enableScrollBarUpdates( true ); + + sheet = sheet.nextSibling(); + ++num; + } + + if ( selTable ) + ksdoc->setDisplaySheet( selTable ); + + emit sigProgress(100); + if ( bSuccess ) + return KoFilter::OK; + else + return KoFilter::StupidError; +} + +#include <gnumericimport.moc> |