Merge lp:~zsombi/ubuntu-ui-toolkit/qml-role-and-loader-removal into lp:ubuntu-ui-toolkit
- qml-role-and-loader-removal
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Tim Peeters |
Approved revision: | 263 |
Merged at revision: | 285 |
Proposed branch: | lp:~zsombi/ubuntu-ui-toolkit/qml-role-and-loader-removal |
Merge into: | lp:ubuntu-ui-toolkit |
Diff against target: |
1832 lines (+271/-939) 19 files modified
CHANGES (+2/-1) modules/Ubuntu/Components/plugin/itemstyleattached.cpp (+78/-39) modules/Ubuntu/Components/plugin/itemstyleattached.h (+1/-0) modules/Ubuntu/Components/plugin/itemstyleattached_p.h (+5/-7) modules/Ubuntu/Components/plugin/plugin.pro (+1/-6) modules/Ubuntu/Components/plugin/qmlloader.cpp (+0/-117) modules/Ubuntu/Components/plugin/qmlloader_p.h (+0/-41) modules/Ubuntu/Components/plugin/qmlthemeloader.cpp (+30/-17) modules/Ubuntu/Components/plugin/rule.cpp (+0/-382) modules/Ubuntu/Components/plugin/rule.h (+0/-75) modules/Ubuntu/Components/plugin/rule_p.h (+0/-47) modules/Ubuntu/Components/plugin/suffixtree.cpp (+68/-44) modules/Ubuntu/Components/plugin/suffixtree_p.h (+13/-6) modules/Ubuntu/Components/plugin/themeengine.cpp (+42/-110) modules/Ubuntu/Components/plugin/themeengine.h (+1/-4) modules/Ubuntu/Components/plugin/themeengine_p.h (+3/-3) tests/resources/test.qmltheme (+0/-3) tests/unit/tst_theme_engine/tst_theme_enginetest.cpp (+0/-25) tests/unit/tst_theme_engine_private/tst_theme_engine_privatetest.cpp (+27/-12) |
To merge this branch: | bzr merge lp:~zsombi/ubuntu-ui-toolkit/qml-role-and-loader-removal |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Peeters | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Juhapekka Piiroinen (community) | Approve | ||
Review via email: mp+142522@code.launchpad.net |
This proposal supersedes a proposal from 2013-01-08.
Commit message
Description of the change
QML Role element and qml-loader removed. Role functionality distributed between StyleTree and ItemStyle. ThemeEngine contains only QML API.
Juhapekka Piiroinen (juhapekka-piiroinen) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:259
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:260
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Tim Peeters (tpeeters) wrote : | # |
27 + // class name may have_QMLTYPE_XX or _QML_XX suffixes
add space after have in the comment
Tim Peeters (tpeeters) wrote : | # |
// class name may have_QMLTYPE_XX or _QML_XX suffixes
className = className.
styleData.
styleData.
Is this correct? It sets the classname to _qml. Shouldn't you use className.right?
Tim Peeters (tpeeters) wrote : | # |
your addition to CHANGES was reverted when merging trunk
Tim Peeters (tpeeters) wrote : | # |
result = (rule != 0) && !(rule->path() == path);
why not rule->path() != path?
Tim Peeters (tpeeters) wrote : | # |
looking good, I only didn't check the tests yet.
Juhapekka Piiroinen (juhapekka-piiroinen) wrote : | # |
tests looks ok to me
Tim Peeters (tpeeters) wrote : | # |
oh wait, first the small comments I gave above
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
Approved revid is not set in launchpad (maybe a permission problem?).
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Zsombor Egri (zsombi) wrote : | # |
On 01/11/2013 01:51 PM, Tim Peeters wrote:
> 27 + // class name may have_QMLTYPE_XX or _QML_XX suffixes
>
> add space after have in the comment
ack
Zsombor Egri (zsombi) wrote : | # |
On 01/11/2013 01:55 PM, Tim Peeters wrote:
> // class name may have_QMLTYPE_XX or _QML_XX suffixes
> className = className.
> styleData.className = className;
> styleData.
>
> Is this correct? It sets the classname to _qml. Shouldn't you use className.right?
What do you mean it sets classname to _qml? Cuts off everything
starting from index of "_QML", so if a classname is
"ScrollBar_
Zsombor Egri (zsombi) wrote : | # |
On 01/11/2013 02:51 PM, Tim Peeters wrote:
> result = (rule != 0) && !(rule->path() == path);
>
> why not rule->path() != path?
Right :)
- 261. By Zsombor Egri
-
comments applied
- 262. By Zsombor Egri
-
trunk merge
- 263. By Zsombor Egri
-
CHANGES updated
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:263
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Tim Peeters (tpeeters) wrote : | # |
> On 01/11/2013 01:55 PM, Tim Peeters wrote:
> > // class name may have_QMLTYPE_XX or _QML_XX suffixes
> > className = className.
> > styleData.className = className;
> > styleData.
> >
> > Is this correct? It sets the classname to _qml. Shouldn't you use
> className.right?
> What do you mean it sets classname to _qml? Cuts off everything
> starting from index of "_QML", so if a classname is
> "ScrollBar_
You are right. I was thinking _qml was the prefix, not postfix.
Preview Diff
1 | === modified file 'CHANGES' |
2 | --- CHANGES 2013-01-08 18:46:48 +0000 |
3 | +++ CHANGES 2013-01-14 14:26:22 +0000 |
4 | @@ -15,7 +15,8 @@ |
5 | API Changes |
6 | *********** |
7 | |
8 | -* None |
9 | +* ThemeEngine - contains only public API, no C++ specific API |
10 | +* Role element removed |
11 | |
12 | |
13 | SDK 0.1.25 |
14 | |
15 | === modified file 'modules/Ubuntu/Components/plugin/itemstyleattached.cpp' |
16 | --- modules/Ubuntu/Components/plugin/itemstyleattached.cpp 2012-11-20 10:07:44 +0000 |
17 | +++ modules/Ubuntu/Components/plugin/itemstyleattached.cpp 2013-01-14 14:26:22 +0000 |
18 | @@ -19,10 +19,10 @@ |
19 | #include <QtQml/QQmlComponent> |
20 | #include <QtQml/QQmlContext> |
21 | #include <QtQml/QQmlEngine> |
22 | +#include <QtQuick/QQuickItem> |
23 | |
24 | #include "itemstyleattached.h" |
25 | #include "itemstyleattached_p.h" |
26 | -#include "rule.h" |
27 | #include "themeengine.h" |
28 | #include "themeengine_p.h" |
29 | |
30 | @@ -144,12 +144,16 @@ |
31 | delegate(0), |
32 | componentContext(0), |
33 | styleRule(0), |
34 | - delegateRule(0), |
35 | delayApplyingStyle(true), |
36 | customStyle(false), |
37 | customDelegate(false), |
38 | connectedToEngine(false) |
39 | { |
40 | + QString className = QString(attachee->metaObject()->className()).toLower(); |
41 | + // class name may have _QMLTYPE_XX or _QML_XX suffixes |
42 | + className = className.left(className.indexOf("_qml")); |
43 | + styleData.className = className; |
44 | + styleData.styleClass = className; |
45 | // refresh style upon reparenting! |
46 | // there is no reason to do styling till the parent is not set and this applies |
47 | // to the root objects too as even those have an internal parent |
48 | @@ -161,14 +165,43 @@ |
49 | componentContext = new QQmlContext(QQmlEngine::contextForObject(attachee)); |
50 | componentContext->setContextProperty(itemProperty, attachee); |
51 | } |
52 | - |
53 | } |
54 | |
55 | ItemStyleAttachedPrivate::~ItemStyleAttachedPrivate() |
56 | { |
57 | // remove name from the theming engine |
58 | - if (!name.isEmpty()) |
59 | - ThemeEngine::instance()->registerName(attachee, QString()); |
60 | + if (!styleData.styleId.isEmpty()) |
61 | + ThemeEnginePrivate::registerName(attachee, QString()); |
62 | +} |
63 | + |
64 | +bool ItemStyleAttachedPrivate::updateStyleSelector() |
65 | +{ |
66 | + Selector path; |
67 | + SelectorNode::Relationship relation = SelectorNode::Child; |
68 | + QQuickItem *parent = attachee->parentItem(); |
69 | + ItemStyleAttached *parentStyle = 0; |
70 | + |
71 | + path << styleData; |
72 | + |
73 | + while (parent) { |
74 | + parentStyle = ThemeEnginePrivate::attachedStyle(parent); |
75 | + if (!parentStyle) |
76 | + relation = SelectorNode::Descendant; |
77 | + else { |
78 | + path[0].relationship = relation; |
79 | + path.prepend(parentStyle->d_ptr->styleData); |
80 | + relation = SelectorNode::Child; |
81 | + } |
82 | + parent = parent->parentItem(); |
83 | + } |
84 | + |
85 | + if (path != styleSelector) { |
86 | + styleSelector = path; |
87 | + // need to refresh the style rule(s) |
88 | + styleRule = ThemeEnginePrivate::styleRuleForPath(styleSelector); |
89 | + return true; |
90 | + } |
91 | + return false; |
92 | } |
93 | |
94 | bool ItemStyleAttachedPrivate::updateStyle() |
95 | @@ -186,11 +219,9 @@ |
96 | style = 0; |
97 | } |
98 | // make sure we have a theme |
99 | - result = (styleRule = ThemeEngine::instance()->lookupStyleRule(attachee)); |
100 | - if (!result || (result && !styleRule->style())) |
101 | - result = (styleRule = ThemeEngine::instance()->lookupStyleRule(attachee, true)); |
102 | - if (result) { |
103 | - style = styleRule->createStyle(componentContext); |
104 | + if (styleRule && styleRule->style) { |
105 | + style = styleRule->style->create(componentContext); |
106 | + result = (style != 0); |
107 | } |
108 | } else |
109 | result = true; |
110 | @@ -218,11 +249,9 @@ |
111 | delegate = 0; |
112 | } |
113 | // make sure we have a theme |
114 | - result = (delegateRule = ThemeEngine::instance()->lookupStyleRule(attachee)); |
115 | - if (!result || (result && !delegateRule->delegate())) |
116 | - result = (delegateRule = ThemeEngine::instance()->lookupStyleRule(attachee, true)); |
117 | - if (result) { |
118 | - delegate = delegateRule->createDelegate(componentContext); |
119 | + if (styleRule && styleRule->delegate) { |
120 | + delegate = qobject_cast<QQuickItem*>(styleRule->delegate->create(componentContext)); |
121 | + result = (delegate != 0); |
122 | } |
123 | } else |
124 | result = true; |
125 | @@ -269,16 +298,14 @@ |
126 | { |
127 | bool result = true; |
128 | Q_Q(ItemStyleAttached); |
129 | - if (ThemeEngine::instance()->registerName(attachee, id)) { |
130 | - name = id; |
131 | - attachee->setProperty("name", name); |
132 | + if (ThemeEnginePrivate::registerName(attachee, id)) { |
133 | + styleData.styleId = id; |
134 | + attachee->setProperty("name", styleData.styleId); |
135 | } else { |
136 | - QString className = q->metaObject()->className(); |
137 | - className = className.left(className.indexOf("_QMLTYPE")); |
138 | ThemeEnginePrivate::setError(QString("Instance %1 already registered. Resetting instance for %2.") |
139 | - .arg(name) |
140 | - .arg(className)); |
141 | - name = QString(); |
142 | + .arg(styleData.styleId) |
143 | + .arg(styleData.className)); |
144 | + styleData.styleId = QString(); |
145 | result = false; |
146 | } |
147 | return result; |
148 | @@ -293,26 +320,33 @@ |
149 | { |
150 | Q_Q(ItemStyleAttached); |
151 | if (!customStyle || !customDelegate) { |
152 | - if (!connectedToEngine) |
153 | + if (!connectedToEngine) { |
154 | connectedToEngine = (bool)QObject::connect(ThemeEngine::instance(), SIGNAL(themeChanged()), q, SLOT(_q_refreshStyle())); |
155 | + updateStyleSelector(); |
156 | + } |
157 | } else { |
158 | if (connectedToEngine) |
159 | connectedToEngine = !QObject::disconnect(ThemeEngine::instance(), SIGNAL(themeChanged()), q, SLOT(_q_refreshStyle())); |
160 | + if (!connectedToEngine) |
161 | + styleRule = 0; |
162 | } |
163 | } |
164 | |
165 | |
166 | /*! |
167 | \internal |
168 | - Internal slot to update the style of an item. The slot is connected to the item's |
169 | - connected() signal. This is called only if the item defines "Component.onCompleted()" |
170 | - attached signal. |
171 | + Internal slot to update the style of an item when the theme is changed. The slot |
172 | + is connected to the engine's themeChanged() signal. The slot should not be used |
173 | + from other methods as it will cause performance problems. |
174 | */ |
175 | void ItemStyleAttachedPrivate::_q_refreshStyle() |
176 | { |
177 | // no need to delay style applying any longer |
178 | delayApplyingStyle = false; |
179 | |
180 | + // ... but style refresh is needed as the old styles are dead |
181 | + styleRule = ThemeEnginePrivate::styleRuleForPath(styleSelector); |
182 | + |
183 | updateCurrentStyle(); |
184 | } |
185 | |
186 | @@ -326,7 +360,10 @@ |
187 | // the component is most likely used in a delegate or is being deleted |
188 | return; |
189 | |
190 | - _q_refreshStyle(); |
191 | + if (updateStyleSelector() || delayApplyingStyle) { |
192 | + delayApplyingStyle = false; |
193 | + updateCurrentStyle(); |
194 | + } |
195 | |
196 | // need to reapply styling on each child of the attachee! |
197 | // this will cause performance issues! |
198 | @@ -369,7 +406,7 @@ |
199 | QString ItemStyleAttached::name() const |
200 | { |
201 | Q_D(const ItemStyleAttached); |
202 | - return d->name; |
203 | + return d->styleData.styleId; |
204 | } |
205 | /*! |
206 | Updates the name property. |
207 | @@ -377,10 +414,11 @@ |
208 | void ItemStyleAttached::setName(const QString &name) |
209 | { |
210 | Q_D(ItemStyleAttached); |
211 | - if (d->name.compare(name, Qt::CaseInsensitive)) { |
212 | + if (d->styleData.styleId.compare(name, Qt::CaseInsensitive)) { |
213 | if (d->registerName(name.toLower())) { |
214 | d->listenThemeEngine(); |
215 | - d->updateCurrentStyle(); |
216 | + if (d->updateStyleSelector()) |
217 | + d->updateCurrentStyle(); |
218 | } |
219 | } |
220 | } |
221 | @@ -399,7 +437,7 @@ |
222 | QString ItemStyleAttached::styleClass() const |
223 | { |
224 | Q_D(const ItemStyleAttached); |
225 | - return d->styleClass; |
226 | + return d->styleData.styleClass; |
227 | } |
228 | /*! |
229 | Sets the class property value. |
230 | @@ -407,10 +445,11 @@ |
231 | void ItemStyleAttached::setStyleClass(const QString &styleClass) |
232 | { |
233 | Q_D(ItemStyleAttached); |
234 | - if (d->styleClass.compare(styleClass, Qt::CaseInsensitive)) { |
235 | - d->styleClass = styleClass.toLower(); |
236 | + if (d->styleData.styleClass.compare(styleClass, Qt::CaseInsensitive)) { |
237 | + d->styleData.styleClass = styleClass.toLower(); |
238 | d->listenThemeEngine(); |
239 | - d->updateCurrentStyle(); |
240 | + if (d->updateStyleSelector()) |
241 | + d->updateCurrentStyle(); |
242 | } |
243 | } |
244 | |
245 | @@ -421,7 +460,9 @@ |
246 | QString ItemStyleAttached::path() const |
247 | { |
248 | Q_D(const ItemStyleAttached); |
249 | - return d->styleRule ? d->styleRule->selector() : QString("(null)"); |
250 | + return d->styleRule ? |
251 | + ThemeEnginePrivate::selectorToString(d->styleRule->path()) : |
252 | + QString("(null)"); |
253 | } |
254 | |
255 | /*! |
256 | @@ -461,7 +502,7 @@ |
257 | d->style = 0; |
258 | } |
259 | d->customStyle = (style != 0); |
260 | - if (d->customStyle) |
261 | + if (d->customStyle && d->customDelegate) |
262 | d->styleRule = 0; |
263 | d->style = style; |
264 | d->listenThemeEngine(); |
265 | @@ -504,8 +545,6 @@ |
266 | d->delegate->deleteLater(); |
267 | } |
268 | d->customDelegate = (delegate != 0); |
269 | - if (d->customDelegate) |
270 | - d->delegateRule = 0; |
271 | d->delegate = delegate; |
272 | d->listenThemeEngine(); |
273 | if (d->updateDelegate()) |
274 | |
275 | === modified file 'modules/Ubuntu/Components/plugin/itemstyleattached.h' |
276 | --- modules/Ubuntu/Components/plugin/itemstyleattached.h 2012-11-07 13:07:23 +0000 |
277 | +++ modules/Ubuntu/Components/plugin/itemstyleattached.h 2013-01-14 14:26:22 +0000 |
278 | @@ -62,6 +62,7 @@ |
279 | Q_DISABLE_COPY(ItemStyleAttached) |
280 | Q_DECLARE_PRIVATE(ItemStyleAttached) |
281 | QScopedPointer<ItemStyleAttachedPrivate> d_ptr; |
282 | + friend class ThemeEnginePrivate; |
283 | |
284 | Q_PRIVATE_SLOT(d_func(), void _q_reapplyStyling(QQuickItem *)) |
285 | Q_PRIVATE_SLOT(d_func(), void _q_refreshStyle()) |
286 | |
287 | === modified file 'modules/Ubuntu/Components/plugin/itemstyleattached_p.h' |
288 | --- modules/Ubuntu/Components/plugin/itemstyleattached_p.h 2012-11-07 13:07:23 +0000 |
289 | +++ modules/Ubuntu/Components/plugin/itemstyleattached_p.h 2013-01-14 14:26:22 +0000 |
290 | @@ -20,11 +20,9 @@ |
291 | #define ITEMSTYLEATTACHED_P_H |
292 | |
293 | #include "itemstyleattached.h" |
294 | +#include "suffixtree_p.h" |
295 | |
296 | -class QQmlComponent; |
297 | class QQmlContext; |
298 | -class Rule; |
299 | - |
300 | class ItemStyleAttachedPrivate { |
301 | Q_DECLARE_PUBLIC(ItemStyleAttached) |
302 | public: |
303 | @@ -35,18 +33,18 @@ |
304 | QQuickItem *attachee; |
305 | QObject *style; |
306 | QQuickItem *delegate; |
307 | - QString styleClass; |
308 | - QString name; |
309 | + SelectorNode styleData; |
310 | + Selector styleSelector; |
311 | |
312 | // internal members |
313 | QQmlContext *componentContext; |
314 | - Rule *styleRule; |
315 | - Rule *delegateRule; |
316 | + StyleTreeNode *styleRule; |
317 | bool delayApplyingStyle; |
318 | bool customStyle; |
319 | bool customDelegate; |
320 | bool connectedToEngine; |
321 | |
322 | + bool updateStyleSelector(); |
323 | bool updateStyle(); |
324 | bool updateDelegate(); |
325 | void updateCurrentStyle(); |
326 | |
327 | === modified file 'modules/Ubuntu/Components/plugin/plugin.pro' |
328 | --- modules/Ubuntu/Components/plugin/plugin.pro 2013-01-07 07:59:56 +0000 |
329 | +++ modules/Ubuntu/Components/plugin/plugin.pro 2013-01-14 14:26:22 +0000 |
330 | @@ -24,10 +24,7 @@ |
331 | suffixtree_p.h \ |
332 | itemstyleattached.h \ |
333 | itemstyleattached_p.h \ |
334 | - rule.h \ |
335 | - rule_p.h \ |
336 | - qmlloader_p.h \ |
337 | - qmlthemeloader_p.h \ |
338 | + qmlthemeloader.h \ |
339 | i18n.h \ |
340 | listener.h \ |
341 | ucscalingimageprovider.h \ |
342 | @@ -43,8 +40,6 @@ |
343 | suffixtree.cpp \ |
344 | themesettings.cpp \ |
345 | itemstyleattached.cpp \ |
346 | - rule.cpp \ |
347 | - qmlloader.cpp \ |
348 | qmlthemeloader.cpp \ |
349 | i18n.cpp \ |
350 | listener.cpp \ |
351 | |
352 | === removed file 'modules/Ubuntu/Components/plugin/qmlloader.cpp' |
353 | --- modules/Ubuntu/Components/plugin/qmlloader.cpp 2012-10-24 16:03:03 +0000 |
354 | +++ modules/Ubuntu/Components/plugin/qmlloader.cpp 1970-01-01 00:00:00 +0000 |
355 | @@ -1,117 +0,0 @@ |
356 | -/* |
357 | - * Copyright 2012 Canonical Ltd. |
358 | - * |
359 | - * This program is free software; you can redistribute it and/or modify |
360 | - * it under the terms of the GNU Lesser General Public License as published by |
361 | - * the Free Software Foundation; version 3. |
362 | - * |
363 | - * This program is distributed in the hope that it will be useful, |
364 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
365 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
366 | - * GNU Lesser General Public License for more details. |
367 | - * |
368 | - * You should have received a copy of the GNU Lesser General Public License |
369 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
370 | - * |
371 | - * Author: Zsombor Egri <zsombor.egri@canonical.com> |
372 | - */ |
373 | - |
374 | -#include "themeengine.h" |
375 | -#include "themeengine_p.h" |
376 | -#include "qmlloader_p.h" |
377 | -#include "rule.h" |
378 | -#include "itemstyleattached.h" |
379 | -#include <QtQml/QQmlEngine> |
380 | -#include <QtQml/QQmlContext> |
381 | -#include <QtQml/QQmlComponent> |
382 | -#include <QtQuick/QQuickItem> |
383 | -#include <QtCore/QDebug> |
384 | - |
385 | -/*! |
386 | - \internal |
387 | - The QmlTheme class loads a QML theme and builds up the ThemeEngine's Rule-element |
388 | - suffix-tree. |
389 | - */ |
390 | - |
391 | -/*============================================================================= |
392 | - QML THEME LOADER |
393 | -=============================================================================*/ |
394 | - |
395 | -QmlLoader::QmlLoader(QQmlEngine *engine) : |
396 | - QObject(engine), |
397 | - themeComponent(0), |
398 | - async(false) |
399 | -{ |
400 | - m_engine = engine; |
401 | -} |
402 | - |
403 | -/*! |
404 | - \internal |
405 | - Loads a QML theme and builds up the style rule tree. |
406 | - */ |
407 | -StyleTreeNode *QmlLoader::loadTheme(const QUrl &path, QStringList &themeFiles) |
408 | -{ |
409 | - async = false; |
410 | - themeComponent = new QQmlComponent(m_engine, path); |
411 | - // create the root node |
412 | - styleTree = new StyleTreeNode; |
413 | - if (themeComponent->isLoading()) { |
414 | - // the QML engine should be initialized by now, so use 0 for accessing instance |
415 | - async = true; |
416 | - QObject::connect(themeComponent, SIGNAL(statusChanged(QQmlComponent::Status)), |
417 | - ThemeEngine::instance(), SLOT(_q_continueThemeLoading)); |
418 | - } else |
419 | - finalizeThemeLoading(); |
420 | - |
421 | - if (styleTree) |
422 | - themeFiles << path.path(); |
423 | - return styleTree; |
424 | -} |
425 | - |
426 | -/*! |
427 | - \internal |
428 | - Finalizes theme loading. Parses theme for style rules and builds up the cache from it. |
429 | -*/ |
430 | -void QmlLoader::finalizeThemeLoading() |
431 | -{ |
432 | - if (!themeComponent->isError()) { |
433 | - QObject *theme = themeComponent->create(); |
434 | - if (theme) { |
435 | - // parse its children for Styles |
436 | - QList<Rule*> rules = theme->findChildren<Rule*>(); |
437 | - |
438 | - Q_FOREACH (Rule *rule, rules) { |
439 | - const QString selector = rule->selector(); |
440 | - if (selector.isEmpty()) { |
441 | - qWarning() << "Rule without selector!"; |
442 | - continue; |
443 | - } |
444 | - QList<Selector> pathList = ThemeEnginePrivate::parseSelector(selector); |
445 | - Q_FOREACH (const Selector &path, pathList) { |
446 | - styleTree->addStyleRule(path, rule); |
447 | - } |
448 | - } |
449 | - |
450 | - // emit themeChanged() using meta-object |
451 | - if (async) |
452 | - QMetaObject::invokeMethod(ThemeEngine::instance(), "themeChanged()", Qt::QueuedConnection); |
453 | - } |
454 | - } else { |
455 | - ThemeEnginePrivate::setError(QString("Error loading style\n%1"). |
456 | - arg(themeComponent->errorString())); |
457 | - // leave the root node as that might have been given already to the |
458 | - // theme engine due to asynchronousity |
459 | - if (async) |
460 | - styleTree->clear(); |
461 | - else { |
462 | - delete styleTree; |
463 | - styleTree = 0; |
464 | - } |
465 | - } |
466 | - |
467 | - // reset component |
468 | - delete themeComponent; |
469 | - themeComponent = 0; |
470 | -} |
471 | - |
472 | - |
473 | |
474 | === removed file 'modules/Ubuntu/Components/plugin/qmlloader_p.h' |
475 | --- modules/Ubuntu/Components/plugin/qmlloader_p.h 2012-10-24 16:03:03 +0000 |
476 | +++ modules/Ubuntu/Components/plugin/qmlloader_p.h 1970-01-01 00:00:00 +0000 |
477 | @@ -1,41 +0,0 @@ |
478 | -/* |
479 | - * Copyright 2012 Canonical Ltd. |
480 | - * |
481 | - * This program is free software; you can redistribute it and/or modify |
482 | - * it under the terms of the GNU Lesser General Public License as published by |
483 | - * the Free Software Foundation; version 3. |
484 | - * |
485 | - * This program is distributed in the hope that it will be useful, |
486 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
487 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
488 | - * GNU Lesser General Public License for more details. |
489 | - * |
490 | - * You should have received a copy of the GNU Lesser General Public License |
491 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
492 | - * |
493 | - * Author: Zsombor Egri <zsombor.egri@canonical.com> |
494 | - */ |
495 | - |
496 | -#ifndef QMLLOADER_P_H |
497 | -#define QMLLOADER_P_H |
498 | - |
499 | -#include "themeengine_p.h" |
500 | -#include "themeloader_p.h" |
501 | - |
502 | -// QML theme loader |
503 | -class QmlLoader : public QObject, public ThemeLoader { |
504 | - Q_OBJECT |
505 | -public: |
506 | - QmlLoader(QQmlEngine *engine); |
507 | - virtual ~QmlLoader(){} |
508 | - StyleTreeNode *loadTheme(const QUrl &path, QStringList &themeFiles); |
509 | - |
510 | -private Q_SLOTS: |
511 | - void finalizeThemeLoading(); |
512 | -private: |
513 | - QQmlComponent *themeComponent; |
514 | - StyleTreeNode *styleTree; |
515 | - bool async; |
516 | -}; |
517 | - |
518 | -#endif // QMLLOADER_P_H |
519 | |
520 | === modified file 'modules/Ubuntu/Components/plugin/qmlthemeloader.cpp' |
521 | --- modules/Ubuntu/Components/plugin/qmlthemeloader.cpp 2012-12-07 15:04:12 +0000 |
522 | +++ modules/Ubuntu/Components/plugin/qmlthemeloader.cpp 2013-01-14 14:26:22 +0000 |
523 | @@ -19,7 +19,6 @@ |
524 | #include "themeengine.h" |
525 | #include "themeengine_p.h" |
526 | #include "qmlthemeloader_p.h" |
527 | -#include "rule.h" |
528 | #include <QtQml/QQmlEngine> |
529 | #include <QtQml/QQmlContext> |
530 | #include <QtQml/QQmlComponent> |
531 | @@ -85,6 +84,28 @@ |
532 | } |
533 | |
534 | /*! |
535 | + * \internal |
536 | + * Create a QQmlComponent from a given QML string using the given engine |
537 | + */ |
538 | +QQmlComponent *createComponent(QQmlEngine *engine, const QString &qmlCode) |
539 | +{ |
540 | + if (qmlCode.isEmpty()) |
541 | + return 0; |
542 | + |
543 | + QQmlComponent *ret = new QQmlComponent(engine); |
544 | + ret->setData(qmlCode.toLatin1(), QUrl()); |
545 | + if (ret->isError() || !ret->isReady()) { |
546 | + QString errorString = ret->isError() ? ret->errorString() : "Component not ready"; |
547 | + ThemeEnginePrivate::setError(QString("Error on creating style rule: \n%2\n%3") |
548 | + .arg(qmlCode) |
549 | + .arg(errorString)); |
550 | + delete ret; |
551 | + ret = 0; |
552 | + } |
553 | + return ret; |
554 | +} |
555 | + |
556 | +/*! |
557 | * \brief QmlThemeLoader::urlMacro resolves the QmlTheme url() macro. |
558 | */ |
559 | QString QmlThemeLoader::urlMacro(const QString ¶m, const QTextStream &stream) |
560 | @@ -433,8 +454,8 @@ |
561 | |
562 | bool QmlThemeLoader::generateStyleQml() |
563 | { |
564 | - QString style; |
565 | - QString delegate; |
566 | + QString styleQml; |
567 | + QString delegateQml; |
568 | |
569 | // go through the selector map and build the styles to each |
570 | QHashIterator<Selector, QHash<QString, QString> > i(selectorTable); |
571 | @@ -443,25 +464,17 @@ |
572 | Selector selector = i.key(); |
573 | PropertyHash properties = i.value(); |
574 | |
575 | - buildStyleAndDelegate(selector, properties, style, delegate); |
576 | + buildStyleAndDelegate(selector, properties, styleQml, delegateQml); |
577 | |
578 | // normalize selector so we build the Rule with the proper one |
579 | normalizeSelector(selector); |
580 | |
581 | - // creating components from internal QML source is synchronous, unless |
582 | - // one of the imported elements require threaded loading. Therefore we use |
583 | - // Rule to create style and delegate components so Rule can handle |
584 | - // asynchronous completion of those. |
585 | - |
586 | - Rule *rule = new Rule(m_engine, |
587 | - ThemeEnginePrivate::selectorToString(selector), |
588 | - style, |
589 | - delegate); |
590 | - if (!ThemeEngine::instance()->error().isEmpty()) { |
591 | - delete rule; |
592 | + QQmlComponent *style = createComponent(m_engine, styleQml); |
593 | + QQmlComponent *delegate = createComponent(m_engine, delegateQml); |
594 | + if (!style && !delegate) { |
595 | return false; |
596 | - } else |
597 | - styleTree->addStyleRule(selector, rule); |
598 | + } |
599 | + styleTree->addStyleRule(selector, style, delegate); |
600 | } |
601 | |
602 | return true; |
603 | |
604 | === removed file 'modules/Ubuntu/Components/plugin/rule.cpp' |
605 | --- modules/Ubuntu/Components/plugin/rule.cpp 2012-11-20 10:07:44 +0000 |
606 | +++ modules/Ubuntu/Components/plugin/rule.cpp 1970-01-01 00:00:00 +0000 |
607 | @@ -1,382 +0,0 @@ |
608 | -/* |
609 | - * Copyright 2012 Canonical Ltd. |
610 | - * |
611 | - * This program is free software; you can redistribute it and/or modify |
612 | - * it under the terms of the GNU Lesser General Public License as published by |
613 | - * the Free Software Foundation; version 3. |
614 | - * |
615 | - * This program is distributed in the hope that it will be useful, |
616 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
617 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
618 | - * GNU Lesser General Public License for more details. |
619 | - * |
620 | - * You should have received a copy of the GNU Lesser General Public License |
621 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
622 | - * |
623 | - * Author: Zsombor Egri <zsombor.egri@canonical.com> |
624 | - */ |
625 | - |
626 | -#include "rule.h" |
627 | -#include "rule_p.h" |
628 | -#include "themeengine.h" |
629 | -#include "themeengine_p.h" |
630 | -#include <QtQml/QQmlEngine> |
631 | -#include <QtQml/QQmlContext> |
632 | -#include <QtCore/QString> |
633 | - |
634 | -/*! |
635 | - \qmltype Rule |
636 | - \internal |
637 | - \inqmlmodule Ubuntu.Components 0.1 |
638 | - \ingroup theming |
639 | - \brief The Rule element defines the styling rule to be applied when a item |
640 | - satisfies the conditions specified by the rule. The condition is specified by |
641 | - the selector property, using the CSS selector syntax. |
642 | - |
643 | - The following example defines a style rule that is applied on "frame" style |
644 | - class items. items satisfying the condition will use visuals defined in |
645 | - the delegate property and configured based on the values set by the style |
646 | - component. |
647 | - |
648 | - \qml |
649 | - // Snapshot of a theme file |
650 | - import QtQuick 2.0 |
651 | - import Ubuntu.Components 0.1 |
652 | - |
653 | - Item { |
654 | - Rule { |
655 | - selector: ".frame" |
656 | - style: QtObject { |
657 | - property color color: "lightgray" |
658 | - property color frameColor: "blue" |
659 | - } |
660 | - delegate: Component { |
661 | - Rectangle { |
662 | - anchors.fill: item |
663 | - color: itemStyle.color |
664 | - radius: 5 |
665 | - border { |
666 | - width: 2 |
667 | - color: itemStyle.frameColor |
668 | - } |
669 | - } |
670 | - } |
671 | - } |
672 | - } |
673 | - \endqml |
674 | - |
675 | - |
676 | - Rules can be declared either in a theme or in a ItemStyleAttached, in which case the |
677 | - style will be private for the item, and the item won't load any style from |
678 | - the themes. |
679 | - |
680 | - The theming subsystem declares the context property called "item" through which |
681 | - styles can access the targetted item properties, states, signals and functions, |
682 | - everything that is declared public in the item. |
683 | - |
684 | - There can be cases when the content of the item is anchored to the visuals or |
685 | - when the content of a item needs to stand on top of the visuals. In these cases |
686 | - delegates can declare an item, which will hold all the item content (item |
687 | - children) and name it as "contentItem". The theming engine will search for this |
688 | - property and if found, will reparent the item content to it. |
689 | - |
690 | - Example: |
691 | - \qml |
692 | - |
693 | - Rule { |
694 | - selector: ".frame" |
695 | - style: QtObject { |
696 | - property color color: "lightgray" |
697 | - property color frameColor: "blue" |
698 | - } |
699 | - delegate: Component { |
700 | - Rectangle { |
701 | - property alias contentItem: body |
702 | - anchors.fill: item |
703 | - color: itemStyle.color |
704 | - radius: 5 |
705 | - border { |
706 | - width: 2 |
707 | - color: itemStyle.frameColor |
708 | - } |
709 | - Item { |
710 | - id: body |
711 | - anchors.fill: parent |
712 | - anchors.margins: 10 |
713 | - } |
714 | - } |
715 | - } |
716 | - } |
717 | - |
718 | - \endqml |
719 | - In this example all item content to which the style is applied will get |
720 | - reparented to the body item. |
721 | -*/ |
722 | - |
723 | -/*! |
724 | - \preliminary |
725 | - \qmlsignal Rule::ruleChanged() |
726 | - Emitted when the rule creation gets completed. |
727 | -*/ |
728 | - |
729 | - |
730 | -RulePrivate::RulePrivate(Rule *qq) : |
731 | - q_ptr(qq), |
732 | - style(0), |
733 | - delegate(0), |
734 | - qmlThemeStyle(false) |
735 | -{ |
736 | -} |
737 | - |
738 | -/* |
739 | - Alternate constructor used in ".qmltheme" styles, when style and delegate component creation may be delayed. |
740 | - */ |
741 | -RulePrivate::RulePrivate(Rule *qq, QQmlEngine *engine, const QString &selector, const QString &styleRule, const QString &delegateRule) : |
742 | - q_ptr(qq), |
743 | - style(0), |
744 | - delegate(0), |
745 | - selector(selector), |
746 | - styleQml(styleRule), |
747 | - delegateQml(delegateRule), |
748 | - qmlThemeStyle(true) |
749 | -{ |
750 | - // create style component |
751 | - if (!styleQml.isEmpty()) |
752 | - createComponent(engine, styleQml, &style); |
753 | - |
754 | - // create delegate component |
755 | - if (!delegateQml.isEmpty()) |
756 | - createComponent(engine, delegateQml, &delegate); |
757 | -} |
758 | - |
759 | -/* |
760 | - Destroys style and delegate components in case the rule was created by a ".qmltheme" theme. |
761 | - */ |
762 | -RulePrivate::~RulePrivate() |
763 | -{ |
764 | - if (qmlThemeStyle) { |
765 | - if (!style) |
766 | - delete style; |
767 | - style = 0; |
768 | - if (delegate) |
769 | - delete delegate; |
770 | - delegate = 0; |
771 | - } |
772 | -} |
773 | - |
774 | -/* |
775 | - Initiates component creation for a given QML code |
776 | - */ |
777 | -void RulePrivate::createComponent(QQmlEngine *engine, const QString &qmlCode, QQmlComponent **component) |
778 | -{ |
779 | - *component = new QQmlComponent(engine); |
780 | - (*component)->setData(qmlCode.toLatin1(), QUrl()); |
781 | - if ((*component)->isLoading() && !(*component)->isError()) { |
782 | - QObject::connect(*component, SIGNAL(statusChanged(QQmlComponent::Status)), q_ptr, SLOT(_q_componentCompleted(QQmlComponent::Status))); |
783 | - } else |
784 | - completeComponent(*component); |
785 | -} |
786 | - |
787 | -/* |
788 | - Completes (style or delegate) component creation. If both created style and |
789 | - delegate components are ready, emits the ruleChanged signal to update ItemStyleAttacheds. |
790 | - */ |
791 | -void RulePrivate::completeComponent(QQmlComponent *sender) |
792 | -{ |
793 | - Q_ASSERT_X(sender, Q_FUNC_INFO, "Cannot have NULL component"); |
794 | - if (sender->isError()) { |
795 | - ThemeEnginePrivate::setError(QString("Error on creating rule for selector[%1]: \n%2\n%3") |
796 | - .arg(selector) |
797 | - .arg((sender == style) ? styleQml : delegateQml) |
798 | - .arg(sender->errorString())); |
799 | - } else if (!sender->isReady()) { |
800 | - ThemeEnginePrivate::setError(QString("Component not ready for selector[%1] \n%2\n%3") |
801 | - .arg(selector) |
802 | - .arg((sender == style) ? styleQml : delegateQml) |
803 | - .arg(sender->errorString())); |
804 | - } else { |
805 | - bool styleCompleted = false, delegateCompleted = false; |
806 | - if (!style || (style && (style->status() == QQmlComponent::Ready))) |
807 | - styleCompleted = true; |
808 | - if (!delegate || (delegate && (delegate->status() == QQmlComponent::Ready))) |
809 | - delegateCompleted = true; |
810 | - if (styleCompleted && delegateCompleted) { |
811 | - Q_Q(Rule); |
812 | - Q_EMIT q->ruleChanged(); |
813 | - } |
814 | - } |
815 | -} |
816 | - |
817 | -/* |
818 | - Slot completing the component (style or delegate) creation. Calls completeComponent |
819 | - with the signal sender. |
820 | - */ |
821 | -void RulePrivate::_q_componentCompleted(QQmlComponent::Status) |
822 | -{ |
823 | - Q_Q(Rule); |
824 | - QQmlComponent *sender = qobject_cast<QQmlComponent*>(q->sender()); |
825 | - completeComponent(sender); |
826 | -} |
827 | - |
828 | -/*============================================================================= |
829 | -=============================================================================*/ |
830 | - |
831 | -/*! |
832 | - \class Rule rule.h |
833 | - |
834 | - \internal |
835 | -*/ |
836 | - |
837 | -/*! |
838 | - Creates the rule element. This is used when QML theme file format is loaded. |
839 | - */ |
840 | -Rule::Rule(QObject *parent) : |
841 | - QObject(parent), |
842 | - d_ptr(new RulePrivate(this)) |
843 | -{} |
844 | - |
845 | -/*! |
846 | - Creates rule element used when QmlTheme format themes are loaded. The style and delegate |
847 | - components are created by the rule element as delayed completion can occur. |
848 | - */ |
849 | -Rule::Rule(QQmlEngine *engine, const QString &selector, const QString &styleRule, const QString &delegateRule, QObject *parent) : |
850 | - QObject(parent), |
851 | - d_ptr(new RulePrivate(this, engine, selector, styleRule, delegateRule)) |
852 | -{} |
853 | - |
854 | -/*! |
855 | - */ |
856 | -Rule::~Rule() |
857 | -{} |
858 | - |
859 | -/*! |
860 | - */ |
861 | -void Rule::classBegin() |
862 | -{ |
863 | - // from QQmlParserStatus |
864 | -} |
865 | - |
866 | -/*! |
867 | - */ |
868 | -void Rule::componentComplete() |
869 | -{ |
870 | - // trigger changed signal; this is needed when developer defines a private Rule |
871 | - // for a item so property bindings done with the rule are updated |
872 | - Q_EMIT ruleChanged(); |
873 | -} |
874 | - |
875 | -/*! |
876 | - Creates a style object in the \a context. Use this method instead of creating |
877 | - style objects straight from the style component, as this one checks the readyness |
878 | - of the style component of the rule. |
879 | - */ |
880 | -QObject *Rule::createStyle(QQmlContext *context) |
881 | -{ |
882 | - Q_D(Rule); |
883 | - if (d->qmlThemeStyle && d->style && (d->style->status() != QQmlComponent::Ready)) { |
884 | - ThemeEnginePrivate::setError(QString("Style not ready for [%1]\n%2") |
885 | - .arg(d->selector) |
886 | - .arg(d->styleQml)); |
887 | - return 0; |
888 | - } |
889 | - return d->style ? d->style->create(context) : 0; |
890 | -} |
891 | - |
892 | -/*! |
893 | - Creates the visuals item in the \a context. Use this method instead of creating |
894 | - visuals straight from the delegate component, as this one checks the readyness |
895 | - of the delegate component of the rule. |
896 | - */ |
897 | -QQuickItem *Rule::createDelegate(QQmlContext *context) |
898 | -{ |
899 | - Q_D(Rule); |
900 | - if (d->qmlThemeStyle && d->delegate && (d->delegate->status() != QQmlComponent::Ready)) { |
901 | - ThemeEnginePrivate::setError(QString("Delegate not ready for [%1]\n%2") |
902 | - .arg(d->selector) |
903 | - .arg(d->delegateQml)); |
904 | - return 0; |
905 | - } |
906 | - return d->delegate ? qobject_cast<QQuickItem*>(d->delegate->create(context)) : 0; |
907 | -} |
908 | - |
909 | - |
910 | -/*! |
911 | - \qmlproperty string Rule::selector |
912 | - This property holds the rule selector. The selector syntax follows some elements |
913 | - of the CSS-selector syntax as specified in W3C specifications as follows: |
914 | - - Type selectors, e.g: "Button" |
915 | - - Descendant selectors, e.g: "Dialog Button" |
916 | - - Child selectors, e.g: "Dialog > Button" |
917 | - - ID selectors, e.g: "Button#mySpecialButton" |
918 | - - Grouping, e.g: "Button#foo, Checkbox, #bar" |
919 | - */ |
920 | - |
921 | -/*! |
922 | - Rule selector value |
923 | - */ |
924 | -QString Rule::selector() const |
925 | -{ |
926 | - Q_D(const Rule); |
927 | - return d->selector; |
928 | -} |
929 | - |
930 | -/*! |
931 | - Sets the rule selector value |
932 | - */ |
933 | -void Rule::setSelector(const QString &selector) |
934 | -{ |
935 | - Q_D(Rule); |
936 | - d->selector = selector; |
937 | -} |
938 | - |
939 | -/*! |
940 | - \qmlproperty Component Rule::style |
941 | - This property holds the style configuration component. The style configuration |
942 | - component usually is a QtObject or a derivate of a QtObject, which enumerates |
943 | - the properties that can be configured on the rule delegate. A valid Rule must |
944 | - have either style or delegate, or both style and delegate set. |
945 | - */ |
946 | -/*! |
947 | - Rule style. |
948 | - */ |
949 | -QQmlComponent *Rule::style() |
950 | -{ |
951 | - Q_D(const Rule); |
952 | - return d->style; |
953 | -} |
954 | - |
955 | -/*! |
956 | - Sets the style property |
957 | - */ |
958 | -void Rule::setStyle(QQmlComponent *style) |
959 | -{ |
960 | - Q_D(Rule); |
961 | - d->style = style; |
962 | -} |
963 | - |
964 | -/*! |
965 | - \qmlproperty Component Rule::delegate |
966 | - This property holds the visuals component of the style. items implementations |
967 | - can decide on the separation of the visuals, either partially or completely. |
968 | - It is not mandatory for a item to rely fully on the visuals defined in themes. |
969 | - */ |
970 | - |
971 | -/*! |
972 | - Rule delegate. |
973 | - */ |
974 | -QQmlComponent *Rule::delegate() |
975 | -{ |
976 | - Q_D(const Rule); |
977 | - return d->delegate; |
978 | -} |
979 | - |
980 | -/*! |
981 | - Sets the delegate property value |
982 | - */ |
983 | -void Rule::setDelegate(QQmlComponent *delegate) |
984 | -{ |
985 | - Q_D(Rule); |
986 | - d->delegate = delegate; |
987 | -} |
988 | - |
989 | -#include "moc_rule.cpp" |
990 | |
991 | === removed file 'modules/Ubuntu/Components/plugin/rule.h' |
992 | --- modules/Ubuntu/Components/plugin/rule.h 2012-10-18 13:15:24 +0000 |
993 | +++ modules/Ubuntu/Components/plugin/rule.h 1970-01-01 00:00:00 +0000 |
994 | @@ -1,75 +0,0 @@ |
995 | -/* |
996 | - * Copyright 2012 Canonical Ltd. |
997 | - * |
998 | - * This program is free software; you can redistribute it and/or modify |
999 | - * it under the terms of the GNU Lesser General Public License as published by |
1000 | - * the Free Software Foundation; version 3. |
1001 | - * |
1002 | - * This program is distributed in the hope that it will be useful, |
1003 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1004 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1005 | - * GNU Lesser General Public License for more details. |
1006 | - * |
1007 | - * You should have received a copy of the GNU Lesser General Public License |
1008 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1009 | - * |
1010 | - * Author: Zsombor Egri <zsombor.egri@canonical.com> |
1011 | - */ |
1012 | - |
1013 | -#ifndef STYLE_H |
1014 | -#define STYLE_H |
1015 | - |
1016 | -#include <QtCore/QObject> |
1017 | -#include <QtCore/QStringList> |
1018 | -#include <QtQuick/QQuickItem> |
1019 | -#include <QtQml/QQmlParserStatus> |
1020 | - |
1021 | -class RulePrivate; |
1022 | -class QQmlComponent; |
1023 | -class QQmlEngine; |
1024 | -class Rule : public QObject, public QQmlParserStatus |
1025 | -{ |
1026 | - Q_OBJECT |
1027 | - Q_INTERFACES(QQmlParserStatus) |
1028 | - |
1029 | - Q_PROPERTY(QString selector READ selector WRITE setSelector) |
1030 | - Q_PROPERTY(QQmlComponent *style READ style WRITE setStyle) |
1031 | - Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate) |
1032 | - |
1033 | -public: |
1034 | - Rule(QObject *parent = 0); |
1035 | - Rule(QQmlEngine *engine, const QString &selector, const QString &styleRule, const QString &delegateRule, QObject *parent = 0); |
1036 | - ~Rule(); |
1037 | - |
1038 | - void classBegin(); |
1039 | - void componentComplete(); |
1040 | - |
1041 | - //create objects from style |
1042 | - QObject *createStyle(QQmlContext *context); |
1043 | - QQuickItem *createDelegate(QQmlContext *context); |
1044 | - |
1045 | - //internal |
1046 | - |
1047 | -Q_SIGNALS: |
1048 | - // the signal is emitted once the rule is completed |
1049 | - void ruleChanged(); |
1050 | - |
1051 | -public Q_SLOTS: |
1052 | - |
1053 | -public: //getters |
1054 | - QString selector() const; |
1055 | - QQmlComponent *style(); |
1056 | - QQmlComponent *delegate(); |
1057 | -private: //setters |
1058 | - void setSelector(const QString &selector); |
1059 | - void setStyle(QQmlComponent *style); |
1060 | - void setDelegate(QQmlComponent *delegate); |
1061 | - |
1062 | -private: |
1063 | - Q_DISABLE_COPY(Rule) |
1064 | - Q_DECLARE_PRIVATE(Rule) |
1065 | - QScopedPointer<RulePrivate> d_ptr; |
1066 | - Q_PRIVATE_SLOT(d_func(), void _q_componentCompleted(QQmlComponent::Status)) |
1067 | -}; |
1068 | - |
1069 | -#endif // STYLE_H |
1070 | |
1071 | === removed file 'modules/Ubuntu/Components/plugin/rule_p.h' |
1072 | --- modules/Ubuntu/Components/plugin/rule_p.h 2012-10-18 13:15:24 +0000 |
1073 | +++ modules/Ubuntu/Components/plugin/rule_p.h 1970-01-01 00:00:00 +0000 |
1074 | @@ -1,47 +0,0 @@ |
1075 | -/* |
1076 | - * Copyright 2012 Canonical Ltd. |
1077 | - * |
1078 | - * This program is free software; you can redistribute it and/or modify |
1079 | - * it under the terms of the GNU Lesser General Public License as published by |
1080 | - * the Free Software Foundation; version 3. |
1081 | - * |
1082 | - * This program is distributed in the hope that it will be useful, |
1083 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1084 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1085 | - * GNU Lesser General Public License for more details. |
1086 | - * |
1087 | - * You should have received a copy of the GNU Lesser General Public License |
1088 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1089 | - * |
1090 | - * Author: Zsombor Egri <zsombor.egri@canonical.com> |
1091 | - */ |
1092 | - |
1093 | -#ifndef STYLE_P_H |
1094 | -#define STYLE_P_H |
1095 | - |
1096 | -#include "rule.h" |
1097 | - |
1098 | -class RulePrivate |
1099 | -{ |
1100 | - Q_DECLARE_PUBLIC(Rule) |
1101 | - |
1102 | -public: |
1103 | - RulePrivate(Rule *qq); |
1104 | - RulePrivate(Rule *qq, QQmlEngine *engine, const QString &selector, const QString &styleRule, const QString &delegateRule); |
1105 | - ~RulePrivate(); |
1106 | - |
1107 | - Rule *q_ptr; |
1108 | - |
1109 | - QQmlComponent *style; |
1110 | - QQmlComponent *delegate; |
1111 | - QString selector; |
1112 | - QString styleQml; |
1113 | - QString delegateQml; |
1114 | - bool qmlThemeStyle; |
1115 | - |
1116 | - void createComponent(QQmlEngine *engine, const QString &rule, QQmlComponent **component); |
1117 | - void completeComponent(QQmlComponent *sender); |
1118 | - void _q_componentCompleted(QQmlComponent::Status); |
1119 | -}; |
1120 | - |
1121 | -#endif // STYLE_P_H |
1122 | |
1123 | === modified file 'modules/Ubuntu/Components/plugin/suffixtree.cpp' |
1124 | --- modules/Ubuntu/Components/plugin/suffixtree.cpp 2012-10-24 10:41:44 +0000 |
1125 | +++ modules/Ubuntu/Components/plugin/suffixtree.cpp 2013-01-14 14:26:22 +0000 |
1126 | @@ -18,7 +18,6 @@ |
1127 | |
1128 | #include "themeengine.h" |
1129 | #include "themeengine_p.h" |
1130 | -#include "rule.h" |
1131 | #include "suffixtree_p.h" |
1132 | #include <QtQml/QQmlEngine> |
1133 | #include <QtQml/QQmlContext> |
1134 | @@ -34,7 +33,8 @@ |
1135 | */ |
1136 | |
1137 | SelectorNode::SelectorNode() : |
1138 | - relationship(Descendant) |
1139 | + relationship(Descendant), |
1140 | + sensitivity(Normal) |
1141 | {} |
1142 | /*! |
1143 | \internal |
1144 | @@ -61,6 +61,10 @@ |
1145 | result += "> "; |
1146 | if (!styleClass.isEmpty()) |
1147 | result += "." + styleClass; |
1148 | + else if (!className.isEmpty()) { |
1149 | + qDebug() << "use" << className; |
1150 | + result += '.' + className; |
1151 | + } |
1152 | if (((sensitivity & IgnoreStyleId) != IgnoreStyleId) && !styleId.isEmpty()) |
1153 | result += "#" + styleId; |
1154 | return result; |
1155 | @@ -68,7 +72,10 @@ |
1156 | |
1157 | bool SelectorNode::operator==(const SelectorNode &other) |
1158 | { |
1159 | - bool ret = (styleClass == other.styleClass) && |
1160 | + QString myClass = (styleClass.isEmpty()) ? className : styleClass; |
1161 | + QString otherClass = (other.styleClass.isEmpty()) ? other.className : other.styleClass; |
1162 | + |
1163 | + bool ret = (myClass == otherClass) && |
1164 | (((sensitivity & IgnoreStyleId) == IgnoreStyleId) ? true : styleId == other.styleId) && |
1165 | (((sensitivity & IgnoreRelationship) == IgnoreRelationship) ? true : relationship == other.relationship); |
1166 | return ret; |
1167 | @@ -85,12 +92,12 @@ |
1168 | |
1169 | |
1170 | StyleTreeNode::StyleTreeNode(StyleTreeNode *parent) : |
1171 | - parent(parent), styleNode("", "", SelectorNode::Descendant), styleRule(0) |
1172 | + parent(parent), styleNode("", "", SelectorNode::Descendant), style(0), delegate(0) |
1173 | { |
1174 | } |
1175 | |
1176 | -StyleTreeNode::StyleTreeNode(StyleTreeNode *parent, const SelectorNode &node, Rule *styleRule) : |
1177 | - parent(parent), styleNode(node), styleRule(styleRule) |
1178 | +StyleTreeNode::StyleTreeNode(StyleTreeNode *parent, const SelectorNode &node, QQmlComponent *style, QQmlComponent *delegate) : |
1179 | + parent(parent), styleNode(node), style(style), delegate(delegate) |
1180 | { |
1181 | } |
1182 | |
1183 | @@ -116,7 +123,7 @@ |
1184 | \internal |
1185 | Adds a style rule to the style tree based on the selector path specified. |
1186 | */ |
1187 | -void StyleTreeNode::addStyleRule(const Selector &path, Rule *styleRule) |
1188 | +void StyleTreeNode::addStyleRule(const Selector &path, QQmlComponent *style, QQmlComponent *delegate) |
1189 | { |
1190 | Selector sparePath = path; |
1191 | SelectorNode nextNode = path.last(); |
1192 | @@ -130,26 +137,49 @@ |
1193 | // check if we have the node already, as it could be part of a previous path that |
1194 | // had not yet have a style set |
1195 | if (children.contains(nodeKey)) { |
1196 | - children.value(nodeKey)->styleRule = styleRule; |
1197 | + StyleTreeNode *node = children.value(nodeKey); |
1198 | + node->style = style; |
1199 | + node->delegate = delegate; |
1200 | } else { |
1201 | // new leaf |
1202 | - StyleTreeNode * node = new StyleTreeNode(this, nextNode, styleRule); |
1203 | + StyleTreeNode * node = new StyleTreeNode(this, nextNode, style, delegate); |
1204 | children.insert(nodeKey, node); |
1205 | } |
1206 | } else { |
1207 | // check if we have the node in the hash |
1208 | if (children.contains(nodeKey)) { |
1209 | - children.value(nodeKey)->addStyleRule(sparePath, styleRule); |
1210 | + children.value(nodeKey)->addStyleRule(sparePath, style, delegate); |
1211 | } else { |
1212 | - // new node |
1213 | - StyleTreeNode *node = new StyleTreeNode(this, nextNode, 0); |
1214 | + // new intermediate node |
1215 | + StyleTreeNode *node = new StyleTreeNode(this, nextNode, 0, 0); |
1216 | children.insert(nodeKey, node); |
1217 | - node->addStyleRule(sparePath, styleRule); |
1218 | + node->addStyleRule(sparePath, style, delegate); |
1219 | } |
1220 | } |
1221 | } |
1222 | |
1223 | /*! |
1224 | + * \internal |
1225 | + * The method returns the selector path from the current node built using its parent |
1226 | + * nodes. |
1227 | + */ |
1228 | +Selector StyleTreeNode::path() const |
1229 | +{ |
1230 | + Selector result; |
1231 | + |
1232 | + result << styleNode; |
1233 | + |
1234 | + StyleTreeNode *p = parent; |
1235 | + while (p) { |
1236 | + if (p->parent) |
1237 | + result.append(p->styleNode); |
1238 | + p = p->parent; |
1239 | + } |
1240 | + return result; |
1241 | +} |
1242 | + |
1243 | + |
1244 | +/*! |
1245 | \internal |
1246 | Search for the style best matching the item path. The path is parsed from the |
1247 | tail as the styles are stored in the tree in suffix form. The \a strict |
1248 | @@ -165,7 +195,7 @@ |
1249 | returned for the ".box > .frame > .button" Item. If the theme would have only |
1250 | the ".box .frame .button" rule defined, the lookup would not match that rule. |
1251 | */ |
1252 | -Rule *StyleTreeNode::lookupStyleRule(const Selector &path, bool strict) |
1253 | +StyleTreeNode *StyleTreeNode::lookupStyleRule(const Selector &path, bool strict) |
1254 | { |
1255 | // the spare contains the remainder |
1256 | Selector sparePath = path; |
1257 | @@ -175,17 +205,17 @@ |
1258 | sparePath.removeLast(); |
1259 | } |
1260 | |
1261 | + StyleTreeNode *rule = 0; |
1262 | + |
1263 | // special case: root node forwards the lookup to its children |
1264 | if (!parent) { |
1265 | - return testNode(nextPathNode, sparePath, strict); |
1266 | + rule = testNode(nextPathNode, sparePath, strict); |
1267 | } else { |
1268 | // check whether we have a child that satisfies the node |
1269 | // try to remove elements from the path, maybe we still can get a match |
1270 | - while (true) { |
1271 | - Rule *rule = testNode(nextPathNode, sparePath, strict); |
1272 | - if (rule) |
1273 | - return rule; |
1274 | - if (!sparePath.isEmpty()) { |
1275 | + while (!rule) { |
1276 | + rule = testNode(nextPathNode, sparePath, strict); |
1277 | + if (!rule && !sparePath.isEmpty()) { |
1278 | nextPathNode = sparePath.last(); |
1279 | sparePath.removeLast(); |
1280 | } else |
1281 | @@ -194,41 +224,35 @@ |
1282 | } |
1283 | |
1284 | // we have consumed the path, return the style from the node/leaf |
1285 | - return styleRule; |
1286 | + if (!rule && (style || delegate)) |
1287 | + rule = this; |
1288 | + |
1289 | + return rule; |
1290 | } |
1291 | |
1292 | /*! |
1293 | \internal |
1294 | Test whether a child matches the criteria |
1295 | */ |
1296 | -Rule *StyleTreeNode::testNode(SelectorNode &nextNode, const Selector &sparePath, bool &strict) |
1297 | +StyleTreeNode *StyleTreeNode::testNode(SelectorNode &nextNode, const Selector &sparePath, bool &strict) |
1298 | { |
1299 | - Rule *rule = 0; |
1300 | + StyleTreeNode *rule = 0; |
1301 | QString nodeKey = nextNode.toString(); |
1302 | + |
1303 | if (children.contains(nodeKey)) { |
1304 | rule = children.value(nodeKey)->lookupStyleRule(sparePath, strict); |
1305 | } |
1306 | - //if (!rule && !strict && (nextNode.relationship == SelectorNode::Child)) { |
1307 | - if (!rule && !strict) { |
1308 | - // check if we find something without the style name |
1309 | - if (!nextNode.styleId.isEmpty()) |
1310 | - nextNode.styleId = QString(); |
1311 | - nodeKey = nextNode.toString(); |
1312 | - strict = true; |
1313 | - if (children.contains(nodeKey)) { |
1314 | - rule = children.value(nodeKey)->lookupStyleRule(sparePath, strict); |
1315 | - } |
1316 | - if (!rule && (nextNode.relationship == SelectorNode::Child)) { |
1317 | - // check if the searched node had Child relationship; if yes, |
1318 | - // change it to Descendant and look after the style again; if |
1319 | - // found, the lookup after this point should be strict |
1320 | - nextNode.relationship = SelectorNode::Descendant; |
1321 | - nodeKey = nextNode.toString(); |
1322 | - strict = true; |
1323 | - if (children.contains(nodeKey)) { |
1324 | - rule = children.value(nodeKey)->lookupStyleRule(sparePath, strict); |
1325 | - } |
1326 | - } |
1327 | + if (!rule && !nextNode.styleId.isEmpty()) { |
1328 | + nextNode.sensitivity |= SelectorNode::IgnoreStyleId; |
1329 | + nodeKey = nextNode.toString(); |
1330 | + if (children.contains(nodeKey)) |
1331 | + rule = children.value(nodeKey)->lookupStyleRule(sparePath, strict); |
1332 | + } |
1333 | + if (!rule && (nextNode.relationship == SelectorNode::Child)) { |
1334 | + nextNode.sensitivity |= SelectorNode::IgnoreRelationship; |
1335 | + nodeKey = nextNode.toString(); |
1336 | + if (children.contains(nodeKey)) |
1337 | + rule = children.value(nodeKey)->lookupStyleRule(sparePath, strict); |
1338 | } |
1339 | |
1340 | return rule; |
1341 | |
1342 | === modified file 'modules/Ubuntu/Components/plugin/suffixtree_p.h' |
1343 | --- modules/Ubuntu/Components/plugin/suffixtree_p.h 2012-10-22 15:32:04 +0000 |
1344 | +++ modules/Ubuntu/Components/plugin/suffixtree_p.h 2013-01-14 14:26:22 +0000 |
1345 | @@ -19,6 +19,9 @@ |
1346 | #ifndef SUFFIXTREE_P_H |
1347 | #define SUFFIXTREE_P_H |
1348 | |
1349 | +#include <QtCore/QHash> |
1350 | +#include <QtCore/QString> |
1351 | + |
1352 | // node of a selector |
1353 | class SelectorNode { |
1354 | public: |
1355 | @@ -29,9 +32,10 @@ |
1356 | IgnoreStyleId = 0x02, |
1357 | IgnoreAll = IgnoreRelationship | IgnoreStyleId}; |
1358 | SelectorNode(); |
1359 | - SelectorNode(const QString &styleClass, const QString &styleId, Relationship relationship, NodeSensitivity sensitivity = Normal); |
1360 | + SelectorNode(const QString &styleClass, const QString &styleId, Relationship relationship = Descendant, NodeSensitivity sensitivity = Normal); |
1361 | QString toString() const; |
1362 | bool operator==(const SelectorNode &other); |
1363 | + QString className; |
1364 | QString styleClass; |
1365 | QString styleId; |
1366 | Relationship relationship; |
1367 | @@ -43,20 +47,23 @@ |
1368 | uint qHash(const Selector &key); |
1369 | |
1370 | // style rule tree |
1371 | +class QQmlComponent; |
1372 | class StyleTreeNode { |
1373 | public: |
1374 | StyleTreeNode(StyleTreeNode *parent = 0); |
1375 | - StyleTreeNode(StyleTreeNode *parent, const SelectorNode &node, Rule *styleRule); |
1376 | + StyleTreeNode(StyleTreeNode *parent, const SelectorNode &node, QQmlComponent *style, QQmlComponent *delegate); |
1377 | ~StyleTreeNode(); |
1378 | void clear(); |
1379 | - void addStyleRule(const Selector &path, Rule *styleRule); |
1380 | - Rule *lookupStyleRule(const Selector &path, bool strict = false); |
1381 | - Rule *testNode(SelectorNode &nextNode, const Selector &sparePath, bool &strict); |
1382 | + void addStyleRule(const Selector &path, QQmlComponent *style, QQmlComponent *delegate); |
1383 | + Selector path() const; |
1384 | + StyleTreeNode *lookupStyleRule(const Selector &path, bool strict = false); |
1385 | + StyleTreeNode *testNode(SelectorNode &nextNode, const Selector &sparePath, bool &strict); |
1386 | |
1387 | public: |
1388 | StyleTreeNode *parent; |
1389 | SelectorNode styleNode; |
1390 | - Rule *styleRule; |
1391 | + QQmlComponent *style; |
1392 | + QQmlComponent *delegate; |
1393 | // the key is the next style node's "relationship class#name" combination |
1394 | QHash<QString, StyleTreeNode*> children; |
1395 | }; |
1396 | |
1397 | === modified file 'modules/Ubuntu/Components/plugin/themeengine.cpp' |
1398 | --- modules/Ubuntu/Components/plugin/themeengine.cpp 2012-11-13 16:19:17 +0000 |
1399 | +++ modules/Ubuntu/Components/plugin/themeengine.cpp 2013-01-14 14:26:22 +0000 |
1400 | @@ -18,11 +18,10 @@ |
1401 | |
1402 | #include "themeengine.h" |
1403 | #include "themeengine_p.h" |
1404 | -#include "rule.h" |
1405 | #include "itemstyleattached.h" |
1406 | +#include "itemstyleattached_p.h" |
1407 | #include "themeloader_p.h" |
1408 | #include "qmlthemeloader_p.h" |
1409 | -#include "qmlloader_p.h" |
1410 | #include <QtCore/QString> |
1411 | #include <QtQml/QQmlEngine> |
1412 | #include <QtQml/QJSEngine> |
1413 | @@ -57,7 +56,8 @@ |
1414 | themeEngine = q_ptr; |
1415 | |
1416 | // register theme loaders |
1417 | - themeLoaders[".qml"] = new QmlLoader(m_engine); |
1418 | + // so far we have one single loader, however keep the design so we can add |
1419 | + // more of them later if needed |
1420 | themeLoaders[".qmltheme"] = new QmlThemeLoader(m_engine); |
1421 | |
1422 | // connect theme settings to capture theme updates |
1423 | @@ -157,61 +157,18 @@ |
1424 | |
1425 | /*! |
1426 | \internal |
1427 | - Traverses and returns the path from \a obj up to root as a list of class |
1428 | - and name pairs, setting the relationship between the selector nodes |
1429 | - depending on the relationship between the parent and child, i.e. if a certain |
1430 | - ItemStyleAttached's parent is also a ItemStyleAttached, the SelectorNode::Child |
1431 | - relation, otherwise SelectorNode::Descendant relation is used. |
1432 | - |
1433 | - The obj is an Item derived element and should have class and name properties |
1434 | - to be used if styling happens on them. |
1435 | - */ |
1436 | -Selector ThemeEnginePrivate::getSelector(QQuickItem *obj, bool forceClassName) const |
1437 | -{ |
1438 | - Selector selector; |
1439 | - QQuickItem *parent; |
1440 | - |
1441 | - while (obj) { |
1442 | - ItemStyleAttached *style = attachedStyle(obj); |
1443 | - QString styleClass = style ? style->styleClass() : QString(); |
1444 | - |
1445 | - parent = obj->parentItem(); |
1446 | - |
1447 | - // we talk about Child relationship when the parent has styling properties |
1448 | - // otherwise we talk about Descendant |
1449 | - ItemStyleAttached *parentStyle = attachedStyle(parent); |
1450 | - SelectorNode::Relationship relation = parentStyle ? |
1451 | - SelectorNode::Child : SelectorNode::Descendant; |
1452 | - |
1453 | - // if class is not defined, use the component's meta class name |
1454 | - if (styleClass.isEmpty() || forceClassName) { |
1455 | - styleClass = obj->metaObject()->className(); |
1456 | - styleClass = styleClass.left(styleClass.indexOf("_QMLTYPE")).toLower(); |
1457 | - } |
1458 | - QString styleId = style->name(); |
1459 | - if (!styleClass.isEmpty() || !styleId.isEmpty()) { |
1460 | - selector.prepend(SelectorNode(styleClass, styleId, relation)); |
1461 | - } |
1462 | - |
1463 | - // get the next ItemStyleAttached, we don't care the rest |
1464 | - while (parent && !parentStyle) { |
1465 | - parent = parent->parentItem(); |
1466 | - parentStyle = attachedStyle(parent); |
1467 | - } |
1468 | - obj = parent; |
1469 | - } |
1470 | - return selector; |
1471 | -} |
1472 | - |
1473 | -/*! |
1474 | - \internal |
1475 | - Wrapper function above the style tree lookup. Exposed for functional testing. |
1476 | + This method searches for styling components matching the given selector (style path). |
1477 | */ |
1478 | -Rule *ThemeEnginePrivate::styleRuleForPath(const Selector &path) |
1479 | +StyleTreeNode *ThemeEnginePrivate::styleRuleForPath(const Selector &path) |
1480 | { |
1481 | - if (!m_styleTree) |
1482 | + if (!themeEngine->d_ptr->m_styleTree) |
1483 | return 0; |
1484 | - Rule *rule = m_styleTree->lookupStyleRule(path); |
1485 | + if (themeEngine->d_ptr->m_styleCache.contains(path)) |
1486 | + return themeEngine->d_ptr->m_styleCache.value(path); |
1487 | + |
1488 | + StyleTreeNode *rule = themeEngine->d_ptr->m_styleTree->lookupStyleRule(path); |
1489 | + if (rule) |
1490 | + themeEngine->d_ptr->m_styleCache.insert(path, rule); |
1491 | return rule; |
1492 | } |
1493 | |
1494 | @@ -222,6 +179,36 @@ |
1495 | |
1496 | /*! |
1497 | \internal |
1498 | + Checks whether the instance can be registered to the given name, and registers it. |
1499 | + Removes any previous registration. |
1500 | +*/ |
1501 | +bool ThemeEnginePrivate::registerName(QQuickItem *item, const QString &newName) |
1502 | +{ |
1503 | + bool ret = true; |
1504 | + |
1505 | + // check first whether the next ID is valid and can be registered |
1506 | + QString prevName(item->property("name").toString()); |
1507 | + if (newName.isEmpty()) { |
1508 | + // remove the previous occurence |
1509 | + if (!prevName.isEmpty()) |
1510 | + themeEngine->d_ptr->m_instanceCache.remove(prevName); |
1511 | + } else { |
1512 | + if (themeEngine->d_ptr->m_instanceCache.contains(newName)) |
1513 | + ret = false; |
1514 | + else { |
1515 | + // remove the previous occurence |
1516 | + if (!prevName.isEmpty()) |
1517 | + themeEngine->d_ptr->m_instanceCache.remove(prevName); |
1518 | + // register instance |
1519 | + themeEngine->d_ptr->m_instanceCache.insert(newName, item); |
1520 | + } |
1521 | + } |
1522 | + |
1523 | + return ret; |
1524 | +} |
1525 | + |
1526 | +/*! |
1527 | + \internal |
1528 | Sets the error string and emits the signal associated to the public property, |
1529 | so error handling is propagated to the UI. |
1530 | */ |
1531 | @@ -357,61 +344,6 @@ |
1532 | } |
1533 | |
1534 | /*! |
1535 | - \internal |
1536 | - Checks whether the instance can be registered to the given name, and registers it. |
1537 | - Removes any previous registration. |
1538 | -*/ |
1539 | -bool ThemeEngine::registerName(QQuickItem *item, const QString &newName) |
1540 | -{ |
1541 | - Q_D(ThemeEngine); |
1542 | - bool ret = true; |
1543 | - |
1544 | - // check first whether the next ID is valid and can be registered |
1545 | - QString prevName(item->property("name").toString()); |
1546 | - if (newName.isEmpty()) { |
1547 | - // remove the previous occurence |
1548 | - if (!prevName.isEmpty()) |
1549 | - d->m_instanceCache.remove(prevName); |
1550 | - } else { |
1551 | - if (d->m_instanceCache.contains(newName)) |
1552 | - ret = false; |
1553 | - else { |
1554 | - // remove the previous occurence |
1555 | - if (!prevName.isEmpty()) |
1556 | - d->m_instanceCache.remove(prevName); |
1557 | - // register instance |
1558 | - d->m_instanceCache.insert(newName, item); |
1559 | - } |
1560 | - } |
1561 | - |
1562 | - return ret; |
1563 | -} |
1564 | - |
1565 | -/*! |
1566 | - \internal |
1567 | - This method searches for a Rule element that matches the conditions for an |
1568 | - Item. The selector identifying the Rule is built up by traversing the \a item |
1569 | - parents and considering only those having ItemStyle elements attached in the hierarchy. |
1570 | - */ |
1571 | -Rule *ThemeEngine::lookupStyleRule(QQuickItem *item, bool forceClassName) |
1572 | -{ |
1573 | - Q_D(ThemeEngine); |
1574 | - |
1575 | - Selector path = d->getSelector(item, forceClassName); |
1576 | - |
1577 | - // check whether we have the path cached |
1578 | - if (d->m_styleCache.contains(path)) { |
1579 | - return d->m_styleCache.value(path); |
1580 | - } |
1581 | - Rule *rule = d->styleRuleForPath(path); |
1582 | - if (rule) { |
1583 | - // cache the rule |
1584 | - d->m_styleCache.insert(path, rule); |
1585 | - } |
1586 | - return rule; |
1587 | -} |
1588 | - |
1589 | -/*! |
1590 | \preliminary |
1591 | \qmlmethod bool Theme::loadTheme(const QUrl &themeFile) |
1592 | Loads a theme file from any location, and updates the \a currentTheme property |
1593 | |
1594 | === modified file 'modules/Ubuntu/Components/plugin/themeengine.h' |
1595 | --- modules/Ubuntu/Components/plugin/themeengine.h 2012-10-24 16:03:03 +0000 |
1596 | +++ modules/Ubuntu/Components/plugin/themeengine.h 2013-01-14 14:26:22 +0000 |
1597 | @@ -21,8 +21,8 @@ |
1598 | |
1599 | #include <QtCore/QObject> |
1600 | #include <QtCore/QUrl> |
1601 | +#include "suffixtree_p.h" |
1602 | |
1603 | -class Rule; |
1604 | class QQmlEngine; |
1605 | class QJSEngine; |
1606 | class QQuickItem; |
1607 | @@ -42,9 +42,6 @@ |
1608 | static QObject *initializeEngine(QQmlEngine *engine); |
1609 | static ThemeEngine *instance(); |
1610 | |
1611 | - bool registerName(QQuickItem *item, const QString &newId); |
1612 | - Rule *lookupStyleRule(QQuickItem *item, bool forceClassName = false); |
1613 | - |
1614 | // getter/setters |
1615 | QString error() const; |
1616 | void resetError(); |
1617 | |
1618 | === modified file 'modules/Ubuntu/Components/plugin/themeengine_p.h' |
1619 | --- modules/Ubuntu/Components/plugin/themeengine_p.h 2012-11-08 10:51:41 +0000 |
1620 | +++ modules/Ubuntu/Components/plugin/themeengine_p.h 2013-01-14 14:26:22 +0000 |
1621 | @@ -50,7 +50,7 @@ |
1622 | QQmlEngine *m_engine; |
1623 | // suffix tree for the styles |
1624 | StyleTreeNode *m_styleTree; |
1625 | - QHash<Selector, Rule*> m_styleCache; |
1626 | + QHash<Selector, StyleTreeNode*> m_styleCache; |
1627 | InstanceHash m_instanceCache; |
1628 | QStringList importPaths; |
1629 | QMap<QString, ThemeLoader*> themeLoaders; |
1630 | @@ -66,10 +66,10 @@ |
1631 | void removeWatchedFiles(); |
1632 | void addWatchedFiles(const QStringList &watchedThemeFiles); |
1633 | void loadTheme(const QUrl &themeFile); |
1634 | - Selector getSelector(QQuickItem *obj, bool forceClassName) const; |
1635 | - Rule *styleRuleForPath(const Selector &path); |
1636 | |
1637 | // utility functions that are independent from the instance |
1638 | + static StyleTreeNode *styleRuleForPath(const Selector &path); |
1639 | + static bool registerName(QQuickItem *item, const QString &newName); |
1640 | static void setError(const QString &error); |
1641 | static ItemStyleAttached *attachedStyle(QObject *obj); |
1642 | static QString selectorToString(const Selector &path); |
1643 | |
1644 | === modified file 'tests/resources/test.qmltheme' |
1645 | --- tests/resources/test.qmltheme 2012-12-07 15:04:12 +0000 |
1646 | +++ tests/resources/test.qmltheme 2013-01-14 14:26:22 +0000 |
1647 | @@ -3,9 +3,6 @@ |
1648 | @qml-mapping(.baseA, , Item); |
1649 | @qml-mapping(.testA .baseA, , Text); |
1650 | |
1651 | -@qml-import("test", .); |
1652 | -@qml-import("test2", .); |
1653 | - |
1654 | .baseA { |
1655 | test_base_A_A: "new:: test.qmltheme/.baseA"; |
1656 | prop_baseA_A: "overload:: test.qmltheme/.baseA"; |
1657 | |
1658 | === modified file 'tests/unit/tst_theme_engine/tst_theme_enginetest.cpp' |
1659 | --- tests/unit/tst_theme_engine/tst_theme_enginetest.cpp 2012-11-20 18:00:45 +0000 |
1660 | +++ tests/unit/tst_theme_engine/tst_theme_enginetest.cpp 2013-01-14 14:26:22 +0000 |
1661 | @@ -31,7 +31,6 @@ |
1662 | |
1663 | #include "themeengine.h" |
1664 | #include "themeengine_p.h" |
1665 | -#include "rule.h" |
1666 | #include "itemstyleattached.h" |
1667 | |
1668 | class tst_ThemeEngine : public QObject |
1669 | @@ -46,9 +45,7 @@ |
1670 | void cleanupTestCase(); |
1671 | |
1672 | void testCase_initializeEngine(); |
1673 | - void testCase_registerName(); |
1674 | void testCase_loadTheme(); |
1675 | - void testCase_lookupStyleRule(); |
1676 | void testCase_reparenting(); |
1677 | void testCase_blockDeclaration(); |
1678 | void testCase_selectorDelegates(); |
1679 | @@ -91,28 +88,6 @@ |
1680 | QCOMPARE(result, true); |
1681 | } |
1682 | |
1683 | -void tst_ThemeEngine::testCase_registerName() |
1684 | -{ |
1685 | - ThemeEngine::instance()->resetError(); |
1686 | - QQuickItem *item = new QQuickItem(0); |
1687 | - // first time must pass |
1688 | - bool result = ThemeEngine::instance()->registerName(item, "test"); |
1689 | - QCOMPARE(result, true); |
1690 | - // second time should fail |
1691 | - result = ThemeEngine::instance()->registerName(item, "test"); |
1692 | - QCOMPARE(result, false); |
1693 | - // this should pass always |
1694 | - result = ThemeEngine::instance()->registerName(item, QString()); |
1695 | - QCOMPARE(result, true); |
1696 | - delete item; |
1697 | -} |
1698 | - |
1699 | -void tst_ThemeEngine::testCase_lookupStyleRule() |
1700 | -{ |
1701 | - //ThemeEngine::lookupStyleRule requires a complete QML environment therefore its |
1702 | - // functionality will be tested using its privates |
1703 | -} |
1704 | - |
1705 | void tst_ThemeEngine::testCase_loadTheme() |
1706 | { |
1707 | ThemeEngine::instance()->resetError(); |
1708 | |
1709 | === modified file 'tests/unit/tst_theme_engine_private/tst_theme_engine_privatetest.cpp' |
1710 | --- tests/unit/tst_theme_engine_private/tst_theme_engine_privatetest.cpp 2012-11-14 07:24:18 +0000 |
1711 | +++ tests/unit/tst_theme_engine_private/tst_theme_engine_privatetest.cpp 2013-01-14 14:26:22 +0000 |
1712 | @@ -22,11 +22,12 @@ |
1713 | #include <QtCore/QCoreApplication> |
1714 | #include <QtQml/QQmlEngine> |
1715 | #include <QtQuick/QQuickView> |
1716 | +#include <QtQuick/QQuickItem> |
1717 | |
1718 | #include "themeengine.h" |
1719 | #include "themeengine_p.h" |
1720 | #include "itemstyleattached.h" |
1721 | -#include "rule.h" |
1722 | +#include "suffixtree_p.h" |
1723 | |
1724 | class tst_ThemeEnginePrivate : public QObject |
1725 | { |
1726 | @@ -38,6 +39,7 @@ |
1727 | private Q_SLOTS: |
1728 | void initTestCase(); |
1729 | void cleanupTestCase(); |
1730 | + void testCase_registerName(); |
1731 | void testCase_loadTheme(); |
1732 | void testCase_urlMacro(); |
1733 | void testCase_styleRuleForPath(); |
1734 | @@ -64,10 +66,7 @@ |
1735 | // declarative does not create the Rule objects but QObjects, and does |
1736 | // not give any error... |
1737 | |
1738 | - const char *uri = QString("Ubuntu.Components").toLatin1(); |
1739 | ThemeEngine::initializeEngine(quickEngine); |
1740 | - qmlRegisterType<Rule>(uri, 0, 1, "Rule"); |
1741 | - qmlRegisterType<ItemStyleAttached>(uri, 0, 1, "ItemStyle"); |
1742 | |
1743 | // engine privates can be created with its public class; therefore |
1744 | // we create an engine class and use its privates |
1745 | @@ -78,6 +77,22 @@ |
1746 | { |
1747 | } |
1748 | |
1749 | +void tst_ThemeEnginePrivate::testCase_registerName() |
1750 | +{ |
1751 | + ThemeEngine::instance()->resetError(); |
1752 | + QQuickItem *item = new QQuickItem(0); |
1753 | + // first time must pass |
1754 | + bool result = ThemeEnginePrivate::registerName(item, "test"); |
1755 | + QCOMPARE(result, true); |
1756 | + // second time should fail |
1757 | + result = ThemeEnginePrivate::registerName(item, "test"); |
1758 | + QCOMPARE(result, false); |
1759 | + // this should pass always |
1760 | + result = ThemeEnginePrivate::registerName(item, QString()); |
1761 | + QCOMPARE(result, true); |
1762 | + delete item; |
1763 | +} |
1764 | + |
1765 | void tst_ThemeEnginePrivate::testCase_loadTheme() |
1766 | { |
1767 | engine->errorString = QString(); |
1768 | @@ -102,11 +117,11 @@ |
1769 | engine->loadTheme(themeFile); |
1770 | |
1771 | Selector selector = engine->parseSelector(".baseA")[0]; |
1772 | - Rule *rule = engine->styleRuleForPath(selector); |
1773 | + StyleTreeNode *rule = engine->styleRuleForPath(selector); |
1774 | QVERIFY2(rule, "Failure"); |
1775 | if (rule) { |
1776 | // create style from the rule so we can check the validity of the URLs |
1777 | - QObject *style = rule->createStyle(quickEngine->rootContext()); |
1778 | + QObject *style = rule->style ? rule->style->create(quickEngine->rootContext()) : 0; |
1779 | QVERIFY2(style, "FAILURE"); |
1780 | |
1781 | QString url = style->property("prop_baseA_A").toString(); |
1782 | @@ -143,13 +158,13 @@ |
1783 | QCOMPARE(engine->errorString, QString()); |
1784 | |
1785 | bool result = true; |
1786 | - Rule *rule; |
1787 | + StyleTreeNode *rule; |
1788 | Selector path, expected; |
1789 | |
1790 | path << SelectorNode("baseA", "", SelectorNode::Descendant); |
1791 | rule = engine->styleRuleForPath(path); |
1792 | // should pass |
1793 | - result = (rule != 0) && (engine->parseSelector(rule->selector())[0] == path); |
1794 | + result = (rule != 0) && (rule->path() == path); |
1795 | QCOMPARE(result, true); |
1796 | |
1797 | path.clear(); |
1798 | @@ -157,7 +172,7 @@ |
1799 | path << SelectorNode("baseA", "", SelectorNode::Descendant); |
1800 | rule = engine->styleRuleForPath(path); |
1801 | // should pass |
1802 | - result = (rule != 0) && (engine->parseSelector(rule->selector())[0] == path); |
1803 | + result = (rule != 0) && (rule->path() == path); |
1804 | QCOMPARE(result, true); |
1805 | |
1806 | path.clear(); |
1807 | @@ -167,7 +182,7 @@ |
1808 | expected << SelectorNode("baseA", "", SelectorNode::Descendant); |
1809 | rule = engine->styleRuleForPath(path); |
1810 | // should pass, but should be ".testA .baseA" |
1811 | - result = (rule != 0) && (engine->parseSelector(rule->selector())[0] == expected); |
1812 | + result = (rule != 0) && (rule->path() == expected); |
1813 | QCOMPARE(result, true); |
1814 | |
1815 | path.clear(); |
1816 | @@ -175,7 +190,7 @@ |
1817 | path << SelectorNode("baseA", "", SelectorNode::Child); |
1818 | rule = engine->styleRuleForPath(path); |
1819 | // should pass |
1820 | - result = (rule != 0) && (engine->parseSelector(rule->selector())[0] == path); |
1821 | + result = (rule != 0) && (rule->path() == path); |
1822 | QCOMPARE(result, true); |
1823 | |
1824 | path.clear(); |
1825 | @@ -183,7 +198,7 @@ |
1826 | path << SelectorNode("baseA", "", SelectorNode::Descendant); |
1827 | rule = engine->styleRuleForPath(path); |
1828 | // should fail |
1829 | - result = (rule != 0) && !(engine->parseSelector(rule->selector())[0] == path); |
1830 | + result = (rule != 0) && (rule->path() != path); |
1831 | QCOMPARE(result, true); |
1832 | } |
1833 |
This MR needs to be resubmitted against the new trunk.