Merge lp:~zsombi/ubuntu-ui-toolkit/qml-role-and-loader-removal into lp:ubuntu-ui-toolkit

Proposed by Zsombor Egri
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
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.

Description of the change

QML Role element and qml-loader removed. Role functionality distributed between StyleTree and ItemStyle. ThemeEngine contains only QML API.

To post a comment you must log in.
Revision history for this message
Juhapekka Piiroinen (juhapekka-piiroinen) wrote : Posted in a previous version of this proposal

This MR needs to be resubmitted against the new trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

27 + // class name may have_QMLTYPE_XX or _QML_XX suffixes

add space after have in the comment

Revision history for this message
Tim Peeters (tpeeters) wrote :

    // class name may have_QMLTYPE_XX or _QML_XX suffixes
    className = className.left(className.indexOf("_qml"));
    styleData.className = className;
    styleData.styleClass = className;

Is this correct? It sets the classname to _qml. Shouldn't you use className.right?

Revision history for this message
Tim Peeters (tpeeters) wrote :

your addition to CHANGES was reverted when merging trunk

Revision history for this message
Tim Peeters (tpeeters) wrote :

result = (rule != 0) && !(rule->path() == path);

why not rule->path() != path?

Revision history for this message
Tim Peeters (tpeeters) wrote :

looking good, I only didn't check the tests yet.

Revision history for this message
Juhapekka Piiroinen (juhapekka-piiroinen) wrote :

tests looks ok to me

review: Approve
Revision history for this message
Tim Peeters (tpeeters) wrote :

okay, great!

review: Approve
Revision history for this message
Tim Peeters (tpeeters) wrote :

oh wait, first the small comments I gave above

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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

Revision history for this message
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.left(className.indexOf("_qml"));
> styleData.className = className;
> styleData.styleClass = className;
>
> 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_QMLTYPE_72" then the classname will be "scrollbar".

Revision history for this message
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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
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.left(className.indexOf("_qml"));
> > styleData.className = className;
> > styleData.styleClass = className;
> >
> > 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_QMLTYPE_72" then the classname will be "scrollbar".

You are right. I was thinking _qml was the prefix, not postfix.

Revision history for this message
Tim Peeters (tpeeters) wrote :

looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 &param, 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

Subscribers

People subscribed via source and target branches

to status/vote changes: