1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /* This file is part of the KDE project
8    Copyright (c) 2003 Lukas Tinkl <lukas@kde.org>
9    Copyright (c) 2003 David Faure <faure@kde.org>
10 
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Library General Public
13    License as published by the Free Software Foundation; either
14    version 2 of the License, or (at your option) any later version.
15 
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Library General Public License for more details.
20 
21    You should have received a copy of the GNU Library General Public License
22    along with this library; see the file COPYING.LIB.  If not, write to
23    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24    Boston, MA 02110-1301, USA.
25 */
26 
27 #ifndef STYLESTACK_H
28 #define STYLESTACK_H
29 
30 #include <QDomElement>
31 #include <QStringList>
32 #include <QList>
33 #include <QStack>
34 
35 
36 /**
37  *  This class implements a stack for the different styles of an object.
38  *
39  *  There can be several styles that are valid for one object. For example
40  *  a textobject on a page has styles 'pr3' and 'P7' and a paragraph in
41  *  that textobject has styles 'P1' and 'T3'. And some styles even have
42  *  parent-styles...
43  *
44  *  If you want to know if there is, for example,  the attribute 'fo:font-family'
45  *  for this paragraph, you have to look into style 'T3', 'P1', 'P7' and 'pr3'.
46  *  When you find this attribute in one style you have to stop processing the list
47  *  and take the found attribute for this object.
48  *
49  *  This is what this class does. You can push styles on the stack while walking
50  *  through the xml-tree to your object and then ask the stack if any of the styles
51  *  provides a certain attribute. The stack will search from top to bottom, i.e.
52  *  in our example from 'T3' to 'pr3' and return the first occurrence of the wanted
53  *  attribute.
54  *
55  *  So this is some sort of inheritance where the styles on top of the stack overwrite
56  *  the same attribute of a lower style on the stack.
57  */
58 class StyleStack
59 {
60 public:
61     StyleStack();
62     virtual ~StyleStack();
63 
64 	enum Mode
65 	{
66 		OODraw1x = 1,
67 		OODraw2x = 2
68 	};
69 
70 	/**
71      * Set attribute analysis mode.
72      */
73 	void setMode( const StyleStack::Mode mode );
74 
75     /**
76      * Clears the complete stack.
77      */
78     void clear();
79 
80     /**
81      * Save the current state of the stack. Any items added between
82      * this call and its corresponding restore() will be removed when calling restore().
83      */
84     void save();
85 
86     /**
87      * Restore the stack to the state it was at the corresponding save() call.
88      */
89     void restore();
90 
91     /**
92      * Removes the style on top of the stack.
93      */
94     void pop();
95 
96     /**
97      * Pushes the new style onto the stack.
98      */
99     void push( const QDomElement& style );
100 
101     /**
102      * Check if any of the styles on the stack has an attribute called 'name'.
103      */
104 	bool hasAttribute( const QString& name ) const;
105 
106     /**
107      * Search for the attribute called 'name', starting on top of the stack,
108      * and return it.
109      */
110     QString attribute( const QString& name ) const;
111 
112     /**
113      * Check if any of the styles on the stack has an attribute called 'name'-'detail'
114      * where detail is e.g. left, right, top or bottom.
115      * This allows to also find 'name' alone (e.g. padding implies padding-left, padding-right etc.)
116      */
117     bool hasAttribute( const QString& name, const QString& detail ) const;
118 
119     /**
120      * Search for the attribute called 'name', starting on top of the stack,
121      * and return it.
122      */
123 	QString attribute( const QString& name, const QString& detail ) const;
124 
125     /**
126      * Check if any of the styles on the stack has a child node called 'name'.
127      */
128     bool hasChildNode(const QString & name) const;
129 
130     /**
131      * Search for a child node called 'name', starting on top of the stack,
132      * and return it.
133      */
134     QDomNode childNode(const QString & name) const;
135 
136     /**
137      * Special case for the current font size, due to special handling of fo:font-size="115%".
138      */
139     double fontSize() const;
140 
141     /**
142      * Return the name of the style specified by the user,
143      * i.e. not an auto style
144      */
145     QString userStyleName() const;
146 
147 private:
148 
149 	// Node names to look for style properties
150 	QStringList m_nodeNames;
151 
152     // For save/restore: stack of "marks". Each mark is an index in m_stack.
153     QStack<int> m_marks;
154 
155     // We use QValueList instead of QValueStack because we need access to all styles
156     // not only the top one.
157     QList<QDomElement> m_stack;
158 
159 	// Get node name to look for according to property type
160 	void fillNodeNameList( QStringList& names, const StyleStack::Mode mode );
161 
162 	// Search a specific attribute amongst childs of an element
163 	QDomElement searchAttribute( const QDomElement& element, const QStringList& names,const QString& name ) const;
164 
165 	// Search a specific attribute amongst childs of an element
166 	QDomElement searchAttribute( const QDomElement& element, const QStringList& names, const QString& name, const QString& fullName ) const;
167 };
168 
169 
170 #endif /* STYLESTACK_H */
171