Added nice css styling instead of simple class based. now uses scopes and object...
[kworship.git] / kworship / css / KwCssScope.cpp
blob5d903ac20bfb6a27a9d8682984a77d18d5501339
1 /**
2 * @file KwCssScope.cpp
3 * @brief Cascading style scope.
4 * @author James Hogan <james@albanarts.com>
5 */
7 #include "KwCssScope.h"
8 #include "KwCssStyleRule.h"
9 #include "KwCssStyleSheet.h"
12 * Constructors + destructors
15 /// Primary constructor.
16 KwCssScope::KwCssScope(KwCssScope* parent)
17 : m_parentScope(parent)
18 , m_childScopes()
19 , m_name()
20 , m_classes()
21 , m_styleSheets()
22 , m_styles()
24 if (0 != m_parentScope)
26 parent->m_childScopes.insert(this);
30 /// Destructor.
31 KwCssScope::~KwCssScope()
33 // Remove from parent's child list.
34 if (0 != m_parentScope)
36 m_parentScope->m_childScopes.remove(this);
39 // Remove from children and recalculate styles.
41 ScopeSet::iterator it;
42 for (it = m_childScopes.begin(); it != m_childScopes.end(); ++it)
44 (*it)->m_parentScope = 0;
45 (*it)->recalculateStyles();
49 // Clean style sheets
51 StyleSheetList::iterator it;
52 for (it = m_styleSheets.begin(); it != m_styleSheets.end(); ++it)
54 /// @todo reference count
55 delete *it;
61 * Main interface
64 /// Add a stylesheet for this scope.
65 void KwCssScope::addStyleSheet(KwCssStyleSheet* styleSheet)
67 m_styleSheets.push_back(styleSheet);
68 recalculateStyles();
71 /// Add a class to this scope.
72 void KwCssScope::addClass(QString className)
74 m_classes += className;
75 recalculateStyles();
78 /// Get all the styles included in this scope.
79 const KwCssStyleStates& KwCssScope::getStyles() const
81 return m_cachedStyles;
84 /// Recalculate all styles.
85 void KwCssScope::recalculateStyles()
88 * cached styles
89 * unmatched rules stylesheet
91 * get parent styles
92 * add classes
93 * get parent unmatched style rules
94 * go through stylesheets
95 * apply any rules that match in order, removing as we go from local list
96 * apply explicit styles
98 // Get the base styles from the parent
99 if (0 != m_parentScope)
101 m_cachedStyles = m_parentScope->getStyles();
102 m_cachedStyleSheet = m_parentScope->m_cachedStyleSheet;
103 m_cachedClasses = m_parentScope->m_cachedClasses;
105 else
107 m_cachedStyles.clear();
108 m_cachedStyleSheet.clear();
110 // Add local stylesheets
112 StyleSheetList::iterator it;
113 for (it = m_styleSheets.begin(); it != m_styleSheets.end(); ++it)
115 m_cachedStyleSheet.importStyleSheet(*it);
118 // Add local classes
119 m_cachedClasses += m_classes;
121 // process rules
122 bool processRules;
125 processRules = false;
126 QSet<QString> triggerableClasses;
127 KwCssStyleSheet::Iterator it;
128 for (it = m_cachedStyleSheet.getRules().begin(); it != m_cachedStyleSheet.getRules().end();)
130 // Match the keys
131 KwCssStyleRule::KeyList& keys = (*it).getCriteriaKeys();
132 if (!keys.empty() && isKeyMatching(keys.first()))
134 keys.pop_front();
136 // Match the classes
137 KwCssStyleRule::StringSet& classes = (*it).getCriteriaClasses();
138 classes -= m_cachedClasses;
140 if (!classes.empty())
142 triggerableClasses += classes;
143 ++it;
145 else if (keys.empty())
147 // Nothing left to match, we can apply this style and remove it from the list
148 m_cachedStyles << *(*it).getStyles();
149 QSet<QString> classesToApply = (*it).getIncludedStyles() - m_cachedClasses;
150 if (!classesToApply.empty())
152 m_cachedClasses += classesToApply;
153 QSet<QString> classesToTrigger = triggerableClasses & classesToApply;
154 if (!classesToTrigger.empty())
156 triggerableClasses -= classesToTrigger;
157 processRules = true;
160 // Remove from stylesheet since it's now applied
161 KwCssStyleSheet::Iterator cur = it;
162 ++it;
163 m_cachedStyleSheet.getRules().erase(cur);
165 else
167 ++it;
171 while (processRules);
173 // Apply each style
174 m_cachedStyles << m_styles;
176 // Recurse to children
178 ScopeSet::iterator it;
179 for (it = m_childScopes.begin(); it != m_childScopes.end(); ++it)
181 (*it)->recalculateStyles();
187 * Virtual interface
190 /// Get the type id corresponding to this type.
191 KwCssScopeKey::ScopeTypeId KwCssScope::getTypeId() const
193 /// @todo optimise by caching type id
194 return KwCssScopeKey::registerScopeType("scope");
198 * Accessors
201 /// Get explicit styles.
202 const KwCssStyles& KwCssScope::getExplicitStyles() const
204 return m_styles;
207 /// Get the scope's key.
208 KwCssScopeKey KwCssScope::getKey() const
210 return KwCssScopeKey(getTypeId(), m_name);
213 /// Find whether a scope key matches this scope.
214 bool KwCssScope::isKeyMatching(KwCssScopeKey key) const
216 return (!key.isTypeSpecified() || key.getTypeId() == getTypeId())
217 && (!key.isNameSpecified() || key.getName() == m_name);
221 * Mutators
224 /// Set the parent scope.
225 void KwCssScope::setParentScope(KwCssScope* parent)
227 if (0 != m_parentScope)
229 m_parentScope->m_childScopes.remove(this);
231 m_parentScope = parent;
232 if (0 != parent)
234 m_parentScope->m_childScopes.insert(this);
236 recalculateStyles();