00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "KoStyleStack.h"
00022 #include "KoUnit.h"
00023 #include "KoDom.h"
00024 #include "KoXmlNS.h"
00025
00026 #include <kdebug.h>
00027
00028
00029
00030 KoStyleStack::KoStyleStack()
00031 : m_styleNSURI( KoXmlNS::style ), m_foNSURI( KoXmlNS::fo )
00032 {
00033 clear();
00034 }
00035
00036 KoStyleStack::KoStyleStack( const char* styleNSURI, const char* foNSURI )
00037 : m_propertiesTagName( "properties" ), m_styleNSURI( styleNSURI ), m_foNSURI( foNSURI )
00038 {
00039 clear();
00040 }
00041
00042 KoStyleStack::~KoStyleStack()
00043 {
00044 }
00045
00046 void KoStyleStack::clear()
00047 {
00048 m_stack.clear();
00049 #ifdef DEBUG_STYLESTACK
00050 kdDebug(30003) << "clear!" << endl;
00051 #endif
00052 }
00053
00054 void KoStyleStack::save()
00055 {
00056 m_marks.push( m_stack.count() );
00057 #ifdef DEBUG_STYLESTACK
00058 kdDebug(30003) << "save (level " << m_marks.count() << ") -> index " << m_stack.count() << endl;
00059 #endif
00060 }
00061
00062 void KoStyleStack::restore()
00063 {
00064 Q_ASSERT( !m_marks.isEmpty() );
00065 int toIndex = m_marks.pop();
00066 #ifdef DEBUG_STYLESTACK
00067 kdDebug(30003) << "restore (level " << m_marks.count()+1 << ") -> to index " << toIndex << endl;
00068 #endif
00069 Q_ASSERT( toIndex > -1 );
00070 Q_ASSERT( toIndex <= (int)m_stack.count() );
00071 for ( int index = (int)m_stack.count() - 1; index >= toIndex; --index )
00072 m_stack.pop_back();
00073 }
00074
00075 void KoStyleStack::pop()
00076 {
00077 Q_ASSERT( !m_stack.isEmpty() );
00078 m_stack.pop_back();
00079 #ifdef DEBUG_STYLESTACK
00080 kdDebug(30003) << "pop -> count=" << m_stack.count() << endl;
00081 #endif
00082 }
00083
00084 void KoStyleStack::push( const QDomElement& style )
00085 {
00086 m_stack.append( style );
00087 #ifdef DEBUG_STYLESTACK
00088 kdDebug(30003) << "pushed " << style.attributeNS( m_styleNSURI, "name", QString::null ) << " -> count=" << m_stack.count() << endl;
00089 #endif
00090 }
00091
00092 bool KoStyleStack::hasAttribute( const QString& name, const QString& detail ) const
00093 {
00094 QString fullName( name );
00095 if ( !detail.isEmpty() )
00096 {
00097 fullName += '-';
00098 fullName += detail;
00099 }
00100 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00101 while ( it != m_stack.begin() )
00102 {
00103 --it;
00104 QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
00105 if ( properties.hasAttribute( name ) ||
00106 ( !detail.isEmpty() && properties.hasAttribute( fullName ) ) )
00107 return true;
00108 }
00109 return false;
00110 }
00111
00112 QString KoStyleStack::attribute( const QString& name, const QString& detail ) const
00113 {
00114 QString fullName( name );
00115 if ( !detail.isEmpty() )
00116 {
00117 fullName += '-';
00118 fullName += detail;
00119 }
00120 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00121 while ( it != m_stack.begin() )
00122 {
00123 --it;
00124 QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
00125 if ( properties.hasAttribute( name ) )
00126 return properties.attribute( name );
00127 if ( !detail.isEmpty() && properties.hasAttribute( fullName ) )
00128 return properties.attribute( fullName );
00129 }
00130 return QString::null;
00131 }
00132
00133 QString KoStyleStack::attributeNS( const char* nsURI, const char* name, const char* detail ) const
00134 {
00135 QString fullName( name );
00136 if ( detail )
00137 {
00138 fullName += '-';
00139 fullName += detail;
00140 }
00141 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00142 while ( it != m_stack.begin() )
00143 {
00144 --it;
00145 QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
00146 if ( properties.hasAttributeNS( nsURI, name ) )
00147 return properties.attributeNS( nsURI, name, QString::null );
00148 if ( detail && properties.hasAttributeNS( nsURI, fullName ) )
00149 return properties.attributeNS( nsURI, fullName, QString::null );
00150 }
00151 return QString::null;
00152 }
00153
00154 bool KoStyleStack::hasAttributeNS( const char* nsURI, const char* name, const char* detail ) const
00155 {
00156 QString fullName( name );
00157 if ( detail )
00158 {
00159 fullName += '-';
00160 fullName += detail;
00161 }
00162 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00163 while ( it != m_stack.begin() )
00164 {
00165 --it;
00166 QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
00167 if ( properties.hasAttributeNS( nsURI, name ) ||
00168 ( detail && properties.hasAttributeNS( nsURI, fullName ) ) )
00169 return true;
00170 }
00171 return false;
00172 }
00173
00174
00175
00176
00177 double KoStyleStack::fontSize() const
00178 {
00179 const QString name = "font-size";
00180 double percent = 1;
00181 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00182
00183 while ( it != m_stack.begin() )
00184 {
00185 --it;
00186 QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName ).toElement();
00187 if ( properties.hasAttributeNS( m_foNSURI, name ) ) {
00188 const QString value = properties.attributeNS( m_foNSURI, name, QString::null );
00189 if ( value.endsWith( "%" ) )
00190 percent *= value.left( value.length() - 1 ).toDouble() / 100.0;
00191 else
00192 return percent * KoUnit::parseValue( value );
00193 }
00194 }
00195 return 0;
00196 }
00197
00198 bool KoStyleStack::hasChildNode(const QString & name) const
00199 {
00200 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00201 while ( it != m_stack.begin() )
00202 {
00203 --it;
00204 QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
00205 if ( !properties.namedItem( name ).isNull() )
00206 return true;
00207 }
00208
00209 return false;
00210 }
00211
00212 QDomElement KoStyleStack::childNode(const QString & name) const
00213 {
00214 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00215
00216 while ( it != m_stack.begin() )
00217 {
00218 --it;
00219 QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
00220 if ( !properties.namedItem( name ).isNull() )
00221 return properties.namedItem( name ).toElement();
00222 }
00223
00224 return QDomElement();
00225 }
00226
00227 bool KoStyleStack::hasChildNodeNS( const char* nsURI, const char* localName ) const
00228 {
00229 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00230 while ( it != m_stack.begin() )
00231 {
00232 --it;
00233 QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
00234 if ( !KoDom::namedItemNS( properties, nsURI, localName ).isNull() )
00235 return true;
00236 }
00237
00238 return false;
00239 }
00240
00241 QDomElement KoStyleStack::childNodeNS( const char* nsURI, const char* localName) const
00242 {
00243 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00244
00245 while ( it != m_stack.begin() )
00246 {
00247 --it;
00248 QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
00249 QDomElement e = KoDom::namedItemNS( properties, nsURI, localName );
00250 if ( !e.isNull() )
00251 return e;
00252 }
00253
00254 return QDomElement();
00255 }
00256
00257 bool KoStyleStack::isUserStyle( const QDomElement& e, const QString& family ) const
00258 {
00259 if ( e.attributeNS( m_styleNSURI, "family", QString::null ) != family )
00260 return false;
00261 const QDomElement parent = e.parentNode().toElement();
00262
00263 return parent.localName() == "styles" ;
00264 }
00265
00266 QString KoStyleStack::userStyleName( const QString& family ) const
00267 {
00268 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00269 while ( it != m_stack.begin() )
00270 {
00271 --it;
00272
00273 if ( isUserStyle( *it, family ) )
00274 return (*it).attributeNS( m_styleNSURI, "name", QString::null );
00275 }
00276
00277 return "Standard";
00278 }
00279
00280 QString KoStyleStack::userStyleDisplayName( const QString& family ) const
00281 {
00282 QValueList<QDomElement>::ConstIterator it = m_stack.end();
00283 while ( it != m_stack.begin() )
00284 {
00285 --it;
00286
00287 if ( isUserStyle( *it, family ) )
00288 return (*it).attributeNS( m_styleNSURI, "display-name", QString::null );
00289 }
00290 return QString::null;
00291 }
00292
00293 void KoStyleStack::setTypeProperties( const char* typeProperties )
00294 {
00295 m_propertiesTagName = typeProperties == 0 ? QCString( "properties" ) : ( QCString( typeProperties ) + "-properties" );
00296 }