KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

397 lines
11KB

  1. /* This file is part of the KDE project
  2. Copyright (C) 2003 Norbert Andres, nandres@web.de
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. * Boston, MA 02110-1301, USA.
  15. */
  16. #include <tqdom.h>
  17. #include <tqstringlist.h>
  18. #include <kdebug.h>
  19. #include <tdelocale.h>
  20. #include <KoOasisStyles.h>
  21. #include <KoXmlNS.h>
  22. #include "kspread_doc.h"
  23. #include "kspread_style.h"
  24. #include "kspread_style_manager.h"
  25. using namespace KSpread;
  26. StyleManager::StyleManager()
  27. : m_defaultStyle( new CustomStyle() )
  28. {
  29. }
  30. StyleManager::~StyleManager()
  31. {
  32. delete m_defaultStyle;
  33. Styles::iterator iter = m_styles.begin();
  34. Styles::iterator end = m_styles.end();
  35. while ( iter != end )
  36. {
  37. delete iter.data();
  38. ++iter;
  39. }
  40. }
  41. void StyleManager::saveOasis( KoGenStyles &mainStyles )
  42. {
  43. kdDebug() << "StyleManager: Saving default cell style" << endl;
  44. KoGenStyle defaultStyle = KoGenStyle( Doc::STYLE_CELL_USER, "table-cell" );
  45. m_defaultStyle->saveOasis( defaultStyle, mainStyles );
  46. Styles::iterator iter = m_styles.begin();
  47. Styles::iterator end = m_styles.end();
  48. while ( iter != end )
  49. {
  50. kdDebug() << "StyleManager: Saving common cell style " << iter.key() <<endl;
  51. CustomStyle * styleData = iter.data();
  52. KoGenStyle customStyle = KoGenStyle( Doc::STYLE_CELL_USER, "table-cell" );
  53. styleData->saveOasis( customStyle, mainStyles );
  54. ++iter;
  55. }
  56. }
  57. void StyleManager::loadOasisStyleTemplate( KoOasisStyles& oasisStyles )
  58. {
  59. // reset the map of OpenDocument Styles
  60. m_oasisStyles.clear();
  61. // loading default style first
  62. const TQDomElement* defaultStyle = oasisStyles.defaultStyle( "table-cell" );
  63. if ( defaultStyle )
  64. {
  65. kdDebug() << "StyleManager: Loading default cell style" << endl;
  66. m_defaultStyle->loadOasis( oasisStyles, *defaultStyle, "Default" );
  67. m_defaultStyle->setType( Style::BUILTIN );
  68. }
  69. else
  70. {
  71. delete m_defaultStyle;
  72. m_defaultStyle = new CustomStyle();
  73. }
  74. // insert it into the the map sorted the OpenDocument name
  75. m_oasisStyles["Default"] = m_defaultStyle;
  76. uint nStyles = oasisStyles.userStyles().count();
  77. for (unsigned int item = 0; item < nStyles; item++) {
  78. TQDomElement styleElem = oasisStyles.userStyles()[item];
  79. // assume the name assigned by the application
  80. const TQString oasisName = styleElem.attributeNS( KoXmlNS::style, "name", TQString() );
  81. // then replace by user-visible one (if any)
  82. const TQString name = styleElem.attributeNS( KoXmlNS::style, "display-name", oasisName );
  83. kdDebug() << " StyleManager: Loading common cell style: " << oasisName << " (display name: " << name << ")" << endl;
  84. if ( !name.isEmpty() )
  85. {
  86. CustomStyle * style = 0;
  87. if ( styleElem.hasAttributeNS( KoXmlNS::style, "parent-style-name" ) )
  88. // The style's parent name will be set in Style::loadOasis(..).
  89. // After all styles are loaded the pointer to the parent is set.
  90. style = new CustomStyle( name, 0 );
  91. else
  92. style = new CustomStyle( name, m_defaultStyle );
  93. //fixme test return;
  94. style->loadOasis( oasisStyles, styleElem, name );
  95. m_styles[name] = style;
  96. // insert it into the the map sorted the OpenDocument name
  97. m_oasisStyles[oasisName] = style;
  98. kdDebug() << "Style " << name << ": " << style << endl;
  99. }
  100. }
  101. // set the parent pointers after we loaded all styles
  102. Styles::iterator iter = m_styles.begin();
  103. Styles::iterator end = m_styles.end();
  104. while ( iter != end )
  105. {
  106. CustomStyle * styleData = iter.data();
  107. if ( styleData->name() != "Default" )
  108. if ( !styleData->parent() && !styleData->parentName().isNull() )
  109. styleData->setParent( m_oasisStyles[ styleData->parentName() ] );
  110. ++iter;
  111. }
  112. }
  113. TQDomElement StyleManager::save( TQDomDocument & doc )
  114. {
  115. kdDebug() << "Saving styles" << endl;
  116. TQDomElement styles = doc.createElement( "styles" );
  117. kdDebug() << "Saving default style" << endl;
  118. m_defaultStyle->save( doc, styles );
  119. Styles::iterator iter = m_styles.begin();
  120. Styles::iterator end = m_styles.end();
  121. while ( iter != end )
  122. {
  123. kdDebug() << "Saving style" << endl;
  124. CustomStyle * styleData = iter.data();
  125. styleData->save( doc, styles );
  126. ++iter;
  127. }
  128. kdDebug() << "End saving styles" << endl;
  129. return styles;
  130. }
  131. bool StyleManager::loadXML( TQDomElement const & styles )
  132. {
  133. TQDomElement e = styles.firstChild().toElement();
  134. while ( !e.isNull() )
  135. {
  136. TQString name;
  137. if ( e.hasAttribute( "name" ) )
  138. name = e.attribute( "name" );
  139. if ( name == "Default" )
  140. {
  141. if ( !m_defaultStyle->loadXML( e, name ) )
  142. return false;
  143. m_defaultStyle->setType( Style::BUILTIN );
  144. }
  145. else if ( !name.isNull() )
  146. {
  147. CustomStyle * style = 0;
  148. if ( e.hasAttribute( "parent" ) && e.attribute( "parent" ) == "Default" )
  149. style = new CustomStyle( name, m_defaultStyle );
  150. else
  151. style = new CustomStyle( name, 0 );
  152. if ( !style->loadXML( e, name ) )
  153. {
  154. delete style;
  155. return false;
  156. }
  157. if ( style->type() == Style::AUTO )
  158. style->setType( Style::CUSTOM );
  159. m_styles[name] = style;
  160. kdDebug() << "Style " << name << ": " << style << endl;
  161. }
  162. e = e.nextSibling().toElement();
  163. }
  164. Styles::iterator iter = m_styles.begin();
  165. Styles::iterator end = m_styles.end();
  166. while ( iter != end )
  167. {
  168. CustomStyle * styleData = iter.data();
  169. if ( !styleData->parent() && !styleData->parentName().isNull() )
  170. styleData->setParent( m_styles[ styleData->parentName() ] );
  171. ++iter;
  172. }
  173. m_defaultStyle->setName( "Default" );
  174. m_defaultStyle->setType( Style::BUILTIN );
  175. return true;
  176. }
  177. void StyleManager::createBuiltinStyles()
  178. {
  179. CustomStyle * header1 = new CustomStyle( i18n( "Header" ), m_defaultStyle );
  180. TQFont f( header1->font() );
  181. f.setItalic( true );
  182. f.setPointSize( f.pointSize() + 2 );
  183. f.setBold( true );
  184. header1->changeFont( f );
  185. header1->setType( Style::BUILTIN );
  186. m_styles[ header1->name() ] = header1;
  187. CustomStyle * header2 = new CustomStyle( i18n( "Header1" ), header1 );
  188. TQColor color( "#F0F0FF" );
  189. header2->changeBgColor( color );
  190. TQPen pen( TQt::black, 1, TQt::SolidLine );
  191. header2->changeBottomBorderPen( pen );
  192. header2->setType( Style::BUILTIN );
  193. m_styles[ header2->name() ] = header2;
  194. }
  195. CustomStyle * StyleManager::style( TQString const & name ) const
  196. {
  197. Styles::const_iterator iter( m_styles.find( name ) );
  198. if ( iter != m_styles.end() )
  199. return iter.data();
  200. if ( name == "Default" )
  201. return m_defaultStyle;
  202. return 0;
  203. }
  204. void StyleManager::takeStyle( CustomStyle * style )
  205. {
  206. CustomStyle * parent = style->parent();
  207. Styles::iterator iter = m_styles.begin();
  208. Styles::iterator end = m_styles.end();
  209. while ( iter != end )
  210. {
  211. if ( iter.data()->parent() == style )
  212. iter.data()->setParent( parent );
  213. ++iter;
  214. }
  215. Styles::iterator i( m_styles.find( style->name() ) );
  216. if ( i != m_styles.end() )
  217. {
  218. kdDebug() << "Erasing style entry for " << style->name() << endl;
  219. m_styles.erase( i );
  220. }
  221. }
  222. bool StyleManager::checkCircle( TQString const & name, TQString const & parent )
  223. {
  224. CustomStyle * s = style( parent );
  225. if ( !s || s->parent() == 0 )
  226. return true;
  227. if ( s->parentName() == name )
  228. return false;
  229. else
  230. return checkCircle( name, s->parentName() );
  231. }
  232. bool StyleManager::validateStyleName( TQString const & name, CustomStyle * style )
  233. {
  234. if ( m_defaultStyle->name() == name || name == "Default" )
  235. return false;
  236. Styles::const_iterator iter = m_styles.begin();
  237. Styles::const_iterator end = m_styles.end();
  238. while ( iter != end )
  239. {
  240. if ( iter.key() == name && iter.data() != style )
  241. return false;
  242. ++iter;
  243. }
  244. return true;
  245. }
  246. void StyleManager::changeName( TQString const & oldName, TQString const & newName )
  247. {
  248. Styles::iterator iter = m_styles.begin();
  249. Styles::iterator end = m_styles.end();
  250. while ( iter != end )
  251. {
  252. if ( iter.data()->parentName() == oldName )
  253. iter.data()->refreshParentName();
  254. ++iter;
  255. }
  256. iter = m_styles.find( oldName );
  257. if ( iter != end )
  258. {
  259. CustomStyle * s = iter.data();
  260. m_styles.erase( iter );
  261. m_styles[newName] = s;
  262. }
  263. }
  264. TQStringList StyleManager::styleNames() const
  265. {
  266. TQStringList list;
  267. list.push_back( i18n("Default") );
  268. Styles::const_iterator iter = m_styles.begin();
  269. Styles::const_iterator end = m_styles.end();
  270. while ( iter != end )
  271. {
  272. list.push_back( iter.key() );
  273. ++iter;
  274. }
  275. return list;
  276. }
  277. TQDict<Style> StyleManager::loadOasisAutoStyles( KoOasisStyles& oasisStyles )
  278. {
  279. TQDictIterator<TQDomElement> it( oasisStyles.styles("table-cell") );
  280. TQDict<Style> autoStyles;
  281. for (;it.current();++it)
  282. {
  283. if ( it.current()->hasAttributeNS( KoXmlNS::style , "name" ) )
  284. {
  285. TQString name = it.current()->attributeNS( KoXmlNS::style , "name" , TQString() );
  286. kdDebug() << "StyleManager: Preloading automatic cell style: " << name << endl;
  287. autoStyles.insert( name , new Style());
  288. autoStyles[name]->loadOasisStyle( oasisStyles , *(it.current()) );
  289. if ( it.current()->hasAttributeNS( KoXmlNS::style, "parent-style-name" ) )
  290. {
  291. TQString parentStyleName = it.current()->attributeNS( KoXmlNS::style, "parent-style-name", TQString() );
  292. if ( m_oasisStyles.contains( parentStyleName ) )
  293. {
  294. autoStyles[name]->setParent( m_oasisStyles[parentStyleName] );
  295. }
  296. kdDebug() << "\t parent-style-name:" << parentStyleName << endl;
  297. }
  298. else
  299. {
  300. autoStyles[name]->setParent( m_defaultStyle );
  301. }
  302. }
  303. }
  304. return autoStyles;
  305. }
  306. void StyleManager::releaseUnusedAutoStyles( TQDict<Style> autoStyles )
  307. {
  308. TQDictIterator<Style> styleIt( autoStyles );
  309. for (;styleIt.current();++styleIt)
  310. {
  311. Style* style = styleIt.current();
  312. if (style->release())
  313. delete style;
  314. }
  315. // Now, we can clear the map of styles sorted by OpenDocument name.
  316. m_oasisStyles.clear();
  317. }