00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00079 m_oasisStyles.clear();
00080
00081
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
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
00102 const QString oasisName = styleElem.attributeNS( KoXmlNS::style, "name", QString::null );
00103
00104
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
00113
00114 style = new CustomStyle( name, 0 );
00115 else
00116 style = new CustomStyle( name, m_defaultStyle );
00117
00118
00119 style->loadOasis( oasisStyles, styleElem, name );
00120 m_styles[name] = style;
00121
00122 m_oasisStyles[oasisName] = style;
00123 kdDebug() << "Style " << name << ": " << style << endl;
00124 }
00125 }
00126
00127
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
00395 m_oasisStyles.clear();
00396 }