File indexing completed on 2025-01-19 13:27:32

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