Warning, file /office/calligra/libs/odf/KoColumns.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright 2012 Friedrich W. H. Kossebau <kossebau@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KoColumns.h" 0021 0022 #include "KoXmlWriter.h" 0023 #include "KoGenStyle.h" 0024 #include "KoXmlReader.h" 0025 #include "KoXmlNS.h" 0026 #include "KoUnit.h" 0027 #include "OdfDebug.h" 0028 0029 static const int defaultColumnCount = 1; 0030 static const KoColumns::SeparatorStyle defaultSeparatorStyle = KoColumns::None; 0031 static const int defaultSeparatorHeight = 100; 0032 static const Qt::GlobalColor defaultSeparatorColor = Qt::black; 0033 static const KoColumns::SeparatorVerticalAlignment defaultSeparatorVerticalAlignment = KoColumns::AlignTop; 0034 static const int defaultColumnGapWidth = 17; // in pt, ~ 6mm 0035 0036 0037 0038 const char * KoColumns::separatorStyleString(KoColumns::SeparatorStyle separatorStyle) 0039 { 0040 const char * result; 0041 0042 // skip KoColumns::None, is default 0043 if (separatorStyle == Solid) { 0044 result = "solid"; 0045 } else if (separatorStyle == Dotted) { 0046 result = "dotted"; 0047 } else if (separatorStyle == Dashed) { 0048 result = "dashed"; 0049 } else if (separatorStyle == DotDashed) { 0050 result = "dot-dashed"; 0051 } else { 0052 result = "none"; 0053 } 0054 0055 return result; 0056 } 0057 0058 const char * KoColumns::separatorVerticalAlignmentString(KoColumns::SeparatorVerticalAlignment separatorVerticalAlignment) 0059 { 0060 const char * result; 0061 0062 // skip KoColumns::AlignTop, is default 0063 if (separatorVerticalAlignment == AlignVCenter) { 0064 result = "middle"; 0065 } else if (separatorVerticalAlignment == AlignBottom) { 0066 result = "bottom"; 0067 } else { 0068 result = "top"; 0069 } 0070 0071 return result; 0072 } 0073 0074 KoColumns::SeparatorVerticalAlignment KoColumns::parseSeparatorVerticalAlignment(const QString &value) 0075 { 0076 // default to AlignTop 0077 SeparatorVerticalAlignment result = defaultSeparatorVerticalAlignment; 0078 0079 if (! value.isEmpty()) { 0080 // skip "top", is default 0081 if (value == QLatin1String("middle")) { 0082 result = AlignVCenter; 0083 } else if (value == QLatin1String("bottom")) { 0084 result = AlignBottom; 0085 } 0086 } 0087 0088 return result; 0089 } 0090 0091 QColor KoColumns::parseSeparatorColor(const QString &value) 0092 { 0093 QColor result(value); 0094 0095 if (! result.isValid()) 0096 // default is black, cmp. ODF 1.2 ยง19.467 0097 result = QColor(defaultSeparatorColor); 0098 0099 return result; 0100 } 0101 0102 // TODO: see if there is another parse method somewhere which can be used here 0103 int KoColumns::parseSeparatorHeight(const QString &value) 0104 { 0105 int result = defaultSeparatorHeight; 0106 0107 // only try to convert if it ends with a %, so is also not empty 0108 if (value.endsWith(QLatin1Char('%'))) { 0109 bool ok = false; 0110 // try to convert 0111 result = value.leftRef(value.length()-1).toInt(&ok); 0112 // reset to 100% if conversion failed (which sets result to 0) 0113 if (! ok) { 0114 result = defaultSeparatorHeight; 0115 } 0116 } 0117 0118 return result; 0119 } 0120 0121 KoColumns::SeparatorStyle KoColumns::parseSeparatorStyle(const QString &value) 0122 { 0123 SeparatorStyle result = None; 0124 if (! value.isEmpty()) { 0125 // skip "none", is default 0126 if (value == QLatin1String("solid")) { 0127 result = Solid; 0128 } else if (value == QLatin1String("dotted")) { 0129 result = Dotted; 0130 } else if (value == QLatin1String("dashed")) { 0131 result = Dashed; 0132 } else if (value == QLatin1String("dot-dashed")) { 0133 result = DotDashed; 0134 } 0135 } 0136 0137 return result; 0138 } 0139 0140 int KoColumns::parseRelativeWidth(const QString &value) 0141 { 0142 int result = 0; 0143 0144 // only try to convert if it ends with a *, so is also not empty 0145 if (value.endsWith(QLatin1Char('*'))) { 0146 bool ok = false; 0147 // try to convert 0148 result = value.leftRef(value.length()-1).toInt(&ok); 0149 if (! ok) { 0150 result = 0; 0151 } 0152 } 0153 0154 return result; 0155 } 0156 0157 KoColumns::KoColumns() 0158 : count(defaultColumnCount) 0159 , gapWidth(defaultColumnGapWidth) 0160 , separatorStyle(defaultSeparatorStyle) 0161 , separatorColor(defaultSeparatorColor) 0162 , separatorVerticalAlignment(defaultSeparatorVerticalAlignment) 0163 , separatorHeight(defaultSeparatorHeight) 0164 { 0165 } 0166 0167 void KoColumns::reset() 0168 { 0169 count = defaultColumnCount; 0170 gapWidth = defaultColumnGapWidth; 0171 separatorStyle = defaultSeparatorStyle; 0172 separatorColor = QColor(defaultSeparatorColor); 0173 separatorVerticalAlignment = defaultSeparatorVerticalAlignment; 0174 separatorHeight = defaultSeparatorHeight; 0175 } 0176 0177 bool KoColumns::operator==(const KoColumns& rhs) const { 0178 return 0179 count == rhs.count && 0180 (columnData.isEmpty() && rhs.columnData.isEmpty() ? 0181 (qAbs(gapWidth - rhs.gapWidth) <= 1E-10) : 0182 (columnData == rhs.columnData)); 0183 } 0184 0185 bool KoColumns::operator!=(const KoColumns& rhs) const { 0186 return 0187 count != rhs.count || 0188 (columnData.isEmpty() && rhs.columnData.isEmpty() ? 0189 qAbs(gapWidth - rhs.gapWidth) > 1E-10 : 0190 ! (columnData == rhs.columnData)); 0191 } 0192 0193 void KoColumns::loadOdf(const KoXmlElement &style) 0194 { 0195 KoXmlElement columnsElement = KoXml::namedItemNS(style, KoXmlNS::style, "columns"); 0196 if (!columnsElement.isNull()) { 0197 count = columnsElement.attributeNS(KoXmlNS::fo, "column-count").toInt(); 0198 if (count < 1) 0199 count = 1; 0200 gapWidth = KoUnit::parseValue(columnsElement.attributeNS(KoXmlNS::fo, "column-gap")); 0201 0202 KoXmlElement columnSep = KoXml::namedItemNS(columnsElement, KoXmlNS::style, "column-sep"); 0203 if (! columnSep.isNull()) { 0204 separatorStyle = parseSeparatorStyle(columnSep.attributeNS(KoXmlNS::style, "style")); 0205 separatorWidth = KoUnit::parseValue(columnSep.attributeNS(KoXmlNS::style, "width")); 0206 separatorHeight = parseSeparatorHeight(columnSep.attributeNS(KoXmlNS::style, "height")); 0207 separatorColor = parseSeparatorColor(columnSep.attributeNS(KoXmlNS::style, "color")); 0208 separatorVerticalAlignment = 0209 parseSeparatorVerticalAlignment(columnSep.attributeNS(KoXmlNS::style, "vertical-align")); 0210 } 0211 0212 KoXmlElement columnElement; 0213 forEachElement(columnElement, columnsElement) { 0214 if(columnElement.localName() != QLatin1String("column") || 0215 columnElement.namespaceURI() != KoXmlNS::style) 0216 continue; 0217 0218 ColumnDatum datum; 0219 datum.leftMargin = KoUnit::parseValue(columnElement.attributeNS(KoXmlNS::fo, "start-indent"), 0.0); 0220 datum.rightMargin = KoUnit::parseValue(columnElement.attributeNS(KoXmlNS::fo, "end-indent"), 0.0); 0221 datum.topMargin = KoUnit::parseValue(columnElement.attributeNS(KoXmlNS::fo, "space-before"), 0.0); 0222 datum.bottomMargin = KoUnit::parseValue(columnElement.attributeNS(KoXmlNS::fo, "space-after"), 0.0); 0223 datum.relativeWidth = parseRelativeWidth(columnElement.attributeNS(KoXmlNS::style, "rel-width")); 0224 // on a bad relativeWidth just drop all data 0225 if (datum.relativeWidth <= 0) { 0226 columnData.clear(); 0227 break; 0228 } 0229 0230 columnData.append(datum); 0231 } 0232 0233 if (! columnData.isEmpty() && count != columnData.count()) { 0234 warnOdf << "Found not as many <style:column> elements as attribute fo:column-count has set:"<< count; 0235 columnData.clear(); 0236 } 0237 } else { 0238 reset(); 0239 } 0240 } 0241 0242 void KoColumns::saveOdf(KoGenStyle &style) const 0243 { 0244 if (count > 1) { 0245 QBuffer buffer; 0246 buffer.open(QIODevice::WriteOnly); 0247 KoXmlWriter writer(&buffer); 0248 0249 writer.startElement("style:columns"); 0250 writer.addAttribute("fo:column-count", count); 0251 if (columnData.isEmpty()) { 0252 writer.addAttributePt("fo:column-gap", gapWidth); 0253 } 0254 0255 if (separatorStyle != KoColumns::None) { 0256 writer.startElement("style:column-sep"); 0257 writer.addAttribute("style:style", separatorStyleString(separatorStyle)); 0258 writer.addAttributePt("style:width", separatorWidth); 0259 writer.addAttribute("style:height", QString::number(separatorHeight)+QLatin1Char('%')); 0260 writer.addAttribute("style:color", separatorColor.name()); 0261 writer.addAttribute("style:vertical-align", separatorVerticalAlignmentString(separatorVerticalAlignment)); 0262 writer.endElement(); // style:column-sep 0263 } 0264 0265 foreach(const ColumnDatum &cd, columnData) { 0266 writer.startElement("style:column"); 0267 writer.addAttributePt("fo:start-indent", cd.leftMargin); 0268 writer.addAttributePt("fo:end-indent", cd.rightMargin); 0269 writer.addAttributePt("fo:space-before", cd.topMargin); 0270 writer.addAttributePt("fo:space-after", cd.bottomMargin); 0271 writer.addAttribute("style:rel-width", QString::number(cd.relativeWidth)+QLatin1Char('*')); 0272 writer.endElement(); // style:column 0273 } 0274 0275 writer.endElement(); // style:columns 0276 0277 QString contentElement = QString::fromUtf8(buffer.buffer(), buffer.buffer().size()); 0278 style.addChildElement("style:columns", contentElement); 0279 } 0280 }