/* This file is part of the KDE project Copyright (C) 2001 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoStyleCollection.h" #include "KoOasisContext.h" #include "KoParagCounter.h" #include #include #include #include #include #include #include KoStyleCollection::KoStyleCollection() : KoUserStyleCollection( "paragsty" ) { } KoStyleCollection::~KoStyleCollection() { } int KoStyleCollection::loadOasisStyles( KoOasisContext& context ) { TQStringList followingStyles; TQValueVector userStyles = context.oasisStyles().userStyles(); bool defaultStyleDeleted = false; int stylesLoaded = 0; const unsigned int nStyles = userStyles.count(); for (unsigned int item = 0; item < nStyles; item++) { TQDomElement styleElem = userStyles[item]; Q_ASSERT( !styleElem.isNull() ); if ( styleElem.attributeNS( KoXmlNS::style, "family", TQString() ) != "paragraph" ) continue; if( !defaultStyleDeleted ) { // we are going to import at least one style. KoParagStyle *s = defaultStyle(); //kdDebug() << "loadOasisStyles looking for Standard, to delete it. Found " << s << endl; if(s) // delete the standard style. removeStyle(s); defaultStyleDeleted = true; } KoParagStyle *sty = new KoParagStyle( TQString() ); // Load the style sty->loadStyle( styleElem, context ); // Style created, now let's try to add it const int oldStyleCount = count(); sty = addStyle( sty ); // the real value of followingStyle is set below after loading all styles sty->setFollowingStyle( sty ); kdDebug() << " Loaded style " << sty->name() << endl; if ( count() > oldStyleCount ) { const TQString following = styleElem.attributeNS( KoXmlNS::style, "next-style-name", TQString() ); followingStyles.append( following ); ++stylesLoaded; } else kdWarning() << "Found duplicate style declaration, overwriting former " << sty->name() << endl; } if( followingStyles.count() != styleList().count() ) { kdDebug() << "Ouch, " << followingStyles.count() << " following-styles, but " << styleList().count() << " styles in styleList" << endl; } unsigned int i=0; for( TQValueList::ConstIterator it = followingStyles.begin(); it != followingStyles.end(); ++it, ++i ) { const TQString followingStyleName = *it; if ( !followingStyleName.isEmpty() ) { KoParagStyle * style = findStyle( followingStyleName ); if ( style ) styleAt(i)->setFollowingStyle( style ); } } // TODO the same thing for style inheritance (style:parent-style-name) and setParentStyle() Q_ASSERT( defaultStyle() ); return stylesLoaded; } void KoStyleCollection::saveOasis( KoGenStyles& styles, int styleType, KoSavingContext& context ) const { // In order to reduce the bloat, we define that the first style (usually Standard) // is the "parent" (reference) for the others. // ## This is mostly a hack due to lack of proper style inheritance. // Once that's implemented, default to 'styles derive from Standard', but save normally. TQString refStyleName; for ( TQValueList::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) { KoParagStyle* style = static_cast( *styleIt ); style->saveStyle( styles, styleType, refStyleName, context ); kdDebug() << k_funcinfo << "Saved style " << style->displayName() << " to OASIS format as " << style->name() << endl; if ( refStyleName.isEmpty() ) // i.e. first style refStyleName = style->name(); } // Now edit the kogenstyle and set the next-style-name. This works here // because the style's m_name is already unique so there's no risk of // "two styles being only different due to their following-style"; the // display-name will also be different, and will ensure they get two kogenstyles. for ( TQValueList::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) { KoParagStyle* style = static_cast( *styleIt ); if ( style->followingStyle() && style->followingStyle() != style ) { const TQString fsname = style->followingStyle()->name(); KoGenStyle* gs = styles.styleForModification( style->name() ); Q_ASSERT( gs ); if ( gs ) gs->addAttribute( "style:next-style-name", fsname ); } } } void KoStyleCollection::importStyles( const KoStyleCollection& styleCollection ) { const TQValueList styles = styleCollection.styleList(); TQMap followStyle; for ( TQValueList::const_iterator styleIt = styles.begin(), styleEnd = styles.end() ; styleIt != styleEnd ; ++styleIt ) { KoParagStyle* p = static_cast( *styleIt ); KoParagStyle* style = new KoParagStyle( *p ); if ( style->followingStyle() ) { followStyle.insert( style->name(), style->followingStyle()->name() ); } style = addStyle( style ); } TQMapIterator itFollow = followStyle.begin(); for ( ; itFollow != followStyle.end(); ++itFollow ) { KoParagStyle * style = findStyle(itFollow.key()); const TQString followingStyleName = followStyle[ itFollow.key() ]; KoParagStyle * styleFollow = findStyle(followingStyleName); //kdDebug() << " " << style << " " << itFollow.key() << ": followed by " << styleFollow << " (" << followingStyleName << ")" << endl; Q_ASSERT(styleFollow); if ( styleFollow ) style->setFollowingStyle( styleFollow ); else style->setFollowingStyle( style ); } } void KoStyleCollection::saveOasisOutlineStyles( KoXmlWriter& writer ) const { bool first = true; TQValueVector styles = outlineStyles(); for ( int i = 0 ; i < 10 ; ++i ) { if ( styles[i] ) { if ( first ) { writer.startElement( "text:outline-style" ); first = false; } writer.startElement( "text:outline-level-style" ); styles[i]->paragLayout().counter->saveOasisListLevel( writer, true, true ); writer.endElement(); } } if ( !first ) writer.endElement(); // text:outline-style } TQValueVector KoStyleCollection::outlineStyles() const { TQValueVector lst( 10, 0 ); for ( int i = 0 ; i < 10 ; ++i ) { KoParagStyle* style = outlineStyleForLevel( i ); if ( style ) lst[i] = style; } return lst; } KoParagStyle* KoStyleCollection::outlineStyleForLevel( int level ) const { for ( TQValueList::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) { KoParagStyle* style = static_cast( *styleIt ); if ( style->isOutline() && style->paragLayout().counter ) { int styleLevel = style->paragLayout().counter->depth(); if ( styleLevel == level ) return style; } } return 0; } KoParagStyle* KoStyleCollection::numberedStyleForLevel( int level ) const { for ( TQValueList::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) { KoParagStyle* style = static_cast( *styleIt ); KoParagCounter* counter = style->paragLayout().counter; if ( !style->isOutline() && counter && counter->numbering() != KoParagCounter::NUM_NONE && !counter->isBullet() ) { int styleLevel = counter->depth(); if ( styleLevel == level ) return style; } } return 0; } KoParagStyle* KoStyleCollection::defaultStyle() const { return findStyle( "Standard" ); // includes the fallback to first style } #ifndef NDEBUG void KoStyleCollection::printDebug() const { for ( TQValueList::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) { KoParagStyle* style = static_cast( *styleIt ); // short version: // kdDebug() << style << " " << style->name() << " " << style->displayName() << " followingStyle=" << style->followingStyle() << endl; kdDebug() << "Style " << style << " " << style->name() << " isOutline=" << style->isOutline() << endl; kdDebug() << " format: " << style->format().key() <paragLayout().alignment] << endl; if ( style->paragLayout().counter ) kdDebug() << " counter level=" << style->paragLayout().counter->depth() << endl; kdDebug() << " following style: " << style->followingStyle() << " " << ( style->followingStyle() ? style->followingStyle()->name() : TQString() ) << endl; } } #endif