andre@1: /**************************************************************************** andre@1: ** Copyright (c) 2013-2014 Debao Zhang andre@1: ** All right reserved. andre@1: ** andre@1: ** Permission is hereby granted, free of charge, to any person obtaining andre@1: ** a copy of this software and associated documentation files (the andre@1: ** "Software"), to deal in the Software without restriction, including andre@1: ** without limitation the rights to use, copy, modify, merge, publish, andre@1: ** distribute, sublicense, and/or sell copies of the Software, and to andre@1: ** permit persons to whom the Software is furnished to do so, subject to andre@1: ** the following conditions: andre@1: ** andre@1: ** The above copyright notice and this permission notice shall be andre@1: ** included in all copies or substantial portions of the Software. andre@1: ** andre@1: ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, andre@1: ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF andre@1: ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND andre@1: ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE andre@1: ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION andre@1: ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION andre@1: ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. andre@1: ** andre@1: ****************************************************************************/ andre@1: #include "xlsxrichstring.h" andre@1: #include "xlsxsharedstrings_p.h" andre@1: #include "xlsxutility_p.h" andre@1: #include "xlsxformat_p.h" andre@1: #include "xlsxcolor_p.h" andre@1: #include andre@1: #include andre@1: #include andre@1: #include andre@1: #include andre@1: #include andre@1: andre@1: namespace QXlsx { andre@1: andre@1: /* andre@1: * Note that, when we open an existing .xlsx file (broken file?), andre@1: * duplicated string items may exist in the shared string table. andre@1: * andre@1: * In such case, the size of stringList will larger than stringTable. andre@1: * Duplicated items can be removed once we loaded all the worksheets. andre@1: */ andre@1: andre@1: SharedStrings::SharedStrings(CreateFlag flag) andre@1: :AbstractOOXmlFile(flag) andre@1: { andre@1: m_stringCount = 0; andre@1: } andre@1: andre@1: int SharedStrings::count() const andre@1: { andre@1: return m_stringCount; andre@1: } andre@1: andre@1: bool SharedStrings::isEmpty() const andre@1: { andre@1: return m_stringList.isEmpty(); andre@1: } andre@1: andre@1: int SharedStrings::addSharedString(const QString &string) andre@1: { andre@1: return addSharedString(RichString(string)); andre@1: } andre@1: andre@1: int SharedStrings::addSharedString(const RichString &string) andre@1: { andre@1: m_stringCount += 1; andre@1: andre@1: if (m_stringTable.contains(string)) { andre@1: XlsxSharedStringInfo &item = m_stringTable[string]; andre@1: item.count += 1; andre@1: return item.index; andre@1: } andre@1: andre@1: int index = m_stringList.size(); andre@1: m_stringTable[string] = XlsxSharedStringInfo(index); andre@1: m_stringList.append(string); andre@1: return index; andre@1: } andre@1: andre@1: void SharedStrings::incRefByStringIndex(int idx) andre@1: { andre@1: if (idx <0 || idx >= m_stringList.size()) { andre@1: qDebug("SharedStrings: invlid index"); andre@1: return; andre@1: } andre@1: andre@1: addSharedString(m_stringList[idx]); andre@1: } andre@1: andre@1: /* andre@1: * Broken, don't use. andre@1: */ andre@1: void SharedStrings::removeSharedString(const QString &string) andre@1: { andre@1: removeSharedString(RichString(string)); andre@1: } andre@1: andre@1: /* andre@1: * Broken, don't use. andre@1: */ andre@1: void SharedStrings::removeSharedString(const RichString &string) andre@1: { andre@1: if (!m_stringTable.contains(string)) andre@1: return; andre@1: andre@1: m_stringCount -= 1; andre@1: andre@1: XlsxSharedStringInfo &item = m_stringTable[string]; andre@1: item.count -= 1; andre@1: andre@1: if (item.count <= 0) { andre@1: for (int i=item.index+1; i= 0) andre@1: return m_stringList[index]; andre@1: return RichString(); andre@1: } andre@1: andre@1: QList SharedStrings::getSharedStrings() const andre@1: { andre@1: return m_stringList; andre@1: } andre@1: andre@1: void SharedStrings::writeRichStringPart_rPr(QXmlStreamWriter &writer, const Format &format) const andre@1: { andre@1: if (!format.hasFontData()) andre@1: return; andre@1: andre@1: if (format.fontBold()) andre@1: writer.writeEmptyElement(QStringLiteral("b")); andre@1: if (format.fontItalic()) andre@1: writer.writeEmptyElement(QStringLiteral("i")); andre@1: if (format.fontStrikeOut()) andre@1: writer.writeEmptyElement(QStringLiteral("strike")); andre@1: if (format.fontOutline()) andre@1: writer.writeEmptyElement(QStringLiteral("outline")); andre@1: if (format.boolProperty(FormatPrivate::P_Font_Shadow)) andre@1: writer.writeEmptyElement(QStringLiteral("shadow")); andre@1: if (format.hasProperty(FormatPrivate::P_Font_Underline)) { andre@1: Format::FontUnderline u = format.fontUnderline(); andre@1: if (u != Format::FontUnderlineNone) { andre@1: writer.writeEmptyElement(QStringLiteral("u")); andre@1: if (u== Format::FontUnderlineDouble) andre@1: writer.writeAttribute(QStringLiteral("val"), QStringLiteral("double")); andre@1: else if (u == Format::FontUnderlineSingleAccounting) andre@1: writer.writeAttribute(QStringLiteral("val"), QStringLiteral("singleAccounting")); andre@1: else if (u == Format::FontUnderlineDoubleAccounting) andre@1: writer.writeAttribute(QStringLiteral("val"), QStringLiteral("doubleAccounting")); andre@1: } andre@1: } andre@1: if (format.hasProperty(FormatPrivate::P_Font_Script)) { andre@1: Format::FontScript s = format.fontScript(); andre@1: if (s != Format::FontScriptNormal) { andre@1: writer.writeEmptyElement(QStringLiteral("vertAlign")); andre@1: if (s == Format::FontScriptSuper) andre@1: writer.writeAttribute(QStringLiteral("val"), QStringLiteral("superscript")); andre@1: else andre@1: writer.writeAttribute(QStringLiteral("val"), QStringLiteral("subscript")); andre@1: } andre@1: } andre@1: andre@1: if (format.hasProperty(FormatPrivate::P_Font_Size)) { andre@1: writer.writeEmptyElement(QStringLiteral("sz")); andre@1: writer.writeAttribute(QStringLiteral("val"), QString::number(format.fontSize())); andre@1: } andre@1: andre@1: if (format.hasProperty(FormatPrivate::P_Font_Color)) { andre@1: XlsxColor color = format.property(FormatPrivate::P_Font_Color).value(); andre@1: color.saveToXml(writer); andre@1: } andre@1: andre@1: if (!format.fontName().isEmpty()) { andre@1: writer.writeEmptyElement(QStringLiteral("rFont")); andre@1: writer.writeAttribute(QStringLiteral("val"), format.fontName()); andre@1: } andre@1: if (format.hasProperty(FormatPrivate::P_Font_Family)) { andre@1: writer.writeEmptyElement(QStringLiteral("family")); andre@1: writer.writeAttribute(QStringLiteral("val"), QString::number(format.intProperty(FormatPrivate::P_Font_Family))); andre@1: } andre@1: andre@1: if (format.hasProperty(FormatPrivate::P_Font_Scheme)) { andre@1: writer.writeEmptyElement(QStringLiteral("scheme")); andre@1: writer.writeAttribute(QStringLiteral("val"), format.stringProperty(FormatPrivate::P_Font_Scheme)); andre@1: } andre@1: } andre@1: andre@1: void SharedStrings::saveToXmlFile(QIODevice *device) const andre@1: { andre@1: QXmlStreamWriter writer(device); andre@1: andre@1: if (m_stringList.size() != m_stringTable.size()) { andre@1: //Duplicated string items exist in m_stringList andre@1: //Clean up can not be done here, as the indices andre@1: //have been used when we save the worksheets part. andre@1: } andre@1: andre@1: writer.writeStartDocument(QStringLiteral("1.0"), true); andre@1: writer.writeStartElement(QStringLiteral("sst")); andre@1: writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://schemas.openxmlformats.org/spreadsheetml/2006/main")); andre@1: writer.writeAttribute(QStringLiteral("count"), QString::number(m_stringCount)); andre@1: writer.writeAttribute(QStringLiteral("uniqueCount"), QString::number(m_stringList.size())); andre@1: andre@1: foreach (RichString string, m_stringList) { andre@1: writer.writeStartElement(QStringLiteral("si")); andre@1: if (string.isRichString()) { andre@1: //Rich text string andre@1: for (int i=0; i