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