lib

KoStyleCollection.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 David Faure <faure@kde.org>
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 "KoStyleCollection.h"
00021 #include "KoOasisContext.h"
00022 #include "KoParagCounter.h"
00023 
00024 #include <KoOasisStyles.h>
00025 #include <KoGenStyles.h>
00026 #include <KoXmlWriter.h>
00027 #include <KoXmlNS.h>
00028 
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 
00032 #include <qdom.h>
00033 
00034 KoStyleCollection::KoStyleCollection()
00035     : KoUserStyleCollection( "paragsty" )
00036 {
00037 }
00038 
00039 KoStyleCollection::~KoStyleCollection()
00040 {
00041 }
00042 
00043 int KoStyleCollection::loadOasisStyles( KoOasisContext& context )
00044 {
00045     QStringList followingStyles;
00046     QValueVector<QDomElement> userStyles = context.oasisStyles().userStyles();
00047     bool defaultStyleDeleted = false;
00048     int stylesLoaded = 0;
00049     const unsigned int nStyles = userStyles.count();
00050     for (unsigned int item = 0; item < nStyles; item++) {
00051         QDomElement styleElem = userStyles[item];
00052     Q_ASSERT( !styleElem.isNull() );
00053 
00054         if ( styleElem.attributeNS( KoXmlNS::style, "family", QString::null ) != "paragraph" )
00055             continue;
00056 
00057         if( !defaultStyleDeleted ) { // we are going to import at least one style.
00058             KoParagStyle *s = defaultStyle();
00059             //kdDebug() << "loadOasisStyles looking for Standard, to delete it. Found " << s << endl;
00060             if(s) // delete the standard style.
00061                 removeStyle(s);
00062             defaultStyleDeleted = true;
00063         }
00064 
00065         KoParagStyle *sty = new KoParagStyle( QString::null );
00066         // Load the style
00067         sty->loadStyle( styleElem, context );
00068         // Style created, now let's try to add it
00069         const int oldStyleCount = count();
00070         sty = addStyle( sty );
00071         // the real value of followingStyle is set below after loading all styles
00072         sty->setFollowingStyle( sty );
00073 
00074         kdDebug() << " Loaded style " << sty->name() << endl;
00075 
00076         if ( count() > oldStyleCount )
00077         {
00078             const QString following = styleElem.attributeNS( KoXmlNS::style, "next-style-name", QString::null );
00079             followingStyles.append( following );
00080             ++stylesLoaded;
00081         }
00082         else
00083             kdWarning() << "Found duplicate style declaration, overwriting former " << sty->name() << endl;
00084     }
00085 
00086     if( followingStyles.count() != styleList().count() ) {
00087         kdDebug() << "Ouch, " << followingStyles.count() << " following-styles, but "
00088                        << styleList().count() << " styles in styleList" << endl;
00089     }
00090 
00091     unsigned int i=0;
00092     for( QValueList<QString>::ConstIterator it = followingStyles.begin(); it != followingStyles.end(); ++it, ++i ) {
00093         const QString followingStyleName = *it;
00094     if ( !followingStyleName.isEmpty() ) {
00095             KoParagStyle * style = findStyle( followingStyleName );
00096         if ( style )
00097                 styleAt(i)->setFollowingStyle( style );
00098     }
00099     }
00100 
00101     // TODO the same thing for style inheritance (style:parent-style-name) and setParentStyle()
00102 
00103     Q_ASSERT( defaultStyle() );
00104     return stylesLoaded;
00105 }
00106 
00107 void KoStyleCollection::saveOasis( KoGenStyles& styles, int styleType, KoSavingContext& context ) const
00108 {
00109     // In order to reduce the bloat, we define that the first style (usually Standard)
00110     // is the "parent" (reference) for the others.
00111     // ## This is mostly a hack due to lack of proper style inheritance.
00112     // Once that's implemented, default to 'styles derive from Standard', but save normally.
00113     QString refStyleName;
00114 
00115     for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
00116         KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
00117         style->saveStyle( styles, styleType, refStyleName, context );
00118         kdDebug() << k_funcinfo << "Saved style " << style->displayName() << " to OASIS format as " << style->name() << endl;
00119         if ( refStyleName.isEmpty() ) // i.e. first style
00120             refStyleName = style->name();
00121     }
00122     // Now edit the kogenstyle and set the next-style-name. This works here
00123     // because the style's m_name is already unique so there's no risk of
00124     // "two styles being only different due to their following-style"; the
00125     // display-name will also be different, and will ensure they get two kogenstyles.
00126     for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
00127         KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
00128         if ( style->followingStyle() && style->followingStyle() != style ) {
00129             const QString fsname = style->followingStyle()->name();
00130             KoGenStyle* gs = styles.styleForModification( style->name() );
00131             Q_ASSERT( gs );
00132             if ( gs )
00133                 gs->addAttribute( "style:next-style-name", fsname );
00134         }
00135     }
00136 }
00137 
00138 void KoStyleCollection::importStyles( const KoStyleCollection& styleCollection )
00139 {
00140     const QValueList<KoUserStyle *> styles = styleCollection.styleList();
00141     QMap<QString, QString> followStyle;
00142     for ( QValueList<KoUserStyle *>::const_iterator styleIt = styles.begin(), styleEnd = styles.end() ; styleIt != styleEnd ; ++styleIt ) {
00143         KoParagStyle* p = static_cast<KoParagStyle *>( *styleIt );
00144         KoParagStyle* style = new KoParagStyle( *p );
00145         if ( style->followingStyle() ) {
00146             followStyle.insert( style->name(), style->followingStyle()->name() );
00147         }
00148         style = addStyle( style );
00149     }
00150 
00151     QMapIterator<QString, QString> itFollow = followStyle.begin();
00152     for ( ; itFollow != followStyle.end(); ++itFollow )
00153     {
00154         KoParagStyle * style = findStyle(itFollow.key());
00155         const QString followingStyleName = followStyle[ itFollow.key() ];
00156         KoParagStyle * styleFollow = findStyle(followingStyleName);
00157         //kdDebug() << "    " << style << "  " << itFollow.key() << ": followed by " << styleFollow << " (" << followingStyleName << ")" << endl;
00158         Q_ASSERT(styleFollow);
00159         if ( styleFollow )
00160             style->setFollowingStyle( styleFollow );
00161         else
00162             style->setFollowingStyle( style );
00163     }
00164 }
00165 
00166 void KoStyleCollection::saveOasisOutlineStyles( KoXmlWriter& writer ) const
00167 {
00168     bool first = true;
00169     QValueVector<KoParagStyle *> styles = outlineStyles();
00170     for ( int i = 0 ; i < 10 ; ++i ) {
00171         if ( styles[i] ) {
00172             if ( first ) {
00173                 writer.startElement( "text:outline-style" );
00174                 first = false;
00175             }
00176             writer.startElement( "text:outline-level-style" );
00177             styles[i]->paragLayout().counter->saveOasisListLevel( writer, true, true );
00178             writer.endElement();
00179         }
00180     }
00181     if ( !first )
00182         writer.endElement(); // text:outline-style
00183 }
00184 
00185 QValueVector<KoParagStyle *> KoStyleCollection::outlineStyles() const
00186 {
00187     QValueVector<KoParagStyle *> lst( 10, 0 );
00188     for ( int i = 0 ; i < 10 ; ++i ) {
00189         KoParagStyle* style = outlineStyleForLevel( i );
00190         if ( style )
00191             lst[i] = style;
00192     }
00193     return lst;
00194 }
00195 
00196 
00197 KoParagStyle* KoStyleCollection::outlineStyleForLevel( int level ) const
00198 {
00199     for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
00200         KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
00201         if ( style->isOutline() && style->paragLayout().counter )
00202         {
00203             int styleLevel = style->paragLayout().counter->depth();
00204             if ( styleLevel == level )
00205                 return style;
00206         }
00207     }
00208     return 0;
00209 }
00210 
00211 KoParagStyle* KoStyleCollection::numberedStyleForLevel( int level ) const
00212 {
00213     for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
00214         KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
00215         KoParagCounter* counter = style->paragLayout().counter;
00216         if ( !style->isOutline() && counter
00217              && counter->numbering() != KoParagCounter::NUM_NONE
00218              && !counter->isBullet() )
00219         {
00220             int styleLevel = counter->depth();
00221             if ( styleLevel == level )
00222                 return style;
00223         }
00224     }
00225     return 0;
00226 }
00227 
00228 KoParagStyle* KoStyleCollection::defaultStyle() const
00229 {
00230     return findStyle( "Standard" ); // includes the fallback to first style
00231 }
00232 
00233 #ifndef NDEBUG
00234 void KoStyleCollection::printDebug() const
00235 {
00236     for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt ) {
00237         KoParagStyle* style = static_cast<KoParagStyle *>( *styleIt );
00238 
00239         // short version:
00240         // kdDebug() << style << "  " << style->name() << "    " << style->displayName() << "  followingStyle=" << style->followingStyle() << endl;
00241 
00242         kdDebug() << "Style " << style << "  " << style->name() << "  isOutline=" << style->isOutline() << endl;
00243         kdDebug() << "   format: " << style->format().key() <<endl;
00244         static const char * const s_align[] = { "Auto", "Left", "Right", "ERROR", "HCenter", "ERR", "ERR", "ERR", "Justify", };
00245         kdDebug() << "  align: " << s_align[(Qt::AlignmentFlags)style->paragLayout().alignment] << endl;
00246         if ( style->paragLayout().counter )
00247             kdDebug() << "  counter level=" << style->paragLayout().counter->depth() << endl;
00248 
00249         kdDebug() << "   following style: " << style->followingStyle() << " "
00250                   << ( style->followingStyle() ? style->followingStyle()->name() : QString::null ) << endl;
00251 
00252     }
00253 }
00254 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys