diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
| commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
| tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /filters/kspread/opencalc | |
| download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip | |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'filters/kspread/opencalc')
| -rw-r--r-- | filters/kspread/opencalc/Makefile.am | 21 | ||||
| -rw-r--r-- | filters/kspread/opencalc/kspread_opencalc_export.desktop | 59 | ||||
| -rw-r--r-- | filters/kspread/opencalc/kspread_opencalc_import.desktop | 62 | ||||
| -rw-r--r-- | filters/kspread/opencalc/opencalcexport.cc | 1329 | ||||
| -rw-r--r-- | filters/kspread/opencalc/opencalcexport.h | 89 | ||||
| -rw-r--r-- | filters/kspread/opencalc/opencalcimport.cc | 2826 | ||||
| -rw-r--r-- | filters/kspread/opencalc/opencalcimport.h | 119 | ||||
| -rw-r--r-- | filters/kspread/opencalc/opencalcstyleexport.cc | 546 | ||||
| -rw-r--r-- | filters/kspread/opencalc/opencalcstyleexport.h | 167 | ||||
| -rw-r--r-- | filters/kspread/opencalc/status.html | 208 |
10 files changed, 5426 insertions, 0 deletions
diff --git a/filters/kspread/opencalc/Makefile.am b/filters/kspread/opencalc/Makefile.am new file mode 100644 index 000000000..65741b1d7 --- /dev/null +++ b/filters/kspread/opencalc/Makefile.am @@ -0,0 +1,21 @@ +####### General stuff + +INCLUDES= -I$(srcdir)/../../liboofilter -I$(srcdir) -I$(top_srcdir)/kspread $(KOFFICE_INCLUDES) \ + $(KOTEXT_INCLUDES) $(all_includes) + +####### Files +kde_module_LTLIBRARIES = libopencalcimport.la libopencalcexport.la + +libopencalcexport_la_SOURCES = opencalcexport.cc opencalcstyleexport.cc +libopencalcexport_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +libopencalcexport_la_LIBADD = ../../../kspread/libkspreadcommon.la ../../liboofilter/liboofilter.la $(KOFFICE_LIBS) + +libopencalcimport_la_SOURCES = opencalcimport.cc +libopencalcimport_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +libopencalcimport_la_LIBADD = ../../../kspread/libkspreadcommon.la ../../liboofilter/liboofilter.la $(KOFFICE_LIBS) + +METASOURCES = AUTO + +service_DATA = kspread_opencalc_import.desktop kspread_opencalc_export.desktop + +servicedir = $(kde_servicesdir) diff --git a/filters/kspread/opencalc/kspread_opencalc_export.desktop b/filters/kspread/opencalc/kspread_opencalc_export.desktop new file mode 100644 index 000000000..d120960b8 --- /dev/null +++ b/filters/kspread/opencalc/kspread_opencalc_export.desktop @@ -0,0 +1,59 @@ +[Desktop Entry] +Type=Service +Name=OpenOffice.org Calc Export Filter for KSpread +Name[bg]=Филтър за експортиране от KSpread в OpenOffice.org Calc +Name[br]=Sil ezporzh OpenOffice.org Calc evit KSpread +Name[ca]=Filtre d'exportació OpenOffice.org Calc per a KSpread +Name[cs]=OpenOffice.org Calc exportní filtr pro KSpread +Name[cy]=Hidlen Allforio OpenOffice.org Calc ar gyfer KSpread +Name[da]=OpenOffice.rog-Calc eksportfilter for KSpread +Name[de]=KSpread OpenOffice.org Calc-Exportfilter +Name[el]=Φίλτρο εξαγωγής OpenOffice.org Calc για το KSpread +Name[eo]=OpenOffice.org Calc-eksportfiltrilo por KSpread +Name[es]=Filtro de exportación de OpenOffice.org Calc para KSpread +Name[et]=KSpreadi OpenOffice.org Calc'i ekspordifilter +Name[eu]=KSpread-en OpenOffice.org Calc esportaziorako iragazkia +Name[fa]=پالایۀ صادرات OpenOffice.org Calc برای KSpread +Name[fi]=OpenOffice.org Calc -vientisuodin KSpreadille +Name[fr]=Filtre d'exportation OpenOffice.org Calc pour KSpread +Name[fy]=OpenOffice.org Calc Eksportfilter foar KSpread +Name[ga]=Scagaire Easpórtála OpenOffice.org Calc le haghaidh KSpread +Name[gl]=Filtro de Exportación de OpenOffice.org Calc para KSpread +Name[he]=מסנן ייצוא מ־KSpread ל־OpenOffice.org Calc +Name[hi]=के-स्प्रेड के लिए ओपन-ऑफ़िस.ऑर्ग केल्क निर्यात छननी +Name[hr]=OpenOffice.org Calc filtar izvoza za KSpread +Name[hu]=OpenOffice.org Calc exportszűrő a KSpreadhez +Name[is]=OpenOffice.org Calc útflutningssía fyrir KSpread +Name[it]=Filtro di esportazione OpenOffice.org Calc per KSpread +Name[ja]=KSpread OpenOffice.org Calc エクスポートフィルタ +Name[km]=តម្រងនាំចេញ OpenOffice.org Calc សម្រាប់ KSpread +Name[lt]=OpenOffice.org Calc eksportavimo filtras skirtas KSpread +Name[lv]=OpenOffice.org Calc eksporta filtrs priekš KSpread +Name[ms]=Penapis Eksport OpenOffice.org Calc bagi KSpread +Name[nb]=OpenOffice.org Calc-eksportfilter for KSpread +Name[nds]="OpenOffice.org Calc"-Exportfilter för KSpread +Name[ne]=केडीई स्प्रिेडका लागि OpenOffice.org क्याल्क निर्यात फिल्टर +Name[nl]=OpenOffice.org Calc Exportfilter voor KSpread +Name[nn]=OpenOffice.org Calc-eksportfilter for KSpread +Name[pl]=Filtr eksportu do formatu OpenOffice.org Calc dla KSpread +Name[pt]=Filtro de Exportação de OpenOffice.org Calc para o KSpread +Name[pt_BR]=Filtro de Exportação OpenOffice.org Calc do KSpread +Name[ru]=Фильтр экспорта таблиц KSpread в OpenOffice.org Calc +Name[se]=KSpread:a OpenOffice.org Calc-olggosfievrridansilli +Name[sk]=OpenCalc filter pre export do KSpread +Name[sl]=Izvozni filter OpenOffice.org Calc za KSpread +Name[sr]=KSpread-ов филтер за извоз у OpenOffice.org-ов Calc +Name[sr@Latn]=KSpread-ov filter za izvoz u OpenOffice.org-ov Calc +Name[sv]=OpenOffice.org Calc-exportfilter för Kspread +Name[ta]=கேஸ்பெரெட்டுக்கான OpenOffice.org கால்க் ஏற்றும் அலங்காரம் +Name[tr]=KSpread için OpenOffice.org Calc Aktarma Filtresi +Name[uk]=Фільтр експорту OpenOffice.org Calc для KSpread +Name[uz]=KSpread uchun OpenOffice.org Calc eksport filteri +Name[uz@cyrillic]=KSpread учун OpenOffice.org Calc экспорт филтери +Name[zh_CN]=KSpread 的 OpenOffice.org Calc 导出过滤器 +Name[zh_TW]=KSpread 的 OpenOffice.org Calc 匯出過濾程式 +X-KDE-Export=application/vnd.sun.xml.calc +X-KDE-Import=application/x-kspread +X-KDE-Weight=1 +X-KDE-Library=libopencalcexport +ServiceTypes=KOfficeFilter diff --git a/filters/kspread/opencalc/kspread_opencalc_import.desktop b/filters/kspread/opencalc/kspread_opencalc_import.desktop new file mode 100644 index 000000000..c7dde5ef5 --- /dev/null +++ b/filters/kspread/opencalc/kspread_opencalc_import.desktop @@ -0,0 +1,62 @@ +[Desktop Entry] +Type=Service +Name=OpenOffice.org Calc Import Filter for KSpread +Name[bg]=Филтър за импортиране от OpenOffice.org Calc в KSpread +Name[br]=Sil enporzh OpenOffice.org Calc evit KSpread +Name[ca]=Filtre d'importació OpenOffice.org Calc per a KSpread +Name[cs]=OpenOffice.org Calc importní filtr pro KSpread +Name[cy]=Hidl Mewnforio OpenOffice.org Calc ar gyfer KSpread +Name[da]=OpenOffice.org-Calc importfilter for KSpread +Name[de]=KSpread OpenOffice.org Calc-Importfilter +Name[el]=Φίλτρο εισαγωγής OpenOffice.org Calc για το KSpread +Name[eo]=OpenOffice.org Calc-importfiltrilo por KSpread +Name[es]=Filtro de importación de OpenOffice.org Calc para KSpread +Name[et]=KSpreadi OpenOffice.org Calc'i impordifilter +Name[eu]=KSpread-en OpenOffice.org Calc inportaziorako iragazkia +Name[fa]=پالایۀ واردات OpenOffice.org Calc برای KSpread +Name[fi]=OpenOffice.org Calc -tuontisuodin KSpreadille +Name[fr]=Filtre d'importation OpenOffice.org Calc pour KSpread +Name[fy]=OpenOffice.org Calc Ymportfilter foar KSpread +Name[ga]=Scagaire Iompórtála OpenOffice.org Calc le haghaidh KSpread +Name[gl]=Filtro de Importación de OpenOffice.org Calc para KSpread +Name[he]=מסנן ייבוא מ־OpenOffice.org Calc ל־KSpread +Name[hi]=के-स्प्रेड के लिए ओपन-ऑफ़िस.ऑर्ग केल्क आयात छननी +Name[hr]=OpenOffice.org Calc filtar uvoza za KSpread +Name[hu]=OpenOffice.org importszűrő a KSpreadhez +Name[is]=OpenOffice.org Calc innflutningssía fyrir KSpread +Name[it]=Filtro di importazione OpenOffice.org Calc per KSpread +Name[ja]=KSpread OpenOffice.org Calc インポートフィルタ +Name[km]=តម្រងនាំចូល OpenOffice.org Calc សម្រាប់ KSpread +Name[lt]=OpenOffice.org Calc importavimo filtras skirtas KSpread +Name[lv]=OpenOffice.org Calc importa filtrs priekš KSpread +Name[ms]=Penapis Import OpenOffice.org Calc bagi KSpread +Name[nb]=OpenOffice.org Calc-importfilter for KSpread +Name[nds]="OpenOffice.org Calc"-Importfilter för KSpread +Name[ne]=केडीई स्प्रिेडका लागि OpenOffice.org क्याल्क आयात फिल्टर +Name[nl]=OpenOffice.org Calc Importfilter voor KSpread +Name[nn]=OpenOffice.org Calc-importfilter for KSpread +Name[pl]=Filtr importu formatu OpenOffice.org dla KSpread +Name[pt]=Filtro de Importação de OpenOffice.org Calc para o KSpread +Name[pt_BR]=Filtro de Importação OpenOffice.org Calc do KSpread +Name[ru]=Фильтр импорта таблиц OpenOffice.org Calc в KSpread +Name[se]=KSpread:a OpenOffice.org Calc-sisafievrridansilli +Name[sk]=OpenCalc filter pre import z KSpread +Name[sl]=Uvozni filter OpenOffice.org Calc za KSpread +Name[sr]=KSpread-ов филтер за увоз из OpenOffice.org-овог Calc-а +Name[sr@Latn]=KSpread-ov filter za uvoz iz OpenOffice.org-ovog Calc-a +Name[sv]=OpenOffice.org Calc-importfilter för Kspread +Name[ta]=கேஸ்பெரெட்டுக்கான OpenOffice.org கால்க் இறக்கும் அலங்காரம் +Name[tr]=KSpread için OpenOffice.org Calc Alma Filtresi +Name[uk]=Фільтр імпорту OpenOffice.org Calc для KSpread +Name[uz]=KSpread uchun OpenOffice.org Calc import filteri +Name[uz@cyrillic]=KSpread учун OpenOffice.org Calc импорт филтери +Name[zh_CN]=KSpread 的 OpenOffice.org Calc 导入过滤器 +Name[zh_TW]=KSpread 的 OpenOffice.org Calc 匯入過濾程式 +X-KDE-Export=application/x-kspread +X-KDE-Import=application/vnd.sun.xml.calc,application/vnd.sun.xml.calc.template +X-KDE-Weight=1 +X-KDE-Library=libopencalcimport +X-KDE-LibraryMajor=1 +X-KDE-LibraryMinor=0 +X-KDE-LibraryDependencies= +ServiceTypes=KOfficeFilter diff --git a/filters/kspread/opencalc/opencalcexport.cc b/filters/kspread/opencalc/opencalcexport.cc new file mode 100644 index 000000000..20915b516 --- /dev/null +++ b/filters/kspread/opencalc/opencalcexport.cc @@ -0,0 +1,1329 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <faure@kde.org> + Copyright (C) 2000 Norbert Andres <nandres@web.de> + 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. +*/ + +#include <float.h> +#include <math.h> + +#include <opencalcexport.h> + +#include <qdatetime.h> +#include <qdom.h> +#include <qfile.h> +#include <qregexp.h> +#include <qvaluelist.h> + +#include <kdebug.h> +#include <kmessagebox.h> +#include <kmdcodec.h> +#include <kgenericfactory.h> +#include <klocale.h> + +#include <KoDocumentInfo.h> +#include <KoFilterChain.h> +#include <KoGlobal.h> + +#include <kspread_aboutdata.h> +#include <kspread_cell.h> +#include <kspread_doc.h> +#include <kspread_format.h> +#include <kspread_map.h> +#include <kspread_view.h> +#include <kspread_canvas.h> +#include <kspread_sheet.h> +#include <kspread_sheetprint.h> +#include <kspread_style.h> +#include <kspread_style_manager.h> +#include <kspread_util.h> + +using namespace KSpread; + +typedef QValueList<Reference> AreaList; + +class OpenCalcExportFactory : KGenericFactory<OpenCalcExport, KoFilter> +{ +public: + OpenCalcExportFactory(void) : KGenericFactory<OpenCalcExport, KoFilter> ("kspreadopencalcexport") + {} +protected: + virtual void setupTranslations( void ) + { + KGlobal::locale()->insertCatalogue( "kofficefilters" ); + } +}; + +K_EXPORT_COMPONENT_FACTORY( libopencalcexport, OpenCalcExportFactory() ) + +#define STOPEXPORT \ + do \ + { \ + delete store; \ + return false; \ + } while(0) + +OpenCalcExport::OpenCalcExport( KoFilter *, const char *, const QStringList & ) + : KoFilter(), m_locale( 0 ) +{ +} + +KoFilter::ConversionStatus OpenCalcExport::convert( const QCString & from, + const QCString & to ) +{ + /* later... + KSpreadLeader * leader = new KSpreadLeader( m_chain ); + OpenCalcWorker * worker = new OpenCalcWorker(); + leader->setWorker( worker ); + + KoFilter::ConversionStatus status = leader->convert(); + + delete worker; + delete leader; + + return status; + */ + + KoDocument * document = m_chain->inputDocument(); + + if ( !document ) + return KoFilter::StupidError; + + if ( !::qt_cast<const KSpread::Doc *>( document ) ) + { + kdWarning(30518) << "document isn't a KSpread::Doc but a " + << document->className() << endl; + return KoFilter::NotImplemented; + } + + if ( ( to != "application/vnd.sun.xml.calc") || (from != "application/x-kspread" ) ) + { + kdWarning(30518) << "Invalid mimetypes " << to << " " << from << endl; + return KoFilter::NotImplemented; + } + + const Doc * ksdoc = static_cast<const Doc *>(document); + + if ( ksdoc->mimeType() != "application/x-kspread" ) + { + kdWarning(30518) << "Invalid document mimetype " << ksdoc->mimeType() << endl; + return KoFilter::NotImplemented; + } + + m_locale = static_cast<Doc*>(document)->locale(); + if ( !writeFile( ksdoc ) ) + return KoFilter::CreationError; + + emit sigProgress( 100 ); + + return KoFilter::OK; +} + +bool OpenCalcExport::writeFile( const Doc * ksdoc ) +{ + KoStore * store = KoStore::createStore( m_chain->outputFile(), KoStore::Write, "", KoStore::Zip ); + + if ( !store ) + return false; + + uint filesWritten = 0; + + if ( !exportContent( store, ksdoc ) ) + STOPEXPORT; + else + filesWritten |= contentXML; + + // TODO: pass sheet number and cell number + if ( !exportDocInfo( store, ksdoc ) ) + STOPEXPORT; + else + filesWritten |= metaXML; + + if ( !exportStyles( store, ksdoc ) ) + STOPEXPORT; + else + filesWritten |= stylesXML; + + if ( !exportSettings( store, ksdoc ) ) + STOPEXPORT; + else + filesWritten |= settingsXML; + + if ( !writeMetaFile( store, filesWritten ) ) + STOPEXPORT; + + // writes zip file to disc + delete store; + store = 0; + + return true; +} + +bool OpenCalcExport::exportDocInfo( KoStore * store, const Doc* ksdoc ) +{ + if ( !store->open( "meta.xml" ) ) + return false; + + KoDocumentInfo * docInfo = ksdoc->documentInfo(); + KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>( docInfo->page( "about" ) ); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) ); + + QDomDocument meta; + meta.appendChild( meta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); + + QDomElement content = meta.createElement( "office:document-meta" ); + content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office"); + content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); + content.setAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/" ); + content.setAttribute( "xmlns:meta", "http://openoffice.org/2000/meta" ); + content.setAttribute( "office:version", "1.0" ); + + QDomNode officeMeta = meta.createElement( "office:meta" ); + + QDomElement data = meta.createElement( "meta:generator" ); + QString app( "KSpread " ); + app += KSpread::version; + data.appendChild( meta.createTextNode( app ) ); + officeMeta.appendChild( data ); + + data = meta.createElement( "meta:initial-creator" ); + data.appendChild( meta.createTextNode( authorPage->fullName() ) ); + officeMeta.appendChild( data ); + + data = meta.createElement( "meta:creator" ); + data.appendChild( meta.createTextNode( authorPage->fullName() ) ); + officeMeta.appendChild( data ); + + data = meta.createElement( "dc:description" ); + data.appendChild( meta.createTextNode( aboutPage->abstract() ) ); + officeMeta.appendChild( data ); + + data = meta.createElement( "meta:keywords" ); + QDomElement dataItem = meta.createElement( "meta:keyword" ); + dataItem.appendChild( meta.createTextNode( aboutPage->keywords() ) ); + data.appendChild( dataItem ); + officeMeta.appendChild( data ); + + data = meta.createElement( "dc:title" ); + data.appendChild( meta.createTextNode( aboutPage->title() ) ); + officeMeta.appendChild( data ); + + data = meta.createElement( "dc:subject" ); + data.appendChild( meta.createTextNode( aboutPage->subject() ) ); + officeMeta.appendChild( data ); + + const QDateTime dt ( QDateTime::currentDateTime() ); + if ( dt.isValid() ) + { + data = meta.createElement( "dc:date" ); + data.appendChild( meta.createTextNode( dt.toString( Qt::ISODate ) ) ); + officeMeta.appendChild( data ); + } + + /* TODO: + <meta:creation-date>2003-01-08T23:57:31</meta:creation-date> + <dc:language>en-US</dc:language> + <meta:editing-cycles>2</meta:editing-cycles> + <meta:editing-duration>PT38S</meta:editing-duration> + <meta:user-defined meta:name="Info 3"/> + <meta:user-defined meta:name="Info 4"/> + */ + + data = meta.createElement( "meta:document-statistic" ); + data.setAttribute( "meta:table-count", QString::number( ksdoc->map()->count() ) ); + // TODO: data.setAttribute( "meta:cell-count", ); + officeMeta.appendChild( data ); + + content.appendChild( officeMeta ); + meta.appendChild( content ); + + QCString doc( meta.toCString() ); + kdDebug(30518) << "Meta: " << doc << endl; + + store->write( doc, doc.length() ); + + if ( !store->close() ) + return false; + + return true; +} + +bool OpenCalcExport::exportSettings( KoStore * store, const Doc * ksdoc ) +{ + if ( !store->open( "settings.xml" ) ) + return false; + + QDomDocument doc; + doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); + + QDomElement settings = doc.createElement( "office:document-settings" ); + settings.setAttribute( "xmlns:office", "http://openoffice.org/2000/office"); + settings.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); + settings.setAttribute( "xmlns:config", "http://openoffice.org/2001/config" ); + settings.setAttribute( "office:version", "1.0" ); + + QDomElement begin = doc.createElement( "office:settings" ); + + QDomElement configItem = doc.createElement("config:config-item-set" ); + configItem.setAttribute( "config:name", "view-settings" ); + + QDomElement mapIndexed = doc.createElement( "config:config-item-map-indexed" ); + mapIndexed.setAttribute("config:name", "Views" ); + configItem.appendChild( mapIndexed ); + + QDomElement mapItem = doc.createElement("config:config-item-map-entry" ); + + QDomElement attribute = doc.createElement("config:config-item" ); + attribute.setAttribute( "config:name", "ActiveTable" ); + attribute.setAttribute( "config:type", "string" ); + + View * view = static_cast<View*>( ksdoc->views().getFirst()); + QString activeTable; + if ( view ) // no view if embedded document + { + Canvas * canvas = view->canvasWidget(); + activeTable = canvas->activeSheet()->sheetName(); + // save current sheet selection before to save marker, otherwise current pos is not saved + view->saveCurrentSheetSelection(); + } + attribute.appendChild( doc.createTextNode( activeTable ) ); + mapItem.appendChild( attribute ); + + QDomElement configmaped = doc.createElement( "config:config-item-map-named" ); + configmaped.setAttribute( "config:name","Tables" ); + + QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() ); + for( ; it.current(); ++it ) + { + QPoint marker; + if ( view ) + { + marker = view->markerFromSheet( *it ); + } + QDomElement tmpItemMapNamed = doc.createElement( "config:config-item-map-entry" ); + tmpItemMapNamed.setAttribute( "config:name", ( *it )->tableName() ); + + QDomElement sheetAttribute = doc.createElement( "config:config-item" ); + sheetAttribute.setAttribute( "config:name", "CursorPositionX" ); + sheetAttribute.setAttribute( "config:type", "int" ); + sheetAttribute.appendChild( doc.createTextNode( QString::number(marker.x() ) ) ); + tmpItemMapNamed.appendChild( sheetAttribute ); + + sheetAttribute = doc.createElement( "config:config-item" ); + sheetAttribute.setAttribute( "config:name", "CursorPositionY" ); + sheetAttribute.setAttribute( "config:type", "int" ); + sheetAttribute.appendChild( doc.createTextNode( QString::number(marker.y() ) ) ); + tmpItemMapNamed.appendChild( sheetAttribute ); + + configmaped.appendChild( tmpItemMapNamed ); + } + mapItem.appendChild( configmaped ); + + + + mapIndexed.appendChild( mapItem ); + + begin.appendChild( configItem ); + + settings.appendChild( begin ); + + doc.appendChild( settings ); + + QCString f( doc.toCString() ); + kdDebug(30518) << "Settings: " << (char const * ) f << endl; + + store->write( f, f.length() ); + + if ( !store->close() ) + return false; + + return true; +} + +bool OpenCalcExport::exportContent( KoStore * store, const Doc * ksdoc ) +{ + if ( !store->open( "content.xml" ) ) + return false; + + createDefaultStyles(); + + QDomDocument doc; + doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); + + QDomElement content = doc.createElement( "office:document-content" ); + content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office"); + content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" ); + content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" ); + content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" ); + content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" ); + content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" ); + content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); + content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" ); + content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" ); + content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" ); + content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" ); + content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" ); + content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" ); + content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" ); + content.setAttribute( "office:class", "spreadsheet" ); + content.setAttribute( "office:version", "1.0" ); + + QDomElement data = doc.createElement( "office:script" ); + content.appendChild( data ); + + if ( !exportBody( doc, content, ksdoc ) ) + return false; + + doc.appendChild( content ); + + QCString f( doc.toCString() ); + kdDebug(30518) << "Content: " << (char const * ) f << endl; + + store->write( f, f.length() ); + + if ( !store->close() ) + return false; + + return true; +} + +void exportNamedExpr( QDomDocument & doc, QDomElement & parent, + AreaList const & namedAreas ) +{ + AreaList::const_iterator it = namedAreas.begin(); + AreaList::const_iterator end = namedAreas.end(); + + while ( it != end ) + { + QDomElement namedRange = doc.createElement( "table:named-range" ); + + Reference ref = *it; + + namedRange.setAttribute( "table:name", ref.ref_name ); + namedRange.setAttribute( "table:base-cell-address", convertRefToBase( ref.sheet_name, ref.rect ) ); + namedRange.setAttribute( "table:cell-range-address", convertRefToRange( ref.sheet_name, ref.rect ) ); + + parent.appendChild( namedRange ); + + ++it; + } +} + +bool OpenCalcExport::exportBody( QDomDocument & doc, QDomElement & content, const Doc * ksdoc ) +{ + QDomElement fontDecls = doc.createElement( "office:font-decls" ); + QDomElement autoStyles = doc.createElement( "office:automatic-styles" ); + QDomElement body = doc.createElement( "office:body" ); + + if ( ksdoc->map()->isProtected() ) + { + body.setAttribute( "table:structure-protected", "true" ); + + QCString passwd; + ksdoc->map()->password( passwd ); + if ( passwd.length() > 0 ) + { + QCString str( KCodecs::base64Encode( passwd ) ); + body.setAttribute( "table:protection-key", QString( str.data() ) ); + } + } + + + + QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() ); + + for( it.toFirst(); it.current(); ++it ) + { + SheetStyle ts; + int maxCols = 1; + int maxRows = 1; + Sheet * sheet = it.current(); + + ts.visible = !sheet->isHidden(); + + QDomElement tabElem = doc.createElement( "table:table" ); + tabElem.setAttribute( "table:style-name", m_styles.sheetStyle( ts ) ); + + if ( sheet->isProtected() ) + { + tabElem.setAttribute( "table:protected", "true" ); + + QCString passwd; + sheet->password( passwd ); + if ( passwd.length() > 0 ) + { + QCString str( KCodecs::base64Encode( passwd ) ); + tabElem.setAttribute( "table:protection-key", QString( str.data() ) ); + } + } + + QString name( sheet->tableName() ); + + int n = name.find( ' ' ); + if ( n != -1 ) + { + kdDebug(30518) << "Sheet name converting: " << name << endl; + name[n] == '_'; + kdDebug(30518) << "Sheet name converted: " << name << endl; + } + name = name.replace( ' ', "_" ); + + QRect _printRange = sheet->print()->printRange(); + if ( _printRange != ( QRect( QPoint( 1, 1 ), QPoint( KS_colMax, KS_rowMax ) ) ) ) + { + QString range= convertRangeToRef( name, _printRange ); + //kdDebug(30518)<<" range : "<<range<<endl; + tabElem.setAttribute( "table:print-ranges", range ); + } + + + tabElem.setAttribute( "table:name", name ); + + maxRowCols( sheet, maxCols, maxRows ); + + exportSheet( doc, tabElem, sheet, maxCols, maxRows ); + + body.appendChild( tabElem ); + } + + KoDocument * document = m_chain->inputDocument(); + Doc * kspreadDoc = static_cast<Doc *>( document ); + + AreaList namedAreas = kspreadDoc->listArea(); + if ( namedAreas.count() > 0 ) + { + QDomElement namedExpr = doc.createElement( "table:named-expressions" ); + exportNamedExpr( doc, namedExpr, namedAreas ); + + body.appendChild( namedExpr ); + } + + m_styles.writeStyles( doc, autoStyles ); + m_styles.writeFontDecl( doc, fontDecls ); + + content.appendChild( fontDecls ); + content.appendChild( autoStyles ); + content.appendChild( body ); + + return true; +} + +void OpenCalcExport::exportSheet( QDomDocument & doc, QDomElement & tabElem, + const Sheet * sheet, int maxCols, int maxRows ) +{ + kdDebug(30518) << "exportSheet: " << sheet->tableName() << endl; + int i = 1; + + while ( i <= maxCols ) + { + const ColumnFormat * column = sheet->columnFormat( i ); + ColumnStyle cs; + cs.breakB = ::Style::automatic; + cs.size = column->mmWidth() / 10; + bool hide = column->isHide(); + + int j = i + 1; + int repeated = 1; + while ( j <= maxCols ) + { + const ColumnFormat *c = sheet->columnFormat( j ); + ColumnStyle cs1; + cs1.breakB = ::Style::automatic; + cs1.size = c->mmWidth() / 10; + + if ( ColumnStyle::isEqual( &cs, cs1 ) && ( hide == c->isHide() ) ) + ++repeated; + else + break; + ++j; + } + + QDomElement colElem = doc.createElement( "table:table-column" ); + colElem.setAttribute( "table:style-name", m_styles.columnStyle( cs ) ); + colElem.setAttribute( "table:default-cell-style-name", "Default" );//todo fixme create style from cell + if ( hide ) + colElem.setAttribute( "table:visibility", "collapse" ); + + if ( repeated > 1 ) + colElem.setAttribute( "table:number-columns-repeated", QString::number( repeated ) ); + + tabElem.appendChild( colElem ); + i += repeated; + } + + for ( i = 1; i <= maxRows; ++i ) + { + const RowFormat * row = sheet->rowFormat( i ); + RowStyle rs; + rs.breakB = ::Style::automatic; + rs.size = row->mmHeight() / 10; + + QDomElement rowElem = doc.createElement( "table:table-row" ); + rowElem.setAttribute( "table:style-name", m_styles.rowStyle( rs ) ); + if ( row->isHide() ) + rowElem.setAttribute( "table:visibility", "collapse" ); + + exportCells( doc, rowElem, sheet, i, maxCols ); + + tabElem.appendChild( rowElem ); + } +} + +void OpenCalcExport::exportCells( QDomDocument & doc, QDomElement & rowElem, + const Sheet *sheet, int row, int maxCols ) +{ + int i = 1; + while ( i <= maxCols ) + { + int repeated = 1; + bool hasComment = false; + const Cell* cell = sheet->cellAt( i, row ); + QDomElement cellElem; + + if ( !cell->isPartOfMerged() ) + cellElem = doc.createElement( "table:table-cell" ); + else + cellElem = doc.createElement( "table:covered-table-cell" ); + + QFont font; + Value const value( cell->value() ); + if ( !cell->isDefault() ) + { + font = cell->format()->textFont( i, row ); + m_styles.addFont( font ); + + if ( cell->format()->hasProperty( Format::PComment ) ) + hasComment = true; + } + + CellStyle c; + CellStyle::loadData( c, cell ); // TODO: number style + + cellElem.setAttribute( "table:style-name", m_styles.cellStyle( c ) ); + + // group empty cells with the same style + if ( cell->isEmpty() && !hasComment && !cell->isPartOfMerged() && !cell->doesMergeCells() ) + { + int j = i + 1; + while ( j <= maxCols ) + { + const Cell *cell1 = sheet->cellAt( j, row ); + + CellStyle c1; + CellStyle::loadData( c1, cell1 ); // TODO: number style + + if ( cell1->isEmpty() && !cell->format()->hasProperty( Format::PComment ) + && CellStyle::isEqual( &c, c1 ) && !cell->isPartOfMerged() && !cell->doesMergeCells() ) + ++repeated; + else + break; + ++j; + } + if ( repeated > 1 ) + cellElem.setAttribute( "table:number-columns-repeated", QString::number( repeated ) ); + } + + if ( value.isBoolean() ) + { + kdDebug(30518) << "Type: Boolean" << endl; + cellElem.setAttribute( "table:value-type", "boolean" ); + cellElem.setAttribute( "table:boolean-value", ( value.asBoolean() ? "true" : "false" ) ); + } + else if ( value.isNumber() ) + { + kdDebug(30518) << "Type: Number" << endl; + FormatType type = cell->format()->getFormatType( i, row ); + + if ( type == Percentage_format ) + cellElem.setAttribute( "table:value-type", "percentage" ); + else + cellElem.setAttribute( "table:value-type", "float" ); + + cellElem.setAttribute( "table:value", QString::number( value.asFloat() ) ); + } + else + { + kdDebug(30518) << "Type: " << value.type() << endl; + } + + if ( cell->isFormula() ) + { + kdDebug(30518) << "Formula found" << endl; + + QString formula( convertFormula( cell->text() ) ); + cellElem.setAttribute( "table:formula", formula ); + } + else if ( !cell->link().isEmpty() ) + { + QDomElement link = doc.createElement( "text:p" ); + QDomElement linkref = doc.createElement( "text:a" ); + + QString tmp = cell->link(); + if ( localReferenceAnchor( tmp ) ) + linkref.setAttribute( "xlink:href", ( "#"+tmp ) ); + else + linkref.setAttribute( "xlink:href", tmp ); + + linkref.appendChild( doc.createTextNode( cell->text() ) ); + + link.appendChild( linkref ); + cellElem.appendChild( link ); + } + else if ( !cell->isEmpty() ) + { + QDomElement textElem = doc.createElement( "text:p" ); + textElem.appendChild( doc.createTextNode( cell->strOutText() ) ); + + cellElem.appendChild( textElem ); + kdDebug(30518) << "Cell StrOut: " << cell->strOutText() << endl; + } + + if ( cell->doesMergeCells() ) + { + int colSpan = cell->mergedXCells() + 1; + int rowSpan = cell->mergedYCells() + 1; + + if ( colSpan > 1 ) + cellElem.setAttribute( "table:number-columns-spanned", QString::number( colSpan ) ); + + if ( rowSpan > 1 ) + cellElem.setAttribute( "table:number-rows-spanned", QString::number( rowSpan ) ); + } + + if ( hasComment ) + { + QString comment( cell->format()->comment( i, row ) ); + QDomElement annotation = doc.createElement( "office:annotation" ); + QDomElement text = doc.createElement( "text:p" ); + text.appendChild( doc.createTextNode( comment ) ); + + annotation.appendChild( text ); + cellElem.appendChild( annotation ); + } + + rowElem.appendChild( cellElem ); + + i += repeated; + } +} + +void OpenCalcExport::maxRowCols( const Sheet *sheet, + int & maxCols, int & maxRows ) +{ + Cell const * cell = sheet->firstCell(); + + while ( cell ) + { + if ( cell->column() > maxCols ) + maxCols = cell->column(); + + if ( cell->row() > maxRows ) + maxRows = cell->row(); + + cell = cell->nextCell(); + } + + RowFormat const * row = sheet->firstRow(); + + while ( row ) + { + if ( row->row() > maxRows ) + maxRows = row->row(); + + row = row->next(); + } + + ColumnFormat const * col = sheet->firstCol(); + while ( col ) + { + if ( col->column() > maxCols ) + maxCols = col->column(); + + col = col->next(); + } + +} + +bool OpenCalcExport::exportStyles( KoStore * store, const Doc *ksdoc ) +{ + if ( !store->open( "styles.xml" ) ) + return false; + + QDomDocument doc; + doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); + + QDomElement content = doc.createElement( "office:document-styles" ); + content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office" ); + content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" ); + content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" ); + content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" ); + content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" ); + content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" ); + content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); + content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" ); + content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" ); + content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" ); + content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" ); + content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" ); + content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" ); + content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" ); + content.setAttribute( "office:version", "1.0" ); + + // order important here! + QDomElement officeStyles = doc.createElement( "office:styles" ); + exportDefaultCellStyle( doc, officeStyles ); + + QDomElement fontDecls = doc.createElement( "office:font-decls" ); + m_styles.writeFontDecl( doc, fontDecls ); + + // TODO: needs in new number/date/time parser... + // exportDefaultNumberStyles( doc, officeStyles ); + + QDomElement defaultStyle = doc.createElement( "style:style" ); + defaultStyle.setAttribute( "style:name", "Default" ); + defaultStyle.setAttribute( "style:family", "table-cell" ); + officeStyles.appendChild( defaultStyle ); + + QDomElement autoStyles = doc.createElement( "office:automatic-styles" ); + exportPageAutoStyles( doc, autoStyles, ksdoc ); + + QDomElement masterStyles = doc.createElement( "office:master-styles" ); + exportMasterStyles( doc, masterStyles, ksdoc ); + + content.appendChild( fontDecls ); + content.appendChild( officeStyles ); + content.appendChild( autoStyles ); + content.appendChild( masterStyles ); + + doc.appendChild( content ); + + QCString f( doc.toCString() ); + kdDebug(30518) << "Content: " << (char const * ) f << endl; + + store->write( f, f.length() ); + + if ( !store->close() ) + return false; + + return true; +} + +void OpenCalcExport::exportDefaultCellStyle( QDomDocument & doc, QDomElement & officeStyles ) +{ + QDomElement defStyle = doc.createElement( "style:default-style" ); + defStyle.setAttribute( "style:family", "table-cell" ); + + KoDocument * document = m_chain->inputDocument(); + Doc * ksdoc = static_cast<Doc *>(document); + + Format * format = new Format( 0, ksdoc->styleManager()->defaultStyle() ); + const KLocale *locale = ksdoc->locale(); + QString language; + QString country; + QString charSet; + + QString l( locale->language() ); + KLocale::splitLocale( l, language, country, charSet ); + QFont font( format->font() ); + m_styles.addFont( font, true ); + + QDomElement style = doc.createElement( "style:properties" ); + style.setAttribute( "style:font-name", font.family() ); + style.setAttribute( "fo:font-size", QString( "%1pt" ).arg( font.pointSize() ) ); + style.setAttribute( "style:decimal-places", QString::number( locale->fracDigits() ) ); + style.setAttribute( "fo:language", language ); + style.setAttribute( "fo:country", country ); + style.setAttribute( "style:font-name-asian", "HG Mincho Light J" ); + style.setAttribute( "style:language-asian", "none" ); + style.setAttribute( "style:country-asian", "none" ); + style.setAttribute( "style:font-name-complex", "Arial Unicode MS" ); + style.setAttribute( "style:language-complex", "none" ); + style.setAttribute( "style:country-complex", "none" ); + style.setAttribute( "style:tab-stop-distance", "1.25cm" ); + + defStyle.appendChild( style ); + officeStyles.appendChild( defStyle ); + delete format; +} + +void OpenCalcExport::createDefaultStyles() +{ + // TODO: default number styles, currency styles,... +} + +void OpenCalcExport::exportPageAutoStyles( QDomDocument & doc, QDomElement & autoStyles, + const Doc *ksdoc ) +{ + QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() ); + const Sheet * sheet = it.toFirst(); + + float width = 20.999; + float height = 29.699; + + if ( sheet ) + { + width = sheet->print()->paperWidth() / 10; + height = sheet->print()->paperHeight() / 10; + } + + QString sWidth = QString( "%1cm" ).arg( width ); + QString sHeight = QString( "%1cm" ).arg( height ); + + QDomElement pageMaster = doc.createElement( "style:page-master" ); + pageMaster.setAttribute( "style:name", "pm1" ); + + QDomElement properties = doc.createElement( "style:properties" ); + properties.setAttribute( "fo:page-width", sWidth ); + properties.setAttribute( "fo:page-height", sHeight ); + properties.setAttribute( "fo:border", "0.002cm solid #000000" ); + properties.setAttribute( "fo:padding", "0cm" ); + properties.setAttribute( "fo:background-color", "transparent" ); + + pageMaster.appendChild( properties ); + + QDomElement header = doc.createElement( "style:header-style" ); + properties = doc.createElement( "style:properties" ); + properties.setAttribute( "fo:min-height", "0.75cm" ); + properties.setAttribute( "fo:margin-left", "0cm" ); + properties.setAttribute( "fo:margin-right", "0cm" ); + properties.setAttribute( "fo:margin-bottom", "0.25cm" ); + + header.appendChild( properties ); + + QDomElement footer = doc.createElement( "style:header-style" ); + properties = doc.createElement( "style:properties" ); + properties.setAttribute( "fo:min-height", "0.75cm" ); + properties.setAttribute( "fo:margin-left", "0cm" ); + properties.setAttribute( "fo:margin-right", "0cm" ); + properties.setAttribute( "fo:margin-bottom", "0.25cm" ); + + footer.appendChild( properties ); + + pageMaster.appendChild( header ); + pageMaster.appendChild( footer ); + + autoStyles.appendChild( pageMaster ); +} + +void OpenCalcExport::exportMasterStyles( QDomDocument & doc, QDomElement & masterStyles, + const Doc * ksdoc ) +{ + QDomElement masterPage = doc.createElement( "style:master-page" ); + masterPage.setAttribute( "style:name", "Default" ); + masterPage.setAttribute( "style:page-master-name", "pm1" ); + + QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() ); + const Sheet * sheet = it.toFirst(); + + QString headerLeft; + QString headerCenter; + QString headerRight; + QString footerLeft; + QString footerCenter; + QString footerRight; + + if ( sheet ) + { + headerLeft = sheet->print()->headLeft(); + headerCenter = sheet->print()->headMid(); + headerRight = sheet->print()->headRight(); + footerLeft = sheet->print()->footLeft(); + footerCenter = sheet->print()->footMid(); + footerRight = sheet->print()->footRight(); + } + + if ( ( headerLeft.length() > 0 ) || ( headerCenter.length() > 0 ) + || ( headerRight.length() > 0 ) ) + { + QDomElement header = doc.createElement( "style:header" ); + QDomElement left = doc.createElement( "style:region-left" ); + QDomElement text = doc.createElement( "text:p" ); + convertPart( headerLeft, doc, text, ksdoc ); + left.appendChild( text ); + + QDomElement center = doc.createElement( "style:region-center" ); + QDomElement text1 = doc.createElement( "text:p" ); + convertPart( headerCenter, doc, text1, ksdoc ); + center.appendChild( text1 ); + + QDomElement right = doc.createElement( "style:region-right" ); + QDomElement text2 = doc.createElement( "text:p" ); + convertPart( headerRight, doc, text2, ksdoc ); + right.appendChild( text2 ); + + header.appendChild( left ); + header.appendChild( center ); + header.appendChild( right ); + + masterPage.appendChild( header ); + } + else + { + QDomElement header = doc.createElement( "style:header" ); + QDomElement text = doc.createElement( "text:p" ); + QDomElement name = doc.createElement( "text:sheet-name" ); + name.appendChild( doc.createTextNode( "???" ) ); + text.appendChild( name ); + header.appendChild( text ); + + masterPage.appendChild( header ); + } + + if ( ( footerLeft.length() > 0 ) || ( footerCenter.length() > 0 ) + || ( footerRight.length() > 0 ) ) + { + QDomElement footer = doc.createElement( "style:footer" ); + QDomElement left = doc.createElement( "style:region-left" ); + QDomElement text = doc.createElement( "text:p" ); + convertPart( footerLeft, doc, text, ksdoc ); + left.appendChild( text ); + + QDomElement center = doc.createElement( "style:region-center" ); + QDomElement text1 = doc.createElement( "text:p" ); + convertPart( footerCenter, doc, text1, ksdoc ); + center.appendChild( text1 ); + + QDomElement right = doc.createElement( "style:region-right" ); + QDomElement text2 = doc.createElement( "text:p" ); + convertPart( footerRight, doc, text2, ksdoc ); + right.appendChild( text2 ); + + footer.appendChild( left ); + footer.appendChild( center ); + footer.appendChild( right ); + + masterPage.appendChild( footer ); + } + else + { + QDomElement footer = doc.createElement( "style:footer" ); + QDomElement text = doc.createElement( "text:p" ); + text.appendChild( doc.createTextNode( i18n( "Page " ) ) ); + QDomElement number = doc.createElement( "text:page-number" ); + number.appendChild( doc.createTextNode( "1" ) ); + text.appendChild( number ); + footer.appendChild( text ); + + masterPage.appendChild( footer ); + } + + masterStyles.appendChild( masterPage ); +} + +void OpenCalcExport::addText( QString const & text, QDomDocument & doc, + QDomElement & parent ) +{ + if (text.length() > 0 ) + parent.appendChild( doc.createTextNode( text ) ); +} + +void OpenCalcExport::convertPart( QString const & part, QDomDocument & doc, + QDomElement & parent, const Doc * ksdoc ) +{ + QString text; + QString var; + + bool inVar = false; + uint i = 0; + uint l = part.length(); + while ( i < l ) + { + if ( inVar || part[i] == '<' ) + { + inVar = true; + var += part[i]; + if ( part[i] == '>' ) + { + inVar = false; + if ( var == "<page>" ) + { + addText( text, doc, parent ); + + QDomElement page = doc.createElement( "text:page-number" ); + page.appendChild( doc.createTextNode( "1" ) ); + parent.appendChild( page ); + } + else if ( var == "<pages>" ) + { + addText( text, doc, parent ); + + QDomElement page = doc.createElement( "text:page-count" ); + page.appendChild( doc.createTextNode( "99" ) ); + parent.appendChild( page ); + } + else if ( var == "<date>" ) + { + addText( text, doc, parent ); + + QDomElement t = doc.createElement( "text:date" ); + t.setAttribute( "text:date-value", "0-00-00" ); + // todo: "style:data-style-name", "N2" + t.appendChild( doc.createTextNode( QDate::currentDate().toString() ) ); + parent.appendChild( t ); + } + else if ( var == "<time>" ) + { + addText( text, doc, parent ); + + QDomElement t = doc.createElement( "text:time" ); + t.appendChild( doc.createTextNode( QTime::currentTime().toString() ) ); + parent.appendChild( t ); + } + else if ( var == "<file>" ) // filepath + name + { + addText( text, doc, parent ); + + QDomElement t = doc.createElement( "text:file-name" ); + t.setAttribute( "text:display", "full" ); + t.appendChild( doc.createTextNode( "???" ) ); + parent.appendChild( t ); + } + else if ( var == "<name>" ) // filename + { + addText( text, doc, parent ); + + QDomElement t = doc.createElement( "text:title" ); + t.appendChild( doc.createTextNode( "???" ) ); + parent.appendChild( t ); + } + else if ( var == "<author>" ) + { + KoDocumentInfo * docInfo = ksdoc->documentInfo(); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) ); + + text += authorPage->fullName(); + + addText( text, doc, parent ); + } + else if ( var == "<email>" ) + { + KoDocumentInfo * docInfo = ksdoc->documentInfo(); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) ); + + text += authorPage->email(); + + addText( text, doc, parent ); + } + else if ( var == "<org>" ) + { + KoDocumentInfo * docInfo = ksdoc->documentInfo(); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) ); + + text += authorPage->company(); + + addText( text, doc, parent ); + } + else if ( var == "<sheet>" ) + { + addText( text, doc, parent ); + + QDomElement s = doc.createElement( "text:sheet-name" ); + s.appendChild( doc.createTextNode( "???" ) ); + parent.appendChild( s ); + } + else + { + // no known variable: + text += var; + addText( text, doc, parent ); + } + + text = ""; + var = ""; + } + } + else + { + text += part[i]; + } + ++i; + } + if ( !text.isEmpty() || !var.isEmpty() ) + { + //we don't have var at the end =>store it + addText( text+var, doc, parent ); + } +} + +QString OpenCalcExport::convertFormula( QString const & formula ) const +{ + QChar decimalSymbol( '.' ); + if ( m_locale ) + { + const QString decimal ( m_locale->decimalSymbol() ); + if ( !decimal.isEmpty() ) + { + decimalSymbol = decimal.at( 0 ); + } + } + + QString s; + QRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)"); + int n = exp.search( formula, 0 ); + kdDebug(30518) << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length() + << ", Matched length: " << exp.matchedLength() << endl; + + bool inQuote1 = false; + bool inQuote2 = false; + int i = 0; + int l = (int) formula.length(); + if ( l <= 0 ) + return formula; + while ( i < l ) + { + if ( ( n != -1 ) && ( n < i ) ) + { + n = exp.search( formula, i ); + kdDebug(30518) << "Exp: " << formula.right( l - i ) << ", n: " << n << endl; + } + if ( formula[i] == '"' ) + { + inQuote1 = !inQuote1; + s += formula[i]; + ++i; + continue; + } + if ( formula[i] == '\'' ) + { + // named area + inQuote2 = !inQuote2; + ++i; + continue; + } + if ( inQuote1 || inQuote2 ) + { + s += formula[i]; + ++i; + continue; + } + if ( ( formula[i] == '=' ) && ( formula[i + 1] == '=' ) ) + { + s += '='; + ++i;++i; + continue; + } + if ( formula[i] == '!' ) + { + insertBracket( s ); + s += '.'; + ++i; + continue; + } + else if ( formula[i] == decimalSymbol ) + { + s += '.'; // decimal point + ++i; + continue; + } + if ( n == i ) + { + int ml = exp.matchedLength(); + if ( formula[ i + ml ] == '!' ) + { + kdDebug(30518) << "No cell ref but sheet name" << endl; + s += formula[i]; + ++i; + continue; + } + if ( ( i > 0 ) && ( formula[i - 1] != '!' ) ) + s += "[."; + for ( int j = 0; j < ml; ++j ) + { + s += formula[i]; + ++i; + } + s += ']'; + continue; + } + + s += formula[i]; + ++i; + } + + return s; +} + +bool OpenCalcExport::writeMetaFile( KoStore * store, uint filesWritten ) +{ + store->enterDirectory( "META-INF" ); + if ( !store->open( "manifest.xml" ) ) + return false; + + QDomImplementation impl; + QDomDocumentType type( impl.createDocumentType( "manifest:manifest", "-//OpenOffice.org//DTD Manifest 1.0//EN", "Manifest.dtd" ) ); + + QDomDocument meta( type ); + meta.appendChild( meta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); + + QDomElement content = meta.createElement( "manifest:manifest" ); + content.setAttribute( "xmlns:manifest", "http://openoffice.org/2001/manifest" ); + + QDomElement entry = meta.createElement( "manifest:file-entry" ); + entry.setAttribute( "manifest:media-type", "application/vnd.sun.xml.calc" ); + entry.setAttribute( "manifest:full-path", "/" ); + content.appendChild( entry ); + + entry = meta.createElement( "manifest:file-entry" ); + content.appendChild( entry ); + + if ( filesWritten & contentXML ) + { + entry = meta.createElement( "manifest:file-entry" ); + entry.setAttribute( "manifest:media-type", "text/xml" ); + entry.setAttribute( "manifest:full-path", "content.xml" ); + content.appendChild( entry ); + } + + if ( filesWritten & stylesXML ) + { + entry = meta.createElement( "manifest:file-entry" ); + entry.setAttribute( "manifest:media-type", "text/xml" ); + entry.setAttribute( "manifest:full-path", "styles.xml" ); + content.appendChild( entry ); + } + + if ( filesWritten & metaXML ) + { + entry = meta.createElement( "manifest:file-entry" ); + entry.setAttribute( "manifest:media-type", "text/xml" ); + entry.setAttribute( "manifest:full-path", "meta.xml" ); + content.appendChild( entry ); + } + + if ( filesWritten & settingsXML ) + { + entry = meta.createElement( "manifest:file-entry" ); + entry.setAttribute( "manifest:media-type", "text/xml" ); + entry.setAttribute( "manifest:full-path", "settings.xml" ); + content.appendChild( entry ); + } + + meta.appendChild( content ); + + QCString doc( meta.toCString() ); + kdDebug(30518) << "Manifest: " << doc << endl; + + store->write( doc, doc.length() ); + + if ( !store->close() ) + return false; + + return true; +} + +#include <opencalcexport.moc> diff --git a/filters/kspread/opencalc/opencalcexport.h b/filters/kspread/opencalc/opencalcexport.h new file mode 100644 index 000000000..6a265fce5 --- /dev/null +++ b/filters/kspread/opencalc/opencalcexport.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 2000 - 2003 David Faure <faure@kde.org> + Copyright (C) 2003 Norbert Andres <nandres@web.de> + + 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. +*/ + +#ifndef OPENCALCEXPORT_H +#define OPENCALCEXPORT_H + +#include "opencalcstyleexport.h" + +#include <KoFilter.h> +#include <qptrlist.h> + +class QDomDocument; +class QDomElement; +class KLocale; +class KoStore; + +namespace KSpread +{ +class Doc; +class Sheet; +} + +class OpenCalcExport : public KoFilter +{ + Q_OBJECT + + public: + OpenCalcExport( KoFilter * parent, const char * name, const QStringList & ); + virtual ~OpenCalcExport() {} + + virtual KoFilter::ConversionStatus convert( const QCString & from, + const QCString & to ); + + private: + enum files { metaXML = 0x01, contentXML = 0x02, stylesXML = 0x04, settingsXML = 0x08 }; + OpenCalcStyles m_styles; + + bool writeFile( const KSpread::Doc * ksdoc ); + + bool exportDocInfo( KoStore * store, const KSpread::Doc * ksdoc ); + bool exportStyles ( KoStore * store, const KSpread::Doc * ksdoc ); + bool exportContent( KoStore * store, const KSpread::Doc * ksdoc ); + bool exportSettings( KoStore * store, const KSpread::Doc * ksdoc ); + + bool exportBody( QDomDocument & doc, QDomElement & content, const KSpread::Doc * ksdoc ); + void exportSheet( QDomDocument & doc, QDomElement & tabElem, + const KSpread::Sheet * sheet, int maxCols, int maxRows ); + void exportCells( QDomDocument & doc, QDomElement & rowElem, + const KSpread::Sheet * sheet, int row, int maxCols ); + void exportDefaultCellStyle( QDomDocument & doc, QDomElement & officeStyles ); + void exportPageAutoStyles( QDomDocument & doc, QDomElement & autoStyles, + const KSpread::Doc * ksdoc ); + void exportMasterStyles( QDomDocument & doc, QDomElement & masterStyles, + const KSpread::Doc *ksdoc ); + + bool writeMetaFile( KoStore * store, uint filesWritten ); + + void maxRowCols( const KSpread::Sheet * sheet, + int & maxCols, int & maxRows ); + void convertPart( QString const & part, QDomDocument & doc, + QDomElement & parent, const KSpread::Doc * ksdoc ); + void addText( QString const & text, QDomDocument & doc, + QDomElement & parent ); + + void createDefaultStyles(); + QString convertFormula( QString const & formula ) const; +private: + /// Pointer to the KSpread locale + KLocale* m_locale; +}; + +#endif diff --git a/filters/kspread/opencalc/opencalcimport.cc b/filters/kspread/opencalc/opencalcimport.cc new file mode 100644 index 000000000..8330519f1 --- /dev/null +++ b/filters/kspread/opencalc/opencalcimport.cc @@ -0,0 +1,2826 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Norbert Andres <nandres@web.de> + Copyright (C) 2004 - 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. +*/ + +#include <float.h> +#include <math.h> + +#include <qcolor.h> +#include <qfile.h> +#include <qfont.h> +#include <qpen.h> +#include <qxml.h> + +#include "opencalcimport.h" + +#include <kdebug.h> +#include <KoDocumentInfo.h> +#include <kgenericfactory.h> +#include <kmessagebox.h> +#include <kmdcodec.h> +#include <KoFilterChain.h> +#include <KoGlobal.h> +#include <KoUnit.h> +#include <KoStyleStack.h> +#include <KoDom.h> +#include <ooutils.h> + +#include <kspread_cell.h> +#include <kspread_condition.h> +#include <kspread_doc.h> +#include <kspread_global.h> +#include <kspread_map.h> +#include <kspread_sheet.h> +#include <kspread_sheetprint.h> +#include <kspread_style.h> +#include <kspread_style_manager.h> +#include <kspread_util.h> +#include <kspread_value.h> + +#define SECSPERDAY (24 * 60 * 60) + +using namespace KSpread; + +class OpenCalcImportFactory : KGenericFactory<OpenCalcImport, KoFilter> +{ +public: + OpenCalcImportFactory(void) : KGenericFactory<OpenCalcImport, KoFilter> ("kspreadopencalcimport") + {} +protected: + virtual void setupTranslations( void ) + { + KGlobal::locale()->insertCatalogue( "kofficefilters" ); + } +}; + +K_EXPORT_COMPONENT_FACTORY( libopencalcimport, OpenCalcImportFactory() ) + +OpenCalcImport::OpenCalcPoint::OpenCalcPoint( QString const & str ) + : isRange( false ) +{ + bool inQuote = false; + + int l = str.length(); + int colonPos = -1; + QString range; + + // replace '.' with '!' + for ( int i = 0; i < l; ++i ) + { + if ( str[i] == '$' ) + continue; + if ( str[i] == '\'' ) + { + inQuote = !inQuote; + } + else if ( str[i] == '.' ) + { + if ( !inQuote ) + { + if ( i != 0 && i != (colonPos + 1) ) // no empty table names + range += '!'; + } + else + range += '.'; + } + else if ( str[i] == ':' ) + { + if ( !inQuote ) + { + isRange = true; + colonPos = i; + } + range += ':'; + } + else + range += str[i]; + } + + translation = range; + + if ( isRange ) + { + KSpread::Range newRange( range ); + table = newRange.sheetName(); + topLeft = newRange.range().topLeft(); + botRight = newRange.range().bottomRight(); + } + else + { + Point newPoint( range ); + table = newPoint.sheetName(); + topLeft = newPoint.pos(); + botRight = newPoint.pos(); + } +} + + +OpenCalcImport::OpenCalcImport( KoFilter *, const char *, const QStringList & ) + : KoFilter(), + m_styles( 17, true ), + m_defaultStyles( 17, true ), + m_formats( 17, true ) +{ + m_styles.setAutoDelete( true ); + m_defaultStyles.setAutoDelete( true ); + m_formats.setAutoDelete( true ); +} + +OpenCalcImport::~OpenCalcImport() +{ +} + +double timeToNum( int h, int m, int s ) +{ + int secs = h * 3600 + m * 60 + s; + return (double) secs / (double) SECSPERDAY; +} + +bool OpenCalcImport::readRowFormat( QDomElement & rowNode, QDomElement * rowStyle, + Sheet * table, int & row, int & number, + bool isLast ) +{ + if ( rowNode.isNull() ) + return false; + + QDomNode node; + if ( rowStyle ) + { + node = rowStyle->firstChild(); + kdDebug(30518) << "RowStyle: " << rowStyle << ", " << rowStyle->tagName() << endl; + } + + double height = -1.0; + bool insertPageBreak = false; + Format layout( table, table->doc()->styleManager()->defaultStyle() ); + + while( !node.isNull() ) + { + QDomElement property = node.toElement(); + + kdDebug(30518) << "Row: Child exists: " << property.tagName() << endl; + if ( !property.isNull() && property.localName() == "properties" && property.namespaceURI() == ooNS::style ) + { + if ( property.hasAttributeNS( ooNS::style, "row-height" ) ) + { + height = KoUnit::parseValue( property.attributeNS( ooNS::style, "row-height", QString::null ) , -1 ); + } + + if ( property.hasAttributeNS( ooNS::fo, "break-before" ) ) + { + if ( property.attributeNS( ooNS::fo, "break-before", QString::null ) == "page" ) + { + insertPageBreak = true; + } + } + + loadStyleProperties( &layout, property ); + } + + node = node.nextSibling(); + } + + if ( rowNode.hasAttributeNS( ooNS::table, "number-rows-repeated" ) ) + { + bool ok = true; + int n = rowNode.attributeNS( ooNS::table, "number-rows-repeated", QString::null ).toInt( &ok ); + if ( ok ) + number = n; + kdDebug(30518) << "Row repeated: " << number << endl; + } + + if ( isLast ) + { + if ( number > 30 ) + number = 30; + } + else + { + if ( number > 256 ) + number = 256; + } + + for ( int i = 0; i < number; ++i ) + { + RowFormat * rowL = table->nonDefaultRowFormat( row ); + rowL->copy( layout ); + + if ( height != -1 ) + { + kdDebug(30518) << "Setting row height to " << height << endl; + rowL->setHeight( int( height ) ); + } + + // if ( insertPageBreak ) TODO: + // rowL->setPageBreak( true ) + + // kdDebug(30518) << "Added RowFormat: " << row << endl; + ++row; + } + + return true; +} + +QString OpenCalcImport::translatePar( QString & par ) const +{ + OpenCalcPoint point( par ); + kdDebug(30518) << " Parameter: " << par << ", Translation: " << point.translation << endl; + + return point.translation; +} + +void OpenCalcImport::checkForNamedAreas( QString & formula ) const +{ + int l = formula.length(); + int i = 0; + QString word; + int start = 0; + while ( i < l ) + { + if ( formula[i].isLetterOrNumber() ) + { + word += formula[i]; + ++i; + continue; + } + if ( word.length() > 0 ) + { + if ( m_namedAreas.find( word ) != m_namedAreas.end() ) + { + formula = formula.replace( start, word.length(), "'" + word + "'" ); + l = formula.length(); + ++i; + kdDebug(30518) << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl; + } + } + + ++i; + word = ""; + start = i; + } + if ( word.length() > 0 ) + { + if ( m_namedAreas.find( word ) != m_namedAreas.end() ) + { + formula = formula.replace( start, word.length(), "'" + word + "'" ); + l = formula.length(); + ++i; + kdDebug(30518) << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl; + } + } +} + +void OpenCalcImport::convertFormula( QString & text, QString const & f ) const +{ + kdDebug(30518) << "Parsing formula: " << f << endl; + + QString formula; + QString parameter; + + int l = f.length(); + int p = 0; + + while ( p < l ) + { + if ( f[p] == '(' || f[p] == '[' ) + { + break; + } + + formula += f[p]; + ++p; + } + + if ( parameter.isEmpty() ) + { + checkForNamedAreas( formula ); + } + + kdDebug(30518) << "Formula: " << formula << ", Parameter: " << parameter << ", P: " << p << endl; + + + // replace formula names here + if ( formula == "=MULTIPLE.OPERATIONS" ) + formula = "=MULTIPLEOPERATIONS"; + + QString par; + bool isPar = false; + bool inQuote = false; + + while ( p < l ) + { + if ( f[p] == '"' ) + { + inQuote = !inQuote; + parameter += '"'; + } + else if ( f[p] == '[' ) + { + if ( !inQuote ) + isPar = true; + else + parameter += '['; + } + else if ( f[p] == ']' ) + { + if ( inQuote ) + { + parameter += ']'; + continue; + } + + isPar = false; + parameter += translatePar( par ); + par = ""; + } + else if ( isPar ) + { + par += f[p]; + } + else if ( f[p] == '=' ) // TODO: check if StarCalc has a '==' sometimes + { + if ( inQuote ) + parameter += '='; + else + parameter += "=="; + } + else if ( f[p] == ')' ) + { + if ( !inQuote ) + parameter += ")"; + } + else + parameter += f[p]; + + ++p; + if ( p == l ) + checkForNamedAreas( parameter ); + } + + text = formula + parameter; + kdDebug(30518) << "New formula: " << text << endl; +} + +bool OpenCalcImport::readCells( QDomElement & rowNode, Sheet * table, int row, int & columns ) +{ + bool ok = true; + int spanC = 1; + int spanR = 1; + //Cell* defCell = table->defaultCell(); + + QDomNode cellNode = KoDom::namedItemNS( rowNode, ooNS::table, "table-cell" ); + + while ( !cellNode.isNull() ) + { + spanR = 1; spanC = 1; + + QDomElement e = cellNode.toElement(); + if ( e.isNull() ) + { + ++columns; + + cellNode = cellNode.nextSibling(); + continue; + } + + Cell* cell = 0; + + kdDebug(30518) << " Cell: " << columns << ", " << row << endl; + + // ="3" table:number-rows-spanned="1" + if ( e.hasAttributeNS( ooNS::table, "number-columns-spanned" ) ) + { + int span = e.attributeNS( ooNS::table, "number-columns-spanned", QString::null ).toInt( &ok ); + if ( ok ) + spanC = span; + } + if ( e.hasAttributeNS( ooNS::table, "number-rows-spanned" ) ) + { + int span = e.attributeNS( ooNS::table, "number-rows-spanned", QString::null ).toInt( &ok ); + if ( ok ) + spanR = span; + } + + QString text; + QDomElement textP = KoDom::namedItemNS( e, ooNS::text, "p" ); + if ( !textP.isNull() ) + { + QDomElement subText = textP.firstChild().toElement(); // ## wrong + if ( !subText.isNull() ) + { + // something in <text:p>, e.g. links + text = subText.text(); + + if ( subText.hasAttributeNS( ooNS::xlink, "href" ) ) + { + QString link = subText.attributeNS( ooNS::xlink, "href", QString::null ); + if ( link[0]=='#' ) + link=link.remove( 0, 1 ); + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + cell->setLink( link ); + } + } + else + text = textP.text(); // our text, could contain formating for value or result of formula + } + QDomElement annotation = KoDom::namedItemNS( e, ooNS::office, "annotation" ); + if ( !annotation.isNull() ) + { + QString comment; + QDomNode node = annotation.firstChild(); + while( !node.isNull() ) + { + QDomElement commentElement = node.toElement(); + if( !commentElement.isNull() ) + if ( commentElement.localName() == "p" && e.namespaceURI()==ooNS::text) + { + if( !comment.isEmpty() ) comment.append( '\n' ); + comment.append( commentElement.text() ); + } + + node = node.nextSibling(); + } + + if( !comment.isEmpty() ) + { + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + kdDebug(30518)<<" columns :"<<columns<<" row :"<<row<<endl; + cell->format()->setComment( comment ); + } + } + + kdDebug(30518) << "Contains: " << text << endl; + bool isFormula = false; + + if ( e.hasAttributeNS( ooNS::table, "style-name" ) ) + { + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + + QString psName( "Default" ); + if ( e.hasAttributeNS( ooNS::style, "parent-style-name" ) ) + psName = e.attributeNS( ooNS::style, "parent-style-name", QString::null ); + + kdDebug(30518) << "Default style: " << psName << endl; + Format * layout = m_defaultStyles[psName]; + + if ( layout ) + cell->format()->copy( *layout ); + + QDomElement * st = 0; + if ( e.hasAttributeNS( ooNS::table, "style-name" ) ) + { + kdDebug(30518) << "Style: " << e.attributeNS( ooNS::table, "style-name", QString::null ) << endl; + st = m_styles[ e.attributeNS( ooNS::table, "style-name", QString::null ) ]; + } + if ( st ) + { + kdDebug(30518) << "Style: adapting " << endl; + QDomNode node = st->firstChild(); + bool foundValidation = false; + while( !node.isNull() ) + { + QDomElement property = node.toElement(); + if ( !property.isNull() ) + { + kdDebug(30518)<<"property.tagName() :"<<property.tagName()<<endl; + if ( property.localName()=="map" && property.namespaceURI() == ooNS::style && !foundValidation) + { + loadCondition( cell, property ); + foundValidation = true; + } + if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style ) + { + loadStyleProperties( cell->format(), property ); + if ( cell->format()->getAngle( columns, row ) != 0 ) + { + QFontMetrics fm( cell->format()->textFont( columns, row ) ); + int tmpAngle = cell->format()->getAngle( columns, row ); + int textHeight = static_cast<int>( cos( tmpAngle * M_PI / 180 ) + * ( fm.ascent() + fm.descent() ) + + abs ( ( int )( fm.width( cell->strOutText() ) + * sin( tmpAngle * M_PI / 180 ) ) ) ); + /* + int textWidth = static_cast<int>( abs ( ( int ) ( sin( tmpAngle * M_PI / 180 ) + * ( fm.ascent() + fm.descent() ) ) ) + + fm.width( cell->strOutText() ) + * cos( tmpAngle * M_PI / 180 ) ); + */ + kdDebug(30518) << "Rotation: height: " << textHeight << endl; + + RowFormat * l = table->rowFormat( row ); + if ( l->height() < textHeight ) + { + if ( l->isDefault() ) + l = table->nonDefaultRowFormat( row ); + + l->setHeight( textHeight + 2 ); + } + } + } + } + node = node.nextSibling(); + } + } + } + else + { + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + + QString psName( "Default" ); + kdDebug(30518) << "Default style: " << psName << endl; + Format * layout = m_defaultStyles[psName]; + + if ( layout ) + cell->format()->copy( *layout ); + } + if ( e.hasAttributeNS( ooNS::table, "formula" ) ) + { + isFormula = true; + QString formula; + convertFormula( formula, e.attributeNS( ooNS::table, "formula", QString::null ) ); + + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + cell->setCellText( formula ); + } + if ( e.hasAttributeNS( ooNS::table, "validation-name" ) ) + { + kdDebug(30518)<<" Celle has a validation :"<<e.attributeNS( ooNS::table, "validation-name", QString::null )<<endl; + loadOasisValidation( cell->getValidity(), e.attributeNS( ooNS::table, "validation-name", QString::null ) ); + } + if ( e.hasAttributeNS( ooNS::table, "value-type" ) ) + { + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + + cell->setCellText( text ); + + QString value = e.attributeNS( ooNS::table, "value", QString::null ); + QString type = e.attributeNS( ooNS::table, "value-type", QString::null ); + + kdDebug(30518) << "Value: " << value << ", type: " << type << endl; + + bool ok = false; + double dv = 0.0; + + if ( ( type == "float" ) || ( type == "currency" ) ) + { + dv = value.toDouble( &ok ); + if ( ok ) + { + if ( !isFormula ) + cell->setValue( dv ); + + if ( type == "currency" ) + { + cell->format()->setCurrency( 1, e.attributeNS( ooNS::table, "currency", QString::null ) ); + cell->format()->setFormatType( Money_format ); + } + } + } + else + if ( type == "percentage" ) + { + dv = value.toDouble( &ok ); + if ( ok ) + { + if ( !isFormula ) + cell->setValue( dv ); + //TODO fixme + //cell->setFactor( 100 ); + // TODO: replace with custom... + cell->format()->setFormatType( Percentage_format ); + } + } + else if ( type == "boolean" ) + { + if ( value.isEmpty() ) + value = e.attributeNS( ooNS::table, "boolean-value", QString::null ); + + kdDebug(30518) << "Type: boolean" << endl; + if ( value == "true" ) + cell->setValue( true ); + else + cell->setValue( false ); + ok = true; + cell->format()->setFormatType( Custom_format ); + } + else if ( type == "date" ) + { + if ( value.isEmpty() ) + value = e.attributeNS( ooNS::table, "date-value", QString::null ); + kdDebug(30518) << "Type: date, value: " << value << endl; + + // "1980-10-15" + int year=0, month=0, day=0; + ok = false; + + int p1 = value.find( '-' ); + if ( p1 > 0 ) + year = value.left( p1 ).toInt( &ok ); + + kdDebug(30518) << "year: " << value.left( p1 ) << endl; + + int p2 = value.find( '-', ++p1 ); + + if ( ok ) + month = value.mid( p1, p2 - p1 ).toInt( &ok ); + + kdDebug(30518) << "month: " << value.mid( p1, p2 - p1 ) << endl; + + if ( ok ) + day = value.right( value.length() - p2 - 1 ).toInt( &ok ); + + kdDebug(30518) << "day: " << value.right( value.length() - p2 ) << endl; + + if ( ok ) + { + QDateTime dt( QDate( year, month, day ) ); + // KSpreadValue kval( dt ); + // cell->setValue( kval ); + cell->setValue( QDate( year, month, day ) ); + kdDebug(30518) << "Set QDate: " << year << " - " << month << " - " << day << endl; + } + } + else if ( type == "time" ) + { + if ( value.isEmpty() ) + value = e.attributeNS( ooNS::table, "time-value", QString::null ); + + kdDebug(30518) << "Type: time: " << value << endl; + // "PT15H10M12S" + int hours=0, minutes=0, seconds=0; + int l = value.length(); + QString num; + + for ( int i = 0; i < l; ++i ) + { + if ( value[i].isNumber() ) + { + num += value[i]; + continue; + } + else if ( value[i] == 'H' ) + hours = num.toInt( &ok ); + else if ( value[i] == 'M' ) + minutes = num.toInt( &ok ); + else if ( value[i] == 'S' ) + seconds = num.toInt( &ok ); + else + continue; + + kdDebug(30518) << "Num: " << num << endl; + + num = ""; + if ( !ok ) + break; + } + + kdDebug(30518) << "Hours: " << hours << ", " << minutes << ", " << seconds << endl; + + if ( ok ) + { + // KSpreadValue kval( timeToNum( hours, minutes, seconds ) ); + // cell->setValue( kval ); + cell->setValue( QTime( hours % 24, minutes, seconds ) ); + cell->format()->setFormatType( Custom_format ); + } + } + + + if ( !ok ) // just in case we couldn't set the value directly + cell->setCellText( text ); + } + else if ( !text.isEmpty() ) + { + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + cell->setCellText( text ); + } + + if ( spanR > 1 || spanC > 1 ) + { + if ( !cell ) + cell = table->nonDefaultCell( columns, row ); + cell->mergeCells( columns, row, spanC - 1, spanR - 1 ); + } + + cellNode = cellNode.nextSibling(); + + if ( e.hasAttributeNS( ooNS::table, "number-columns-repeated" ) ) + { + // copy cell from left + bool ok = false; + int number = e.attributeNS( ooNS::table, "number-columns-repeated", QString::null ).toInt( &ok ); + Cell* cellDest = 0; + + // don't repeat more than 10 if it is the last cell and empty + if ( !ok || cellNode.isNull() ) + { + if ( number > 10 ) + number = 10; + } + + for ( int i = 1; i < number; ++i ) + { + ++columns; + + if ( cell ) + { + cellDest = table->nonDefaultCell( columns, row ); + cellDest->copyAll( cell ); + } + } + } + + ++columns; + } + + return true; +} + + +void OpenCalcImport::loadCondition( Cell*cell,const QDomElement &property ) +{ + kdDebug(30518)<<"void OpenCalcImport::loadCondition( Cell*cell,const QDomElement &property )*******\n"; + loadOasisCondition( cell, property ); +} + +void OpenCalcImport::loadOasisCondition(Cell*cell,const QDomElement &property ) +{ + QDomElement elementItem( property ); + StyleManager * manager = cell->sheet()->doc()->styleManager(); + + QValueList<Conditional> cond; + while ( !elementItem.isNull() ) + { + kdDebug(30518)<<"elementItem.tagName() :"<<elementItem.tagName()<<endl; + + if ( elementItem.localName()== "map" && property.namespaceURI() == ooNS::style ) + { + bool ok = true; + kdDebug(30518)<<"elementItem.attribute(style:condition ) :"<<elementItem.attributeNS( ooNS::style, "condition", QString::null )<<endl; + Conditional newCondition; + loadOasisConditionValue( elementItem.attributeNS( ooNS::style, "condition", QString::null ), newCondition ); + if ( elementItem.hasAttributeNS( ooNS::style, "apply-style-name" ) ) + { + kdDebug(30518)<<"elementItem.attribute( style:apply-style-name ) :"<<elementItem.attributeNS( ooNS::style, "apply-style-name", QString::null )<<endl; + newCondition.styleName = new QString( elementItem.attributeNS( ooNS::style, "apply-style-name", QString::null ) ); + newCondition.style = manager->style( *newCondition.styleName ); + if ( !newCondition.style ) + ok = false; + else + ok = true; + } + + if ( ok ) + cond.append( newCondition ); + else + kdDebug(30518) << "Error loading condition " << elementItem.nodeName()<< endl; + } + elementItem = elementItem.nextSibling().toElement(); + } + if ( !cond.isEmpty() ) + cell->setConditionList( cond ); +} + +void OpenCalcImport::loadOasisConditionValue( const QString &styleCondition, Conditional &newCondition ) +{ + QString val( styleCondition ); + if ( val.contains( "cell-content()" ) ) + { + val = val.remove( "cell-content()" ); + loadOasisCondition( val,newCondition ); + } + //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value) + //for the moment we support just int/double value, not text/date/time :( + if ( val.contains( "cell-content-is-between(" ) ) + { + val = val.remove( "cell-content-is-between(" ); + val = val.remove( ")" ); + QStringList listVal = QStringList::split( "," , val ); + loadOasisValidationValue( listVal, newCondition ); + newCondition.cond = Conditional::Between; + } + if ( val.contains( "cell-content-is-not-between(" ) ) + { + val = val.remove( "cell-content-is-not-between(" ); + val = val.remove( ")" ); + QStringList listVal = QStringList::split( ",", val ); + loadOasisValidationValue( listVal,newCondition ); + newCondition.cond = Conditional::Different; + } + +} + + +void OpenCalcImport::loadOasisCondition( QString &valExpression, Conditional &newCondition ) +{ + QString value; + if (valExpression.find( "<=" )==0 ) + { + value = valExpression.remove( 0,2 ); + newCondition.cond = Conditional::InferiorEqual; + } + else if (valExpression.find( ">=" )==0 ) + { + value = valExpression.remove( 0,2 ); + newCondition.cond = Conditional::SuperiorEqual; + } + else if (valExpression.find( "!=" )==0 ) + { + //add Differentto attribute + value = valExpression.remove( 0,2 ); + newCondition.cond = Conditional::DifferentTo; + } + else if ( valExpression.find( "<" )==0 ) + { + value = valExpression.remove( 0,1 ); + newCondition.cond = Conditional::Inferior; + } + else if(valExpression.find( ">" )==0 ) + { + value = valExpression.remove( 0,1 ); + newCondition.cond = Conditional::Superior; + } + else if (valExpression.find( "=" )==0 ) + { + value = valExpression.remove( 0,1 ); + newCondition.cond = Conditional::Equal; + } + else + kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl; + kdDebug(30518)<<" value :"<<value<<endl; + bool ok = false; + newCondition.val1 = value.toDouble(&ok); + if ( !ok ) + { + newCondition.val1 = value.toInt(&ok); + if ( !ok ) + { + newCondition.strVal1 = new QString( value ); + kdDebug(30518)<<" Try to parse this value :"<<value<<endl; + } + + } +} + + +void OpenCalcImport::loadOasisValidationValue( const QStringList &listVal, Conditional &newCondition ) +{ + bool ok = false; + kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl; + + newCondition.val1 = listVal[0].toDouble(&ok); + if ( !ok ) + { + newCondition.val1 = listVal[0].toInt(&ok); + if ( !ok ) + { + newCondition.strVal1 = new QString( listVal[0] ); + kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl; + } + } + ok=false; + newCondition.val2 = listVal[1].toDouble(&ok); + if ( !ok ) + { + newCondition.val2 = listVal[1].toInt(&ok); + if ( !ok ) + { + newCondition.strVal2 = new QString( listVal[1] ); + kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl; + } + } +} + + +bool OpenCalcImport::readRowsAndCells( QDomElement & content, Sheet * table ) +{ + kdDebug(30518) << endl << "Reading in rows " << endl; + + int i = 1; + int row = 1; + int columns = 1; + int backupRow = 1; + QDomElement * rowStyle = 0; + //Cell* cell = 0; + //Cell* cellDest = 0; + //Cell* defCell = table->defaultCell(); + QDomNode rowNode = KoDom::namedItemNS( content, ooNS::table, "table-row" ); + + while ( !rowNode.isNull() ) + { + bool collapsed = false; + + int number = 1; + QDomElement r = rowNode.toElement(); + + if ( r.isNull() ) + return false; + + if ( r.hasAttributeNS( ooNS::table, "style-name" ) ) + { + QString style = r.attributeNS( ooNS::table, "style-name", QString::null ); + rowStyle = m_styles[ style ]; + kdDebug(30518) << "Row style: " << style << endl; + } + + collapsed = ( r.attributeNS( ooNS::table, "visibility", QString::null ) == "collapse" ); + + backupRow = row; + + rowNode = rowNode.nextSibling(); + + if ( !readRowFormat( r, rowStyle, table, row, number, rowNode.isNull() ) ) // updates "row" + return false; + + if ( !readCells( r, table, backupRow, columns ) ) + return false; + + RowFormat * srcLayout = table->nonDefaultRowFormat( backupRow ); + RowFormat * layout = 0; + + if ( collapsed ) + srcLayout->setHide( true ); + + for ( i = 1; i < number; ++i ) + { + layout = table->nonDefaultRowFormat( backupRow + i ); + + layout->copy( *srcLayout ); + + /* + * TODO: Test: do we need to copy the cells, too? + * if so we will probably also need to copy them for repeated col layouts. + for ( j = 1; j <= columns; ++j ) + { + Cell* cell = table->cellAt( j, backupRow ); + + kdDebug(30518) << "Cell: " << cell << "DefCell: " << defCell << endl; + if ( cell && (cell != defCell) ) + { + cellDest = table->nonDefaultCell( j, backupRow + i ); + cellDest->copyAll( cell ); + } + } + */ + } + + rowStyle = 0; + columns = 1; + } + + kdDebug(30518) << "Reading in rows done" << endl << endl; + + return true; +} + +bool OpenCalcImport::readColLayouts( QDomElement & content, Sheet * table ) +{ + kdDebug(30518) << endl << "Reading in columns..." << endl; + + QDomNode colLayout = KoDom::namedItemNS( content, ooNS::table, "table-column" ); + int column = 1; + + while ( !colLayout.isNull() ) + { + if ( colLayout.nodeName() != "table:table-column" ) + return true; // all cols read in. + + QDomElement e = colLayout.toElement(); + + if ( e.isNull() ) + return false; // error, that's it... + + kdDebug(30518) << "New column: " << column << endl; + + int number = 1; + double width = -1.0; + bool collapsed = ( e.attributeNS( ooNS::table, "visibility", QString::null ) == "collapse" ); + bool insertPageBreak = false; + Format styleLayout( table, table->doc()->styleManager()->defaultStyle() ); + + kdDebug(30518) << "Check table:number-columns-repeated" << endl; + if ( e.hasAttributeNS( ooNS::table, "number-columns-repeated" ) ) + { + bool ok = true; + number = e.attributeNS( ooNS::table, "number-columns-repeated", QString::null ).toInt( &ok ); + if ( !ok ) + number = 1; + + kdDebug(30518) << "Repeated: " << number << endl; + } + + kdDebug(30518) << "Checking table:default-cell-style-name" << endl; + if ( e.hasAttributeNS( ooNS::table, "default-cell-style-name" ) ) + { + QString n( e.attributeNS( ooNS::table, "default-cell-style-name", QString::null ) ); + kdDebug(30518) << "Has attribute default-cell-style-name: " << n << endl; + Format * defaultStyle = m_defaultStyles[ n ]; + if ( !defaultStyle ) + { + QString name = e.attributeNS( ooNS::table, "default-cell-style-name", QString::null ); + QDomElement * st = m_styles[ name ]; + + kdDebug(30518) << "Default cell style: " << name << endl; + + if ( st && !st->isNull() ) + { + Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() ); + + readInStyle( layout, *st ); + + m_defaultStyles.insert( name, layout ); + kdDebug(30518) << "Insert default cell style: " << name << endl; + + defaultStyle = layout; + } + } + + if ( defaultStyle ) + { + // kdDebug(30518) << "Copying default style, Font: " << defaultStyle->font().toString() << endl; + styleLayout.copy( *defaultStyle ); + } + } + + QDomElement * colStyle = 0; + if ( e.hasAttributeNS( ooNS::table, "style-name" ) ) + { + QString style = e.attributeNS( ooNS::table, "style-name", QString::null ); + colStyle = m_styles[ style ]; + + kdDebug(30518) << "Col Style: " << style << endl; + } + + QDomNode node; + + if ( colStyle ) + node = colStyle->firstChild(); + + while( !node.isNull() ) + { + QDomElement property = node.toElement(); + if ( !property.isNull() && property.localName() == "properties" && property.namespaceURI() == ooNS::style ) + { + if ( property.hasAttributeNS( ooNS::style, "column-width" ) ) + { + QString sWidth = property.attributeNS( ooNS::style, "column-width", QString::null ); + width = KoUnit::parseValue( property.attributeNS( ooNS::style, "column-width", QString::null ), width ); + kdDebug(30518) << "Col Width: " << sWidth << endl; + } + + if ( property.hasAttributeNS( ooNS::fo, "break-before" ) ) + { + if ( property.attributeNS( ooNS::fo, "break-before", QString::null ) == "page" ) + { + insertPageBreak = true; + } + } + + loadStyleProperties( &styleLayout, property ); + } + + node = node.nextSibling(); + } + + colLayout = colLayout.nextSibling(); + + if ( colLayout.isNull() && ( number > 30 ) ) + number = 30; + + for ( int i = 0; i < number; ++i ) + { + kdDebug(30518) << "Inserting colLayout: " << column << endl; + + ColumnFormat * col = new ColumnFormat( table, column ); + col->copy( styleLayout ); + if ( width != -1.0 ) + col->setWidth( int( width ) ); + + // if ( insertPageBreak ) + // col->setPageBreak( true ) + + if ( collapsed ) + col->setHide( true ); + + table->insertColumnFormat( col ); + ++column; + } + } + + return true; +} + +void replaceMacro( QString & text, QString const & old, QString const & newS ) +{ + int n = text.find( old ); + if ( n != -1 ) + text = text.replace( n, old.length(), newS ); +} + +QString getPart( QDomNode const & part ) +{ + QString result; + QDomElement e = KoDom::namedItemNS( part, ooNS::text, "p" ); + while ( !e.isNull() ) + { + QString text = e.text(); + kdDebug(30518) << "PART: " << text << endl; + + QDomElement macro = KoDom::namedItemNS( e, ooNS::text, "time" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<time>" ); + + macro = KoDom::namedItemNS( e, ooNS::text, "date" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<date>" ); + + macro = KoDom::namedItemNS( e, ooNS::text, "page-number" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<page>" ); + + macro = KoDom::namedItemNS( e, ooNS::text, "page-count" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<pages>" ); + + macro = KoDom::namedItemNS( e, ooNS::text, "sheet-name" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<sheet>" ); + + macro = KoDom::namedItemNS( e, ooNS::text, "title" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<name>" ); + + macro = KoDom::namedItemNS( e, ooNS::text, "file-name" ); + if ( !macro.isNull() ) + replaceMacro( text, macro.text(), "<file>" ); + + if ( !result.isEmpty() ) + result += '\n'; + result += text; + e = e.nextSibling().toElement(); + } + + return result; +} + +void OpenCalcImport::loadTableMasterStyle( Sheet * table, + QString const & stylename ) +{ + kdDebug(30518) << "Loading table master style: " << stylename << endl; + + QDomElement * style = m_styles[ stylename ]; + + if ( !style ) + { + kdDebug(30518) << "Master style not found! " << endl; + return; + } + + QDomNode header = KoDom::namedItemNS( *style, ooNS::style, "header" ); + kdDebug(30518) << "Style header " << endl; + + QString hleft, hmiddle, hright; + QString fleft, fmiddle, fright; + + if ( !header.isNull() ) + { + kdDebug(30518) << "Header exists" << endl; + QDomNode part = KoDom::namedItemNS( header, ooNS::style, "region-left" ); + if ( !part.isNull() ) + { + hleft = getPart( part ); + kdDebug(30518) << "Header left: " << hleft << endl; + } + else + kdDebug(30518) << "Style:region:left doesn't exist!" << endl; + part = KoDom::namedItemNS( header, ooNS::style, "region-center" ); + if ( !part.isNull() ) + { + hmiddle = getPart( part ); + kdDebug(30518) << "Header middle: " << hmiddle << endl; + } + part = KoDom::namedItemNS( header, ooNS::style, "region-right" ); + if ( !part.isNull() ) + { + hright = getPart( part ); + kdDebug(30518) << "Header right: " << hright << endl; + } + } + + QDomNode footer = KoDom::namedItemNS( *style, ooNS::style, "footer" ); + + if ( !footer.isNull() ) + { + QDomNode part = KoDom::namedItemNS( footer, ooNS::style, "region-left" ); + if ( !part.isNull() ) + { + fleft = getPart( part ); + kdDebug(30518) << "Footer left: " << fleft << endl; + } + part = KoDom::namedItemNS( footer, ooNS::style, "region-center" ); + if ( !part.isNull() ) + { + fmiddle = getPart( part ); + kdDebug(30518) << "Footer middle: " << fmiddle << endl; + } + part = KoDom::namedItemNS( footer, ooNS::style, "region-right" ); + if ( !part.isNull() ) + { + fright = getPart( part ); + kdDebug(30518) << "Footer right: " << fright << endl; + } + } + + table->print()->setHeadFootLine( hleft, hmiddle, hright, + fleft, fmiddle, fright ); + if ( style->hasAttributeNS( ooNS::style, "page-master-name" ) ) + { + QString masterPageLayoutStyleName=style->attributeNS( ooNS::style, "page-master-name", QString::null ); + kdDebug(30518)<<"masterPageLayoutStyleName :"<<masterPageLayoutStyleName<<endl; + QDomElement *masterLayoutStyle = m_styles[masterPageLayoutStyleName]; + kdDebug(30518)<<"masterLayoutStyle :"<<masterLayoutStyle<<endl; + if ( !masterLayoutStyle ) + return; + KoStyleStack styleStack( ooNS::style, ooNS::fo ); + styleStack.push( *masterLayoutStyle ); + loadOasisMasterLayoutPage( table, styleStack ); + } +} + +void OpenCalcImport::loadOasisMasterLayoutPage( Sheet * table,KoStyleStack &styleStack ) +{ + float left = 0.0; + float right = 0.0; + float top = 0.0; + float bottom = 0.0; + float width = 0.0; + float height = 0.0; + QString orientation = "Portrait"; + QString format; + + // Laurent : Why we stored layout information as Millimeter ?!!!!! + // kspread used point for all other attribute + // I don't understand :( + if ( styleStack.hasAttributeNS( ooNS::fo, "page-width" ) ) + { + width = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-width" ) ) ); + } + if ( styleStack.hasAttributeNS( ooNS::fo, "page-height" ) ) + { + height = KoUnit::toMM( KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-height" ) ) ); + } + if ( styleStack.hasAttributeNS( ooNS::fo, "margin-top" ) ) + { + top = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-top" ) ) ); + } + if ( styleStack.hasAttributeNS( ooNS::fo, "margin-bottom" ) ) + { + bottom = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-bottom" ) ) ); + } + if ( styleStack.hasAttributeNS( ooNS::fo, "margin-left" ) ) + { + left = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-left" ) ) ); + } + if ( styleStack.hasAttributeNS( ooNS::fo, "margin-right" ) ) + { + right = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-right" ) ) ); + } + if ( styleStack.hasAttributeNS( ooNS::style, "writing-mode" ) ) + { + kdDebug(30518)<<"styleStack.hasAttribute( style:writing-mode ) :"<<styleStack.hasAttributeNS( ooNS::style, "writing-mode" )<<endl; + } + if ( styleStack.hasAttributeNS( ooNS::style, "print-orientation" ) ) + { + orientation = ( styleStack.attributeNS( ooNS::style, "print-orientation" )=="landscape" ) ? "Landscape" : "Portrait" ; + } + if ( styleStack.hasAttributeNS( ooNS::style, "num-format" ) ) + { + kdDebug(30518)<<" num-format :"<<styleStack.attributeNS( ooNS::style, "num-format" )<<endl; + //todo fixme + } + if ( styleStack.hasAttributeNS( ooNS::fo, "background-color" ) ) + { + //todo + kdDebug(30518)<<" fo:background-color :"<<styleStack.attributeNS( ooNS::fo, "background-color" )<<endl; + } + if ( styleStack.hasAttributeNS( ooNS::style, "print" ) ) + { + //todo parsing + QString str = styleStack.attributeNS( ooNS::style, "print" ); + kdDebug(30518)<<" style:print :"<<str<<endl; + + if (str.contains( "headers" ) ) + { + //todo implement it into kspread + } + if ( str.contains( "grid" ) ) + { + table->print()->setPrintGrid( true ); + } + if ( str.contains( "annotations" ) ) + { + //todo it's not implemented + } + if ( str.contains( "objects" ) ) + { + //todo it's not implemented + } + if ( str.contains( "charts" ) ) + { + //todo it's not implemented + } + if ( str.contains( "drawings" ) ) + { + //todo it's not implemented + } + if ( str.contains( "formulas" ) ) + { + table->setShowFormula(true); + } + if ( str.contains( "zero-values" ) ) + { + //todo it's not implemented + } + } + if ( styleStack.hasAttributeNS( ooNS::style, "table-centering" ) ) + { + QString str = styleStack.attributeNS( ooNS::style, "table-centering" ); + //not implemented into kspread + kdDebug(30518)<<" styleStack.attribute( style:table-centering ) :"<<str<<endl; +#if 0 + if ( str == "horizontal" ) + { + } + else if ( str == "vertical" ) + { + } + else if ( str == "both" ) + { + } + else if ( str == "none" ) + { + } + else + kdDebug(30518)<<" table-centering unknown :"<<str<<endl; +#endif + } + format = QString( "%1x%2" ).arg( width ).arg( height ); + kdDebug(30518)<<" format : "<<format<<endl; + table->print()->setPaperLayout( left, top, right, bottom, format, orientation ); + + kdDebug(30518)<<" left margin :"<<left<<" right :"<<right<<" top :"<<top<<" bottom :"<<bottom<<endl; +//<style:properties fo:page-width="21.8cm" fo:page-height="28.801cm" fo:margin-top="2cm" fo:margin-bottom="2.799cm" fo:margin-left="1.3cm" fo:margin-right="1.3cm" style:writing-mode="lr-tb"/> +// QString format = paper.attribute( "format" ); +// QString orientation = paper.attribute( "orientation" ); +// m_pPrint->setPaperLayout( left, top, right, bottom, format, orientation ); +// } +} + + +bool OpenCalcImport::parseBody( int numOfTables ) +{ + QDomElement content = m_content.documentElement(); + QDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" ); + + if ( body.isNull() ) + return false; + + loadOasisAreaName( body.toElement() ); + loadOasisCellValidation( body.toElement() ); + + Sheet * table; + QDomNode sheet = KoDom::namedItemNS( body, ooNS::table, "table" ); + + kdDebug()<<" sheet :"<<sheet.isNull()<<endl; + if ( sheet.isNull() ) + return false; + + while ( !sheet.isNull() ) + { + QDomElement t = sheet.toElement(); + if ( t.isNull() ) + { + sheet = sheet.nextSibling(); + continue; + } + if ( t.nodeName() != "table:table" ) + { + sheet = sheet.nextSibling(); + continue; + } + + table = m_doc->map()->addNewSheet(); + + table->setSheetName( t.attributeNS( ooNS::table, "name", QString::null ), true, false ); + kdDebug()<<" table->name()"<<table->name()<<endl; + sheet = sheet.nextSibling(); + } + + sheet = body.firstChild(); + + int step = (int) ( 80 / numOfTables ); + int progress = 15; + + Format::setGlobalColWidth( MM_TO_POINT( 22.7 ) ); + Format::setGlobalRowHeight( MM_TO_POINT( 4.3 ) ); + kdDebug(30518) << "Global Height: " << MM_TO_POINT( 4.3 ) << ", Global width: " << MM_TO_POINT( 22.7) << endl; + + while ( !sheet.isNull() ) + { + QDomElement t = sheet.toElement(); + if ( t.isNull() ) + { + KMessageBox::sorry( 0, i18n( "The file seems to be corrupt. Skipping a table." ) ); + sheet = sheet.nextSibling(); + continue; + } + if ( t.nodeName() != "table:table" ) + { + sheet = sheet.nextSibling(); + continue; + } + + table = m_doc->map()->findSheet( t.attributeNS( ooNS::table, "name", QString::null ) ); + if ( !table ) + { + KMessageBox::sorry( 0, i18n( "Skipping a table." ) ); + sheet = sheet.nextSibling(); + continue; + } + + Format * defaultStyle = m_defaultStyles[ "Default" ]; + if ( defaultStyle ) + { + Cell* defaultCell = table->defaultCell(); + kdDebug(30518) << "Copy default style to default cell" << endl; + defaultCell->format()->copy( *defaultStyle ); + } + table->setDefaultHeight( MM_TO_POINT( 4.3 ) ); + table->setDefaultWidth( MM_TO_POINT( 22.7 ) ); + + kdDebug(30518) << "Added table: " << t.attributeNS( ooNS::table, "name", QString::null ) << endl; + + if ( t.hasAttributeNS( ooNS::table, "style-name" ) ) + { + QString style = t.attributeNS( ooNS::table, "style-name", QString::null ); + QDomElement * tableStyle = m_styles[ style ]; + + QDomNode node; + + if ( tableStyle ) + node = tableStyle->firstChild(); + + while( !node.isNull() ) + { + QDomElement property = node.toElement(); + if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style ) + { + if ( property.hasAttributeNS( ooNS::table, "display" ) ) + { + bool visible = (property.attributeNS( ooNS::table, "display", QString::null ) == "true" ? true : false ); + table->hideSheet( !visible ); + kdDebug(30518) << "Table: " << table->tableName() << ", hidden: " << !visible << endl; + } + } + + node = node.nextSibling(); + } + + if ( tableStyle && tableStyle->hasAttributeNS( ooNS::style, "master-page-name" ) ) + { + QString stylename = "pm" + tableStyle->attributeNS( ooNS::style, "master-page-name", QString::null ); + + loadTableMasterStyle( table, stylename ); + + } + } + if ( t.hasAttributeNS( ooNS::table, "print-ranges" ) ) + { + // e.g.: Sheet4.A1:Sheet4.E28 + QString range = t.attributeNS( ooNS::table, "print-ranges", QString::null ); + OpenCalcPoint point( range ); + + kdDebug(30518) << "Print range: " << point.translation << endl; + KSpread::Range p( point.translation ); + + kdDebug(30518) << "Print table: " << p.sheetName() << endl; + + if ( table->sheetName() == p.sheetName() ) + table->print()->setPrintRange( p.range() ); + } + + if ( !readColLayouts( t, table ) ) + return false; + + if ( !readRowsAndCells( t, table ) ) + return false; + + if ( t.hasAttributeNS( ooNS::table, "protected" ) ) + { + QCString passwd( "" ); + if ( t.hasAttributeNS( ooNS::table, "protection-key" ) ) + { + QString p = t.attributeNS( ooNS::table, "protection-key", QString::null ); + QCString str( p.latin1() ); + kdDebug(30518) << "Decoding password: " << str << endl; + passwd = KCodecs::base64Decode( str ); + } + kdDebug(30518) << "Password hash: '" << passwd << "'" << endl; + table->setProtected( passwd ); + } + + progress += step; + emit sigProgress( progress ); + sheet = sheet.nextSibling(); + } + + QDomElement b = body.toElement(); + if ( b.hasAttributeNS( ooNS::table, "structure-protected" ) ) + { + QCString passwd( "" ); + if ( b.hasAttributeNS( ooNS::table, "protection-key" ) ) + { + QString p = b.attributeNS( ooNS::table, "protection-key", QString::null ); + QCString str( p.latin1() ); + kdDebug(30518) << "Decoding password: " << str << endl; + passwd = KCodecs::base64Decode( str ); + } + kdDebug(30518) << "Password hash: '" << passwd << "'" << endl; + + m_doc->map()->setProtected( passwd ); + } + + emit sigProgress( 98 ); + + return true; +} + +void OpenCalcImport::insertStyles( QDomElement const & element ) +{ + if ( element.isNull() ) + return; + + QDomElement e; + forEachElement( e, element ) + { + if ( e.isNull() || !e.hasAttributeNS( ooNS::style, "name" ) ) + { + continue; + } + + QString name = e.attributeNS( ooNS::style, "name", QString::null ); + kdDebug(30518) << "Style: '" << name << "' loaded " << endl; + m_styles.insert( name, new QDomElement( e ) ); + } +} + + +void OpenCalcImport::loadOasisAreaName( const QDomElement&body ) +{ + QDomNode namedAreas = KoDom::namedItemNS( body, ooNS::table, "named-expressions" ); + if ( !namedAreas.isNull() ) + { + QDomElement e; + forEachElement( e, namedAreas ) + { + if ( e.isNull() || !e.hasAttributeNS( ooNS::table, "name" ) || !e.hasAttributeNS( ooNS::table, "cell-range-address" ) ) + { + kdDebug(30518) << "Reading in named area failed" << endl; + continue; + } + + // TODO: what is: table:base-cell-address + QString name = e.attributeNS( ooNS::table, "name", QString::null ); + QString areaPoint = e.attributeNS( ooNS::table, "cell-range-address", QString::null ); + + m_namedAreas.append( name ); + kdDebug(30518) << "Reading in named area, name: " << name << ", area: " << areaPoint << endl; + + OpenCalcPoint point( areaPoint ); + kdDebug(30518) << "Area: " << point.translation << endl; + + QString range( point.translation ); + + if ( point.translation.find( ':' ) == -1 ) + { + Point p( point.translation ); + + int n = range.find( '!' ); + if ( n > 0 ) + range = range + ":" + range.right( range.length() - n - 1); + + kdDebug(30518) << "=> Area: " << range << endl; + } + + KSpread::Range p( range ); + + m_doc->addAreaName( p.range(), name, p.sheetName() ); + kdDebug(30518) << "Area range: " << p.sheetName() << endl; + } + } +} + +void OpenCalcImport::loadOasisCellValidation( const QDomElement&body ) +{ + QDomNode validation = KoDom::namedItemNS( body, ooNS::table, "content-validations" ); + if ( !validation.isNull() ) + { + QDomElement element; + forEachElement( element, validation ) + { + if ( element.localName() == "content-validation" ) { + m_validationList.insert( element.attributeNS( ooNS::table, "name", QString::null ), element); + kdDebug(30518)<<" validation found :"<<element.attributeNS( ooNS::table, "name", QString::null )<<endl; + } + else { + kdDebug(30518)<<" Tag not recognize :"<<element.tagName()<<endl; + } + } + } +} + + +QString * OpenCalcImport::loadFormat( QDomElement * element, + FormatType & formatType, + QString name ) +{ + if ( !element ) + return 0; + + int i; + bool ok; + + QString * format = 0; + QDomElement e = element->firstChild( ).toElement(); + int precision = 0; + int leadingZ = 1; + bool thousandsSep = false; + bool negRed = false; + + if ( element->localName() == "time-style" ) + formatType = Custom_format; + else if ( element->localName() == "date-style" ) + formatType = Custom_format; + else if ( element->localName() == "percentage-style" ) + formatType = Custom_format; + else if ( element->localName() == "number-style" ) + formatType = Custom_format; + else if ( element->localName() == "currency-style" ) + formatType = Custom_format; + else if ( element->localName() == "boolean-style" ) + formatType = Custom_format; + + if ( !e.isNull() ) + format = new QString(); + + // TODO (element): + // number:automatic-order="true" + // number:truncate-on-overflow="false" + // style:volatile="true" + + while ( !e.isNull() ) + { + if ( e.localName() == "properties" && e.namespaceURI() == ooNS::style ) + { + if ( e.hasAttributeNS( ooNS::fo, "color" ) ) + negRed = true; // we only support red... + } + else if ( e.localName() == "text" && e.namespaceURI()==ooNS::number) + { + if ( negRed && ( e.text() == "-" ) ) + ; + else + format->append( e.text() ); + } + else if ( e.localName() == "currency-symbol" && e.namespaceURI()==ooNS::number) + { + QString sym( e.text() ); + kdDebug(30518) << "Currency: " << sym << endl; + format->append( sym ); + // number:language="de" number:country="DE">€</number:currency-symbol> + } + else if ( e.localName() == "day-of-week" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "dddd" ); + else + format->append( "ddd" ); + } + else + format->append( "ddd" ); + } + else if ( e.localName() == "day" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "dd" ); + else + format->append( "d" ); + } + else + format->append( "d" ); + } + else if ( e.localName() == "month" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "textual" ) ) + { + if ( e.attributeNS( ooNS::number, "textual", QString::null ) == "true" ) + format->append( "mm" ); + } + + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "mm" ); + else + format->append( "m" ); + } + else + format->append( "m" ); + } + else if ( e.localName() == "year" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "yyyy" ); + else + format->append( "yy" ); + } + else + format->append( "yy" ); + } + else if ( e.localName() == "hours" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "hh" ); + else + format->append( "h" ); + } + else + format->append( "h" ); + } + else if ( e.localName() == "minutes" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "mm" ); + else + format->append( "m" ); + } + else + format->append( "m" ); + } + else if ( e.localName() == "seconds" && e.namespaceURI()==ooNS::number) + { + if ( e.hasAttributeNS( ooNS::number, "style" ) ) + { + if ( e.attributeNS( ooNS::number, "style", QString::null ) == "long" ) + format->append( "ss" ); + else + format->append( "s" ); + } + else + format->append( "s" ); + } + else if ( e.localName() == "am-pm" && e.namespaceURI()==ooNS::number) + { + format->append( "AM/PM" ); + } + else if ( e.localName() == "number" && e.namespaceURI()==ooNS::number) + { + // TODO: number:grouping="true" + + if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) ) + { + int d = e.attributeNS( ooNS::number, "decimal-places", QString::null ).toInt( &ok ); + if ( ok ) + precision = d; + } + + if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) ) + { + int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok ); + if ( ok ) + leadingZ = d; + } + + if ( thousandsSep && leadingZ <= 3 ) + { + format->append( "#," ); + for ( i = leadingZ; i <= 3; ++i ) + format->append( '#' ); + } + + for ( i = 1; i <= leadingZ; ++i ) + { + format->append( '0' ); + if ( ( i % 3 == 0 ) && thousandsSep ) + format->append( ',' ); + } + + format->append( '.' ); + for ( i = 0; i < precision; ++i ) + format->append( '0' ); + } + else if ( e.localName() == "scientific-number" && e.namespaceURI()==ooNS::number) + { + int exp = 2; + + if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) ) + { + int d = e.attributeNS( ooNS::number, "decimal-places", QString::null ).toInt( &ok ); + if ( ok ) + precision = d; + } + + if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) ) + { + int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok ); + if ( ok ) + leadingZ = d; + } + + if ( e.hasAttributeNS( ooNS::number, "min-exponent-digits" ) ) + { + int d = e.attributeNS( ooNS::number, "min-exponent-digits", QString::null ).toInt( &ok ); + if ( ok ) + exp = d; + if ( exp <= 0 ) + exp = 1; + } + + if ( thousandsSep && leadingZ <= 3 ) + { + format->append( "#," ); + for ( i = leadingZ; i <= 3; ++i ) + format->append( '#' ); + } + + for ( i = 1; i <= leadingZ; ++i ) + { + format->append( '0' ); + if ( ( i % 3 == 0 ) && thousandsSep ) + format->append( ',' ); + } + + format->append( '.' ); + for ( i = 0; i < precision; ++i ) + format->append( '0' ); + + format->append( "E+" ); + for ( i = 0; i < exp; ++i ) + format->append( '0' ); + + formatType = Custom_format; + } + else if ( e.localName() == "fraction" && e.namespaceURI()==ooNS::number) + { + int integer = 0; + int numerator = 1; + int denominator = 1; + + if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) ) + { + int d = e.attributeNS( ooNS::number, "min-integer-digits", QString::null ).toInt( &ok ); + if ( ok ) + integer = d; + } + if ( e.hasAttributeNS( ooNS::number, "min-numerator-digits" ) ) + { + int d = e.attributeNS( ooNS::number, "min-numerator-digits", QString::null ).toInt( &ok ); + if ( ok ) + numerator = d; + } + if ( e.hasAttributeNS( ooNS::number, "min-denominator-digits" ) ) + { + int d = e.attributeNS( ooNS::number, "min-denominator-digits", QString::null ).toInt( &ok ); + if ( ok ) + denominator = d; + } + + for ( i = 0; i <= integer; ++i ) + format->append( '#' ); + + format->append( ' ' ); + + for ( i = 0; i <= numerator; ++i ) + format->append( '?' ); + + format->append( '/' ); + + for ( i = 0; i <= denominator; ++i ) + format->append( '?' ); + } + // Not needed: + // <style:map style:condition="value()>=0" style:apply-style-name="N106P0"/> + // we handle painting negative numbers in red differently + + e = e.nextSibling().toElement(); + } + + if ( negRed ) + { + QString f( *format ); + format->append( ";[Red]" ); + format->append( f ); + } + + kdDebug(30518) << "*** New FormatString: " << *format << endl << endl; + + m_formats.insert( name, format ); + + return format; +} + +void OpenCalcImport::loadFontStyle( Format * layout, QDomElement const * font ) const +{ + if ( !font || !layout ) + return; + + kdDebug(30518) << "Copy font style from the layout " << font->tagName() << ", " << font->nodeName() << endl; + + if ( font->hasAttributeNS( ooNS::fo, "font-family" ) ) + layout->setTextFontFamily( font->attributeNS( ooNS::fo, "font-family", QString::null ) ); + if ( font->hasAttributeNS( ooNS::fo, "color" ) ) + layout->setTextColor( QColor( font->attributeNS( ooNS::fo, "color", QString::null ) ) ); + if ( font->hasAttributeNS( ooNS::fo, "font-size" ) ) + layout->setTextFontSize( int( KoUnit::parseValue( font->attributeNS( ooNS::fo, "font-size", QString::null ), 10 ) ) ); + else + layout->setTextFontSize( 10 ); + if ( font->hasAttributeNS( ooNS::fo, "font-style" ) ) + { + kdDebug(30518) << "italic" << endl; + layout->setTextFontItalic( true ); // only thing we support + } + if ( font->hasAttributeNS( ooNS::fo, "font-weight" ) ) + layout->setTextFontBold( true ); // only thing we support + if ( font->hasAttributeNS( ooNS::fo, "text-underline" ) || font->hasAttributeNS( ooNS::style, "text-underline" ) ) + layout->setTextFontUnderline( true ); // only thing we support + if ( font->hasAttributeNS( ooNS::style, "text-crossing-out" ) ) + layout->setTextFontStrike( true ); // only thing we support + if ( font->hasAttributeNS( ooNS::style, "font-pitch" ) ) + { + // TODO: possible values: fixed, variable + } + // TODO: + // text-underline-color +} + +void OpenCalcImport::loadBorder( Format * layout, QString const & borderDef, bPos pos ) const +{ + if ( borderDef == "none" ) + return; + + int p = borderDef.find( ' ' ); + if ( p < 0 ) + return; + + QPen pen; + QString w = borderDef.left( p ); + pen.setWidth( (int) KoUnit::parseValue( w ) ); + + + ++p; + int p2 = borderDef.find( ' ', p ); + QString s = borderDef.mid( p, p2 - p ); + + kdDebug(30518) << "Borderstyle: " << s << endl; + + if ( s == "solid" || s == "double" ) + pen.setStyle( Qt::SolidLine ); + else + { +#if 0 + // TODO: not supported by oocalc + pen.setStyle( Qt::DashLine ); + pen.setStyle( Qt::DotLine ); + pen.setStyle( Qt::DashDotLine ); + pen.setStyle( Qt::DashDotDotLine ); +#endif + pen.setStyle( Qt::SolidLine ); //default. + } + + ++p2; + p = borderDef.find( ' ', p2 ); + if ( p == -1 ) + p = borderDef.length(); + + pen.setColor( QColor( borderDef.right( p - p2 ) ) ); + + if ( pos == Left ) + layout->setLeftBorderPen( pen ); + else if ( pos == Top ) + layout->setTopBorderPen( pen ); + else if ( pos == Right ) + layout->setRightBorderPen( pen ); + else if ( pos == Bottom ) + layout->setBottomBorderPen( pen ); + else if ( pos == Border ) + { + layout->setLeftBorderPen( pen ); + layout->setTopBorderPen( pen ); + layout->setRightBorderPen( pen ); + layout->setBottomBorderPen( pen ); + } + // TODO Diagonals not supported by oocalc +} + +void OpenCalcImport::loadStyleProperties( Format * layout, QDomElement const & property ) const +{ + kdDebug(30518) << "*** Loading style properties *****" << endl; + + if ( property.hasAttributeNS( ooNS::style, "decimal-places" ) ) + { + bool ok = false; + int p = property.attributeNS( ooNS::style, "decimal-places", QString::null ).toInt( &ok ); + if (ok ) + layout->setPrecision( p ); + } + + if ( property.hasAttributeNS( ooNS::style, "font-name" ) ) + { + QDomElement * font = m_styles[ property.attributeNS( ooNS::style, "font-name", QString::null ) ]; + loadFontStyle( layout, font ); // generell font style + } + + loadFontStyle( layout, &property ); // specific font style + + // TODO: + // diagonal: fall + goup + // fo:direction="ltr" + // style:text-align-source ("fix") + // style:shadow + // style:text-outline + // indents from right, top, bottom + // style:condition="cell-content()=15" + // => style:apply-style-name="Result" style:base-cell-address="Sheet6.A5"/> + + if ( property.hasAttributeNS( ooNS::style, "rotation-angle" ) ) + { + bool ok = false; + int a = property.attributeNS( ooNS::style, "rotation-angle", QString::null ).toInt( &ok ); + if ( ok ) + layout->setAngle( -a + 1 ); + } + + if ( property.hasAttributeNS( ooNS::fo, "direction" ) ) + { + layout->setVerticalText( true ); + } + if ( property.hasAttributeNS( ooNS::fo, "text-align" ) ) + { + QString s = property.attributeNS( ooNS::fo, "text-align", QString::null ); + if ( s == "center" ) + layout->setAlign( Format::Center ); + else if ( s == "end" ) + layout->setAlign( Format::Right ); + else if ( s == "start" ) + layout->setAlign( Format::Left ); + else if ( s == "justify" ) // TODO in KSpread! + layout->setAlign( Format::Center ); + } + if ( property.hasAttributeNS( ooNS::fo, "margin-left" ) ) + { + kdDebug(30518)<<"margin-left :"<<KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", QString::null ),0.0 )<<endl; + layout->setIndent( KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", QString::null ),0.0 ) ); + } + if ( property.hasAttributeNS( ooNS::fo, "background-color" ) ) + layout->setBgColor( QColor( property.attributeNS( ooNS::fo, "background-color", QString::null ) ) ); + + if ( property.hasAttributeNS( ooNS::style, "print-content" ) ) + { + if ( property.attributeNS( ooNS::style, "print-content", QString::null ) == "false" ) + layout->setDontPrintText( false ); + } + if ( property.hasAttributeNS( ooNS::style, "cell-protect" ) ) + { + QString prot( property.attributeNS( ooNS::style, "cell-protect", QString::null ) ); + if ( prot == "none" ) + { + layout->setNotProtected( true ); + layout->setHideFormula( false ); + layout->setHideAll( false ); + } + else if ( prot == "formula-hidden" ) + { + layout->setNotProtected( true ); + layout->setHideFormula( true ); + layout->setHideAll( false ); + } + else if ( prot == "protected formula-hidden" ) + { + layout->setNotProtected( false ); + layout->setHideFormula( true ); + layout->setHideAll( false ); + } + else if ( prot == "hidden-and-protected" ) + { + layout->setNotProtected( false ); + layout->setHideFormula( false ); + layout->setHideAll( true ); + } + else if ( prot == "protected" ) + { + layout->setNotProtected( false ); + layout->setHideFormula( false ); + layout->setHideAll( false ); + } + kdDebug(30518) << "Cell " << prot << endl; + } + + if ( property.hasAttributeNS( ooNS::fo, "padding-left" ) ) + layout->setIndent( KoUnit::parseValue(property.attributeNS( ooNS::fo, "padding-left", QString::null ) ) ); + + if ( property.hasAttributeNS( ooNS::fo, "vertical-align" ) ) + { + QString s = property.attributeNS( ooNS::fo, "vertical-align", QString::null ); + if ( s == "middle" ) + layout->setAlignY( Format::Middle ); + else if ( s == "bottom" ) + layout->setAlignY( Format::Bottom ); + else + layout->setAlignY( Format::Top ); + } + else + layout->setAlignY( Format::Bottom ); + + if ( property.hasAttributeNS( ooNS::fo, "wrap-option" ) ) + { + layout->setMultiRow( true ); + + /* we do not support anything else yet + QString s = property.attributeNS( ooNS::fo, "wrap-option", QString::null ); + if ( s == "wrap" ) + layout->setMultiRow( true ); + */ + } + + if ( property.hasAttributeNS( ooNS::fo, "border-bottom" ) ) + { + loadBorder( layout, property.attributeNS( ooNS::fo, "border-bottom", QString::null ), Bottom ); + // TODO: style:border-line-width-bottom if double! + } + + if ( property.hasAttributeNS( ooNS::fo, "border-right" ) ) + { + loadBorder( layout, property.attributeNS( ooNS::fo, "border-right", QString::null ), Right ); + // TODO: style:border-line-width-right + } + + if ( property.hasAttributeNS( ooNS::fo, "border-top" ) ) + { + loadBorder( layout, property.attributeNS( ooNS::fo, "border-top", QString::null ), Top ); + // TODO: style:border-line-width-top + } + + if ( property.hasAttributeNS( ooNS::fo, "border-left" ) ) + { + loadBorder( layout, property.attributeNS( ooNS::fo, "border-left", QString::null ), Left ); + // TODO: style:border-line-width-left + } + + if ( property.hasAttributeNS( ooNS::fo, "border" ) ) + { + loadBorder( layout, property.attributeNS( ooNS::fo, "border", QString::null ), Border ); + // TODO: style:border-line-width-left + } +} + +void OpenCalcImport::readInStyle( Format * layout, QDomElement const & style ) +{ + kdDebug(30518) << "** Reading Style: " << style.tagName() << "; " << style.attributeNS( ooNS::style, "name", QString::null) << endl; + if ( style.localName() == "style" && style.namespaceURI()==ooNS::style) + { + if ( style.hasAttributeNS( ooNS::style, "parent-style-name" ) ) + { + Format * cp + = m_defaultStyles.find( style.attributeNS( ooNS::style, "parent-style-name", QString::null ) ); + kdDebug(30518) << "Copying layout from " << style.attributeNS( ooNS::style, "parent-style-name", QString::null ) << endl; + + if ( cp != 0 ) + layout->copy( *cp ); + } + else if ( style.hasAttributeNS( ooNS::style, "family") ) + { + QString name = style.attribute( "style-family" ) + "default"; + Format * cp = m_defaultStyles.find( name ); + + kdDebug(30518) << "Copying layout from " << name << ", " << !cp << endl; + + if ( cp != 0 ) + layout->copy( *cp ); + } + + if ( style.hasAttributeNS( ooNS::style, "data-style-name" ) ) + { + QString * format = m_formats[ style.attributeNS( ooNS::style, "data-style-name", QString::null ) ]; + FormatType formatType; + + if ( !format ) + { + // load and convert it + QString name( style.attributeNS( ooNS::style, "data-style-name", QString::null ) ); + format = loadFormat( m_styles[ name ], formatType, name ); + } + + if ( format ) + { + layout->setFormatString( *format ); + layout->setFormatType( formatType ); + } + + // <number:currency-symbol number:language="de" number:country="DE">€</number:currency-symbol> + } + } + + QDomElement property; + forEachElement( property, style ) + { + if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style ) + loadStyleProperties( layout, property ); + + kdDebug(30518) << layout->textFontFamily( 0, 0 ) << endl; + } +} + +bool OpenCalcImport::createStyleMap( QDomDocument const & styles ) +{ + QDomElement content = styles.documentElement(); + QDomNode docStyles = KoDom::namedItemNS( content, ooNS::office, "document-styles" ); + + if ( content.hasAttributeNS( ooNS::office, "version" ) ) + { + bool ok = true; + double d = content.attributeNS( ooNS::office, "version", QString::null ).toDouble( &ok ); + + if ( ok ) + { + kdDebug(30518) << "OpenCalc version: " << d << endl; + if ( d > 1.0 ) + { + QString message( i18n("This document was created with OpenOffice.org version '%1'. This filter was written for version 1.0. Reading this file could cause strange behavior, crashes or incorrect display of the data. Do you want to continue converting the document?") ); + message.arg( content.attributeNS( ooNS::office, "version", QString::null ) ); + if ( KMessageBox::warningYesNo( 0, message, i18n( "Unsupported document version" ) ) == KMessageBox::No ) + return false; + } + } + } + + QDomNode fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" ); + + if ( !fontStyles.isNull() ) + { + kdDebug(30518) << "Starting reading in font-decl..." << endl; + + insertStyles( fontStyles.toElement() ); + } + else + kdDebug(30518) << "No items found" << endl; + + kdDebug(30518) << "Starting reading in auto:styles" << endl; + + QDomNode autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" ); + if ( !autoStyles.isNull() ) + insertStyles( autoStyles.toElement() ); + else + kdDebug(30518) << "No items found" << endl; + + + kdDebug(30518) << "Reading in master styles" << endl; + + QDomNode masterStyles = KoDom::namedItemNS( content, ooNS::office, "master-styles" ); + + if ( masterStyles.isNull() ) + { + kdDebug(30518) << "Nothing found " << endl; + } + + QDomElement master = KoDom::namedItemNS( masterStyles, ooNS::style, "master-page"); + if ( !master.isNull() ) + { + QString name( "pm" ); + name += master.attributeNS( ooNS::style, "name", QString::null ); + kdDebug(30518) << "Master style: '" << name << "' loaded " << endl; + m_styles.insert( name, new QDomElement( master ) ); + + master = master.nextSibling().toElement(); + } + + + kdDebug(30518) << "Starting reading in office:styles" << endl; + + QDomNode fixedStyles = KoDom::namedItemNS( content, ooNS::office, "styles" ); + + kdDebug(30518) << "Reading in default styles" << endl; + + QDomNode def = KoDom::namedItemNS( fixedStyles, ooNS::style, "default-style" ); + kdDebug()<<" def !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<def.isNull()<<endl; + while ( !def.isNull() ) + { + QDomElement e = def.toElement(); + kdDebug(30518) << "Style found " << e.nodeName() << ", tag: " << e.tagName() << endl; + + if ( e.nodeName() != "style:default-style" ) + { + def = def.nextSibling(); + continue; + } + + if ( !e.isNull() ) + { + Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() ); + + readInStyle( layout, e ); + kdDebug(30518) << "Default style " << e.attributeNS( ooNS::style, "family", QString::null ) << "default" << " loaded " << endl; + + m_defaultStyles.insert( e.attributeNS( ooNS::style, "family", QString::null ) + "default", layout ); + // QFont font = layout->font(); + // kdDebug(30518) << "Font: " << font.family() << ", " << font.toString() << endl; + } + + def = def.nextSibling(); + } + + QDomElement defs = KoDom::namedItemNS( fixedStyles, ooNS::style, "style" ); + while ( !defs.isNull() ) + { + if ( defs.nodeName() != "style:style" ) + break; // done + + if ( !defs.hasAttributeNS( ooNS::style, "name" ) ) + { + // ups... + defs = defs.nextSibling().toElement(); + continue; + } + + Format * layout = new Format( 0, m_doc->styleManager()->defaultStyle() ); + readInStyle( layout, defs ); + kdDebug(30518) << "Default style " << defs.attributeNS( ooNS::style, "name", QString::null ) << " loaded " << endl; + + m_defaultStyles.insert( defs.attributeNS( ooNS::style, "name", QString::null ), layout ); + // kdDebug(30518) << "Font: " << layout->font().family() << ", " << layout->font().toString() << endl; + + defs = defs.nextSibling().toElement(); + } + + if ( !fixedStyles.isNull() ) + insertStyles( fixedStyles.toElement() ); + + kdDebug(30518) << "Starting reading in automatic styles" << endl; + + content = m_content.documentElement(); + autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" ); + + if ( !autoStyles.isNull() ) + insertStyles( autoStyles.toElement() ); + + fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" ); + + if ( !fontStyles.isNull() ) + { + kdDebug(30518) << "Starting reading in special font decl" << endl; + + insertStyles( fontStyles.toElement() ); + } + + kdDebug(30518) << "Styles read in." << endl; + + return true; +} + +void OpenCalcImport::loadOasisValidation( Validity* val, const QString& validationName ) +{ + kdDebug(30518)<<"validationName:"<<validationName<<endl; + QDomElement element = m_validationList[validationName]; + if ( element.hasAttributeNS( ooNS::table, "condition" ) ) + { + QString valExpression = element.attributeNS( ooNS::table, "condition", QString::null ); + kdDebug(30518)<<" element.attribute( table:condition ) "<<valExpression<<endl; + //Condition ::= ExtendedTrueCondition | TrueFunction 'and' TrueCondition + //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time() + //ExtendedTrueCondition ::= ExtendedGetFunction | cell-content-text-length() Operator Value + //TrueCondition ::= GetFunction | cell-content() Operator Value + //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value) + //ExtendedGetFunction ::= cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value) + //Operator ::= '<' | '>' | '<=' | '>=' | '=' | '!=' + //Value ::= NumberValue | String | Formula + //A Formula is a formula without an equals (=) sign at the beginning. See section 8.1.3 for more information. + //A String comprises one or more characters surrounded by quotation marks. + //A NumberValue is a whole or decimal number. It must not contain comma separators for numbers of 1000 or greater. + + //ExtendedTrueCondition + if ( valExpression.contains( "cell-content-text-length()" ) ) + { + //"cell-content-text-length()>45" + valExpression = valExpression.remove("cell-content-text-length()" ); + kdDebug(30518)<<" valExpression = :"<<valExpression<<endl; + val->m_restriction = Restriction::TextLength; + + loadOasisValidationCondition( val, valExpression ); + } + //cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value) + else if ( valExpression.contains( "cell-content-text-length-is-between" ) ) + { + val->m_restriction = Restriction::TextLength; + val->m_cond = Conditional::Between; + valExpression = valExpression.remove( "cell-content-text-length-is-between(" ); + kdDebug(30518)<<" valExpression :"<<valExpression<<endl; + valExpression = valExpression.remove( ")" ); + QStringList listVal = QStringList::split( ",", valExpression ); + loadOasisValidationValue( val, listVal ); + } + else if ( valExpression.contains( "cell-content-text-length-is-not-between" ) ) + { + val->m_restriction = Restriction::TextLength; + val->m_cond = Conditional::Different; + valExpression = valExpression.remove( "cell-content-text-length-is-not-between(" ); + kdDebug(30518)<<" valExpression :"<<valExpression<<endl; + valExpression = valExpression.remove( ")" ); + kdDebug(30518)<<" valExpression :"<<valExpression<<endl; + QStringList listVal = QStringList::split( ",", valExpression ); + loadOasisValidationValue( val, listVal ); + + } + //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time() + else + { + if (valExpression.contains( "cell-content-is-whole-number()" ) ) + { + val->m_restriction = Restriction::Number; + valExpression = valExpression.remove( "cell-content-is-whole-number() and " ); + } + else if (valExpression.contains( "cell-content-is-decimal-number()" ) ) + { + val->m_restriction = Restriction::Integer; + valExpression = valExpression.remove( "cell-content-is-decimal-number() and " ); + } + else if (valExpression.contains( "cell-content-is-date()" ) ) + { + val->m_restriction = Restriction::Date; + valExpression = valExpression.remove( "cell-content-is-date() and " ); + } + else if (valExpression.contains( "cell-content-is-time()" ) ) + { + val->m_restriction = Restriction::Time; + valExpression = valExpression.remove( "cell-content-is-time() and " ); + } + kdDebug(30518)<<"valExpression :"<<valExpression<<endl; + + if ( valExpression.contains( "cell-content()" ) ) + { + valExpression = valExpression.remove( "cell-content()" ); + loadOasisValidationCondition( val, valExpression ); + } + //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value) + //for the moment we support just int/double value, not text/date/time :( + if ( valExpression.contains( "cell-content-is-between(" ) ) + { + valExpression = valExpression.remove( "cell-content-is-between(" ); + valExpression = valExpression.remove( ")" ); + QStringList listVal = QStringList::split( "," , valExpression ); + loadOasisValidationValue( val, listVal ); + + val->m_cond = Conditional::Between; + } + if ( valExpression.contains( "cell-content-is-not-between(" ) ) + { + valExpression = valExpression.remove( "cell-content-is-not-between(" ); + valExpression = valExpression.remove( ")" ); + QStringList listVal = QStringList::split( ",", valExpression ); + loadOasisValidationValue( val, listVal ); + val->m_cond = Conditional::Different; + } + } + } + if ( element.hasAttributeNS( ooNS::table, "allow-empty-cell" ) ) + { + val->allowEmptyCell = ( ( element.attributeNS( ooNS::table, "allow-empty-cell", QString::null )=="true" ) ? true : false ); + + } + if ( element.hasAttributeNS( ooNS::table, "base-cell-address" ) ) + { + //todo what is it ? + } + + QDomElement help = KoDom::namedItemNS( element, ooNS::table, "help-message" ); + if ( !help.isNull() ) + { + if ( help.hasAttributeNS( ooNS::table, "title" ) ) + val->titleInfo = help.attributeNS( ooNS::table, "title", QString::null ); + if ( help.hasAttributeNS( ooNS::table, "display" ) ) + val->displayValidationInformation = ( ( help.attributeNS( ooNS::table, "display", QString::null )=="true" ) ? true : false ); + QDomElement attrText = KoDom::namedItemNS( help, ooNS::text, "p" ); + if ( !attrText.isNull() ) + val->messageInfo = attrText.text(); + } + + QDomElement error = KoDom::namedItemNS( element, ooNS::table, "error-message" ); + if ( !error.isNull() ) + { + if ( error.hasAttributeNS( ooNS::table, "title" ) ) + val->title = error.attributeNS( ooNS::table, "title", QString::null ); + if ( error.hasAttributeNS( ooNS::table, "message-type" ) ) + { + QString str = error.attributeNS( ooNS::table, "message-type", QString::null ); + if ( str == "warning" ) + val->m_action = Action::Warning; + else if ( str == "information" ) + val->m_action = Action::Information; + else if ( str == "stop" ) + val->m_action = Action::Stop; + else + kdDebug(30518)<<"validation : message type unknown :"<<str<<endl; + } + + if ( error.hasAttributeNS( ooNS::table, "display" ) ) + { + kdDebug(30518)<<" display message :"<<error.attributeNS( ooNS::table, "display", QString::null )<<endl; + val->displayMessage = (error.attributeNS( ooNS::table, "display", QString::null )=="true"); + } + QDomElement attrText = KoDom::namedItemNS( error, ooNS::text, "p" ); + if ( !attrText.isNull() ) + val->message = attrText.text(); + } +} + +void OpenCalcImport::loadOasisValidationValue( Validity* val, const QStringList &listVal ) +{ + bool ok = false; + kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl; + + if ( val->m_restriction == Restriction::Date ) + { + val->dateMin = QDate::fromString( listVal[0] ); + val->dateMax = QDate::fromString( listVal[1] ); + } + else if ( val->m_restriction == Restriction::Time ) + { + val->timeMin = QTime::fromString( listVal[0] ); + val->timeMax = QTime::fromString( listVal[1] ); + } + else + { + val->valMin = listVal[0].toDouble(&ok); + if ( !ok ) + { + val->valMin = listVal[0].toInt(&ok); + if ( !ok ) + kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl; + +#if 0 + if ( !ok ) + val->valMin = listVal[0]; +#endif + } + ok=false; + val->valMax = listVal[1].toDouble(&ok); + if ( !ok ) + { + val->valMax = listVal[1].toInt(&ok); + if ( !ok ) + kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl; + +#if 0 + if ( !ok ) + val->valMax = listVal[1]; +#endif + } + } +} + + +void OpenCalcImport::loadOasisValidationCondition( Validity* val,QString &valExpression ) +{ + QString value; + if (valExpression.contains( "<=" ) ) + { + value = valExpression.remove( "<=" ); + val->m_cond = Conditional::InferiorEqual; + } + else if (valExpression.contains( ">=" ) ) + { + value = valExpression.remove( ">=" ); + val->m_cond = Conditional::SuperiorEqual; + } + else if (valExpression.contains( "!=" ) ) + { + //add Differentto attribute + value = valExpression.remove( "!=" ); + val->m_cond = Conditional::DifferentTo; + } + else if ( valExpression.contains( "<" ) ) + { + value = valExpression.remove( "<" ); + val->m_cond = Conditional::Inferior; + } + else if(valExpression.contains( ">" ) ) + { + value = valExpression.remove( ">" ); + val->m_cond = Conditional::Superior; + } + else if (valExpression.contains( "=" ) ) + { + value = valExpression.remove( "=" ); + val->m_cond = Conditional::Equal; + } + else + kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl; + kdDebug(30518)<<" value :"<<value<<endl; + if ( val->m_restriction == Restriction::Date ) + { + val->dateMin = QDate::fromString( value ); + } + else if ( val->m_restriction == Restriction::Date ) + { + val->timeMin = QTime::fromString( value ); + } + else + { + bool ok = false; + val->valMin = value.toDouble(&ok); + if ( !ok ) + { + val->valMin = value.toInt(&ok); + if ( !ok ) + kdDebug(30518)<<" Try to parse this value :"<<value<<endl; + +#if 0 + if ( !ok ) + val->valMin = value; +#endif + } + } +} + + +int OpenCalcImport::readMetaData() +{ + int result = 5; + KoDocumentInfo * docInfo = m_doc->documentInfo(); + KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(docInfo->page( "about" )); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>(docInfo->page( "author" )); + + QDomNode meta = KoDom::namedItemNS( m_meta, ooNS::office, "document-meta" ); + QDomNode office = KoDom::namedItemNS( meta, ooNS::office, "meta" ); + + if ( office.isNull() ) + return 2; + + QDomElement e = KoDom::namedItemNS( office, ooNS::dc, "creator" ); + if ( !e.isNull() && !e.text().isEmpty() ) + authorPage->setFullName( e.text() ); + + e = KoDom::namedItemNS( office, ooNS::dc, "title" ); + if ( !e.isNull() && !e.text().isEmpty() ) + aboutPage->setTitle( e.text() ); + + e = KoDom::namedItemNS( office, ooNS::dc, "description" ); + if ( !e.isNull() && !e.text().isEmpty() ) + aboutPage->setAbstract( e.text() ); + + e = KoDom::namedItemNS( office, ooNS::dc, "subject" ); + if ( !e.isNull() && !e.text().isEmpty() ) + aboutPage->setSubject( e.text() ); + + e= KoDom::namedItemNS( office, ooNS::meta, "keywords" ); + if ( !e.isNull() ) + { + e = KoDom::namedItemNS( e, ooNS::meta, "keyword" ); + if ( !e.isNull() && !e.text().isEmpty() ) + aboutPage->setKeywords( e.text() ); + } + + e = KoDom::namedItemNS( office, ooNS::meta, "document-statistic" ); + if ( !e.isNull() && e.hasAttributeNS( ooNS::meta, "table-count" ) ) + { + bool ok = false; + result = e.attributeNS( ooNS::meta, "table-count", QString::null ).toInt( &ok ); + if ( !ok ) + result = 5; + } + + m_meta.clear(); // not needed anymore + + return result; +} + +KoFilter::ConversionStatus OpenCalcImport::convert( QCString const & from, QCString const & to ) +{ + kdDebug(30518) << "Entering OpenCalc Import filter: " << from << " - " << to << endl; + + KoDocument * document = m_chain->outputDocument(); + if ( !document ) + return KoFilter::StupidError; + + if ( !::qt_cast<const KSpread::Doc *>( document ) ) // it's safer that way :) + { + kdWarning(30518) << "document isn't a KSpread::Doc but a " << document->className() << endl; + return KoFilter::NotImplemented; + } + + if ( ( from != "application/vnd.sun.xml.calc" && from != "application/vnd.sun.xml.calc.template") || to != "application/x-kspread" ) + { + kdWarning(30518) << "Invalid mimetypes " << from << " " << to << endl; + return KoFilter::NotImplemented; + } + + m_doc = ( Doc * ) document; + + if ( m_doc->mimeType() != "application/x-kspread" ) + { + kdWarning(30518) << "Invalid document mimetype " << m_doc->mimeType() << endl; + return KoFilter::NotImplemented; + } + + kdDebug(30518) << "Opening file " << endl; + + KoFilter::ConversionStatus preStatus = openFile(); + + if ( preStatus != KoFilter::OK ) + return preStatus; + + emit sigProgress( 13 ); + int tables = readMetaData(); + + emit sigProgress( 15 ); + + if ( !parseBody( tables ) ) + return KoFilter::StupidError; + + emit sigProgress( 100 ); + return KoFilter::OK; +} + +KoFilter::ConversionStatus OpenCalcImport::openFile() +{ + KoStore * store = KoStore::createStore( m_chain->inputFile(), KoStore::Read); + + kdDebug(30518) << "Store created" << endl; + + if ( !store ) + { + kdWarning(30518) << "Couldn't open the requested file." << endl; + return KoFilter::FileNotFound; + } + + kdDebug(30518) << "Trying to open content.xml" << endl; + QString messageError; + loadAndParse( m_content, "content.xml", store); + kdDebug(30518) << "Opened" << endl; + + QDomDocument styles; + kdDebug(30518) << "file content.xml loaded " << endl; + + loadAndParse( styles, "styles.xml", store); + + loadAndParse( m_meta, "meta.xml", store); + loadAndParse( m_settings, "settings.xml", store); + + delete store; + + emit sigProgress( 10 ); + + if ( !createStyleMap( styles ) ) + return KoFilter::UserCancelled; + + return KoFilter::OK; +} + +KoFilter::ConversionStatus OpenCalcImport::loadAndParse( QDomDocument& doc, const QString& fileName,KoStore *m_store ) +{ + return OoUtils::loadAndParse( fileName, doc, m_store); +} + +#include "opencalcimport.moc" + diff --git a/filters/kspread/opencalc/opencalcimport.h b/filters/kspread/opencalc/opencalcimport.h new file mode 100644 index 000000000..57379796a --- /dev/null +++ b/filters/kspread/opencalc/opencalcimport.h @@ -0,0 +1,119 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Norbert Andres <nandres@web.de> + Copyright (C) 2004 Montel Laurent <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. +*/ + +#ifndef OpenCalc_IMPORT_H__ +#define OpenCalc_IMPORT_H__ + +#include <KoFilter.h> +#include "kspread_format.h" + +#include <qdict.h> +#include <qdom.h> + +class KoStyleStack; +class KoStore; + +namespace KSpread +{ +class Cell; +class Conditional; +class Doc; +class Sheet; +class Validity; +} + +class OpenCalcImport : public KoFilter +{ + Q_OBJECT + public: + OpenCalcImport( KoFilter * parent, const char * name, const QStringList & ); + virtual ~OpenCalcImport(); + + virtual KoFilter::ConversionStatus convert( QCString const & from, QCString const & to ); + + + private: + + class OpenCalcPoint + { + public: + OpenCalcPoint( QString const & str ); + + QString table; + QString translation; + QPoint topLeft; + QPoint botRight; + bool isRange; + }; + + enum bPos { Left, Top, Right, Bottom, Fall, GoUp, Border }; + + KSpread::Doc * m_doc; + KSpread::Format * m_defaultLayout; + + QDomDocument m_content; + QDomDocument m_meta; + QDomDocument m_settings; + + QDict<QDomElement> m_styles; + QDict<KSpread::Format> m_defaultStyles; + QDict<QString> m_formats; + QMap<QString,QDomElement> m_validationList; + + QStringList m_namedAreas; + + int readMetaData(); + bool parseBody( int numOfTables ); + void insertStyles( QDomElement const & element ); + bool createStyleMap( QDomDocument const & styles ); + bool readRowFormat( QDomElement & rowNode, QDomElement * rowStyle, + KSpread::Sheet * table, int & row, int & number, bool last ); + bool readColLayouts( QDomElement & content, KSpread::Sheet * table ); + bool readRowsAndCells( QDomElement & content, KSpread::Sheet * table ); + bool readCells( QDomElement & rowNode, KSpread::Sheet * table, int row, int & columns ); + void convertFormula( QString & text, QString const & f ) const; + void loadFontStyle( KSpread::Format * layout, QDomElement const * font ) const; + void readInStyle( KSpread::Format * layout, QDomElement const & style ); + void loadStyleProperties( KSpread::Format * layout, QDomElement const & property ) const; + void loadBorder( KSpread::Format * layout, QString const & borderDef, bPos pos ) const; + void loadTableMasterStyle( KSpread::Sheet * table, QString const & stylename ); + QString * loadFormat( QDomElement * element, + KSpread::FormatType & formatType, + QString name ); + void checkForNamedAreas( QString & formula ) const; + void loadOasisCellValidation( const QDomElement&body ); + void loadOasisValidation( KSpread::Validity* val, const QString& validationName ); + void loadOasisValidationCondition( KSpread::Validity* val,QString &valExpression ); + void loadOasisAreaName( const QDomElement&body ); + void loadOasisMasterLayoutPage( KSpread::Sheet * table,KoStyleStack &styleStack ); + void loadOasisValidationValue( KSpread::Validity* val, const QStringList &listVal ); + QString translatePar( QString & par ) const; + void loadCondition( KSpread::Cell*cell,const QDomElement &property ); + void loadOasisCondition(KSpread::Cell*cell,const QDomElement &property ); + void loadOasisConditionValue( const QString &styleCondition, KSpread::Conditional &newCondition ); + void loadOasisCondition( QString &valExpression, KSpread::Conditional &newCondition ); + void loadOasisValidationValue( const QStringList &listVal, KSpread::Conditional &newCondition ); + KoFilter::ConversionStatus loadAndParse( QDomDocument& doc, const QString& fileName,KoStore *m_store ); + + KoFilter::ConversionStatus openFile(); +}; + +#endif // OpenCalc_IMPORT_H__ + diff --git a/filters/kspread/opencalc/opencalcstyleexport.cc b/filters/kspread/opencalc/opencalcstyleexport.cc new file mode 100644 index 000000000..34d574beb --- /dev/null +++ b/filters/kspread/opencalc/opencalcstyleexport.cc @@ -0,0 +1,546 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres <nandres@web.de> + + 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. +*/ + +#include <opencalcstyleexport.h> + +#include <KoGlobal.h> + +#include <kspread_cell.h> +#include <kspread_doc.h> +#include <kspread_format.h> +#include <kspread_sheet.h> +#include <kspread_style.h> +#include <kspread_style_manager.h> + +#include <qdom.h> + +using namespace KSpread; + +OpenCalcStyles::OpenCalcStyles() +{ + m_cellStyles.setAutoDelete( true ); + m_columnStyles.setAutoDelete( true ); + m_numberStyles.setAutoDelete( true ); + m_rowStyles.setAutoDelete( true ); + m_sheetStyles.setAutoDelete( true ); + + m_fontList.setAutoDelete( true ); +} + +OpenCalcStyles::~OpenCalcStyles() +{ +} + +void OpenCalcStyles::writeStyles( QDomDocument & doc, QDomElement & autoStyles ) +{ + addColumnStyles( doc, autoStyles ); + addRowStyles( doc, autoStyles ); + addSheetStyles( doc, autoStyles ); + addNumberStyles( doc, autoStyles ); + addCellStyles( doc, autoStyles ); +} + +void OpenCalcStyles::writeFontDecl( QDomDocument & doc, QDomElement & fontDecls ) +{ + QFont * f = m_fontList.first(); + while ( f ) + { + QDomElement fontDecl = doc.createElement( "style:font-decl" ); + + fontDecl.setAttribute( "style:name", f->family() ); + fontDecl.setAttribute( "fo:font-family", f->family() ); + fontDecl.setAttribute( "style:font-pitch", ( f->fixedPitch() ? "fixed" : "variable" ) ); + + // missing: + // style:font-charset="x-symbol" style:font-family-generic="swiss" + // style:font-style-name= "Bold/Standard/Regular" + + fontDecls.appendChild( fontDecl ); + + f = m_fontList.next(); + } +} + +void OpenCalcStyles::addFont( QFont const & font, bool def ) +{ + if ( def ) + m_defaultFont = font; + + QFont * f = m_fontList.first(); + while ( f ) + { + if ( f->family() == font.family() ) + return; + + f = m_fontList.next(); + } + + f = new QFont( font ); + m_fontList.append( f ); +} + +QString OpenCalcStyles::cellStyle( CellStyle const & cs ) +{ + CellStyle * t = m_cellStyles.first(); + while ( t ) + { + if ( CellStyle::isEqual( t, cs ) ) + return t->name; + + t = m_cellStyles.next(); + } + + t = new CellStyle(); + t->copyData( cs ); + + m_cellStyles.append( t ); + + t->name = QString( "ce%1" ).arg( m_cellStyles.count() ); + + return t->name; +} + +QString OpenCalcStyles::columnStyle( ColumnStyle const & cs ) +{ + ColumnStyle * t = m_columnStyles.first(); + while ( t ) + { + if ( ColumnStyle::isEqual( t, cs ) ) + return t->name; + + t = m_columnStyles.next(); + } + + t = new ColumnStyle(); + t->copyData( cs ); + + m_columnStyles.append( t ); + + t->name = QString( "co%1" ).arg( m_columnStyles.count() ); + + return t->name; +} + +QString OpenCalcStyles::numberStyle( NumberStyle const & ) +{ + return ""; +} + +QString OpenCalcStyles::rowStyle( RowStyle const & rs ) +{ + RowStyle * t = m_rowStyles.first(); + while ( t ) + { + if ( RowStyle::isEqual( t, rs ) ) + return t->name; + + t = m_rowStyles.next(); + } + + t = new RowStyle(); + t->copyData( rs ); + + m_rowStyles.append( t ); + + t->name = QString( "ro%1" ).arg( m_rowStyles.count() ); + + return t->name; +} + +QString OpenCalcStyles::sheetStyle( SheetStyle const & ts ) +{ + SheetStyle * t = m_sheetStyles.first(); + while ( t ) + { + if ( SheetStyle::isEqual( t, ts ) ) + return t->name; + + t = m_sheetStyles.next(); + } + + t = new SheetStyle(); + t->copyData( ts ); + + m_sheetStyles.append( t ); + + t->name = QString( "ta%1" ).arg( m_sheetStyles.count() ); + + return t->name; +} + +QString convertPenToString( QPen const & pen ) +{ + QString s( QString( "%1cm solid " ).arg( pen.width() * 0.035 ) ); + s += pen.color().name(); + + return s; +} + +void OpenCalcStyles::addCellStyles( QDomDocument & doc, QDomElement & autoStyles ) +{ + CellStyle * t = m_cellStyles.first(); + while ( t ) + { + QDomElement ts = doc.createElement( "style:style" ); + ts.setAttribute( "style:name", t->name ); + ts.setAttribute( "style:family", "table-cell" ); + ts.setAttribute( "style:parent-style-name", "Default" ); + if ( t->numberStyle.length() > 0 ) + ts.setAttribute( "style:data-style-name", t->numberStyle ); + + QDomElement prop = doc.createElement( "style:properties" ); + + if ( t->font.family() != m_defaultFont.family() ) + prop.setAttribute( "style:font-name", t->font.family() ); + + if ( t->font.bold() != m_defaultFont.bold() ) + prop.setAttribute( "fo:font-weight", ( t->font.bold() ? "bold" : "light" ) ); + + prop.setAttribute( "fo:font-size", QString( "%1pt" ).arg( t->font.pointSize() ) ); + + if ( t->font.underline() != m_defaultFont.underline() ) + { + prop.setAttribute( "style:text-underline", ( t->font.underline() ? "single" : "none" ) ); + if ( t->font.underline() ) + prop.setAttribute( "style:text-underline-color", "font-color" ); + } + + if ( t->font.italic() != m_defaultFont.italic() ) + prop.setAttribute( "fo:font-style", ( t->font.italic() ? "italic" : "none" ) ); + + if ( t->font.strikeOut() != m_defaultFont.strikeOut() ) + prop.setAttribute( "style:text-crossing-out", ( t->font.strikeOut() ? "single-line" : "none" ) ); + + if ( t->color.name() != "#000000" ) + prop.setAttribute( "fo:color", t->color.name() ); + + if ( t->bgColor.name() != "#ffffff" ) + prop.setAttribute( "fo:background-color", t->bgColor.name() ); + + if ( t->alignX != Format::Undefined ) + { + QString value; + if ( t->alignX == Format::Center ) + value = "center"; + else if ( t->alignX == Format::Right ) + value = "end"; + else if ( t->alignX == Format::Left ) + value = "start"; + prop.setAttribute( "fo:text-align", value ); + } + + if ( t->alignY != Format::Bottom ) // default in OpenCalc + prop.setAttribute( "fo:vertical-align", ( t->alignY == Format::Middle ? "middle" : "top" ) ); + + if ( t->indent > 0.0 ) + { + prop.setAttribute( "fo:margin-left", QString( "%1pt" ).arg( t->indent ) ); + if ( t->alignX == Format::Undefined ) + prop.setAttribute( "fo:text-align", "start" ); + } + + if ( t->wrap ) + prop.setAttribute( "fo:wrap-option", "wrap" ); + + if ( t->vertical ) + { + prop.setAttribute( "fo:direction", "ttb" ); + prop.setAttribute( "style:rotation-angle", "0" ); + } + + if ( t->angle != 0 ) + prop.setAttribute( "style:rotation-angle", QString::number( t->angle ) ); + + if ( !t->print ) + prop.setAttribute( "style:print-content", "false" ); + + if ( t->hideAll ) + prop.setAttribute( "style:cell-protect", "hidden-and-protected" ); + else + if ( t->notProtected && !t->hideFormula ) + prop.setAttribute( "style:cell-protect", "none" ); + else + if ( t->notProtected && t->hideFormula ) + prop.setAttribute( "style:cell-protect", "formula-hidden" ); + else if ( t->hideFormula ) + prop.setAttribute( "style:cell-protect", "protected formula-hidden" ); + else if ( !t->notProtected ) + prop.setAttribute( "style:cell-protect", "protected" ); + + + if ( ( t->left == t->right ) && ( t->left == t->top ) && ( t->left == t->bottom ) ) + { + if ( ( t->left.width() != 0 ) && ( t->left.style() != Qt::NoPen ) ) + prop.setAttribute( "fo:border", convertPenToString( t->left ) ); + } + else + { + if ( ( t->left.width() != 0 ) && ( t->left.style() != Qt::NoPen ) ) + prop.setAttribute( "fo:border-left", convertPenToString( t->left ) ); + + if ( ( t->right.width() != 0 ) && ( t->right.style() != Qt::NoPen ) ) + prop.setAttribute( "fo:border-right", convertPenToString( t->right ) ); + + if ( ( t->top.width() != 0 ) && ( t->top.style() != Qt::NoPen ) ) + prop.setAttribute( "fo:border-top", convertPenToString( t->top ) ); + + if ( ( t->bottom.width() != 0 ) && ( t->bottom.style() != Qt::NoPen ) ) + prop.setAttribute( "fo:border-bottom", convertPenToString( t->bottom ) ); + } + + ts.appendChild( prop ); + autoStyles.appendChild( ts ); + + t = m_cellStyles.next(); + } +} + +void OpenCalcStyles::addColumnStyles( QDomDocument & doc, QDomElement & autoStyles ) +{ + ColumnStyle * t = m_columnStyles.first(); + while ( t ) + { + QDomElement ts = doc.createElement( "style:style" ); + ts.setAttribute( "style:name", t->name ); + ts.setAttribute( "style:family", "table-column" ); + + QDomElement prop = doc.createElement( "style:properties" ); + if ( t->breakB != ::Style::none ) + prop.setAttribute( "fo:break-before", ( t->breakB == ::Style::automatic ? "auto" : "page" ) ); + prop.setAttribute( "style:column-width", QString( "%1cm" ).arg( t->size ) ); + + ts.appendChild( prop ); + autoStyles.appendChild( ts ); + + t = m_columnStyles.next(); + } +} + +void OpenCalcStyles::addNumberStyles( QDomDocument & /*doc*/, QDomElement & /*autoStyles*/ ) +{ +} + +void OpenCalcStyles::addRowStyles( QDomDocument & doc, QDomElement & autoStyles ) +{ + RowStyle * t = m_rowStyles.first(); + while ( t ) + { + QDomElement ts = doc.createElement( "style:style" ); + ts.setAttribute( "style:name", t->name ); + ts.setAttribute( "style:family", "table-row" ); + + QDomElement prop = doc.createElement( "style:properties" ); + prop.setAttribute( "style:row-height", QString( "%1cm" ).arg( t->size ) ); + if ( t->breakB != ::Style::none ) + prop.setAttribute( "fo:break-before", ( t->breakB == ::Style::automatic ? "auto" : "page" ) ); + + ts.appendChild( prop ); + autoStyles.appendChild( ts ); + + t = m_rowStyles.next(); + } +} + +void OpenCalcStyles::addSheetStyles( QDomDocument & doc, QDomElement & autoStyles ) +{ + SheetStyle * t = m_sheetStyles.first(); + while ( t ) + { + QDomElement ts = doc.createElement( "style:style" ); + ts.setAttribute( "style:name", t->name ); + ts.setAttribute( "style:family", "table" ); + ts.setAttribute( "style:master-page-name", "Default" ); + + QDomElement prop = doc.createElement( "style:properties" ); + prop.setAttribute( "table:display", ( t->visible ? "true" : "false" ) ); + + ts.appendChild( prop ); + autoStyles.appendChild( ts ); + + t = m_sheetStyles.next(); + } +} + +bool SheetStyle::isEqual( SheetStyle const * const t1, SheetStyle const & t2 ) +{ + if ( t1->visible == t2.visible ) + return true; + + return false; +} + +CellStyle::CellStyle() + : color( Qt::black ), + bgColor( Qt::white ), + indent( -1.0 ), + wrap( false ), + vertical( false ), + angle( 0 ), + print( true ), + left ( Qt::black, 0, Qt::NoPen ), + right( Qt::black, 0, Qt::NoPen ), + top ( Qt::black, 0, Qt::NoPen ), + bottom( Qt::black, 0, Qt::NoPen ), + hideAll( false ), + hideFormula( false ), + notProtected ( false ), + alignX( Format::Undefined ), + alignY( Format::Middle ) +{ +} + +void CellStyle::copyData( CellStyle const & ts ) +{ + font = ts.font; + numberStyle = ts.numberStyle; + color = ts.color; + bgColor = ts.bgColor; + indent = ts.indent; + wrap = ts.wrap; + vertical = ts.vertical; + angle = ts.angle; + print = ts.print; + left = ts.left; + right = ts.right; + top = ts.top; + bottom = ts.bottom; + hideAll = ts.hideAll; + hideFormula = ts.hideFormula; + notProtected = ts.notProtected; + alignX = ts.alignX; + alignY = ts.alignY; +} + +bool CellStyle::isEqual( CellStyle const * const t1, CellStyle const & t2 ) +{ + if ( ( t1->font == t2.font ) && ( t1->numberStyle == t2.numberStyle ) + && ( t1->color == t2.color ) && ( t1->bgColor == t2.bgColor ) + && ( t1->alignX == t2.alignX ) && ( t1->alignY == t2.alignY ) + && ( t1->indent == t2.indent ) && ( t1->wrap == t2.wrap ) + && ( t1->vertical == t2.vertical ) && ( t1->angle == t2.angle ) + && ( t1->print == t2.print ) && ( t1->left == t2.left ) + && ( t1->right == t2.right ) && ( t1->top == t2.top ) + && ( t1->bottom == t2.bottom ) && ( t1->hideAll == t2.hideAll ) + && ( t1->hideFormula == t2.hideFormula ) && ( t1->notProtected == t2.notProtected ) + ) + return true; + + return false; +} + +// all except the number style +void CellStyle::loadData( CellStyle & cs, Cell const * const cell ) +{ + int col = cell->column(); + int row = cell->row(); + + Format * f = new Format( 0, cell->sheet()->doc()->styleManager()->defaultStyle() ); + + QFont font = cell->format()->textFont( col, row ); + if ( font != f->font() ) + cs.font = font; + + QColor color = cell->format()->textColor( col, row ); + if ( color != f->textColor( col, row ) ) + cs.color = color; + + QColor bgColor = cell->bgColor( col, row ); + if ( bgColor != f->bgColor( col, row ) ) + cs.bgColor = bgColor; + + if ( cell->format()->hasProperty( Format::PAlign ) || !cell->format()->hasNoFallBackProperties( Format::PAlign ) ) + cs.alignX = cell->format()->align( col, row ); + + if ( cell->format()->hasProperty( Format::PAlignY ) || !cell->format()->hasNoFallBackProperties( Format::PAlignY ) ) + cs.alignY = cell->format()->alignY( col, row ); + + if ( cell->format()->hasProperty( Format::PIndent ) || !cell->format()->hasNoFallBackProperties( Format::PIndent ) ) + cs.indent = cell->format()->getIndent( col, row ); + + if ( cell->format()->hasProperty( Format::PAngle ) || !cell->format()->hasNoFallBackProperties( Format::PAngle ) ) + cs.angle = -cell->format()->getAngle( col, row ); + + if ( cell->format()->hasProperty( Format::PMultiRow ) || !cell->format()->hasNoFallBackProperties( Format::PMultiRow ) ) + cs.wrap = cell->format()->multiRow( col, row ); + + if ( cell->format()->hasProperty( Format::PVerticalText ) + || !cell->format()->hasNoFallBackProperties( Format::PVerticalText ) ) + cs.vertical = cell->format()->verticalText( col, row ); + + if ( cell->format()->hasProperty( Format::PDontPrintText ) + || !cell->format()->hasNoFallBackProperties( Format::PDontPrintText ) ) + cs.print = !cell->format()->getDontprintText( col, row ); + + if ( cell->format()->hasProperty( Format::PLeftBorder ) || !cell->format()->hasNoFallBackProperties( Format::PLeftBorder ) ) + cs.left = cell->leftBorderPen( col, row ); + + if ( cell->format()->hasProperty( Format::PRightBorder ) || !cell->format()->hasNoFallBackProperties( Format::PRightBorder ) ) + cs.right = cell->rightBorderPen( col, row ); + + if ( cell->format()->hasProperty( Format::PTopBorder ) || !cell->format()->hasNoFallBackProperties( Format::PTopBorder ) ) + cs.top = cell->topBorderPen( col, row ); + + if ( cell->format()->hasProperty( Format::PBottomBorder ) || !cell->format()->hasNoFallBackProperties( Format::PBottomBorder ) ) + cs.bottom = cell->bottomBorderPen( col, row ); + + if ( cell->format()->hasProperty( Format::PNotProtected ) || !cell->format()->hasNoFallBackProperties( Format::PNotProtected ) ) + cs.notProtected = cell->format()->notProtected( col, row ); + + if ( cell->format()->hasProperty( Format::PHideAll ) || !cell->format()->hasNoFallBackProperties( Format::PHideAll ) ) + cs.hideAll = cell->format()->isHideAll( col, row ); + + if ( cell->format()->hasProperty( Format::PHideFormula ) || !cell->format()->hasNoFallBackProperties( Format::PHideFormula ) ) + cs.hideFormula = cell->format()->isHideFormula( col, row ); +} + +bool NumberStyle::isEqual( NumberStyle const * const t1, NumberStyle const & t2 ) +{ + if ( ( t1->type == t2.type ) && ( t1->pattern == t2.pattern ) ) + return true; + + return false; +} + +void ColumnStyle::copyData( ColumnStyle const & cs ) +{ + breakB = cs.breakB; + size = cs.size; +} + +bool ColumnStyle::isEqual( ColumnStyle const * const c1, ColumnStyle const & c2 ) +{ + if ( ( c1->breakB == c2.breakB ) && ( c1->size == c2.size ) ) + return true; + + return false; +} + +void RowStyle::copyData( RowStyle const & cs ) +{ + breakB = cs.breakB; + size = cs.size; +} + +bool RowStyle::isEqual( RowStyle const * const c1, RowStyle const & c2 ) +{ + if ( ( c1->breakB == c2.breakB ) && ( c1->size == c2.size ) ) + return true; + + return false; +} diff --git a/filters/kspread/opencalc/opencalcstyleexport.h b/filters/kspread/opencalc/opencalcstyleexport.h new file mode 100644 index 000000000..2321b5290 --- /dev/null +++ b/filters/kspread/opencalc/opencalcstyleexport.h @@ -0,0 +1,167 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Norbert Andres <nandres@web.de> + + 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. +*/ + + +#ifndef OPENCALCSTYLEEXPORT_H +#define OPENCALCSTYLEEXPORT_H + +#include "kspread_format.h" + +#include <qcolor.h> +#include <qfont.h> +#include <qptrlist.h> +#include <qstring.h> + +namespace KSpread +{ + class Cell; +} + +class QDomDocument; +class QDomElement; + +typedef enum T1 { Boolean, Date, Number, Percentage, Time } NumberType; + +class Style +{ + public: + enum breakBefore { none, automatic, page }; + + Style() : breakB( none ), size( 0.0 ) {} + + QString name; + uint breakB; + double size; +}; + +class SheetStyle +{ + public: + SheetStyle() : visible( true ) {} + + void copyData( SheetStyle const & ts ) { visible = ts.visible; } + static bool isEqual( SheetStyle const * const t1, SheetStyle const & t2 ); + + QString name; + bool visible; +}; + +class NumberStyle +{ + public: + NumberStyle() {} + + void copyData( NumberStyle const & ts ) { type = ts.type; } + static bool isEqual( NumberStyle const * const t1, NumberStyle const & t2 ); + + QString name; + + NumberType type; + QString pattern; +}; + +class CellStyle +{ + public: + CellStyle(); + + void copyData( CellStyle const & ts ); + static bool isEqual( CellStyle const * const t1, CellStyle const & t2 ); + + // all except the number style + static void loadData( CellStyle & cs, KSpread::Cell const * const cell ); + + QString name; + + QFont font; + QString numberStyle; + QColor color; + QColor bgColor; + double indent; + bool wrap; + bool vertical; + int angle; + bool print; + QPen left; + QPen right; + QPen top; + QPen bottom; + bool hideAll; + bool hideFormula; + bool notProtected; + + KSpread::Format::Align alignX; + KSpread::Format::AlignY alignY; +}; + +class ColumnStyle : public Style +{ + public: + ColumnStyle() : Style() {} + + void copyData( ColumnStyle const & cs ); + static bool isEqual( ColumnStyle const * const c1, ColumnStyle const & c2 ); +}; + +class RowStyle : public Style +{ + public: + RowStyle() : Style() {} + + void copyData( RowStyle const & cs ); + static bool isEqual( RowStyle const * const c1, RowStyle const & c2 ); +}; + +class OpenCalcStyles +{ + public: + OpenCalcStyles(); + ~OpenCalcStyles(); + + void writeStyles ( QDomDocument & doc, QDomElement & autoStyles ); + void writeFontDecl( QDomDocument & doc, QDomElement & content ); + + void addFont( QFont const & font, bool def = false ); + + QString cellStyle( CellStyle const & cs ); + QString columnStyle( ColumnStyle const & cs ); + QString numberStyle( NumberStyle const & ns ); + QString rowStyle( RowStyle const & rs ); + QString sheetStyle( SheetStyle const & ts ); + + private: + QPtrList<CellStyle> m_cellStyles; + QPtrList<ColumnStyle> m_columnStyles; + QPtrList<NumberStyle> m_numberStyles; + QPtrList<RowStyle> m_rowStyles; + QPtrList<SheetStyle> m_sheetStyles; + QPtrList<QFont> m_fontList; + + QFont m_defaultFont; + + void addCellStyles( QDomDocument & doc, QDomElement & autoStyles ); + void addColumnStyles( QDomDocument & doc, QDomElement & autoStyles ); + void addNumberStyles( QDomDocument & doc, QDomElement & autoStyles ); + void addRowStyles( QDomDocument & doc, QDomElement & autoStyles ); + void addSheetStyles( QDomDocument & doc, QDomElement & autoStyles ); +}; + + + +#endif diff --git a/filters/kspread/opencalc/status.html b/filters/kspread/opencalc/status.html new file mode 100644 index 000000000..b23f6ae90 --- /dev/null +++ b/filters/kspread/opencalc/status.html @@ -0,0 +1,208 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>KOffice filters status: OpenOffice.org Calc filter</title> +</head> +<body text="#000000" bgcolor="#FFFFFF" link="#000099" vlink="#666666" alink="#666666"> +<a NAME="START"></a> +<center> +<h1> +KOffice filters status: OpenOffice.org Calc</h1></center> + +<hr NOSHADE SIZE=2 WIDTH="70%"><b><font size="-1"><a href="#import">Import</a> +| <a href="#export">Export</a></font></b> +<br> +<br> +<br> +<br> +<center> +<p><a NAME="import"></a></center> +<b><font size="-1"><a href="#START">Up</a></font></b> +<center><table BORDER=0 CELLSPACING=0 WIDTH="100%" BGCOLOR="#000000" > +<tr> +<td> +<table BORDER=0 CELLPADDING=2 WIDTH="100%" BGCOLOR="#FFFFFF" > +<tr BGCOLOR="#DDFFDD"> +<td COLSPAN="2"> +<center><b><i><font size="+1">Import OpenOffice.org Calc for Kspread</font></i></b></center> +</td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP NOWRAP WIDTH="1%"><b><font size="+1">Last update</font></b></td> + +<td>April 22, 2004</td> +</tr> + +<tr BGCOLOR="#CCCCFF"> +<td VALIGN=TOP><b><font size="+1">Features</font></b></td> + <td> + Loading tables, hidden tables, print ranges<br> + Named areas<br> + hidden columns<br> + hidden rows<br> + Comments<br> + Formulas<br> + Links (e-mail, files, web)<br> + cell content<br> + Datatypes: float, percentage, (date), times, booleans (miss some kspread support) <br> + Formating: indents, bold, italic, alignments, colors...<br> + Borders, background colors<br> + column width, row width<br> + column layouts, row layouts<br> + page layout (size, border)<br> + OpenCalc style import, default style<br> + format string translating (not supported by KSpread yet, but this filter produces these strings => needs enhancements in KSpread)<br> + header, footer (including macros)<br> + protected maps, tables, unprotected cells, hidden cells, hidden formulas<br> + validation<br> + not printed cells + </td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP><b><font size="+1">Todo</font></b></td> +<td> + Page breaks (for Columns & Rows)(not supported by KSpread)<br> + leading zeros (not supported by KSpread)<br> + embedded objects (Charts!)<br> + conditional cell attributes<br> + real format string usage(KSpread feature not implemented yet - as soon as it exists this filter will benefit automatically) + check Table names in "'", like 'This is my name'<br> + Settings<br> +</td> +</tr> + +<tr BGCOLOR="#CCCCFF"> +<td VALIGN=TOP><b><font size="+1">History</font></b></td> + +<td> + Sep 26, 2002 - Initial Revision<br> +</td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP><b><font size="+1">Authors</font></b></td> +<td> + <a href="mailto:nandres@web.de">Norbert Andres</a> +</td> +</tr> + +<tr BGCOLOR="#CCCCFF"> +<td VALIGN=TOP><b><font size="+1">Links</font></b></td> +<td><a href="http://xml.openoffice.org">OpenOffice.org XML Web Site</a></td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP><b><font size="+1">Progress report </font></b></td> +<td></td> +</tr> +</table> +</td> +</tr> +</table></center> +<b><font size="-1"><a href="#START">Up</a></font></b> +<br> +<p> +<hr NOSHADE SIZE=1> +<br> +<br> +<br> +<br> +<center> +<p><a NAME="export"></a></center> +<b><font size="-1"><a href="#START">Up</a></font></b> +<center><table BORDER=0 CELLSPACING=0 WIDTH="100%" BGCOLOR="#000000" > +<tr> +<td> +<table BORDER=0 CELLPADDING=2 WIDTH="100%" BGCOLOR="#FFFFFF" > +<tr BGCOLOR="#FFDDDD"> +<td COLSPAN="2"> +<center><b><i><font size="+1">Export Kspread to OpenOffice.org Calc</font></i></b></center> +</td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP NOWRAP WIDTH="1%"><b><font size="+1">Last update</font></b></td> + +<td>Octo 20, 2004</td> +</tr> + +<tr BGCOLOR="#CCCCFF"> +<td VALIGN=TOP><b><font size="+1">Features</font></b></td> +<td> + Saves sheets (supported: hidden sheets, names)<br> + Saves columns and row (supported: widths/heights, page breaks, hidden)<br> + Saves cell contents (including formula conversion)<br> + Document information<br> + Page sizes, header and footer (including variable converting)<br> + Font (sizes, attributes, color)<br> + Background color<br> + Text alignment, angle, vertical text, text wrap and indents<br> + Merged Cells<br> + DontPrint flag<br> + Comments<br> + Named Areas<br> + Cell borders<br> + Link<br> + protected maps, tables, unprotected cells, hidden cells, hidden formulas<br> + not printed cells<br> + Print ranges<br> + Export document settings (active table, cursor position)<br> + Settings<br> + Validation<br> +</td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP><b><font size="+1">Todo</font></b></td> +<td> + Number formats (needs some new features in KSpread)<br> + Embedded objects (charts,...)<br> + Conditions<br> +</td> +</tr> + +<tr BGCOLOR="#CCCCFF"> +<td VALIGN=TOP><b><font size="+1">History</font></b></td> + +<td> + Jan 12, 2003 - Initial Revision<br> + Jan 18, 2003 - page layout, header, footer<br> + Jan 19, 2003 - Added support for fonts, text color, background color, formula +conversion<br> + Jan 19, 2003 - text alignment, indents, comments, NoPrint, Merged Cells<br> + Jan 19, 2003 - angle, vertical text, text wrap<br> + Jan 19, 2003 - named area, hidden columns and rows<br> + Jan 20, 2003 - cell borders<br> + Jan 29, 2003 - protected stuff<br> + Mar 13, 2005 - link<br> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP><b><font size="+1">Authors</font></b></td> + +<td> + <a href="mailto:nandres@web.de">Norbert Andres</a> +</td> +</tr> + +<tr BGCOLOR="#CCCCFF"> +<td VALIGN=TOP><b><font size="+1">Links</font></b></td> + +<td><a href="http://xml.openoffice.org">OpenOffice.org XML Web Site</a></td> +</tr> + +<tr BGCOLOR="#EEEEFF"> +<td VALIGN=TOP><b><font size="+1">Progress report</font></b></td> +<td></td> +</tr> +</table> +</td> +</tr> +</table></center> +<b><font size="-1"><a href="#START">Up</a></font></b> + +</body> +</html> |
