File indexing completed on 2025-07-13 10:51:48
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2003 Norbert Andres <nandres@web.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include <opencalcstyleexport.h> 0008 0009 #include <sheets/core/Cell.h> 0010 #include <sheets/core/Map.h> 0011 #include <sheets/core/Sheet.h> 0012 #include <sheets/core/Style.h> 0013 #include <sheets/core/StyleManager.h> 0014 0015 #include <QDomDocument> 0016 0017 using namespace Calligra::Sheets; 0018 0019 OpenCalcStyles::OpenCalcStyles() 0020 { 0021 } 0022 0023 OpenCalcStyles::~OpenCalcStyles() 0024 { 0025 while (!m_cellStyles.isEmpty()) delete m_cellStyles.takeFirst(); 0026 while (!m_columnStyles.isEmpty()) delete m_columnStyles.takeFirst(); 0027 while (!m_numberStyles.isEmpty()) delete m_numberStyles.takeFirst(); 0028 while (!m_rowStyles.isEmpty()) delete m_rowStyles.takeFirst(); 0029 while (!m_sheetStyles.isEmpty()) delete m_sheetStyles.takeFirst(); 0030 while (!m_fontList.isEmpty()) delete m_fontList.takeFirst(); 0031 } 0032 0033 void OpenCalcStyles::writeStyles(QDomDocument & doc, QDomElement & autoStyles) 0034 { 0035 addColumnStyles(doc, autoStyles); 0036 addRowStyles(doc, autoStyles); 0037 addSheetStyles(doc, autoStyles); 0038 addNumberStyles(doc, autoStyles); 0039 addCellStyles(doc, autoStyles); 0040 } 0041 0042 void OpenCalcStyles::writeFontDecl(QDomDocument & doc, QDomElement & fontDecls) 0043 { 0044 foreach(QFont * f, m_fontList) { 0045 QDomElement fontDecl = doc.createElement("style:font-decl"); 0046 0047 fontDecl.setAttribute("style:name", f->family()); 0048 fontDecl.setAttribute("fo:font-family", f->family()); 0049 fontDecl.setAttribute("style:font-pitch", (f->fixedPitch() ? "fixed" : "variable")); 0050 0051 // missing: 0052 // style:font-charset="x-symbol" style:font-family-generic="swiss" 0053 // style:font-style-name= "Bold/Standard/Regular" 0054 0055 fontDecls.appendChild(fontDecl); 0056 } 0057 } 0058 0059 void OpenCalcStyles::addFont(QFont const & font, bool def) 0060 { 0061 if (def) 0062 m_defaultFont = font; 0063 0064 foreach(QFont * f, m_fontList) { 0065 if (f->family() == font.family()) 0066 return; 0067 0068 } 0069 0070 QFont * f = new QFont(font); 0071 m_fontList.append(f); 0072 } 0073 0074 QString OpenCalcStyles::cellStyle(CellStyle const & cs) 0075 { 0076 CellStyle * t = 0; 0077 foreach(t, m_cellStyles) { 0078 if (CellStyle::isEqual(t, cs)) 0079 return t->name; 0080 } 0081 0082 t = new CellStyle(); 0083 t->copyData(cs); 0084 0085 m_cellStyles.append(t); 0086 0087 t->name = QString("ce%1").arg(m_cellStyles.count()); 0088 0089 return t->name; 0090 } 0091 0092 QString OpenCalcStyles::columnStyle(ColumnStyle const & cs) 0093 { 0094 ColumnStyle * t = 0; 0095 foreach(t, m_columnStyles) { 0096 if (ColumnStyle::isEqual(t, cs)) 0097 return t->name; 0098 } 0099 0100 t = new ColumnStyle(); 0101 t->copyData(cs); 0102 0103 m_columnStyles.append(t); 0104 0105 t->name = QString("co%1").arg(m_columnStyles.count()); 0106 0107 return t->name; 0108 } 0109 0110 QString OpenCalcStyles::numberStyle(NumberStyle const &) 0111 { 0112 return ""; 0113 } 0114 0115 QString OpenCalcStyles::rowStyle(RowStyle const & rs) 0116 { 0117 RowStyle * t = 0; 0118 foreach(t, m_rowStyles) { 0119 if (RowStyle::isEqual(t, rs)) 0120 return t->name; 0121 } 0122 0123 t = new RowStyle(); 0124 t->copyData(rs); 0125 0126 m_rowStyles.append(t); 0127 0128 t->name = QString("ro%1").arg(m_rowStyles.count()); 0129 0130 return t->name; 0131 } 0132 0133 QString OpenCalcStyles::sheetStyle(SheetStyle const & ts) 0134 { 0135 SheetStyle * t = 0; 0136 foreach(t, m_sheetStyles) { 0137 if (SheetStyle::isEqual(t, ts)) 0138 return t->name; 0139 } 0140 0141 t = new SheetStyle(); 0142 t->copyData(ts); 0143 0144 m_sheetStyles.append(t); 0145 0146 t->name = QString("ta%1").arg(m_sheetStyles.count()); 0147 0148 return t->name; 0149 } 0150 0151 QString convertPenToString(QPen const & pen) 0152 { 0153 QString s(QString("%1cm solid ").arg(pen.width() * 0.035)); 0154 s += pen.color().name(); 0155 0156 return s; 0157 } 0158 0159 void OpenCalcStyles::addCellStyles(QDomDocument & doc, QDomElement & autoStyles) 0160 { 0161 0162 CellStyle * t = 0; 0163 foreach(t, m_cellStyles) { 0164 QDomElement ts = doc.createElement("style:style"); 0165 ts.setAttribute("style:name", t->name); 0166 ts.setAttribute("style:family", "table-cell"); 0167 ts.setAttribute("style:parent-style-name", "Default"); 0168 if (t->numberStyle.length() > 0) 0169 ts.setAttribute("style:data-style-name", t->numberStyle); 0170 0171 QDomElement prop = doc.createElement("style:properties"); 0172 0173 if (t->font.family() != m_defaultFont.family()) 0174 prop.setAttribute("style:font-name", t->font.family()); 0175 0176 if (t->font.bold() != m_defaultFont.bold()) 0177 prop.setAttribute("fo:font-weight", (t->font.bold() ? "bold" : "light")); 0178 0179 prop.setAttribute("fo:font-size", QString("%1pt").arg(t->font.pointSize())); 0180 0181 if (t->font.underline() != m_defaultFont.underline()) { 0182 prop.setAttribute("style:text-underline", (t->font.underline() ? "single" : "none")); 0183 if (t->font.underline()) 0184 prop.setAttribute("style:text-underline-color", "font-color"); 0185 } 0186 0187 if (t->font.italic() != m_defaultFont.italic()) 0188 prop.setAttribute("fo:font-style", (t->font.italic() ? "italic" : "none")); 0189 0190 if (t->font.strikeOut() != m_defaultFont.strikeOut()) 0191 prop.setAttribute("style:text-crossing-out", (t->font.strikeOut() ? "single-line" : "none")); 0192 0193 if (t->color.name() != "#000000") 0194 prop.setAttribute("fo:color", t->color.name()); 0195 0196 if (t->bgColor.name() != "#ffffff") 0197 prop.setAttribute("fo:background-color", t->bgColor.name()); 0198 0199 if (t->alignX != Calligra::Sheets::Style::HAlignUndefined) { 0200 QString value; 0201 if (t->alignX == Calligra::Sheets::Style::Center) 0202 value = "center"; 0203 else if (t->alignX == Calligra::Sheets::Style::Right) 0204 value = "end"; 0205 else if (t->alignX == Calligra::Sheets::Style::Left) 0206 value = "start"; 0207 prop.setAttribute("fo:text-align", value); 0208 } 0209 0210 if (t->alignY != Calligra::Sheets::Style::Bottom) // default in OpenCalc 0211 prop.setAttribute("fo:vertical-align", (t->alignY == Calligra::Sheets::Style::Middle ? "middle" : "top")); 0212 0213 if (t->indent > 0.0) { 0214 prop.setAttribute("fo:margin-left", QString("%1pt").arg(t->indent)); 0215 if (t->alignX == Calligra::Sheets::Style::HAlignUndefined) 0216 prop.setAttribute("fo:text-align", "start"); 0217 } 0218 0219 if (t->wrap) 0220 prop.setAttribute("fo:wrap-option", "wrap"); 0221 0222 if (t->vertical) { 0223 prop.setAttribute("fo:direction", "ttb"); 0224 prop.setAttribute("style:rotation-angle", "0"); 0225 } 0226 0227 if (t->angle != 0) 0228 prop.setAttribute("style:rotation-angle", QString::number(t->angle)); 0229 0230 if (!t->print) 0231 prop.setAttribute("style:print-content", "false"); 0232 0233 if (t->hideAll) 0234 prop.setAttribute("style:cell-protect", "hidden-and-protected"); 0235 else if (t->notProtected && !t->hideFormula) 0236 prop.setAttribute("style:cell-protect", "none"); 0237 else if (t->notProtected && t->hideFormula) 0238 prop.setAttribute("style:cell-protect", "formula-hidden"); 0239 else if (t->hideFormula) 0240 prop.setAttribute("style:cell-protect", "protected formula-hidden"); 0241 else if (!t->notProtected) 0242 prop.setAttribute("style:cell-protect", "protected"); 0243 0244 0245 if ((t->left == t->right) && (t->left == t->top) && (t->left == t->bottom)) { 0246 if ((t->left.width() != 0) && (t->left.style() != Qt::NoPen)) 0247 prop.setAttribute("fo:border", convertPenToString(t->left)); 0248 } else { 0249 if ((t->left.width() != 0) && (t->left.style() != Qt::NoPen)) 0250 prop.setAttribute("fo:border-left", convertPenToString(t->left)); 0251 0252 if ((t->right.width() != 0) && (t->right.style() != Qt::NoPen)) 0253 prop.setAttribute("fo:border-right", convertPenToString(t->right)); 0254 0255 if ((t->top.width() != 0) && (t->top.style() != Qt::NoPen)) 0256 prop.setAttribute("fo:border-top", convertPenToString(t->top)); 0257 0258 if ((t->bottom.width() != 0) && (t->bottom.style() != Qt::NoPen)) 0259 prop.setAttribute("fo:border-bottom", convertPenToString(t->bottom)); 0260 } 0261 0262 ts.appendChild(prop); 0263 autoStyles.appendChild(ts); 0264 } 0265 } 0266 0267 void OpenCalcStyles::addColumnStyles(QDomDocument & doc, QDomElement & autoStyles) 0268 { 0269 ColumnStyle * t = 0; 0270 foreach(t, m_columnStyles) { 0271 QDomElement ts = doc.createElement("style:style"); 0272 ts.setAttribute("style:name", t->name); 0273 ts.setAttribute("style:family", "table-column"); 0274 0275 QDomElement prop = doc.createElement("style:properties"); 0276 if (t->breakB != ::Style::none) 0277 prop.setAttribute("fo:break-before", (t->breakB == ::Style::automatic ? "auto" : "page")); 0278 prop.setAttribute("style:column-width", QString("%1cm").arg(t->size)); 0279 0280 ts.appendChild(prop); 0281 autoStyles.appendChild(ts); 0282 } 0283 } 0284 0285 void OpenCalcStyles::addNumberStyles(QDomDocument & /*doc*/, QDomElement & /*autoStyles*/) 0286 { 0287 } 0288 0289 void OpenCalcStyles::addRowStyles(QDomDocument & doc, QDomElement & autoStyles) 0290 { 0291 RowStyle * t = 0; 0292 foreach(t, m_rowStyles) { 0293 QDomElement ts = doc.createElement("style:style"); 0294 ts.setAttribute("style:name", t->name); 0295 ts.setAttribute("style:family", "table-row"); 0296 0297 QDomElement prop = doc.createElement("style:properties"); 0298 prop.setAttribute("style:row-height", QString("%1cm").arg(t->size)); 0299 if (t->breakB != ::Style::none) 0300 prop.setAttribute("fo:break-before", (t->breakB == ::Style::automatic ? "auto" : "page")); 0301 0302 ts.appendChild(prop); 0303 autoStyles.appendChild(ts); 0304 0305 } 0306 } 0307 0308 void OpenCalcStyles::addSheetStyles(QDomDocument & doc, QDomElement & autoStyles) 0309 { 0310 SheetStyle * t = 0; 0311 foreach(t, m_sheetStyles) { 0312 QDomElement ts = doc.createElement("style:style"); 0313 ts.setAttribute("style:name", t->name); 0314 ts.setAttribute("style:family", "table"); 0315 ts.setAttribute("style:master-page-name", "Default"); 0316 0317 QDomElement prop = doc.createElement("style:properties"); 0318 prop.setAttribute("table:display", (t->visible ? "true" : "false")); 0319 0320 ts.appendChild(prop); 0321 autoStyles.appendChild(ts); 0322 } 0323 } 0324 0325 bool SheetStyle::isEqual(SheetStyle const * const t1, SheetStyle const & t2) 0326 { 0327 if (t1->visible == t2.visible) 0328 return true; 0329 0330 return false; 0331 } 0332 0333 CellStyle::CellStyle() 0334 : color(Qt::black), 0335 bgColor(Qt::white), 0336 indent(-1.0), 0337 wrap(false), 0338 vertical(false), 0339 angle(0), 0340 print(true), 0341 left(Qt::black, 0, Qt::NoPen), 0342 right(Qt::black, 0, Qt::NoPen), 0343 top(Qt::black, 0, Qt::NoPen), 0344 bottom(Qt::black, 0, Qt::NoPen), 0345 hideAll(false), 0346 hideFormula(false), 0347 notProtected(false), 0348 alignX(Calligra::Sheets::Style::HAlignUndefined), 0349 alignY(Calligra::Sheets::Style::Middle) 0350 { 0351 } 0352 0353 void CellStyle::copyData(CellStyle const & ts) 0354 { 0355 font = ts.font; 0356 numberStyle = ts.numberStyle; 0357 color = ts.color; 0358 bgColor = ts.bgColor; 0359 indent = ts.indent; 0360 wrap = ts.wrap; 0361 vertical = ts.vertical; 0362 angle = ts.angle; 0363 print = ts.print; 0364 left = ts.left; 0365 right = ts.right; 0366 top = ts.top; 0367 bottom = ts.bottom; 0368 hideAll = ts.hideAll; 0369 hideFormula = ts.hideFormula; 0370 notProtected = ts.notProtected; 0371 alignX = ts.alignX; 0372 alignY = ts.alignY; 0373 } 0374 0375 bool CellStyle::isEqual(CellStyle const * const t1, CellStyle const & t2) 0376 { 0377 if ((t1->font == t2.font) && (t1->numberStyle == t2.numberStyle) 0378 && (t1->color == t2.color) && (t1->bgColor == t2.bgColor) 0379 && (t1->alignX == t2.alignX) && (t1->alignY == t2.alignY) 0380 && (t1->indent == t2.indent) && (t1->wrap == t2.wrap) 0381 && (t1->vertical == t2.vertical) && (t1->angle == t2.angle) 0382 && (t1->print == t2.print) && (t1->left == t2.left) 0383 && (t1->right == t2.right) && (t1->top == t2.top) 0384 && (t1->bottom == t2.bottom) && (t1->hideAll == t2.hideAll) 0385 && (t1->hideFormula == t2.hideFormula) && (t1->notProtected == t2.notProtected) 0386 ) 0387 return true; 0388 0389 return false; 0390 } 0391 0392 // all except the number style 0393 void CellStyle::loadData(CellStyle & cs, const Cell& cell) 0394 { 0395 const Calligra::Sheets::Style style = cell.style(); 0396 const Calligra::Sheets::Style* defaultStyle = cell.fullSheet()->fullMap()->styleManager()->defaultStyle(); 0397 0398 QFont font = style.font(); 0399 if (font != defaultStyle->font()) 0400 cs.font = font; 0401 0402 QColor color = style.fontColor(); 0403 if (color != defaultStyle->fontColor()) 0404 cs.color = color; 0405 0406 QColor bgColor = style.backgroundColor(); 0407 if (bgColor != defaultStyle->backgroundColor()) 0408 cs.bgColor = bgColor; 0409 0410 if (style.hasAttribute(Calligra::Sheets::Style::HorizontalAlignment)) 0411 cs.alignX = style.halign(); 0412 0413 if (style.hasAttribute(Calligra::Sheets::Style::VerticalAlignment)) 0414 cs.alignY = style.valign(); 0415 0416 if (style.hasAttribute(Calligra::Sheets::Style::Indentation)) 0417 cs.indent = style.indentation(); 0418 0419 if (style.hasAttribute(Calligra::Sheets::Style::Angle)) 0420 cs.angle = -style.angle(); 0421 0422 if (style.hasAttribute(Calligra::Sheets::Style::MultiRow)) 0423 cs.wrap = style.wrapText(); 0424 0425 if (style.hasAttribute(Calligra::Sheets::Style::VerticalText)) 0426 cs.vertical = style.verticalText(); 0427 0428 if (style.hasAttribute(Calligra::Sheets::Style::DontPrintText)) 0429 cs.print = style.printText(); 0430 0431 if (style.hasAttribute(Calligra::Sheets::Style::LeftPen)) 0432 cs.left = style.leftBorderPen(); 0433 0434 if (style.hasAttribute(Calligra::Sheets::Style::RightPen)) 0435 cs.right = style.rightBorderPen(); 0436 0437 if (style.hasAttribute(Calligra::Sheets::Style::TopPen)) 0438 cs.top = style.topBorderPen(); 0439 0440 if (style.hasAttribute(Calligra::Sheets::Style::BottomPen)) 0441 cs.bottom = style.bottomBorderPen(); 0442 0443 if (style.hasAttribute(Calligra::Sheets::Style::NotProtected)) 0444 cs.notProtected = style.notProtected(); 0445 0446 if (style.hasAttribute(Calligra::Sheets::Style::HideAll)) 0447 cs.hideAll = style.hideAll(); 0448 0449 if (style.hasAttribute(Calligra::Sheets::Style::HideFormula)) 0450 cs.hideFormula = style.hideFormula(); 0451 } 0452 0453 bool NumberStyle::isEqual(NumberStyle const * const t1, NumberStyle const & t2) 0454 { 0455 if ((t1->type == t2.type) && (t1->pattern == t2.pattern)) 0456 return true; 0457 0458 return false; 0459 } 0460 0461 void ColumnStyle::copyData(ColumnStyle const & cs) 0462 { 0463 breakB = cs.breakB; 0464 size = cs.size; 0465 } 0466 0467 bool ColumnStyle::isEqual(ColumnStyle const * const c1, ColumnStyle const & c2) 0468 { 0469 if ((c1->breakB == c2.breakB) && (c1->size == c2.size)) 0470 return true; 0471 0472 return false; 0473 } 0474 0475 void RowStyle::copyData(RowStyle const & cs) 0476 { 0477 breakB = cs.breakB; 0478 size = cs.size; 0479 } 0480 0481 bool RowStyle::isEqual(RowStyle const * const c1, RowStyle const & c2) 0482 { 0483 if ((c1->breakB == c2.breakB) && (c1->size == c2.size)) 0484 return true; 0485 0486 return false; 0487 }