File indexing completed on 2024-04-28 16:21:33

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 // own header
0021 #include "StyleManager.h"
0022 
0023 #include <QBrush>
0024 #include <QDomDocument>
0025 #include <QDomElement>
0026 #include <QPen>
0027 #include <QStringList>
0028 
0029 #include <KLocalizedString>
0030 
0031 #include "SheetsDebug.h"
0032 #include "CalculationSettings.h"
0033 #include "Condition.h"
0034 #include "Map.h"
0035 #include "Style.h"
0036 
0037 using namespace Calligra::Sheets;
0038 
0039 StyleManager::StyleManager()
0040         : m_defaultStyle(new CustomStyle())
0041 {
0042 }
0043 
0044 StyleManager::~StyleManager()
0045 {
0046     delete m_defaultStyle;
0047     qDeleteAll(m_styles);
0048 }
0049 
0050 QDomElement StyleManager::save(QDomDocument & doc)
0051 {
0052     QDomElement styles = doc.createElement("styles");
0053 
0054     m_defaultStyle->save(doc, styles, this);
0055 
0056     CustomStyles::ConstIterator iter = m_styles.constBegin();
0057     CustomStyles::ConstIterator end  = m_styles.constEnd();
0058 
0059     while (iter != end) {
0060         CustomStyle * styleData = iter.value();
0061 
0062         styleData->save(doc, styles, this);
0063 
0064         ++iter;
0065     }
0066 
0067     return styles;
0068 }
0069 
0070 bool StyleManager::loadXML(KoXmlElement const & styles)
0071 {
0072     bool ok = true;
0073     KoXmlElement e = styles.firstChild().toElement();
0074     while (!e.isNull()) {
0075         QString name;
0076         if (e.hasAttribute("name"))
0077             name = e.attribute("name");
0078         Style::StyleType type = (Style::StyleType)(e.attribute("type").toInt(&ok));
0079         if (!ok)
0080             return false;
0081 
0082         if (name == "Default" && type == Style::BUILTIN) {
0083             if (!m_defaultStyle->loadXML(e, name))
0084                 return false;
0085             m_defaultStyle->setType(Style::BUILTIN);
0086         } else if (!name.isNull()) {
0087             CustomStyle* style = 0;
0088             if (e.hasAttribute("parent") && e.attribute("parent") == "Default")
0089                 style = new CustomStyle(name, m_defaultStyle);
0090             else
0091                 style = new CustomStyle(name);
0092 
0093             if (!style->loadXML(e, name)) {
0094                 delete style;
0095                 return false;
0096             }
0097 
0098             if (style->type() == Style::AUTO)
0099                 style->setType(Style::CUSTOM);
0100             insertStyle(style);
0101             debugSheetsODF << "Style" << name << ":" << style;
0102         }
0103 
0104         e = e.nextSibling().toElement();
0105     }
0106 
0107     // reparent all styles
0108     const QStringList names = styleNames();
0109     QStringList::ConstIterator it;
0110     for (it = names.begin(); it != names.end(); ++it) {
0111         if (*it != "Default") {
0112             CustomStyle * styleData = style(*it);
0113             if (styleData && !styleData->parentName().isNull() && m_styles.value(styleData->parentName()))
0114                 styleData->setParentName(m_styles.value(styleData->parentName())->name());
0115         }
0116     }
0117 
0118     return true;
0119 }
0120 
0121 void StyleManager::resetDefaultStyle()
0122 {
0123     delete m_defaultStyle;
0124     m_defaultStyle = new CustomStyle;
0125 }
0126 
0127 void StyleManager::createBuiltinStyles()
0128 {
0129     CustomStyle * header1 = new CustomStyle(i18n("Header"), m_defaultStyle);
0130     QFont f(header1->font());
0131     f.setItalic(true);
0132     f.setPointSize(f.pointSize() + 2);
0133     f.setBold(true);
0134     header1->setFont(f);
0135     header1->setType(Style::BUILTIN);
0136     m_styles[ header1->name()] = header1;
0137 
0138     CustomStyle * header2 = new CustomStyle(i18n("Header1"), header1);
0139     QColor color("#F0F0FF");
0140     header2->setBackgroundColor(color);
0141     QPen pen(Qt::black, 1, Qt::SolidLine);
0142     header2->setBottomBorderPen(pen);
0143     header2->setType(Style::BUILTIN);
0144 
0145     m_styles[ header2->name()] = header2;
0146 }
0147 
0148 // Mapping between Oasis and our styles. Only used in loading/saving.
0149 void StyleManager::defineOasisStyle(const QString &oasisName, const QString &styleName)
0150 {
0151     m_oasisStyles[oasisName] = styleName;
0152 }
0153 
0154 CustomStyle * StyleManager::style(QString const & name) const
0155 {
0156     if (name.isEmpty())
0157         return 0;
0158     // on OpenDocument loading
0159 //     if ( !m_oasisStyles.isEmpty() )
0160     {
0161         if (m_oasisStyles.contains(name) && m_styles.contains(m_oasisStyles[name]))
0162             return m_styles.value(m_oasisStyles[name]);
0163 //         return 0;
0164     }
0165     if (m_styles.contains(name))
0166         return m_styles[name];
0167     if ((name == "Default") || (name == m_defaultStyle->name()))
0168         return m_defaultStyle;
0169     return 0;
0170 }
0171 
0172 void StyleManager::takeStyle(CustomStyle * style)
0173 {
0174     const QString parentName = style->parentName();
0175 
0176     CustomStyles::ConstIterator iter = m_styles.constBegin();
0177     CustomStyles::ConstIterator end  = m_styles.constEnd();
0178 
0179     while (iter != end) {
0180         if (iter.value()->parentName() == style->name())
0181             iter.value()->setParentName(parentName);
0182 
0183         ++iter;
0184     }
0185 
0186     CustomStyles::iterator i(m_styles.find(style->name()));
0187 
0188     if (i != m_styles.end()) {
0189         debugSheetsODF << "Erasing style entry for" << style->name();
0190         m_styles.erase(i);
0191     }
0192 }
0193 
0194 bool StyleManager::checkCircle(QString const & name, QString const & parent)
0195 {
0196     CustomStyle* style = this->style(parent);
0197     if (!style || style->parentName().isNull())
0198         return true;
0199     if (style->parentName() == name)
0200         return false;
0201     else
0202         return checkCircle(name, style->parentName());
0203 }
0204 
0205 bool StyleManager::validateStyleName(QString const & name, CustomStyle * style)
0206 {
0207     if (m_defaultStyle->name() == name || name == "Default")
0208         return false;
0209 
0210     CustomStyles::const_iterator iter = m_styles.constBegin();
0211     CustomStyles::const_iterator end  = m_styles.constEnd();
0212 
0213     while (iter != end) {
0214         if (iter.key() == name && iter.value() != style)
0215             return false;
0216 
0217         ++iter;
0218     }
0219 
0220     return true;
0221 }
0222 
0223 void StyleManager::changeName(QString const & oldName, QString const & newName)
0224 {
0225     CustomStyles::iterator iter = m_styles.begin();
0226     CustomStyles::iterator end  = m_styles.end();
0227 
0228     while (iter != end) {
0229         if (iter.value()->parentName() == oldName)
0230             iter.value()->setParentName(newName);
0231 
0232         ++iter;
0233     }
0234 
0235     iter = m_styles.find(oldName);
0236     if (iter != end) {
0237         CustomStyle * s = iter.value();
0238         m_styles.erase(iter);
0239         m_styles[newName] = s;
0240     }
0241 }
0242 
0243 void StyleManager::insertStyle(CustomStyle *style)
0244 {
0245     const QString base = style->name();
0246     // do not add the default style
0247     if (base == "Default" && style->type() == Style::BUILTIN)
0248         return;
0249     int num = 1;
0250     QString name = base;
0251     while (name == "Default" || (m_styles.contains(name) && (m_styles[name] != style))) {
0252         name = base;
0253         name += QString::number(num++);
0254     }
0255     if (base != name)
0256         style->setName(name);
0257     m_styles[name] = style;
0258 }
0259 
0260 QStringList StyleManager::styleNames(bool includeDefault) const
0261 {
0262     QStringList list;
0263 
0264     if (includeDefault) list.push_back(i18n("Default"));
0265 
0266     CustomStyles::const_iterator iter = m_styles.begin();
0267     CustomStyles::const_iterator end  = m_styles.end();
0268 
0269     while (iter != end) {
0270         list.push_back(iter.key());
0271 
0272         ++iter;
0273     }
0274 
0275     return list;
0276 }
0277 
0278 void StyleManager::clearOasisStyles()
0279 {
0280     // Now, we can clear the map of styles sorted by OpenDocument name.
0281     m_oasisStyles.clear();
0282 }
0283 
0284 QString StyleManager::openDocumentName(const QString& name) const
0285 {
0286     return m_oasisStyles.value(name);
0287 }
0288 
0289 void StyleManager::dump() const
0290 {
0291     debugSheetsStyle << "Custom styles:";
0292     foreach(const QString &name, m_styles.keys()) {
0293         debugSheetsStyle << name;
0294     }
0295 }