Back to index

scribus-ng  1.3.4.dfsg+svn20071115
stylestack.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /* This file is part of the KDE project
00008    Copyright (c) 2003 Lukas Tinkl <lukas@kde.org>
00009    Copyright (c) 2003 David Faure <faure@kde.org>
00010 
00011    This library is free software; you can redistribute it and/or
00012    modify it under the terms of the GNU Library General Public
00013    License as published by the Free Software Foundation; either
00014    version 2 of the License, or (at your option) any later version.
00015 
00016    This library is distributed in the hope that it will be useful,
00017    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019    Library General Public License for more details.
00020 
00021    You should have received a copy of the GNU Library General Public License
00022    along with this library; see the file COPYING.LIB.  If not, write to
00023    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00024    Boston, MA 02111-1307, USA.
00025 */
00026 
00027 #include "stylestack.h"
00028 #include "oodrawimp.h"
00029 
00030 StyleStack::StyleStack()
00031 {
00032     clear();
00033        fillNodeNameList(m_nodeNames, StyleStack::OODraw1x);
00034 }
00035 
00036 StyleStack::~StyleStack()
00037 {
00038 }
00039 
00040 void StyleStack::setMode( const StyleStack::Mode mode )
00041 {
00042        m_nodeNames.clear();
00043        fillNodeNameList(m_nodeNames, mode);
00044 }
00045 
00046 void StyleStack::clear()
00047 {
00048     m_stack.clear();
00049 }
00050 
00051 void StyleStack::save()
00052 {
00053     m_marks.push( m_stack.count() );
00054 }
00055 
00056 void StyleStack::restore()
00057 {
00058     Q_ASSERT( !m_marks.isEmpty() );
00059     int toIndex = m_marks.pop();
00060     Q_ASSERT( toIndex > -1 );
00061     Q_ASSERT( toIndex <= (int)m_stack.count() ); // If equal, nothing to remove. If greater, bug.
00062     for ( int index = (int)m_stack.count() - 1; index >= toIndex; --index )
00063         m_stack.pop_back();
00064 }
00065 
00066 void StyleStack::pop()
00067 {
00068     m_stack.pop_back();
00069 }
00070 
00071 void StyleStack::push( const QDomElement& style )
00072 {
00073     m_stack.append( style );
00074 }
00075 
00076 bool StyleStack::hasAttribute( const QString& name ) const
00077 {
00078     // TODO: has to be fixed for complex styles like list-styles
00079     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00080     while ( it != m_stack.begin() )
00081     {
00082         --it;
00083               QDomElement properties = searchAttribute( *it, m_nodeNames, name );
00084         if ( properties.hasAttribute( name ) )
00085             return true;
00086     }
00087 
00088     return false;
00089 }
00090 
00091 QString StyleStack::attribute( const QString& name ) const
00092 {
00093     // TODO: has to be fixed for complex styles like list-styles
00094     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00095     while ( it != m_stack.begin() )
00096     {
00097         --it;
00098         QDomElement properties = searchAttribute( *it, m_nodeNames, name );
00099         if ( properties.hasAttribute( name ) )
00100             return properties.attribute( name );
00101     }
00102 
00103     return QString::null;
00104 }
00105 
00106 bool StyleStack::hasAttribute( const QString& name, const QString& detail ) const
00107 {
00108     QString fullName( name );
00109     fullName += '-';
00110     fullName += detail;
00111     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00112     while ( it != m_stack.begin() )
00113     {
00114         --it;
00115               QDomElement properties = searchAttribute( *it, m_nodeNames, name, fullName );
00116         if ( properties.hasAttribute( name ) || properties.hasAttribute( fullName ) )
00117             return true;
00118     }
00119 
00120     return false;
00121 }
00122 
00123 QString StyleStack::attribute( const QString& name, const QString& detail ) const
00124 {
00125     QString fullName( name );
00126     fullName += '-';
00127     fullName += detail;
00128     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00129     while ( it != m_stack.begin() )
00130     {
00131         --it;
00132         QDomElement properties = searchAttribute( *it, m_nodeNames, name, fullName );
00133         if ( properties.hasAttribute( fullName ) )
00134             return properties.attribute( fullName );
00135         if ( properties.hasAttribute( name ) )
00136             return properties.attribute( name );
00137     }
00138 
00139     return QString::null;
00140 }
00141 
00142 // Font size is a bit special. "115%" applies to "the fontsize of the parent style".
00143 // This can be generalized though (hasAttributeThatCanBePercentOfParent() ? :)
00144 // Although, if we also add support for fo:font-size-rel here then it's not general anymore.
00145 double StyleStack::fontSize() const
00146 {
00147     QString name = "fo:font-size";
00148     double percent = 1;
00149     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00150     while ( it != m_stack.begin() )
00151     {
00152         --it;
00153         QDomElement properties = searchAttribute( *it, m_nodeNames, name );
00154         if ( properties.hasAttribute( name ) ) {
00155             QString value = properties.attribute( name );
00156             if ( value.endsWith( "%" ) )
00157                 percent *= value.toDouble() / 100.0;
00158             else
00159                 return percent * OODPlug::parseUnit( value ); // e.g. 12pt
00160         }
00161     }
00162     return 0;
00163 }
00164 
00165 bool StyleStack::hasChildNode(const QString & name) const
00166 {
00167     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00168     while ( it != m_stack.begin() )
00169     {
00170         --it;
00171         QDomElement properties = searchAttribute( *it, m_nodeNames, name );
00172         if ( !properties.namedItem( name ).isNull() )
00173             return true;
00174     }
00175 
00176     return false;
00177 }
00178 
00179 QDomNode StyleStack::childNode(const QString & name) const
00180 {
00181     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00182     while ( it != m_stack.begin() )
00183     {
00184         --it;
00185         QDomElement properties = searchAttribute( *it, m_nodeNames, name );
00186         if ( !properties.namedItem( name ).isNull() )
00187             return properties.namedItem( name );
00188     }
00189 
00190     return QDomNode();          // a null node
00191 }
00192 
00193 static bool isUserStyle( const QDomElement& e )
00194 {
00195     QDomElement parent = e.parentNode().toElement();
00196     return parent.tagName() == "office:styles";
00197 }
00198 
00199 QString StyleStack::userStyleName() const
00200 {
00201     QValueList<QDomElement>::ConstIterator it = m_stack.end();
00202     while ( it != m_stack.begin() )
00203     {
00204         --it;
00205         if ( isUserStyle( *it ) )
00206             return (*it).attribute("style:name");
00207     }
00208     // Can this ever happen?
00209     return "Standard";
00210 }
00211 
00212 void StyleStack::fillNodeNameList( QStringList& names, const StyleStack::Mode mode )
00213 {
00214        if ( mode == StyleStack::OODraw2x )
00215        {
00216               names.append("style:graphic-properties");
00217               names.append("style:paragraph-properties");
00218               names.append("style:page-layout-properties");
00219               names.append("style:drawing-page-properties");
00220               names.append("style:text-properties");
00221        }
00222        else
00223               names.append("style:properties");         
00224 }
00225 
00226 QDomElement StyleStack::searchAttribute( const QDomElement& element, const QStringList& names,const QString& name ) const
00227 {
00228        QDomElement node;
00229        QDomNodeList childNodes;
00230        childNodes = element.childNodes();
00231        for ( uint i = 0; i < childNodes.count(); i++ )
00232        {
00233               QDomNode n = childNodes.item(i);
00234               if ( n.isElement() )
00235               {
00236                      QDomElement* e = (QDomElement*) (&n);
00237                      if ( (names.findIndex(e->nodeName()) >= 0) && e->hasAttribute(name) )
00238                      {
00239                             node = *e;
00240                             break;
00241                      }
00242               }
00243        }
00244        return node;
00245 }
00246 
00247 QDomElement StyleStack::searchAttribute( const QDomElement& element, const QStringList& names, const QString& name, const QString& fullName ) const
00248 {
00249        QDomElement node;
00250        QDomNodeList childNodes;
00251        childNodes = element.childNodes();
00252        for ( uint i = 0; i < childNodes.count(); i++ )
00253        {
00254               QDomNode n = childNodes.item(i);
00255               if ( n.isElement() )
00256               {
00257                      QDomElement* e = (QDomElement*) (&n);
00258                      if ( (names.findIndex(e->nodeName()) >= 0) && (e->hasAttribute(name) || e->hasAttribute(fullName)) )
00259                      {
00260                             node = *e;
00261                             break;
00262                      }
00263               }
00264        }
00265        return node;
00266 }