diff --git a/filters/sheets/excel/import/ExcelImport.cpp b/filters/sheets/excel/import/ExcelImport.cpp index e73d6ab73b1..6828a9aaf27 100644 --- a/filters/sheets/excel/import/ExcelImport.cpp +++ b/filters/sheets/excel/import/ExcelImport.cpp @@ -1,1443 +1,1443 @@ /* This file is part of the KDE project Copyright (C) 2003-2006 Ariya Hidayat Copyright (C) 2006 Marijn Kruisselbrink Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). Contact: Manikandaprasad Chandrasekar Copyright (c) 2010 Carlos Licea 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 "ExcelImport.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swinder.h" #include "objects.h" #include "ODrawClient.h" #include "ImportUtils.h" #include "conditionals.h" // Enable this definition to make the filter output to an ods file instead of // using m_chain.outputDocument() to write the spreadsheet to. //#define OUTPUT_AS_ODS_FILE K_PLUGIN_FACTORY_WITH_JSON(ExcelImportFactory, "calligra_filter_xls2ods.json", registerPlugin();) static const qreal SIDEWINDERPROGRESS = 40.0; static const qreal ODFPROGRESS = 40.0; static const qreal EMBEDDEDPROGRESS = 15.0; using namespace Swinder; using namespace XlsUtils; static qreal offset( unsigned long dimension, unsigned long offset, qreal factor ) { return (float)dimension * (float)offset / factor; } static qreal columnWidth(Sheet* sheet, unsigned long col) { if( sheet->column(col, false) ) return sheet->column(col)->width(); return sheet->defaultColWidth(); } static qreal rowHeight(Sheet* sheet, unsigned long row) { if( sheet->row(row, false) ) return sheet->row(row)->height(); return sheet->defaultRowHeight(); } class ExcelImport::Private { public: Private(ExcelImport *q) : q(q) { } QString inputFile; Calligra::Sheets::DocBase* outputDoc; Workbook *workbook; // for embedded shapes KoStore* storeout; KoGenStyles *shapeStyles; KoGenStyles *dataStyles; KoXmlWriter *shapesXml; void processMetaData(); void processSheet(Sheet* isheet, Calligra::Sheets::Sheet* osheet); void processSheetForHeaderFooter(Sheet* isheet, Calligra::Sheets::Sheet* osheet); void processSheetForFilters(Sheet* isheet, Calligra::Sheets::Sheet* osheet); void processSheetForConditionals(Sheet* isheet, Calligra::Sheets::Sheet* osheet); void processColumn(Sheet* isheet, unsigned column, Calligra::Sheets::Sheet* osheet); void processRow(Sheet* isheet, unsigned row, Calligra::Sheets::Sheet* osheet); void processCell(Cell* icell, Calligra::Sheets::Cell ocell); void processCellObjects(Cell* icell, Calligra::Sheets::Cell ocell); void processEmbeddedObjects(const KoXmlElement& rootElement, KoStore* store); void processNumberFormats(); QString convertHeaderFooter(const QString& xlsHeader); int convertStyle(const Format* format, const QString& formula = QString()); QHash styleCache; QList styleList; QHash dataStyleCache; QHash dataStyleConditions; void processFontFormat(const FormatFont& font, Calligra::Sheets::Style& style); QTextCharFormat convertFontToCharFormat(const FormatFont& font); QPen convertBorder(const Pen& pen); int rowsCountTotal, rowsCountDone; void addProgress(int addValue); QHash cellStyles; QHash rowStyles; QHash columnStyles; QList > cellConditions; QList charts; void processCharts(KoXmlWriter* manifestWriter); void addManifestEntries(KoXmlWriter* ManifestWriter); void insertPictureManifest(const QString& fileName); QMap manifestEntries; KoXmlWriter* beginMemoryXmlWriter(const char* docElement); KoXmlDocument endMemoryXmlWriter(KoXmlWriter* writer); QDateTime convertDate(double timestamp) const; ExcelImport *q; }; ExcelImport::ExcelImport(QObject* parent, const QVariantList&) : KoFilter(parent) { d = new Private(this); d->storeout = 0; } ExcelImport::~ExcelImport() { delete d->storeout; delete d; } KoFilter::ConversionStatus ExcelImport::convert(const QByteArray& from, const QByteArray& to) { if (from != "application/vnd.ms-excel") return KoFilter::NotImplemented; if (to != "application/vnd.oasis.opendocument.spreadsheet") return KoFilter::NotImplemented; d->inputFile = m_chain->inputFile(); #ifndef OUTPUT_AS_ODS_FILE KoDocument* document = m_chain->outputDocument(); if (!document) return KoFilter::StupidError; d->outputDoc = qobject_cast(document); if (!d->outputDoc) { kWarning() << "document isn't a Calligra::Sheets::Doc but a " << document->metaObject()->className(); return KoFilter::WrongFormat; } #else d->outputDoc = new Calligra::Sheets::DocBase(); #endif d->outputDoc->setOutputMimeType(to); emit sigProgress(0); QBuffer storeBuffer; // TODO: use temporary file instead delete d->storeout; d->storeout = KoStore::createStore(&storeBuffer, KoStore::Write); // open inputFile d->workbook = new Swinder::Workbook(d->storeout); connect(d->workbook, SIGNAL(sigProgress(int)), this, SLOT(slotSigProgress(int))); if (!d->workbook->load(d->inputFile.toLocal8Bit())) { delete d->workbook; d->workbook = 0; delete d->storeout; d->storeout = 0; return KoFilter::InvalidFormat; } if (d->workbook->isPasswordProtected()) { delete d->workbook; d->workbook = 0; delete d->storeout; d->storeout = 0; return KoFilter::PasswordProtected; } emit sigProgress(-1); emit sigProgress(0); // count the number of rows in total to provide a good progress value d->rowsCountTotal = d->rowsCountDone = 0; for (unsigned i = 0; i < d->workbook->sheetCount(); ++i) { Sheet* sheet = d->workbook->sheet(i); d->rowsCountTotal += qMin(maximalRowCount, sheet->maxRow()); } d->shapeStyles = new KoGenStyles(); d->dataStyles = new KoGenStyles(); // convert number formats d->processNumberFormats(); d->processMetaData(); d->shapesXml = d->beginMemoryXmlWriter("table:shapes"); Calligra::Sheets::Map* map = d->outputDoc->map(); for (unsigned i = 0; i < d->workbook->sheetCount(); ++i) { d->shapesXml->startElement("table:table"); d->shapesXml->addAttribute("table:id", i); Sheet* sheet = d->workbook->sheet(i); if (i == 0) { map->setDefaultColumnWidth(sheet->defaultColWidth()); map->setDefaultRowHeight(sheet->defaultRowHeight()); } Calligra::Sheets::Sheet* ksheet = map->addNewSheet(sheet->name()); d->processSheet(sheet, ksheet); d->shapesXml->endElement(); } // named expressions const std::map, QString>& namedAreas = d->workbook->namedAreas(); for (std::map, QString>::const_iterator it = namedAreas.begin(); it != namedAreas.end(); ++it) { QString range = it->second; if(range.startsWith(QLatin1Char('[')) && range.endsWith(QLatin1Char(']'))) { range.remove(0, 1).chop(1); } Calligra::Sheets::Region region(Calligra::Sheets::Region::loadOdf(range), d->outputDoc->map()); if (!region.isValid() || !region.lastSheet()) { kDebug() << "invalid area" << range; continue; } d->outputDoc->map()->namedAreaManager()->insert(region, it->first.second); } QBuffer manifestBuffer; KoXmlWriter manifestWriter(&manifestBuffer); manifestWriter.startDocument("manifest:manifest"); manifestWriter.startElement("manifest:manifest"); manifestWriter.addAttribute("xmlns:manifest", KoXmlNS::manifest); manifestWriter.addManifestEntry("/", "application/vnd.oasis.opendocument.spreadsheet"); d->processCharts(&manifestWriter); d->addManifestEntries(&manifestWriter); manifestWriter.endElement(); manifestWriter.endDocument(); if (d->storeout->open("META-INF/manifest.xml")) { d->storeout->write(manifestBuffer.buffer()); d->storeout->close(); } delete d->storeout; d->storeout = 0; storeBuffer.close(); KoStore *store = KoStore::createStore(&storeBuffer, KoStore::Read); // Debug odf for shapes #if 0 d->shapesXml->endElement(); d->shapesXml->endDocument(); d->shapesXml->device()->seek(0); QTextStream input(d->shapesXml->device()); qDebug() << "-- START SHAPES_XML -- size : " << d->shapesXml->device()->size(); qDebug() << input.readAll(); qDebug() << "-- SHAPES_XML --"; #endif KoXmlDocument xmlDoc = d->endMemoryXmlWriter(d->shapesXml); d->processEmbeddedObjects(xmlDoc.documentElement(), store); // sheet background images for (unsigned i = 0; i < d->workbook->sheetCount(); ++i) { Sheet* sheet = d->workbook->sheet(i); Calligra::Sheets::Sheet* ksheet = map->sheet(i); kDebug() << i << sheet->backgroundImage(); if (sheet->backgroundImage().isEmpty()) continue; QByteArray data; store->extractFile(sheet->backgroundImage(), data); QImage image = QImage::fromData(data); if (image.isNull()) continue; ksheet->setBackgroundImage(image); ksheet->setBackgroundImageProperties(Calligra::Sheets::Sheet::BackgroundImageProperties()); } #ifndef OUTPUT_AS_ODS_FILE d->outputDoc->map()->completeLoading(store); #endif delete store; // ensure at least one sheet if (d->outputDoc->map()->count() == 0) { d->outputDoc->map()->addNewSheet(); } // active sheet kDebug() << "ACTIVE " << d->workbook->activeTab(); d->outputDoc->map()->loadingInfo()->setInitialActiveSheet(d->outputDoc->map()->sheet(d->workbook->activeTab())); d->outputDoc->setModified(false); #ifdef OUTPUT_AS_ODS_FILE d->outputDoc->saveNativeFormat(m_chain->outputFile()); delete d->outputDoc; #endif delete d->workbook; delete d->shapeStyles; delete d->dataStyles; d->inputFile.clear(); d->outputDoc = 0; d->shapesXml = 0; emit sigProgress(100); return KoFilter::OK; } void ExcelImport::Private::processMetaData() { KoDocumentInfo* info = outputDoc->documentInfo(); if (workbook->hasProperty(Workbook::PIDSI_TITLE)) { info->setAboutInfo("title", workbook->property(Workbook::PIDSI_TITLE).toString()); } if (workbook->hasProperty(Workbook::PIDSI_SUBJECT)) { info->setAboutInfo("subject", workbook->property(Workbook::PIDSI_SUBJECT).toString()); } if (workbook->hasProperty(Workbook::PIDSI_AUTHOR)) { info->setAuthorInfo("creator", workbook->property(Workbook::PIDSI_AUTHOR).toString()); } if (workbook->hasProperty(Workbook::PIDSI_KEYWORDS)) { info->setAboutInfo("keyword", workbook->property(Workbook::PIDSI_KEYWORDS).toString()); } if (workbook->hasProperty(Workbook::PIDSI_COMMENTS)) { info->setAboutInfo("comments", workbook->property(Workbook::PIDSI_COMMENTS).toString()); } if (workbook->hasProperty(Workbook::PIDSI_REVNUMBER)) { info->setAboutInfo("editing-cycles", workbook->property(Workbook::PIDSI_REVNUMBER).toString()); } if (workbook->hasProperty(Workbook::PIDSI_LASTPRINTED_DTM)) { info->setAboutInfo("print-date", workbook->property(Workbook::PIDSI_LASTPRINTED_DTM).toString()); } if (workbook->hasProperty(Workbook::PIDSI_CREATE_DTM)) { info->setAboutInfo("creation-date", workbook->property(Workbook::PIDSI_CREATE_DTM).toString()); } if (workbook->hasProperty(Workbook::PIDSI_LASTSAVED_DTM)) { info->setAboutInfo("date", workbook->property(Workbook::PIDSI_LASTSAVED_DTM).toString()); } // template // lastauthor // edittime switch (workbook->version()) { case Workbook::Excel95: info->setOriginalGenerator("Calligra xls Filter/Excel 95"); break; case Workbook::Excel97: info->setOriginalGenerator("Calligra xls Filter/Excel 97"); break; case Workbook::Excel2000: info->setOriginalGenerator("Calligra xls Filter/Excel 2000"); break; case Workbook::Excel2002: info->setOriginalGenerator("Calligra xls Filter/Excel 2002"); break; case Workbook::Excel2003: info->setOriginalGenerator("Calligra xls Filter/Excel 2003"); break; case Workbook::Excel2007: info->setOriginalGenerator("Calligra xls Filter/Excel 2007"); break; case Workbook::Excel2010: info->setOriginalGenerator("Calligra xls Filter/Excel 2010"); break; default: info->setOriginalGenerator("Calligra xls Filter/Unknown"); } } void ExcelImport::Private::processEmbeddedObjects(const KoXmlElement& rootElement, KoStore* store) { // save styles to xml KoXmlWriter *stylesXml = beginMemoryXmlWriter("office:styles"); shapeStyles->saveOdfStyles(KoGenStyles::DocumentAutomaticStyles, stylesXml); KoXmlDocument stylesDoc = endMemoryXmlWriter(stylesXml); // Register additional attributes, that identify shapes anchored in cells. // Their dimensions need adjustment after all rows are loaded, // because the position of the end cell is not always known yet. KoShapeLoadingContext::addAdditionalAttributeData(KoShapeLoadingContext::AdditionalAttributeData( KoXmlNS::table, "end-cell-address", "table:end-cell-address")); KoShapeLoadingContext::addAdditionalAttributeData(KoShapeLoadingContext::AdditionalAttributeData( KoXmlNS::table, "end-x", "table:end-x")); KoShapeLoadingContext::addAdditionalAttributeData(KoShapeLoadingContext::AdditionalAttributeData( KoXmlNS::table, "end-y", "table:end-y")); KoOdfStylesReader odfStyles; odfStyles.createStyleMap(stylesDoc, false); KoOdfLoadingContext odfContext(odfStyles, store); KoShapeLoadingContext shapeContext(odfContext, outputDoc->resourceManager()); int numSheetTotal = rootElement.childNodesCount(); int currentSheet = 0; KoXmlElement sheetElement; forEachElement(sheetElement, rootElement) { Q_ASSERT(sheetElement.namespaceURI() == KoXmlNS::table && sheetElement.localName() == "table"); int sheetId = sheetElement.attributeNS(KoXmlNS::table, "id").toInt(); Calligra::Sheets::Sheet* sheet = outputDoc->map()->sheet(sheetId); KoXmlElement cellElement; int numCellElements = sheetElement.childNodesCount(); int currentCell = 0; forEachElement(cellElement, sheetElement) { Q_ASSERT(cellElement.namespaceURI() == KoXmlNS::table); if (cellElement.localName() == "shapes") { KoXmlElement element; forEachElement(element, cellElement) { sheet->loadOdfObject(element, shapeContext); } } else { Q_ASSERT(cellElement.localName() == "table-cell"); int row = cellElement.attributeNS(KoXmlNS::table, "row").toInt(); int col = cellElement.attributeNS(KoXmlNS::table, "column").toInt(); Calligra::Sheets::Cell cell(sheet, col, row); KoXmlElement element; forEachElement(element, cellElement) { cell.loadOdfObject(element, shapeContext); } } ++currentCell; const int progress = int(currentSheet / qreal(numSheetTotal) * EMBEDDEDPROGRESS + (EMBEDDEDPROGRESS / qreal(numSheetTotal) * currentCell/numCellElements) + SIDEWINDERPROGRESS + ODFPROGRESS) + 0.5; emit q->sigProgress(progress); } ++currentSheet; const int progress = int(currentSheet / qreal(numSheetTotal) * EMBEDDEDPROGRESS + SIDEWINDERPROGRESS + ODFPROGRESS + 0.5); emit q->sigProgress(progress); } } static QRectF getRect(const MSO::OfficeArtFSPGR &r) { return QRect(r.xLeft, r.yTop, r.xRight - r.xLeft, r.yBottom - r.yTop); } void ExcelImport::Private::processSheet(Sheet* is, Calligra::Sheets::Sheet* os) { os->setHidden(!is->visible()); //os->setProtected(is->protect()); os->setAutoCalculationEnabled(is->autoCalc()); os->setHideZero(!is->showZeroValues()); os->setShowGrid(is->showGrid()); os->setFirstLetterUpper(false); os->map()->loadingInfo()->setCursorPosition(os, is->firstVisibleCell() + QPoint(1, 1)); os->setShowFormulaIndicator(false); os->setShowCommentIndicator(true); os->setShowPageOutline(is->isPageBreakViewEnabled()); os->setLcMode(false); os->setShowColumnNumber(false); os->setLayoutDirection(is->isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight); // TODO: page layout processSheetForHeaderFooter(is, os); if(is->password() != 0) { //TODO } const unsigned columnCount = qMin(maximalColumnCount, is->maxColumn()); for (unsigned i = 0; i <= columnCount; ++i) { processColumn(is, i, os); } cellStyles.clear(); rowStyles.clear(); columnStyles.clear(); cellConditions.clear(); const unsigned rowCount = qMin(maximalRowCount, is->maxRow()); for (unsigned i = 0; i <= rowCount && i < KS_rowMax; ++i) { processRow(is, i, os); } QList > styles; for (QHash::const_iterator it = columnStyles.constBegin(); it != columnStyles.constEnd(); ++it) { styles.append(qMakePair(it.value(), styleList[it.key()])); } for (QHash::const_iterator it = rowStyles.constBegin(); it != rowStyles.constEnd(); ++it) { styles.append(qMakePair(it.value(), styleList[it.key()])); } for (QHash::const_iterator it = cellStyles.constBegin(); it != cellStyles.constEnd(); ++it) { styles.append(qMakePair(it.value(), styleList[it.key()])); } os->cellStorage()->loadStyles(styles); // sheet shapes if (!is->drawObjects().isEmpty() || is->drawObjectsGroupCount()) { shapesXml->startElement("table:shapes"); ODrawClient client = ODrawClient(is); ODrawToOdf odraw(client); Writer writer(*shapesXml, *shapeStyles, false); const QList objs = is->drawObjects(); for (int i = 0; i < objs.size(); ++i) { OfficeArtObject* o = objs[i]; client.setShapeText(o->text()); client.setZIndex(o->index()); client.setStyleManager(outputDoc->map()->textStyleManager()); odraw.processDrawingObject(o->object(), writer); } for (int i = is->drawObjectsGroupCount()-1; i >= 0; --i) { shapesXml->startElement("draw:g"); const MSO::OfficeArtSpgrContainer& group = is->drawObjectsGroup(i); const MSO::OfficeArtSpContainer* first = group.rgfb.first().anon.get(); if (first && first->clientAnchor && first->shapeGroup) { QRectF oldCoords = client.getGlobalRect(*first->clientAnchor); QRectF newCoords = getRect(*first->shapeGroup); Writer transw = writer.transform(oldCoords, newCoords); const QList gobjs = is->drawObjects(i); for (int j = 0; j < gobjs.size(); ++j) { OfficeArtObject* o = gobjs[j]; client.setShapeText(o->text()); client.setZIndex(o->index()); client.setStyleManager(outputDoc->map()->textStyleManager()); odraw.processDrawingObject(o->object(), transw); } } else { const QList gobjs = is->drawObjects(i); for (int j = 0; j < gobjs.size(); ++j) { OfficeArtObject* o = gobjs[j]; client.setShapeText(o->text()); client.setZIndex(o->index()); client.setStyleManager(outputDoc->map()->textStyleManager()); odraw.processDrawingObject(o->object(), writer); } } shapesXml->endElement(); // draw:g } shapesXml->endElement(); } processSheetForFilters(is, os); processSheetForConditionals(is, os); os->cellStorage()->loadConditions(cellConditions); } void ExcelImport::Private::processSheetForHeaderFooter(Sheet* is, Calligra::Sheets::Sheet* os) { os->print()->headerFooter()->setHeadFootLine( convertHeaderFooter(is->leftHeader()), convertHeaderFooter(is->centerHeader()), convertHeaderFooter(is->rightHeader()), convertHeaderFooter(is->leftFooter()), convertHeaderFooter(is->centerFooter()), convertHeaderFooter(is->rightFooter())); } void ExcelImport::Private::processSheetForFilters(Sheet* is, Calligra::Sheets::Sheet* os) { static int rangeId = 0; // not very nice to do this this way, but I only care about sort of unique names QList filters = workbook->filterRanges(is); foreach (const QRect& filter, filters) { Calligra::Sheets::Database db; db.setName(QString("excel-database-%1").arg(++rangeId)); db.setDisplayFilterButtons(true); QRect r = filter.adjusted(1, 1, 1, 1); r.setBottom(is->maxRow()+1); Calligra::Sheets::Region range(r, os); db.setRange(range); db.setFilter(is->autoFilters()); os->cellStorage()->setDatabase(range, db); // xls files don't seem to make a difference between hidden and filtered rows, so // assume all rows in a database range are filtered, not explicitly hidden int row = r.top() + 1; while (row <= r.bottom()) { int lastRow; bool isHidden = os->rowFormats()->isHidden(row, &lastRow); if (isHidden) { os->rowFormats()->setHidden(row, lastRow, false); os->rowFormats()->setFiltered(row, lastRow, true); } row = lastRow + 1; } } } static Calligra::Sheets::Value convertValue(const Value& v) { if (v.isBoolean()) { return Calligra::Sheets::Value(v.asBoolean()); } else if (v.isFloat()) { return Calligra::Sheets::Value(v.asFloat()); } else if (v.isInteger()) { return Calligra::Sheets::Value(v.asInteger()); } else if (v.isText()) { return Calligra::Sheets::Value(v.asString()); } else if (v.isError()) { Calligra::Sheets::Value kv(Calligra::Sheets::Value::Error); kv.setError(v.asString()); return kv; } else { return Calligra::Sheets::Value(); } } void ExcelImport::Private::processSheetForConditionals(Sheet* is, Calligra::Sheets::Sheet* os) { static int styleNameId = 0; const QList conditionals = is->conditionalFormats(); Calligra::Sheets::StyleManager* styleManager = os->map()->styleManager(); foreach (ConditionalFormat* cf, conditionals) { QRegion r = cf->region().translated(1, 1); QLinkedList conds; foreach (const Conditional& c, cf->conditionals()) { Calligra::Sheets::Conditional kc; switch (c.cond) { case Conditional::None: kc.cond = Calligra::Sheets::Conditional::None; break; case Conditional::Formula: kc.cond = Calligra::Sheets::Conditional::IsTrueFormula; break; case Conditional::Between: kc.cond = Calligra::Sheets::Conditional::Between; break; case Conditional::Outside: kc.cond = Calligra::Sheets::Conditional::Different; break; case Conditional::Equal: kc.cond = Calligra::Sheets::Conditional::Equal; break; case Conditional::NotEqual: kc.cond = Calligra::Sheets::Conditional::DifferentTo; break; case Conditional::Greater: kc.cond = Calligra::Sheets::Conditional::Superior; break; case Conditional::Less: kc.cond = Calligra::Sheets::Conditional::Inferior; break; case Conditional::GreaterOrEqual: kc.cond = Calligra::Sheets::Conditional::SuperiorEqual; break; case Conditional::LessOrEqual: kc.cond = Calligra::Sheets::Conditional::InferiorEqual; break; } qDebug() << "FRM:" << c.cond << kc.cond; kc.value1 = convertValue(c.value1); kc.value2 = convertValue(c.value2); kc.baseCellAddress = Swinder::encodeAddress(is->name(), cf->region().boundingRect().left(), cf->region().boundingRect().top()); Calligra::Sheets::CustomStyle* style = new Calligra::Sheets::CustomStyle(QString("Excel-Condition-Style-%1").arg(styleNameId++)); kc.styleName = style->name(); // TODO: valueFormat if (c.hasFontItalic()) { style->setFontItalic(c.font().italic()); } if (c.hasFontStrikeout()) { style->setFontStrikeOut(c.font().strikeout()); } if (c.hasFontBold()) { style->setFontBold(c.font().bold()); } // TODO: sub/superscript if (c.hasFontUnderline()) { style->setFontUnderline(c.font().underline()); } if (c.hasFontColor()) { style->setFontColor(c.font().color()); } // TODO: other properties styleManager->insertStyle(style); conds.append(kc); } Calligra::Sheets::Conditions kcs; kcs.setConditionList(conds); cellConditions.append(qMakePair(r, kcs)); } } QString ExcelImport::Private::convertHeaderFooter(const QString& text) { QString result; bool skipUnsupported = false; int lastPos; int pos = text.indexOf('&'); int len = text.length(); if ((pos < 0) && (text.length() > 0)) // If ther is no & result += text; else if (pos > 0) // Some text and '&' result += text.mid(0, pos - 1); while (pos >= 0) { switch (text[pos + 1].unicode()) { case 'D': result += ""; break; case 'T': result += "