3 * @brief Cascading style scope.
4 * @author James Hogan <james@albanarts.com>
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
)
24 if (0 != m_parentScope
)
26 parent
->m_childScopes
.insert(this);
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();
51 StyleSheetList::iterator it
;
52 for (it
= m_styleSheets
.begin(); it
!= m_styleSheets
.end(); ++it
)
54 /// @todo reference count
64 /// Add a stylesheet for this scope.
65 void KwCssScope::addStyleSheet(KwCssStyleSheet
* styleSheet
)
67 m_styleSheets
.push_back(styleSheet
);
71 /// Add a class to this scope.
72 void KwCssScope::addClass(QString className
)
74 m_classes
+= className
;
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()
89 * unmatched rules stylesheet
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
;
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
);
119 m_cachedClasses
+= m_classes
;
125 processRules
= false;
126 QSet
<QString
> triggerableClasses
;
127 KwCssStyleSheet::Iterator it
;
128 for (it
= m_cachedStyleSheet
.getRules().begin(); it
!= m_cachedStyleSheet
.getRules().end();)
131 KwCssStyleRule::KeyList
& keys
= (*it
).getCriteriaKeys();
132 if (!keys
.empty() && isKeyMatching(keys
.first()))
137 KwCssStyleRule::StringSet
& classes
= (*it
).getCriteriaClasses();
138 classes
-= m_cachedClasses
;
140 if (!classes
.empty())
142 triggerableClasses
+= classes
;
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
;
160 // Remove from stylesheet since it's now applied
161 KwCssStyleSheet::Iterator cur
= it
;
163 m_cachedStyleSheet
.getRules().erase(cur
);
171 while (processRules
);
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();
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");
201 /// Get explicit styles.
202 const KwCssStyles
& KwCssScope::getExplicitStyles() const
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
);
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
;
234 m_parentScope
->m_childScopes
.insert(this);