1
/* This file is part of the KDE project
2
Copyright (c) 2003 Lukas Tinkl <lukas@kde.org>
3
Copyright (c) 2003 David Faure <faure@kde.org>
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public License
16
along with this library; see the file COPYING.LIB. If not, write to
17
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
Boston, MA 02111-1307, USA.
21
#include "koStyleStack.h"
28
//#define DEBUG_STYLESTACK
30
KoStyleStack::KoStyleStack()
31
: m_styleNSURI( KoXmlNS::style ), m_foNSURI( KoXmlNS::fo )
36
KoStyleStack::KoStyleStack( const char* styleNSURI, const char* foNSURI )
37
: m_propertiesTagName( "properties" ), m_styleNSURI( styleNSURI ), m_foNSURI( foNSURI )
42
KoStyleStack::~KoStyleStack()
46
void KoStyleStack::clear()
49
#ifdef DEBUG_STYLESTACK
50
kdDebug(30003) << "clear!" << endl;
54
void KoStyleStack::save()
56
m_marks.push( m_stack.count() );
57
#ifdef DEBUG_STYLESTACK
58
kdDebug(30003) << "save (level " << m_marks.count() << ") -> index " << m_stack.count() << endl;
62
void KoStyleStack::restore()
64
Q_ASSERT( !m_marks.isEmpty() );
65
int toIndex = m_marks.pop();
66
#ifdef DEBUG_STYLESTACK
67
kdDebug(30003) << "restore (level " << m_marks.count()+1 << ") -> to index " << toIndex << endl;
69
Q_ASSERT( toIndex > -1 );
70
Q_ASSERT( toIndex <= (int)m_stack.count() ); // If equal, nothing to remove. If greater, bug.
71
for ( int index = (int)m_stack.count() - 1; index >= toIndex; --index )
75
void KoStyleStack::pop()
77
Q_ASSERT( !m_stack.isEmpty() );
79
#ifdef DEBUG_STYLESTACK
80
kdDebug(30003) << "pop -> count=" << m_stack.count() << endl;
84
void KoStyleStack::push( const QDomElement& style )
86
m_stack.append( style );
87
#ifdef DEBUG_STYLESTACK
88
kdDebug(30003) << "pushed " << style.attributeNS( m_styleNSURI, "name", QString::null ) << " -> count=" << m_stack.count() << endl;
92
bool KoStyleStack::hasAttribute( const QString& name, const QString& detail ) const
94
QString fullName( name );
95
if ( !detail.isEmpty() )
100
QValueList<QDomElement>::ConstIterator it = m_stack.end();
101
while ( it != m_stack.begin() )
104
QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
105
if ( properties.hasAttribute( name ) ||
106
( !detail.isEmpty() && properties.hasAttribute( fullName ) ) )
112
QString KoStyleStack::attribute( const QString& name, const QString& detail ) const
114
QString fullName( name );
115
if ( !detail.isEmpty() )
120
QValueList<QDomElement>::ConstIterator it = m_stack.end();
121
while ( it != m_stack.begin() )
124
QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
125
if ( properties.hasAttribute( name ) )
126
return properties.attribute( name );
127
if ( !detail.isEmpty() && properties.hasAttribute( fullName ) )
128
return properties.attribute( fullName );
130
return QString::null;
133
QString KoStyleStack::attributeNS( const char* nsURI, const char* name, const char* detail ) const
135
QString fullName( name );
141
QValueList<QDomElement>::ConstIterator it = m_stack.end();
142
while ( it != m_stack.begin() )
145
QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
146
if ( properties.hasAttributeNS( nsURI, name ) )
147
return properties.attributeNS( nsURI, name, QString::null );
148
if ( detail && properties.hasAttributeNS( nsURI, fullName ) )
149
return properties.attributeNS( nsURI, fullName, QString::null );
151
return QString::null;
154
bool KoStyleStack::hasAttributeNS( const char* nsURI, const char* name, const char* detail ) const
156
QString fullName( name );
162
QValueList<QDomElement>::ConstIterator it = m_stack.end();
163
while ( it != m_stack.begin() )
166
QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
167
if ( properties.hasAttributeNS( nsURI, name ) ||
168
( detail && properties.hasAttributeNS( nsURI, fullName ) ) )
174
// Font size is a bit special. "115%" applies to "the fontsize of the parent style".
175
// This can be generalized though (hasAttributeThatCanBePercentOfParent() ? :)
176
// Although, if we also add support for fo:font-size-rel here then it's not general anymore.
177
double KoStyleStack::fontSize() const
179
const QString name = "font-size";
181
QValueList<QDomElement>::ConstIterator it = m_stack.end(); // reverse iterator
183
while ( it != m_stack.begin() )
186
QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName ).toElement();
187
if ( properties.hasAttributeNS( m_foNSURI, name ) ) {
188
const QString value = properties.attributeNS( m_foNSURI, name, QString::null );
189
if ( value.endsWith( "%" ) )
190
percent *= value.left( value.length() - 1 ).toDouble() / 100.0;
192
return percent * KoUnit::parseValue( value ); // e.g. 12pt
198
bool KoStyleStack::hasChildNode(const QString & name) const
200
QValueList<QDomElement>::ConstIterator it = m_stack.end();
201
while ( it != m_stack.begin() )
204
QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
205
if ( !properties.namedItem( name ).isNull() )
212
QDomElement KoStyleStack::childNode(const QString & name) const
214
QValueList<QDomElement>::ConstIterator it = m_stack.end();
216
while ( it != m_stack.begin() )
219
QDomElement properties = (*it).namedItem( "style:"+m_propertiesTagName ).toElement();
220
if ( !properties.namedItem( name ).isNull() )
221
return properties.namedItem( name ).toElement();
224
return QDomElement(); // a null element
227
bool KoStyleStack::hasChildNodeNS( const char* nsURI, const char* localName ) const
229
QValueList<QDomElement>::ConstIterator it = m_stack.end();
230
while ( it != m_stack.begin() )
233
QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
234
if ( !KoDom::namedItemNS( properties, nsURI, localName ).isNull() )
241
QDomElement KoStyleStack::childNodeNS( const char* nsURI, const char* localName) const
243
QValueList<QDomElement>::ConstIterator it = m_stack.end();
245
while ( it != m_stack.begin() )
248
QDomElement properties = KoDom::namedItemNS( *it, m_styleNSURI, m_propertiesTagName );
249
QDomElement e = KoDom::namedItemNS( properties, nsURI, localName );
254
return QDomElement(); // a null element
257
bool KoStyleStack::isUserStyle( const QDomElement& e ) const
259
const QDomElement parent = e.parentNode().toElement();
260
//kdDebug(30003) << k_funcinfo << "tagName=" << e.tagName() << " parent-tagName=" << parent.tagName() << endl;
261
return parent.localName() == "styles" /*&& parent.namespaceURI() == KoXmlNS::office*/;
264
QString KoStyleStack::userStyleName() const
266
QValueList<QDomElement>::ConstIterator it = m_stack.end();
267
while ( it != m_stack.begin() )
270
//kdDebug(30003) << k_funcinfo << (*it).attributeNS( m_styleNSURI, "name") << endl;
271
if ( isUserStyle( *it ) )
272
return (*it).attributeNS( m_styleNSURI, "name", QString::null );
274
// Can this ever happen?
278
QString KoStyleStack::userStyleDisplayName() const
280
QValueList<QDomElement>::ConstIterator it = m_stack.end();
281
while ( it != m_stack.begin() )
284
//kdDebug(30003) << k_funcinfo << (*it).attributeNS( m_styleNSURI, "display-name") << endl;
285
if ( isUserStyle( *it ) )
286
return (*it).attributeNS( m_styleNSURI, "display-name", QString::null );
288
return QString::null; // no display name, this can happen since it's optional
291
void KoStyleStack::setTypeProperties( const char* typeProperties )
293
m_propertiesTagName = typeProperties == 0 ? QCString( "properties" ) : ( QCString( typeProperties ) + "-properties" );