New css schema object for constructing property values from strings
[kworship.git] / kworship / css / KwCssStyleSheet.cpp
blob19b5d303351aec1a234cc8d433d722fe73725797
1 /***************************************************************************
2 * This file is part of KWorship. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * KWorship is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * KWorship 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 *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with KWorship. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file KwCssStyleSheet.cpp
22 * @brief Cascading style sheet.
23 * @author James Hogan <james@albanarts.com>
26 #include "KwCssStyleSheet.h"
27 #include "KwCssStyleRule.h"
29 #include <cassert>
32 * Constructors + destructors
35 /// Default constructor.
36 KwCssStyleSheet::KwCssStyleSheet()
37 : m_rules()
41 /// Copy constructor.
42 /**
43 * This copies all except the actual styles in each rule which are aliased.
45 KwCssStyleSheet::KwCssStyleSheet(const KwCssStyleSheet& copy)
46 : m_rules()
48 /// @todo Copy rules
49 assert(0&&"unimplemented");
52 /// Destructor.
53 KwCssStyleSheet::~KwCssStyleSheet()
58 * Main interface
61 /// Clear the rules.
62 void KwCssStyleSheet::clear()
64 m_rules.clear();
67 /// Append a rule.
68 void KwCssStyleSheet::addRule(const KwCssStyleRule& rule)
70 m_rules.push_back(rule);
73 /// Import another stylesheet.
74 void KwCssStyleSheet::importStyleSheet(const KwCssStyleSheet* styleSheet)
76 m_rules += styleSheet->m_rules;
79 /// Import from CSS-like format into the sheet.
80 void KwCssStyleSheet::import(const KwCssSchema* schema, const QString& sheet)
82 QString css = sheet;
84 // Strip out comments and newlines
85 static QRegExp reComment("\\/\\*([^*]|\\*[^/])*\\*\\/|\n");
86 css.replace(reComment, " ");
88 // Go through rules
89 static QRegExp reRuleStart("^\\s*(\\S[^{]*)?\\s*\\{\\s*");
90 int rulesPos = 0;
91 int lastRulesPos = 0;
92 while (-1 != (rulesPos = reRuleStart.indexIn(css, lastRulesPos, QRegExp::CaretAtOffset)))
94 lastRulesPos = rulesPos + reRuleStart.matchedLength();
95 KwCssStyleRule rule;
97 // Read the key criteria
98 static QRegExp reCriteriaKey("^(\\w*)(#(\\w+))?\\s*");
99 KwCssStyleRule::KeyList keys;
100 QString head = reRuleStart.cap(1);
101 int headPos = 0;
102 int lastHeadPos = 0;
103 while (-1 != (headPos = reCriteriaKey.indexIn(head, lastHeadPos, QRegExp::CaretAtOffset)) && reCriteriaKey.matchedLength() > 0)
105 lastHeadPos = headPos + reCriteriaKey.matchedLength();
106 QString keyTypeName = reCriteriaKey.cap(1);
107 QString keyName = reCriteriaKey.cap(2);
108 int keyType = -1;
109 if (!keyTypeName.isEmpty())
111 keyType = KwCssScopeKey::registerScopeType(keyTypeName);
113 keys += KwCssScopeKey(keyType, keyName);
115 rule.setCriteriaKeys(keys);
117 // Read the class criteria
118 static QRegExp reCriteriaClass("^\\.(\\w+)\\s*");
119 KwCssStyleRule::StringSet classes;
120 while (-1 != (headPos = reCriteriaClass.indexIn(head, lastHeadPos, QRegExp::CaretAtOffset)))
122 lastHeadPos = headPos + reCriteriaClass.matchedLength();
123 classes += reCriteriaClass.cap(1);
125 rule.setCriteriaClasses(classes);
127 // Read the class includes
128 static QRegExp reIncludeStart("^:\\s*");
129 if (-1 != (headPos = reIncludeStart.indexIn(head, lastHeadPos, QRegExp::CaretAtOffset)))
131 lastHeadPos = headPos + reIncludeStart.matchedLength();
132 KwCssStyleRule::StringSet classes;
133 while (-1 != (headPos = reCriteriaClass.indexIn(head, lastHeadPos, QRegExp::CaretAtOffset)))
135 lastHeadPos = headPos + reCriteriaClass.matchedLength();
136 classes += reCriteriaClass.cap(1);
138 rule.setIncludedStyles(classes);
141 // Should be no more head left
142 static QRegExp reWhitespace("^\\s*$");
143 if (-1 == reWhitespace.indexIn(head, lastHeadPos, QRegExp::CaretAtOffset))
145 Q_ASSERT(0&& "Expected '{' near something else");
148 // Read the styles
149 lastRulesPos = rule.getStyles()->import(schema, css, lastRulesPos);
151 // End of rule
152 static QRegExp reRuleEnd("^\\}\\s*");
153 if (-1 != (rulesPos = reRuleEnd.indexIn(css, lastRulesPos, QRegExp::CaretAtOffset)))
155 lastRulesPos = rulesPos + reRuleEnd.matchedLength();
157 else
159 // Expected end of rule but got something else
160 Q_ASSERT(0&& "Expected '}' near something else");
162 m_rules += rule;
167 * Accessors
170 /// Get the rules.
171 KwCssStyleSheet::RuleList& KwCssStyleSheet::getRules()
173 return m_rules;
176 /// Get the constant rules.
177 const KwCssStyleSheet::RuleList& KwCssStyleSheet::getRules() const
179 return m_rules;
182 /// Convert to CSS-like format.
183 QString KwCssStyleSheet::toString() const
185 /// @todo Take into account of shared styles in rules!
186 QString result = "/* Doesn't take shared styles into account */\n";
187 foreach (const KwCssStyleRule& rule, m_rules)
189 result += rule.toString();
191 return result;