kspread

kspread_style_manager.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Norbert Andres, nandres@web.de
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <qdom.h>
00021 #include <qstringlist.h>
00022 
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025 
00026 #include <KoOasisStyles.h>
00027 #include <KoXmlNS.h>
00028 
00029 #include "kspread_doc.h"
00030 #include "kspread_style.h"
00031 #include "kspread_style_manager.h"
00032 
00033 using namespace KSpread;
00034 
00035 StyleManager::StyleManager()
00036   : m_defaultStyle( new CustomStyle() )
00037 {
00038 }
00039 
00040 StyleManager::~StyleManager()
00041 {
00042   delete m_defaultStyle;
00043 
00044   Styles::iterator iter = m_styles.begin();
00045   Styles::iterator end  = m_styles.end();
00046 
00047   while ( iter != end )
00048   {
00049     delete iter.data();
00050 
00051     ++iter;
00052   }
00053 }
00054 
00055 void StyleManager::saveOasis( KoGenStyles &mainStyles )
00056 {
00057     kdDebug() << "StyleManager: Saving default cell style" << endl;
00058     KoGenStyle defaultStyle = KoGenStyle( Doc::STYLE_CELL_USER, "table-cell" );
00059     m_defaultStyle->saveOasis( defaultStyle, mainStyles );
00060 
00061     Styles::iterator iter = m_styles.begin();
00062     Styles::iterator end  = m_styles.end();
00063 
00064     while ( iter != end )
00065     {
00066         kdDebug() << "StyleManager: Saving common cell style " << iter.key() <<endl;
00067         CustomStyle * styleData = iter.data();
00068 
00069         KoGenStyle customStyle = KoGenStyle( Doc::STYLE_CELL_USER, "table-cell" );
00070         styleData->saveOasis( customStyle, mainStyles );
00071 
00072         ++iter;
00073     }
00074 }
00075 
00076 void StyleManager::loadOasisStyleTemplate( KoOasisStyles& oasisStyles )
00077 {
00078     // reset the map of OpenDocument Styles
00079     m_oasisStyles.clear();
00080 
00081     // loading default style first
00082     const QDomElement* defaultStyle = oasisStyles.defaultStyle( "table-cell" );
00083     if ( defaultStyle )
00084     {
00085       kdDebug() << "StyleManager: Loading default cell style" << endl;
00086       m_defaultStyle->loadOasis( oasisStyles, *defaultStyle, "Default" );
00087       m_defaultStyle->setType( Style::BUILTIN );
00088     }
00089     else
00090     {
00091       delete m_defaultStyle;
00092       m_defaultStyle = new CustomStyle();
00093     }
00094     // insert it into the the map sorted the OpenDocument name
00095     m_oasisStyles["Default"] = m_defaultStyle;
00096 
00097     uint nStyles = oasisStyles.userStyles().count();
00098     for (unsigned int item = 0; item < nStyles; item++) {
00099         QDomElement styleElem = oasisStyles.userStyles()[item];
00100 
00101         // assume the name assigned by the application
00102         const QString oasisName = styleElem.attributeNS( KoXmlNS::style, "name", QString::null );
00103 
00104         // then replace by user-visible one (if any)
00105         const QString name = styleElem.attributeNS( KoXmlNS::style, "display-name", oasisName );
00106         kdDebug() << " StyleManager: Loading common cell style: " << oasisName << " (display name: " << name << ")" << endl;
00107 
00108         if ( !name.isEmpty() )
00109         {
00110             CustomStyle * style = 0;
00111             if ( styleElem.hasAttributeNS( KoXmlNS::style, "parent-style-name" ) )
00112                 // The style's parent name will be set in Style::loadOasis(..).
00113                 // After all styles are loaded the pointer to the parent is set.
00114                 style = new CustomStyle( name, 0 );
00115             else
00116                 style = new CustomStyle( name, m_defaultStyle );
00117 
00118             //fixme test return;
00119             style->loadOasis( oasisStyles, styleElem, name );
00120             m_styles[name] = style;
00121             // insert it into the the map sorted the OpenDocument name
00122             m_oasisStyles[oasisName] = style;
00123             kdDebug() << "Style " << name << ": " << style << endl;
00124         }
00125     }
00126 
00127     // set the parent pointers after we loaded all styles
00128     Styles::iterator iter = m_styles.begin();
00129     Styles::iterator end  = m_styles.end();
00130     while ( iter != end )
00131     {
00132         CustomStyle * styleData = iter.data();
00133 
00134         if ( styleData->name() != "Default" )
00135             if ( !styleData->parent() && !styleData->parentName().isNull() )
00136                 styleData->setParent( m_oasisStyles[ styleData->parentName() ] );
00137 
00138         ++iter;
00139     }
00140 }
00141 
00142 QDomElement StyleManager::save( QDomDocument & doc )
00143 {
00144   kdDebug() << "Saving styles" << endl;
00145   QDomElement styles = doc.createElement( "styles" );
00146 
00147   kdDebug() << "Saving default style" << endl;
00148   m_defaultStyle->save( doc, styles );
00149 
00150   Styles::iterator iter = m_styles.begin();
00151   Styles::iterator end  = m_styles.end();
00152 
00153   while ( iter != end )
00154   {
00155     kdDebug() << "Saving style" << endl;
00156     CustomStyle * styleData = iter.data();
00157 
00158     styleData->save( doc, styles );
00159 
00160     ++iter;
00161   }
00162 
00163   kdDebug() << "End saving styles" << endl;
00164   return styles;
00165 }
00166 
00167 bool StyleManager::loadXML( QDomElement const & styles )
00168 {
00169   QDomElement e = styles.firstChild().toElement();
00170   while ( !e.isNull() )
00171   {
00172     QString name;
00173     if ( e.hasAttribute( "name" ) )
00174       name = e.attribute( "name" );
00175 
00176     if ( name == "Default" )
00177     {
00178       if ( !m_defaultStyle->loadXML( e, name ) )
00179         return false;
00180       m_defaultStyle->setType( Style::BUILTIN );
00181     }
00182     else if ( !name.isNull() )
00183     {
00184       CustomStyle * style = 0;
00185       if ( e.hasAttribute( "parent" ) && e.attribute( "parent" ) == "Default" )
00186         style = new CustomStyle( name, m_defaultStyle );
00187       else
00188         style = new CustomStyle( name, 0 );
00189 
00190       if ( !style->loadXML( e, name ) )
00191       {
00192         delete style;
00193         return false;
00194       }
00195 
00196       if ( style->type() == Style::AUTO )
00197         style->setType( Style::CUSTOM );
00198       m_styles[name] = style;
00199       kdDebug() << "Style " << name << ": " << style << endl;
00200     }
00201 
00202     e = e.nextSibling().toElement();
00203   }
00204 
00205   Styles::iterator iter = m_styles.begin();
00206   Styles::iterator end  = m_styles.end();
00207 
00208   while ( iter != end )
00209   {
00210     CustomStyle * styleData = iter.data();
00211 
00212     if ( !styleData->parent() && !styleData->parentName().isNull() )
00213       styleData->setParent( m_styles[ styleData->parentName() ] );
00214 
00215     ++iter;
00216   }
00217 
00218   m_defaultStyle->setName( "Default" );
00219   m_defaultStyle->setType( Style::BUILTIN );
00220 
00221   return true;
00222 }
00223 
00224 void StyleManager::createBuiltinStyles()
00225 {
00226   CustomStyle * header1 = new CustomStyle( i18n( "Header" ), m_defaultStyle );
00227   QFont f( header1->font() );
00228   f.setItalic( true );
00229   f.setPointSize( f.pointSize() + 2 );
00230   f.setBold( true );
00231   header1->changeFont( f );
00232   header1->setType( Style::BUILTIN );
00233   m_styles[ header1->name() ] = header1;
00234 
00235   CustomStyle * header2 = new CustomStyle( i18n( "Header1" ), header1 );
00236   QColor color( "#F0F0FF" );
00237   header2->changeBgColor( color );
00238   QPen pen( Qt::black, 1, Qt::SolidLine );
00239   header2->changeBottomBorderPen( pen );
00240   header2->setType( Style::BUILTIN );
00241 
00242   m_styles[ header2->name() ] = header2;
00243 }
00244 
00245 CustomStyle * StyleManager::style( QString const & name ) const
00246 {
00247   Styles::const_iterator iter( m_styles.find( name ) );
00248 
00249   if ( iter != m_styles.end() )
00250     return iter.data();
00251 
00252   if ( name == "Default" )
00253     return m_defaultStyle;
00254 
00255   return 0;
00256 }
00257 
00258 void StyleManager::takeStyle( CustomStyle * style )
00259 {
00260   CustomStyle * parent = style->parent();
00261 
00262   Styles::iterator iter = m_styles.begin();
00263   Styles::iterator end  = m_styles.end();
00264 
00265   while ( iter != end )
00266   {
00267     if ( iter.data()->parent() == style )
00268       iter.data()->setParent( parent );
00269 
00270     ++iter;
00271   }
00272 
00273   Styles::iterator i( m_styles.find( style->name() ) );
00274 
00275   if ( i != m_styles.end() )
00276   {
00277     kdDebug() << "Erasing style entry for " << style->name() << endl;
00278     m_styles.erase( i );
00279   }
00280 }
00281 
00282 bool StyleManager::checkCircle( QString const & name, QString const & parent )
00283 {
00284   CustomStyle * s = style( parent );
00285   if ( !s || s->parent() == 0 )
00286     return true;
00287   if ( s->parentName() == name )
00288     return false;
00289   else
00290     return checkCircle( name, s->parentName() );
00291 }
00292 
00293 bool StyleManager::validateStyleName( QString const & name, CustomStyle * style )
00294 {
00295   if ( m_defaultStyle->name() == name || name == "Default" )
00296     return false;
00297 
00298   Styles::const_iterator iter = m_styles.begin();
00299   Styles::const_iterator end  = m_styles.end();
00300 
00301   while ( iter != end )
00302   {
00303     if ( iter.key() == name && iter.data() != style )
00304       return false;
00305 
00306     ++iter;
00307   }
00308 
00309   return true;
00310 }
00311 
00312 void StyleManager::changeName( QString const & oldName, QString const & newName )
00313 {
00314   Styles::iterator iter = m_styles.begin();
00315   Styles::iterator end  = m_styles.end();
00316 
00317   while ( iter != end )
00318   {
00319     if ( iter.data()->parentName() == oldName )
00320       iter.data()->refreshParentName();
00321 
00322     ++iter;
00323   }
00324 
00325   iter = m_styles.find( oldName );
00326   if ( iter != end )
00327   {
00328     CustomStyle * s = iter.data();
00329     m_styles.erase( iter );
00330     m_styles[newName] = s;
00331   }
00332 }
00333 
00334 QStringList StyleManager::styleNames() const
00335 {
00336   QStringList list;
00337 
00338   list.push_back( i18n("Default") );
00339 
00340   Styles::const_iterator iter = m_styles.begin();
00341   Styles::const_iterator end  = m_styles.end();
00342 
00343   while ( iter != end )
00344   {
00345     list.push_back( iter.key() );
00346 
00347     ++iter;
00348   }
00349 
00350   return list;
00351 }
00352 
00353 QDict<Style> StyleManager::loadOasisAutoStyles( KoOasisStyles& oasisStyles )
00354 {
00355   QDictIterator<QDomElement> it( oasisStyles.styles("table-cell") );
00356   QDict<Style> autoStyles;
00357   for (;it.current();++it)
00358   {
00359     if ( it.current()->hasAttributeNS( KoXmlNS::style , "name" ) )
00360     {
00361       QString name = it.current()->attributeNS( KoXmlNS::style , "name" , QString::null );
00362       kdDebug() << "StyleManager: Preloading automatic cell style: " << name << endl;
00363       autoStyles.insert( name , new Style());
00364       autoStyles[name]->loadOasisStyle( oasisStyles , *(it.current()) );
00365 
00366       if ( it.current()->hasAttributeNS( KoXmlNS::style, "parent-style-name" ) )
00367       {
00368         QString parentStyleName = it.current()->attributeNS( KoXmlNS::style, "parent-style-name", QString::null );
00369         if ( m_oasisStyles.contains( parentStyleName ) )
00370         {
00371           autoStyles[name]->setParent( m_oasisStyles[parentStyleName] );
00372         }
00373         kdDebug() << "\t parent-style-name:" << parentStyleName << endl;
00374       }
00375       else
00376       {
00377         autoStyles[name]->setParent( m_defaultStyle );
00378       }
00379     }
00380   }
00381   return autoStyles;
00382 }
00383 
00384 void StyleManager::releaseUnusedAutoStyles( QDict<Style> autoStyles )
00385 {
00386   QDictIterator<Style> styleIt( autoStyles );
00387   for (;styleIt.current();++styleIt)
00388   {
00389     Style* style = styleIt.current();
00390     if (style->release())
00391       delete style;
00392   }
00393 
00394   // Now, we can clear the map of styles sorted by OpenDocument name.
00395   m_oasisStyles.clear();
00396 }
KDE Home | KDE Accessibility Home | Description of Access Keys