Merge lp:~tpeeters/ubuntu-ui-toolkit/noPrivateHeader into lp:~bzoltan/ubuntu-ui-toolkit/landing_140514
- noPrivateHeader
- Merge into landing_140514
Status: | Superseded |
---|---|
Proposed branch: | lp:~tpeeters/ubuntu-ui-toolkit/noPrivateHeader |
Merge into: | lp:~bzoltan/ubuntu-ui-toolkit/landing_140514 |
Diff against target: |
5307 lines (+2765/-560) 87 files modified
CHANGES (+1/-0) components.api (+55/-2) debian/changelog (+113/-2) debian/control (+7/-7) examples/ubuntu-ui-toolkit-gallery/ListItems.qml (+11/-2) modules/Ubuntu/Components/AnimatedItem.qml (+1/-38) modules/Ubuntu/Components/Label.qml (+1/-0) modules/Ubuntu/Components/ListItems/Base.qml (+1/-1) modules/Ubuntu/Components/ListItems/Empty.qml (+1/-1) modules/Ubuntu/Components/ListItems/ThinDivider.qml (+5/-2) modules/Ubuntu/Components/Page.qml (+7/-0) modules/Ubuntu/Components/Pickers/DatePicker.qml (+7/-7) modules/Ubuntu/Components/Pickers/PickerRow.qml (+1/-1) modules/Ubuntu/Components/TextInputPopover.qml (+7/-7) modules/Ubuntu/Components/Themes/Ambiance/ActivityIndicatorStyle.qml (+2/-2) modules/Ubuntu/Components/Themes/Ambiance/TabBarStyle.qml (+2/-2) modules/Ubuntu/Components/Toolbar.qml (+3/-3) modules/Ubuntu/Components/ToolbarItems.qml (+1/-1) modules/Ubuntu/Components/plugin/filterbehavior.cpp (+47/-0) modules/Ubuntu/Components/plugin/filterbehavior.h (+46/-0) modules/Ubuntu/Components/plugin/i18n.cpp (+7/-11) modules/Ubuntu/Components/plugin/plugin.cpp (+10/-1) modules/Ubuntu/Components/plugin/plugin.pro (+6/-0) modules/Ubuntu/Components/plugin/shapeitem.cpp (+47/-13) modules/Ubuntu/Components/plugin/shapeitem.h (+8/-0) modules/Ubuntu/Components/plugin/shapeitemtexture.h (+2/-3) modules/Ubuntu/Components/plugin/sortbehavior.cpp (+47/-0) modules/Ubuntu/Components/plugin/sortbehavior.h (+46/-0) modules/Ubuntu/Components/plugin/sortfiltermodel.cpp (+252/-0) modules/Ubuntu/Components/plugin/sortfiltermodel.h (+68/-0) modules/Ubuntu/Components/plugin/thumbnailgenerator.cpp (+6/-3) modules/Ubuntu/Components/plugin/ucalarm.cpp (+15/-4) modules/Ubuntu/Components/plugin/ucthemesettings.cpp (+4/-3) modules/Ubuntu/Layouts/plugin/plugin.pro (+1/-1) modules/Ubuntu/Layouts/plugin/propertychanges.cpp (+18/-33) modules/Ubuntu/Layouts/plugin/propertychanges_p.h (+3/-16) modules/Ubuntu/Layouts/plugin/ulitemlayout.h (+4/-1) modules/Ubuntu/Layouts/plugin/ullayouts.cpp (+92/-81) modules/Ubuntu/Layouts/plugin/ullayouts.h (+8/-3) modules/Ubuntu/Layouts/plugin/ullayouts_p.h (+3/-5) po/ca.po (+2/-2) po/de.po (+2/-2) po/es.po (+2/-2) po/fi.po (+2/-2) po/fr.po (+2/-2) po/gl.po (+2/-2) po/he.po (+2/-2) po/hu.po (+2/-2) po/ko.po (+2/-2) po/my.po (+2/-2) po/nl.po (+2/-2) po/oc.po (+2/-2) po/pt_BR.po (+2/-2) po/sv.po (+2/-2) po/uk.po (+2/-2) tests/autopilot/ubuntuuitoolkit/__init__.py (+4/-2) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py (+4/-2) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_common.py (+45/-1) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_flickable.py (+53/-30) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py (+32/-1) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_mainview.py (+1/-1) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_qquicklistview.py (+28/-11) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_textfield.py (+10/-5) tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/pickers.py (+255/-0) tests/autopilot/ubuntuuitoolkit/emulators.py (+2/-2) tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_date_picker.py (+203/-0) tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_flickable.py (+201/-0) tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_header.py (+50/-24) tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_textfield.py (+27/-0) tests/autopilot/ubuntuuitoolkit/tests/gallery/test_gallery.py (+4/-0) tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py (+47/-80) tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py (+1/-1) tests/qmlapicheck.py (+6/-5) tests/resources/alarm/Alarms.qml (+1/-1) tests/resources/toolbar/header.qml (+143/-0) tests/unit/tst_alarms/tst_alarms.cpp (+46/-0) tests/unit/tst_components/tst_label.qml (+1/-1) tests/unit/tst_components/tst_sortfiltermodel.qml (+123/-0) tests/unit/tst_components/tst_toolbaritems.qml (+10/-1) tests/unit/tst_i18n/localizedApp/.click/status (+1/-0) tests/unit/tst_i18n/src/tst_i18n.cpp (+5/-17) tests/unit/tst_i18n/tst_i18n.pro (+1/-1) tests/unit_x11/tst_components/tst_datepicker.qml (+1/-1) tests/unit_x11/tst_layouts/NestedVisibility.qml (+163/-0) tests/unit_x11/tst_layouts/Visibility.qml (+84/-0) tests/unit_x11/tst_layouts/tst_layouts.cpp (+214/-86) tests/unit_x11/tst_layouts/tst_layouts.pro (+3/-1) |
To merge this branch: | bzr merge lp:~tpeeters/ubuntu-ui-toolkit/noPrivateHeader |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Zoltan Balogh | Pending | ||
Review via email:
|
Commit message
Undo changes of r1082 that cause a regression in messaging-app (and contenthub).
Description of the change
Undo changes of r1082 that cause a regression in messaging-app (and contenthub).
Unmerged revisions
- 1088. By Tim Peeters
-
revert r1082 because it breaks contenthub (and thus messaging-app)
- 1087. By Zoltan Balogh
-
Landing 28/05
- 1086. By Cris Dywan
-
Tweak API parsing to include the Button.font property. Fixes: https:/
/bugs.launchpad .net/bugs/ 1322169. Approved by PS Jenkins bot.
- 1085. By Zsombor Egri
-
Missing "default" keyword added to children property of Base, causing rendering and test case failures on Qt 5.3. Fixes: https:/
/bugs.launchpad .net/bugs/ 1317881. Approved by PS Jenkins bot, Tim Peeters.
- 1084. By Ugo Riboni
-
Allow requesting extra large thumbnails.
Approved by PS Jenkins bot, Zsombor Egri.
- 1083. By Florian Boucault
-
AnimatedItem: deprecated as it was not used and still costly.
Approved by PS Jenkins bot, Zsombor Egri.
- 1082. By Tim Peeters
-
Make Header component internal as it was always documented.
Approved by Zsombor Egri, PS Jenkins bot.
- 1081. By Cris Dywan
-
Call bindtextdomain on /usr if APP_DIR is not defined. Fixes: https:/
/bugs.launchpad .net/bugs/ 1322630. Approved by PS Jenkins bot, Tim Peeters, David Planella.
- 1080. By Zoltan Balogh
-
Replace split with match to work around failing split() function usage.
Approved by Zsombor Egri, PS Jenkins bot.
- 1079. By Cris Dywan
-
More unit tests and property corrections for SortFilterModel.
Approved by Tim Peeters, PS Jenkins bot.
Preview Diff
1 | === modified file 'CHANGES' |
2 | --- CHANGES 2014-04-24 20:35:41 +0000 |
3 | +++ CHANGES 2014-05-28 18:09:57 +0000 |
4 | @@ -19,6 +19,7 @@ |
5 | |
6 | API Changes |
7 | *********** |
8 | +* CHANGED IN: ThinDivider: base class Image TO Rectangle |
9 | * ADDED IN: all modules exported as 0.1 as well as 1.0 version |
10 | * ADDED IN: PickerDelegate: readonly property Picker picker |
11 | * CHANGED IN: OptionSelector: readonly property bool currentlyExpanded TO property bool currentlyExpanded |
12 | |
13 | === modified file 'components.api' |
14 | --- components.api 2014-05-13 09:13:32 +0000 |
15 | +++ components.api 2014-05-28 18:09:57 +0000 |
16 | @@ -31,6 +31,7 @@ |
17 | AbstractButton |
18 | property color color |
19 | property Gradient gradient |
20 | + property font font |
21 | property string iconPosition |
22 | CheckBox 0.1 1.0 |
23 | AbstractButton |
24 | @@ -94,7 +95,7 @@ |
25 | property real __leftIconMargin |
26 | property real __rightIconMargin |
27 | property bool __iconIsItem |
28 | - property internal children |
29 | + default property internal children |
30 | Caption 0.1 1.0 |
31 | Item |
32 | property string text |
33 | @@ -140,6 +141,7 @@ |
34 | property bool expanded |
35 | property bool multiSelection |
36 | property bool colourImage |
37 | + property Component delegate |
38 | property real containerHeight |
39 | property int selectedIndex |
40 | property bool currentlyExpanded |
41 | @@ -175,7 +177,7 @@ |
42 | Base |
43 | property string subText |
44 | ThinDivider 0.1 1.0 |
45 | -Image |
46 | +Rectangle |
47 | ValueSelector 0.1 1.0 |
48 | Empty |
49 | property variant icon |
50 | @@ -204,12 +206,14 @@ |
51 | Object 0.1 1.0 |
52 | QtObject |
53 | default property internal children |
54 | + property list<QtObject> __defaultPropertyFix |
55 | OptionSelector 0.1 1.0 |
56 | ListItem.Empty |
57 | property var model |
58 | property bool expanded |
59 | property bool multiSelection |
60 | property bool colourImage |
61 | + property Component delegate |
62 | property real containerHeight |
63 | property int selectedIndex |
64 | property bool currentlyExpanded |
65 | @@ -235,6 +239,7 @@ |
66 | Page 0.1 1.0 |
67 | PageTreeNode |
68 | property string title |
69 | + property Item tools |
70 | property Item __customHeaderContents |
71 | property Flickable flickable |
72 | property list<Action> actions |
73 | @@ -355,6 +360,7 @@ |
74 | OrientationHelper |
75 | property Item dismissArea |
76 | property bool grabDismissAreaEvents |
77 | + property PropertyAnimation fadingAnimation |
78 | function show() |
79 | function hide() |
80 | function __closeIfHidden() |
81 | @@ -613,6 +619,11 @@ |
82 | function mouseLongPress(item, x, y, button, modifiers, delay) |
83 | function tryCompareFunction(func, expectedResult, timeout) |
84 | plugins.qmltypes |
85 | + name: "FilterBehavior" |
86 | + prototype: "QObject" |
87 | + exports: ["FilterBehavior 1.1"] |
88 | + Property { name: "property"; type: "string" } |
89 | + Property { name: "pattern"; type: "QRegExp" } |
90 | name: "InverseMouseAreaType" |
91 | prototype: "QQuickMouseArea" |
92 | exports: ["InverseMouseArea 0.1", "InverseMouseArea 1.0"] |
93 | @@ -621,6 +632,41 @@ |
94 | Method { |
95 | name: "contains" |
96 | Parameter { name: "point"; type: "QPointF" } |
97 | + name: "QAbstractProxyModel" |
98 | + prototype: "QAbstractItemModel" |
99 | + Property { name: "sourceModel"; type: "QAbstractItemModel"; isPointer: true } |
100 | + name: "QSortFilterProxyModel" |
101 | + prototype: "QAbstractProxyModel" |
102 | + Property { name: "filterRegExp"; type: "QRegExp" } |
103 | + Property { name: "filterKeyColumn"; type: "int" } |
104 | + Property { name: "dynamicSortFilter"; type: "bool" } |
105 | + Property { name: "filterCaseSensitivity"; type: "Qt::CaseSensitivity" } |
106 | + Property { name: "sortCaseSensitivity"; type: "Qt::CaseSensitivity" } |
107 | + Property { name: "isSortLocaleAware"; type: "bool" } |
108 | + Property { name: "sortRole"; type: "int" } |
109 | + Property { name: "filterRole"; type: "int" } |
110 | + Method { |
111 | + name: "setFilterRegExp" |
112 | + Parameter { name: "pattern"; type: "string" } |
113 | + Method { |
114 | + name: "setFilterWildcard" |
115 | + Parameter { name: "pattern"; type: "string" } |
116 | + Method { |
117 | + name: "setFilterFixedString" |
118 | + Parameter { name: "pattern"; type: "string" } |
119 | + Method { name: "clear" } |
120 | + Method { name: "invalidate" } |
121 | + name: "QSortFilterProxyModelQML" |
122 | + prototype: "QSortFilterProxyModel" |
123 | + exports: ["SortFilterModel 1.1"] |
124 | + Property { name: "model"; type: "QAbstractItemModel"; isPointer: true } |
125 | + Property { name: "count"; type: "int"; isReadonly: true } |
126 | + Property { name: "sort"; type: "SortBehavior"; isReadonly: true; isPointer: true } |
127 | + Property { name: "filter"; type: "FilterBehavior"; isReadonly: true; isPointer: true } |
128 | + Method { |
129 | + name: "get" |
130 | + Parameter { name: "row"; type: "int" } |
131 | + Method { name: "count"; type: "int" } |
132 | name: "ShapeItem" |
133 | prototype: "QQuickItem" |
134 | exports: ["Shape 0.1", "Shape 1.0"] |
135 | @@ -636,6 +682,11 @@ |
136 | Property { name: "borderSource"; type: "string" } |
137 | Signal { name: "borderChanged" } |
138 | Method { name: "gridUnitChanged" } |
139 | + name: "SortBehavior" |
140 | + prototype: "QObject" |
141 | + exports: ["SortBehavior 1.1"] |
142 | + Property { name: "property"; type: "string" } |
143 | + Property { name: "order"; type: "Qt::SortOrder" } |
144 | name: "UCAlarm" |
145 | prototype: "QObject" |
146 | exports: ["Alarm 0.1", "Alarm 1.0"] |
147 | @@ -819,6 +870,8 @@ |
148 | exports: ["Layouts 0.1", "Layouts 1.0"] |
149 | Property { name: "currentLayout"; type: "string"; isReadonly: true } |
150 | Property { name: "layouts"; type: "ULConditionalLayout"; isList: true; isReadonly: true } |
151 | + Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } |
152 | + Property { name: "children"; type: "QQuickItem"; isList: true; isReadonly: true } |
153 | name: "ULLayoutsAttached" |
154 | prototype: "QObject" |
155 | Property { name: "item"; type: "string" } |
156 | |
157 | === modified file 'debian/changelog' |
158 | --- debian/changelog 2014-05-16 11:56:17 +0000 |
159 | +++ debian/changelog 2014-05-28 18:09:57 +0000 |
160 | @@ -1,4 +1,115 @@ |
161 | -ubuntu-ui-toolkit (0.1.46+14.10.20140512-0ubuntu2) UNRELEASED; urgency=medium |
162 | +ubuntu-ui-toolkit (0.1.46+14.10.20140527-0ubuntu2) UNRELEASED; urgency=medium |
163 | + |
164 | + [ Christian Dywan ] |
165 | + * Tweak API parsing to include the Button.font property. |
166 | + Fixes: https://bugs.launchpad.net/bugs/1322169 |
167 | + * Call bindtextdomain on /usr if APP_DIR is not defined. |
168 | + Fixes: https://bugs.launchpad.net/bugs/1322630 |
169 | + * More unit tests and property corrections for SortFilterModel. |
170 | + * Read ubuntu-ui-toolkit.ini from $XDG_CONFIG_HOME. |
171 | + * Skip test_ubuntushape which is flakey and add a FIXME. |
172 | + |
173 | + [ Zsombor Egri ] |
174 | + * Missing "default" keyword added to children property of Base, |
175 | + causing rendering and test case failures on Qt 5.3. |
176 | + Fixes: https://bugs.launchpad.net/bugs/1317881 |
177 | + |
178 | + [ Ugo Riboni ] |
179 | + * Allow requesting extra large thumbnails. |
180 | + |
181 | + [ Florian Boucault ] |
182 | + * AnimatedItem: deprecated as it was not used and still costly. |
183 | + * Label: default font weight is now light. |
184 | + |
185 | + [ Tim Peeters ] |
186 | + * Make Header component internal as it was always documented. |
187 | + |
188 | + |
189 | + [ Zoltán Balogh ] |
190 | + * Replace split with match to work around failing split() |
191 | + function usage. |
192 | + |
193 | + -- Zoltán Balogh <zoltan@bakter.hu> Wed, 28 May 2014 11:54:22 +0200 |
194 | + |
195 | +ubuntu-ui-toolkit (0.1.46+14.10.20140527-0ubuntu1) utopic; urgency=medium |
196 | + |
197 | + [ Timo Jyrinki ] |
198 | + * Allow using the renamed QML packages. Allow also old names |
199 | + for eg. trusty backporting. For additional cross-building |
200 | + friendliness, add :any to python build dependencies. |
201 | + |
202 | + [ Leo Arias ] |
203 | + * Rewrite OptionSelector tests using new helpers. |
204 | + * Added autopilot helpers to pick a time from a date picker. |
205 | + * In autopilot select all text only if not already selected. |
206 | + Fixes: https://bugs.launchpad.net/bugs/1321222. |
207 | + |
208 | + [ Christian Dywan ] |
209 | + * Skip flaky test_updateAlarm_Repeating. |
210 | + * Skip test_ubuntushape which is flakey and add a FIXME. |
211 | + * Read ubuntu-ui-toolkit.ini from $XDG_CONFIG_HOME. |
212 | + * More unit tests and property corrections for SortFilterModel. |
213 | + |
214 | + [ Tim Peeters ] |
215 | + * Fix bug where header actions are painted in the middle |
216 | + of the page. Fixes: https://bugs.launchpad.net/bugs/1319861 |
217 | + * Add header demo program to the resources. |
218 | + * Show header if it was not visible before clicking header |
219 | + button in autopilot test. |
220 | + |
221 | + [ Florian Boucault ] |
222 | + * ActivityIndicator: do not rely on the main thread to animate |
223 | + by using an Animator. |
224 | + * ThinDivider: use a Rectangle instead of an Image. |
225 | + 5x faster creation. |
226 | + * Label: default font weight is now light. |
227 | + |
228 | + [ Zsombor Egri ] |
229 | + * Ubuntu Layouts reparents those default layout components which |
230 | + are not subject of layout instead of altering their visible and |
231 | + enabled properties. |
232 | + Fixes: https://bugs.launchpad.net/bugs/1204834 |
233 | + https://bugs.launchpad.net/bugs/1298886 |
234 | + https://bugs.launchpad.net/bugs/1300668. |
235 | + |
236 | + [ Alberto Mardegan ] |
237 | + * Keep a map of windows and associated textures. |
238 | + Fixes: https://bugs.launchpad.net/bugs/1296728. |
239 | + |
240 | + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 27 May 2014 07:51:29 +0000 |
241 | + |
242 | +ubuntu-ui-toolkit (0.1.46+14.10.20140520-0ubuntu1) utopic; urgency=medium |
243 | + |
244 | + [ Leo Arias ] |
245 | + * Added the swipe_into_view method to autopilot helpers. |
246 | + Fixed the name of the QQuickFlickable autopilot helper. |
247 | + Fixes: https://bugs.launchpad.net/bugs/1286479 |
248 | + https://bugs.launchpad.net/bugs/1314433. |
249 | + * On the autopilot helpers, find the top container starting from |
250 | + the flickable. Fixes: https://bugs.launchpad.net/bugs/1314390. |
251 | + |
252 | + [ Christian Dywan ] |
253 | + * Use i18n.dtr for toolkit-owned translations. |
254 | + Fixes: https://bugs.launchpad.net/bugs/1317539 |
255 | + * Introduce QML bindings for SortFilterModel. |
256 | + Fixes: https://bugs.launchpad.net/bugs/1266529 |
257 | + * Pick data path if .click is present. |
258 | + Fixes: https://bugs.launchpad.net/bugs/1317772 |
259 | + |
260 | + [ Tim Peeters ] |
261 | + * Quick fix for TabBarStyle.qml:119: TypeError: Cannot |
262 | + read property of null. |
263 | + |
264 | + [ Zsombor Egri ] |
265 | + * One time alarms omit dayOfWeek value changes. |
266 | + Fixes: https://bugs.launchpad.net/bugs/1319401 |
267 | + |
268 | + [ CI bot ] |
269 | + * Resync trunk |
270 | + |
271 | + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 20 May 2014 08:35:48 +0000 |
272 | + |
273 | +ubuntu-ui-toolkit (0.1.46+14.10.20140516-0ubuntu1) utopic; urgency=medium |
274 | |
275 | [ Tim Peeters ] |
276 | * Take visibility of actions into account when determining whether |
277 | @@ -31,7 +142,7 @@ |
278 | on mobile architectures (less rattling, more realistic). |
279 | Fixes: https://bugs.launchpad.net/bugs/1290201. |
280 | |
281 | - -- Zoltán Balogh <zoltan@bakter.hu> Wed, 14 May 2014 15:46:58 +0300 |
282 | + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 16 May 2014 11:58:25 +0000 |
283 | |
284 | ubuntu-ui-toolkit (0.1.46+14.10.20140512-0ubuntu1) utopic; urgency=low |
285 | |
286 | |
287 | === modified file 'debian/control' |
288 | --- debian/control 2014-05-12 09:33:55 +0000 |
289 | +++ debian/control 2014-05-28 18:09:57 +0000 |
290 | @@ -6,9 +6,9 @@ |
291 | devscripts, |
292 | libgles2-mesa-dev, |
293 | libglib2.0-dev, |
294 | - python3, |
295 | - python, |
296 | - libqt5qml-graphicaleffects | libqt5graphicaleffects5, |
297 | + python3:any, |
298 | + python:any, |
299 | + qml-module-qtgraphicaleffects | libqt5qml-graphicaleffects, |
300 | qt5-default, |
301 | qtbase5-dev, |
302 | qtbase5-private-dev, |
303 | @@ -17,12 +17,12 @@ |
304 | libqt5sql5-sqlite, |
305 | qtdeclarative5-dev-tools, |
306 | qtdeclarative5-private-dev, |
307 | - qtdeclarative5-qtquick2-plugin, |
308 | - qtdeclarative5-test-plugin, |
309 | - qtdeclarative5-window-plugin, |
310 | + qml-module-qtquick2 | qtdeclarative5-qtquick2-plugin, |
311 | + qml-module-qttest | qtdeclarative5-test-plugin, |
312 | + qml-module-qtquick-window2 | qtdeclarative5-window-plugin, |
313 | qtdeclarative5-qtfeedback-plugin, |
314 | qtdeclarative5-unity-action-plugin (>= 1.1.0), |
315 | - qtdeclarative5-localstorage-plugin, |
316 | + qml-module-qtquick-localstorage | qtdeclarative5-localstorage-plugin, |
317 | qtdeclarative5-doc-html, |
318 | qtwebkit5-doc-html, |
319 | qtsvg5-doc-html, |
320 | |
321 | === modified file 'examples/ubuntu-ui-toolkit-gallery/ListItems.qml' |
322 | --- examples/ubuntu-ui-toolkit-gallery/ListItems.qml 2014-04-28 10:30:06 +0000 |
323 | +++ examples/ubuntu-ui-toolkit-gallery/ListItems.qml 2014-05-28 18:09:57 +0000 |
324 | @@ -15,7 +15,7 @@ |
325 | */ |
326 | |
327 | import QtQuick 2.0 |
328 | -import Ubuntu.Components 0.1 as Toolkit |
329 | +import Ubuntu.Components 1.1 as Toolkit |
330 | import Ubuntu.Components.ListItems 0.1 as ListItem |
331 | |
332 | Template { |
333 | @@ -259,11 +259,20 @@ |
334 | ListElement { name: "Potato"; details: "Vegetable" } |
335 | } |
336 | |
337 | + Toolkit.SortFilterModel { |
338 | + id: processedFruits |
339 | + model: fruitModel |
340 | + sort.property: "title" |
341 | + sort.order: Qt.DescendingOrder |
342 | + filter.property: "details" |
343 | + filter.pattern: /Vegetable/ |
344 | + } |
345 | + |
346 | Toolkit.UbuntuListView { |
347 | id: ubuntuListView |
348 | anchors { left: parent.left; right: parent.right } |
349 | height: units.gu(24) |
350 | - model: fruitModel |
351 | + model: processedFruits |
352 | clip: true |
353 | |
354 | delegate: ListItem.Expandable { |
355 | |
356 | === modified file 'modules/Ubuntu/Components/AnimatedItem.qml' |
357 | --- modules/Ubuntu/Components/AnimatedItem.qml 2014-04-23 08:50:20 +0000 |
358 | +++ modules/Ubuntu/Components/AnimatedItem.qml 2014-05-28 18:09:57 +0000 |
359 | @@ -30,45 +30,8 @@ |
360 | id: root |
361 | /*! |
362 | \preliminary |
363 | + \deprecated |
364 | Specifies whether the component is on the visible area of the Flickable or not. |
365 | */ |
366 | property bool onScreen: true |
367 | - |
368 | - QtObject { |
369 | - id: internal |
370 | - property Flickable flickable |
371 | - |
372 | - // returns whether the component is in the visible area of the flickable |
373 | - function checkOnScreen() |
374 | - { |
375 | - var pos = root.mapToItem(flickable, 0, 0) |
376 | - root.onScreen = (pos.y + root.height >= 0) && (pos.y <= internal.flickable.height) && |
377 | - (pos.x + root.width >= 0) && (pos.x <= internal.flickable.width) |
378 | - } |
379 | - // lookup for a flickable parent |
380 | - function updateFlickableParent() |
381 | - { |
382 | - var flickable = root.parent |
383 | - while (flickable) { |
384 | - if (flickable.hasOwnProperty("flicking") && flickable.hasOwnProperty("flickableDirection")) { |
385 | - // non-interactive flickables must be skipped as those do not provide |
386 | - // on-screen detection support |
387 | - if (flickable.interactive) |
388 | - break |
389 | - } |
390 | - flickable = flickable.parent |
391 | - } |
392 | - internal.flickable = flickable |
393 | - } |
394 | - } |
395 | - |
396 | - Connections { |
397 | - target: internal.flickable |
398 | - |
399 | - onContentXChanged: internal.checkOnScreen() |
400 | - onContentYChanged: internal.checkOnScreen() |
401 | - } |
402 | - |
403 | - Component.onCompleted: internal.updateFlickableParent() |
404 | - onParentChanged: internal.updateFlickableParent() |
405 | } |
406 | |
407 | === modified file 'modules/Ubuntu/Components/Label.qml' |
408 | --- modules/Ubuntu/Components/Label.qml 2014-04-23 08:50:20 +0000 |
409 | +++ modules/Ubuntu/Components/Label.qml 2014-05-28 18:09:57 +0000 |
410 | @@ -56,6 +56,7 @@ |
411 | |
412 | font.pixelSize: FontUtils.sizeToPixels(fontSize) |
413 | font.family: "Ubuntu" |
414 | + font.weight: Font.Light |
415 | color: Theme.palette.selected.backgroundText |
416 | |
417 | /* FIXME: workaround for QTBUG 35095 where Text's alignment is incorrect |
418 | |
419 | === modified file 'modules/Ubuntu/Components/ListItems/Base.qml' |
420 | --- modules/Ubuntu/Components/ListItems/Base.qml 2014-04-28 19:24:56 +0000 |
421 | +++ modules/Ubuntu/Components/ListItems/Base.qml 2014-05-28 18:09:57 +0000 |
422 | @@ -159,7 +159,7 @@ |
423 | /*! |
424 | \internal |
425 | */ |
426 | - property alias children: middle.data |
427 | + default property alias children: middle.data |
428 | Item { |
429 | id: middle |
430 | property bool anchorToIconHelper: !__iconIsItem && iconHelper.source != "" |
431 | |
432 | === modified file 'modules/Ubuntu/Components/ListItems/Empty.qml' |
433 | --- modules/Ubuntu/Components/ListItems/Empty.qml 2014-04-30 11:04:41 +0000 |
434 | +++ modules/Ubuntu/Components/ListItems/Empty.qml 2014-05-28 18:09:57 +0000 |
435 | @@ -390,7 +390,7 @@ |
436 | width: units.gu(5) |
437 | } |
438 | Label { |
439 | - text: i18n.tr("Delete") |
440 | + text: i18n.dtr('ubuntu-ui-toolkit', 'Delete') |
441 | verticalAlignment: Text.AlignVCenter |
442 | anchors { |
443 | verticalCenter: parent.verticalCenter |
444 | |
445 | === modified file 'modules/Ubuntu/Components/ListItems/ThinDivider.qml' |
446 | --- modules/Ubuntu/Components/ListItems/ThinDivider.qml 2014-04-20 19:25:12 +0000 |
447 | +++ modules/Ubuntu/Components/ListItems/ThinDivider.qml 2014-05-28 18:09:57 +0000 |
448 | @@ -44,11 +44,14 @@ |
449 | } |
450 | \endqml |
451 | */ |
452 | -Image { |
453 | +Rectangle { |
454 | anchors { |
455 | left: (parent) ? parent.left : null |
456 | right: (parent) ? parent.right : null |
457 | } |
458 | height: (visible) ? units.dp(2) : 0 |
459 | - source: "artwork/ListItemDividerHorizontal.png" |
460 | + gradient: Gradient { |
461 | + GradientStop { position: 0.0; color: "#26000000" } |
462 | + GradientStop { position: 1.0; color: "#14F3F3E7" } |
463 | + } |
464 | } |
465 | |
466 | === removed file 'modules/Ubuntu/Components/ListItems/artwork/ListItemDividerHorizontal@18.png' |
467 | Binary files modules/Ubuntu/Components/ListItems/artwork/ListItemDividerHorizontal@18.png 2013-02-06 11:48:20 +0000 and modules/Ubuntu/Components/ListItems/artwork/ListItemDividerHorizontal@18.png 1970-01-01 00:00:00 +0000 differ |
468 | === modified file 'modules/Ubuntu/Components/Page.qml' |
469 | --- modules/Ubuntu/Components/Page.qml 2014-05-16 11:33:37 +0000 |
470 | +++ modules/Ubuntu/Components/Page.qml 2014-05-28 18:09:57 +0000 |
471 | @@ -185,6 +185,13 @@ |
472 | value: page.pageStack |
473 | when: tools && tools.hasOwnProperty("pageStack") |
474 | } |
475 | + Binding { |
476 | + target: tools |
477 | + property: "visible" |
478 | + value: false |
479 | + when: header && !header.useDeprecatedToolbar && |
480 | + page.tools !== null |
481 | + } |
482 | |
483 | function isVerticalFlickable(object) { |
484 | if (object && object.hasOwnProperty("flickableDirection") && object.hasOwnProperty("contentHeight")) { |
485 | |
486 | === modified file 'modules/Ubuntu/Components/Pickers/DatePicker.qml' |
487 | --- modules/Ubuntu/Components/Pickers/DatePicker.qml 2014-04-23 08:50:20 +0000 |
488 | +++ modules/Ubuntu/Components/Pickers/DatePicker.qml 2014-05-28 18:09:57 +0000 |
489 | @@ -42,7 +42,7 @@ |
490 | Column { |
491 | Label { |
492 | text: "Selected date: W" + datePicker.week + " - " + |
493 | - Qt.formatDate(datePicker.date, "dddd, dd-mmmm-yyyy") |
494 | + Qt.formatDate(datePicker.date, "dddd, dd-MMMM-yyyy") |
495 | } |
496 | DatePicker { |
497 | id: datePicker |
498 | @@ -61,7 +61,7 @@ |
499 | |
500 | Column { |
501 | Label { |
502 | - text: "Selected month: " + Qt.formatDate(datePicker.date, "mmmm-yyyy") |
503 | + text: "Selected month: " + Qt.formatDate(datePicker.date, "MMMM-yyyy") |
504 | } |
505 | DatePicker { |
506 | id: datePicker |
507 | @@ -117,7 +117,7 @@ |
508 | |
509 | Column { |
510 | Label { |
511 | - text: "Selected date: " + Qt.formatDate(datePicker.date, "dddd, dd-mmmm-yyyy") |
512 | + text: "Selected date: " + Qt.formatDate(datePicker.date, "dddd, dd-MMMM-yyyy") |
513 | } |
514 | DatePicker { |
515 | id: datePicker |
516 | @@ -523,7 +523,8 @@ |
517 | function updatePickers() { |
518 | if (completed) { |
519 | // check mode flags first |
520 | - var modes = datePicker.mode.split(/\W/g); |
521 | + // FIXME: The js split(/\W/g) terminates the process on armhf with Qt 5.3 (v4 js) (https://bugreports.qt-project.org/browse/QTBUG-39255) |
522 | + var modes = datePicker.mode.match(/\w+/g); |
523 | |
524 | showYearPicker = showMonthPicker = showDayPicker = |
525 | showHoursPicker = showMinutesPicker = showSecondsPicker = false; |
526 | @@ -607,7 +608,8 @@ |
527 | completed = false; |
528 | |
529 | // use short format to exclude any extra characters |
530 | - var format = datePicker.locale.dateFormat(Locale.ShortFormat).split(/\W/g); |
531 | + // FIXME: The js split(/\W/g) terminates the process on armhf with Qt 5.3 (v4 js) (https://bugreports.qt-project.org/browse/QTBUG-39255) |
532 | + var format = datePicker.locale.dateFormat(Locale.ShortFormat).match(/\w+/g); |
533 | // loop through the format to decide the position of the tumbler |
534 | var formatIndex = 0; |
535 | for (var i in format) { |
536 | @@ -667,5 +669,3 @@ |
537 | } |
538 | } |
539 | } |
540 | - |
541 | - |
542 | |
543 | === modified file 'modules/Ubuntu/Components/Pickers/PickerRow.qml' |
544 | --- modules/Ubuntu/Components/Pickers/PickerRow.qml 2014-04-23 08:50:20 +0000 |
545 | +++ modules/Ubuntu/Components/Pickers/PickerRow.qml 2014-05-28 18:09:57 +0000 |
546 | @@ -96,7 +96,7 @@ |
547 | } |
548 | delegate: PickerDelegate { |
549 | Label { |
550 | - objectName: "PickerRow_PickerLabel" |
551 | + objectName: "PickerRow_PickerLabel" + (pickerModel ? modelData : "") |
552 | text: pickerModel ? pickerModel.text(modelData) : "" |
553 | anchors.fill: parent |
554 | verticalAlignment: Text.AlignVCenter |
555 | |
556 | === modified file 'modules/Ubuntu/Components/TextInputPopover.qml' |
557 | --- modules/Ubuntu/Components/TextInputPopover.qml 2014-04-28 06:48:28 +0000 |
558 | +++ modules/Ubuntu/Components/TextInputPopover.qml 2014-05-28 18:09:57 +0000 |
559 | @@ -22,39 +22,39 @@ |
560 | objectName: "text_input_popover" |
561 | actions: ActionList { |
562 | Action { |
563 | - text: i18n.tr("Select All") |
564 | + text: i18n.dtr('ubuntu-ui-toolkit', "Select All") |
565 | enabled: target && target.text !== "" && target.text !== target.selectedText |
566 | onTriggered: target.selectAll() |
567 | } |
568 | Action { |
569 | - text: i18n.tr("Select Word") |
570 | + text: i18n.dtr('ubuntu-ui-toolkit', "Select Word") |
571 | enabled: target && target.text !== "" && target.selectedText === "" |
572 | onTriggered: target.selectWord() |
573 | } |
574 | Action { |
575 | - text: i18n.tr("Cut") |
576 | + text: i18n.dtr('ubuntu-ui-toolkit', "Cut") |
577 | // If paste/editing is not possible, then disable also "Cut" operation |
578 | // It is applicable for ReadOnly's TextFields and TextAreas |
579 | enabled: target && target.selectedText !== "" && target.canPaste |
580 | onTriggered: target.cut() |
581 | } |
582 | Action { |
583 | - text: i18n.tr("Copy") |
584 | + text: i18n.dtr('ubuntu-ui-toolkit', "Copy") |
585 | enabled: target && target.selectedText !== "" |
586 | onTriggered: target.copy() |
587 | } |
588 | Action { |
589 | - text: i18n.tr("Paste") |
590 | + text: i18n.dtr('ubuntu-ui-toolkit', "Paste") |
591 | enabled: target && target.canPaste |
592 | onTriggered: target.paste() |
593 | } |
594 | Action { |
595 | - text: i18n.tr("Undo") |
596 | + text: i18n.dtr('ubuntu-ui-toolkit', "Undo") |
597 | enabled: target && target.canUndo |
598 | onTriggered: target.undo() |
599 | } |
600 | Action { |
601 | - text: i18n.tr("Redo") |
602 | + text: i18n.dtr('ubuntu-ui-toolkit', "Redo") |
603 | enabled: target && target.canRedo |
604 | onTriggered: target.redo() |
605 | } |
606 | |
607 | === modified file 'modules/Ubuntu/Components/Themes/Ambiance/ActivityIndicatorStyle.qml' |
608 | --- modules/Ubuntu/Components/Themes/Ambiance/ActivityIndicatorStyle.qml 2014-04-23 08:50:20 +0000 |
609 | +++ modules/Ubuntu/Components/Themes/Ambiance/ActivityIndicatorStyle.qml 2014-05-28 18:09:57 +0000 |
610 | @@ -14,7 +14,7 @@ |
611 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
612 | */ |
613 | |
614 | -import QtQuick 2.0 |
615 | +import QtQuick 2.2 |
616 | import Ubuntu.Components 1.1 |
617 | |
618 | Image { |
619 | @@ -28,7 +28,7 @@ |
620 | verticalAlignment: Image.AlignVCenter |
621 | source: "artwork/spinner.png" |
622 | |
623 | - NumberAnimation on rotation { |
624 | + RotationAnimator on rotation { |
625 | running: styledItem.running |
626 | from: 0 |
627 | to: 360 |
628 | |
629 | === modified file 'modules/Ubuntu/Components/Themes/Ambiance/TabBarStyle.qml' |
630 | --- modules/Ubuntu/Components/Themes/Ambiance/TabBarStyle.qml 2014-05-09 11:21:23 +0000 |
631 | +++ modules/Ubuntu/Components/Themes/Ambiance/TabBarStyle.qml 2014-05-28 18:09:57 +0000 |
632 | @@ -116,8 +116,8 @@ |
633 | AbstractButton { |
634 | id: button |
635 | anchors { |
636 | - top: parent.top |
637 | - bottom: parent.bottom |
638 | + top: parent ? parent.top : undefined |
639 | + bottom: parent ? parent.bottom : undefined |
640 | } |
641 | width: text.paintedWidth + text.anchors.leftMargin + text.anchors.rightMargin |
642 | |
643 | |
644 | === modified file 'modules/Ubuntu/Components/Toolbar.qml' |
645 | --- modules/Ubuntu/Components/Toolbar.qml 2014-04-23 08:50:20 +0000 |
646 | +++ modules/Ubuntu/Components/Toolbar.qml 2014-05-28 18:09:57 +0000 |
647 | @@ -27,9 +27,9 @@ |
648 | Panel { |
649 | id: toolbar |
650 | anchors { |
651 | - left: parent.left |
652 | - right: parent.right |
653 | - bottom: parent.bottom |
654 | + left: parent ? parent.left : undefined |
655 | + right: parent ? parent.right : undefined |
656 | + bottom: parent ? parent.bottom : undefined |
657 | } |
658 | height: background.height |
659 | |
660 | |
661 | === modified file 'modules/Ubuntu/Components/ToolbarItems.qml' |
662 | --- modules/Ubuntu/Components/ToolbarItems.qml 2014-04-23 08:50:20 +0000 |
663 | +++ modules/Ubuntu/Components/ToolbarItems.qml 2014-05-28 18:09:57 +0000 |
664 | @@ -139,7 +139,7 @@ |
665 | property Item back: ToolbarButton { |
666 | objectName: "back_toolbar_button" |
667 | iconSource: Qt.resolvedUrl("artwork/back.png") |
668 | - text: i18n.tr("Back") |
669 | + text: i18n.dtr('ubuntu-ui-toolkit', 'Back') |
670 | visible: toolbarItems.pageStack && toolbarItems.pageStack.depth > 1 |
671 | /*! |
672 | If there is a \l PageStack of sufficient depth, triggering the back button |
673 | |
674 | === added file 'modules/Ubuntu/Components/plugin/filterbehavior.cpp' |
675 | --- modules/Ubuntu/Components/plugin/filterbehavior.cpp 1970-01-01 00:00:00 +0000 |
676 | +++ modules/Ubuntu/Components/plugin/filterbehavior.cpp 2014-05-28 18:09:57 +0000 |
677 | @@ -0,0 +1,47 @@ |
678 | +/* |
679 | + * Copyright (C) 2014 Canonical, Ltd. |
680 | + * |
681 | + * Authors: |
682 | + * Christian Dywan <christian.dywan@canonical.com> |
683 | + * |
684 | + * This program is free software; you can redistribute it and/or modify |
685 | + * it under the terms of the GNU Lesser General Public License as published by |
686 | + * the Free Software Foundation; version 3. |
687 | + * |
688 | + * This program is distributed in the hope that it will be useful, |
689 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
690 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
691 | + * GNU Lesser General Public License for more details. |
692 | + * |
693 | + * You should have received a copy of the GNU Lesser General Public License |
694 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
695 | + */ |
696 | + |
697 | +#include "filterbehavior.h" |
698 | + |
699 | +QString |
700 | +FilterBehavior::property() const |
701 | +{ |
702 | + return m_property; |
703 | +} |
704 | + |
705 | +void |
706 | +FilterBehavior::setProperty(const QString& property) |
707 | +{ |
708 | + m_property = property; |
709 | + Q_EMIT propertyChanged(); |
710 | +} |
711 | + |
712 | +QRegExp |
713 | +FilterBehavior::pattern() const |
714 | +{ |
715 | + return m_pattern; |
716 | +} |
717 | + |
718 | +void |
719 | +FilterBehavior::setPattern(QRegExp pattern) |
720 | +{ |
721 | + m_pattern = pattern; |
722 | + Q_EMIT patternChanged(); |
723 | +} |
724 | + |
725 | |
726 | === added file 'modules/Ubuntu/Components/plugin/filterbehavior.h' |
727 | --- modules/Ubuntu/Components/plugin/filterbehavior.h 1970-01-01 00:00:00 +0000 |
728 | +++ modules/Ubuntu/Components/plugin/filterbehavior.h 2014-05-28 18:09:57 +0000 |
729 | @@ -0,0 +1,46 @@ |
730 | +/* |
731 | + * Copyright (C) 2014 Canonical, Ltd. |
732 | + * |
733 | + * Authors: |
734 | + * Christian Dywan <christian.dywan@canonical.com> |
735 | + * |
736 | + * This program is free software; you can redistribute it and/or modify |
737 | + * it under the terms of the GNU Lesser General Public License as published by |
738 | + * the Free Software Foundation; version 3. |
739 | + * |
740 | + * This program is distributed in the hope that it will be useful, |
741 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
742 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
743 | + * GNU Lesser General Public License for more details. |
744 | + * |
745 | + * You should have received a copy of the GNU Lesser General Public License |
746 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
747 | + */ |
748 | + |
749 | +#ifndef FILTERBEHAVIOR_H |
750 | +#define FILTERBEHAVIOR_H |
751 | + |
752 | +#include <QSortFilterProxyModel> |
753 | + |
754 | +class FilterBehavior : public QObject { |
755 | + Q_OBJECT |
756 | + |
757 | + Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged) |
758 | + Q_PROPERTY(QRegExp pattern READ pattern WRITE setPattern NOTIFY patternChanged) |
759 | + |
760 | +public: |
761 | + QString property() const; |
762 | + void setProperty(const QString& property); |
763 | + QRegExp pattern() const; |
764 | + void setPattern(QRegExp pattern); |
765 | + |
766 | +Q_SIGNALS: |
767 | + void propertyChanged(); |
768 | + void patternChanged(); |
769 | + |
770 | +private: |
771 | + QString m_property; |
772 | + QRegExp m_pattern; |
773 | +}; |
774 | + |
775 | +#endif // FILTERBEHAVIOR_H |
776 | |
777 | === modified file 'modules/Ubuntu/Components/plugin/i18n.cpp' |
778 | --- modules/Ubuntu/Components/plugin/i18n.cpp 2014-04-23 08:50:20 +0000 |
779 | +++ modules/Ubuntu/Components/plugin/i18n.cpp 2014-05-28 18:09:57 +0000 |
780 | @@ -17,7 +17,6 @@ |
781 | */ |
782 | |
783 | #include "i18n.h" |
784 | -#include <QtCore/QStandardPaths> |
785 | #include <QtCore/QDir> |
786 | |
787 | namespace C { |
788 | @@ -102,19 +101,16 @@ |
789 | m_domain = domain; |
790 | C::textdomain(domain.toUtf8()); |
791 | /* |
792 | - Look for locale folder as per XDG basedir spec |
793 | The default is /usr/share/locale if we don't set a folder |
794 | - We look for share/domain to pick correctly among multiple prefixes |
795 | + For click we use APP_DIR/share/locale |
796 | + e.g. /usr/share/click/preinstalled/com.example.foo/current/share/locale |
797 | */ |
798 | - QString dataPath(QStandardPaths::locate(QStandardPaths::GenericDataLocation, |
799 | - domain, QStandardPaths::LocateDirectory)); |
800 | - if (!dataPath.isEmpty()) { |
801 | - QDir dataDir(dataPath); |
802 | - if (dataDir.cdUp() && dataDir.cd("locale")) { |
803 | - QString localePath(dataDir.path()); |
804 | - C::bindtextdomain(domain.toUtf8(), localePath.toUtf8()); |
805 | - } |
806 | + QString appDir(getenv("APP_DIR")); |
807 | + if (!QDir::isAbsolutePath (appDir)) { |
808 | + appDir = "/usr"; |
809 | } |
810 | + QString localePath(QDir(appDir).filePath("share/locale")); |
811 | + C::bindtextdomain(domain.toUtf8(), localePath.toUtf8()); |
812 | Q_EMIT domainChanged(); |
813 | } |
814 | |
815 | |
816 | === modified file 'modules/Ubuntu/Components/plugin/plugin.cpp' |
817 | --- modules/Ubuntu/Components/plugin/plugin.cpp 2014-04-20 19:25:12 +0000 |
818 | +++ modules/Ubuntu/Components/plugin/plugin.cpp 2014-05-28 18:09:57 +0000 |
819 | @@ -1,5 +1,5 @@ |
820 | /* |
821 | - * Copyright 2012 Canonical Ltd. |
822 | + * Copyright 2012-2014 Canonical Ltd. |
823 | * |
824 | * This program is free software; you can redistribute it and/or modify |
825 | * it under the terms of the GNU Lesser General Public License as published by |
826 | @@ -48,6 +48,7 @@ |
827 | #include "ucurihandler.h" |
828 | #include "ucmouse.h" |
829 | #include "ucinversemouse.h" |
830 | +#include "sortfiltermodel.h" |
831 | |
832 | #include <sys/types.h> |
833 | #include <unistd.h> |
834 | @@ -186,6 +187,14 @@ |
835 | |
836 | // register custom event |
837 | ForwardedEvent::registerForwardedEvent(); |
838 | + |
839 | + // register parent type so that properties can get/ set it |
840 | + qmlRegisterUncreatableType<QAbstractItemModel>(uri, 1, 1, "QAbstractItemModel", "Not instantiable"); |
841 | + |
842 | + // register 1.1 only API |
843 | + qmlRegisterType<QSortFilterProxyModelQML>(uri, 1, 1, "SortFilterModel"); |
844 | + qmlRegisterUncreatableType<FilterBehavior>(uri, 1, 1, "FilterBehavior", "Not instantiable"); |
845 | + qmlRegisterUncreatableType<SortBehavior>(uri, 1, 1, "SortBehavior", "Not instantiable"); |
846 | } |
847 | |
848 | void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
849 | |
850 | === modified file 'modules/Ubuntu/Components/plugin/plugin.pro' |
851 | --- modules/Ubuntu/Components/plugin/plugin.pro 2014-03-25 06:46:36 +0000 |
852 | +++ modules/Ubuntu/Components/plugin/plugin.pro 2014-05-28 18:09:57 +0000 |
853 | @@ -55,6 +55,9 @@ |
854 | alarmrequest_p_p.h \ |
855 | adapters/alarmsadapter_p.h \ |
856 | ucstatesaver.h \ |
857 | + sortbehavior.h \ |
858 | + filterbehavior.h \ |
859 | + sortfiltermodel.h \ |
860 | statesaverbackend_p.h \ |
861 | ucstatesaver_p.h \ |
862 | ucurihandler.h \ |
863 | @@ -87,6 +90,9 @@ |
864 | thumbnailgenerator.cpp \ |
865 | alarmrequest_p.cpp \ |
866 | ucstatesaver.cpp \ |
867 | + sortbehavior.cpp \ |
868 | + filterbehavior.cpp \ |
869 | + sortfiltermodel.cpp \ |
870 | statesaverbackend_p.cpp \ |
871 | ucurihandler.cpp \ |
872 | ucmousefilters.cpp \ |
873 | |
874 | === modified file 'modules/Ubuntu/Components/plugin/shapeitem.cpp' |
875 | --- modules/Ubuntu/Components/plugin/shapeitem.cpp 2014-04-08 18:41:31 +0000 |
876 | +++ modules/Ubuntu/Components/plugin/shapeitem.cpp 2014-05-28 18:09:57 +0000 |
877 | @@ -32,6 +32,9 @@ |
878 | // Threshold in grid unit defining the texture quality to be used. |
879 | const float lowHighTextureThreshold = 11.0f; |
880 | |
881 | +// Map of windows and associated textures. |
882 | +QHash<QOpenGLContext*, ShapeItem::TextureHandles> ShapeItem::textures_; |
883 | + |
884 | static const char* const shapeVertexShader = |
885 | "uniform lowp mat4 matrix; \n" |
886 | "attribute lowp vec4 positionAttrib; \n" |
887 | @@ -338,6 +341,21 @@ |
888 | update(); |
889 | } |
890 | |
891 | +void ShapeItem::onOpenglContextDestroyed() |
892 | +{ |
893 | + QOpenGLContext* context = qobject_cast<QOpenGLContext*>(sender()); |
894 | + if (Q_UNLIKELY(!context)) return; |
895 | + |
896 | + QHash<QOpenGLContext*, TextureHandles>::iterator it = |
897 | + textures_.find(context); |
898 | + if (it != textures_.end()) { |
899 | + TextureHandles &textureHandles = it.value(); |
900 | + delete textureHandles.high; |
901 | + delete textureHandles.low; |
902 | + textures_.erase(it); |
903 | + } |
904 | +} |
905 | + |
906 | QSGNode* ShapeItem::updatePaintNode(QSGNode* old_node, UpdatePaintNodeData* data) |
907 | { |
908 | Q_UNUSED(data); |
909 | @@ -345,19 +363,28 @@ |
910 | // FIXME(loicm) Shape textures are stored in the read-only data section of the plugin as it |
911 | // avoids having to deal with paths for now. It should preferably be loaded from a file. |
912 | |
913 | - /* Textures created with QWindow::createTextureFromImage() become invalid |
914 | - * when the window is destroyed; therefore, we must keep track of which |
915 | - * window was used to create them and be ready to re-create them if that |
916 | - * window goes away. */ |
917 | - static QPointer<QWindow> textureOwner = 0; |
918 | - if (!textureOwner) { |
919 | - shapeTextureHigh.texture = window()->createTextureFromImage( |
920 | + // OpenGL allocates textures per context, so we store textures reused by |
921 | + // all shape instances per context as well |
922 | + QOpenGLContext* openglContext = window() ? window()->openglContext() : NULL; |
923 | + if (Q_UNLIKELY(!openglContext)) { |
924 | + qCritical() << "Window has no GL context!"; |
925 | + delete old_node; |
926 | + return NULL; |
927 | + } |
928 | + |
929 | + TextureHandles &textureHandles = textures_[openglContext]; |
930 | + // If the hash table didn't contain an entry for the current context, the |
931 | + // line above has just caused the creation of a default-constructed value. |
932 | + if (!textureHandles.high) { |
933 | + textureHandles.high = window()->createTextureFromImage( |
934 | QImage(shapeTextureHigh.data, shapeTextureHigh.width, shapeTextureHigh.height, |
935 | QImage::Format_ARGB32_Premultiplied)); |
936 | - shapeTextureLow.texture = window()->createTextureFromImage( |
937 | + textureHandles.low = window()->createTextureFromImage( |
938 | QImage(shapeTextureLow.data, shapeTextureLow.width, shapeTextureLow.height, |
939 | QImage::Format_ARGB32_Premultiplied)); |
940 | - textureOwner = window(); |
941 | + QObject::connect(openglContext, SIGNAL(aboutToBeDestroyed()), |
942 | + this, SLOT(onOpenglContextDestroyed()), |
943 | + Qt::DirectConnection); |
944 | } |
945 | |
946 | // The image item sets its texture in its updatePaintNode() method when QtQuick iterates through |
947 | @@ -387,8 +414,15 @@ |
948 | |
949 | ShapeTexturedMaterial* texturedMaterial = node->texturedMaterial(); |
950 | ShapeColoredMaterial* coloredMaterial = node->coloredMaterial(); |
951 | - TextureData* textureData = (gridUnit_ > lowHighTextureThreshold) ? |
952 | - &shapeTextureHigh : &shapeTextureLow; |
953 | + TextureData* textureData; |
954 | + QSGTexture* textureHandle; |
955 | + if (gridUnit_ > lowHighTextureThreshold) { |
956 | + textureData = &shapeTextureHigh; |
957 | + textureHandle = textureHandles.high; |
958 | + } else { |
959 | + textureData = &shapeTextureLow; |
960 | + textureHandle = textureHandles.low; |
961 | + } |
962 | |
963 | // Set the shape texture to be used by the materials depending on current grid unit. The radius |
964 | // is set considering the current grid unit and the texture raster grid unit. When the item size |
965 | @@ -406,8 +440,8 @@ |
966 | radius = halfMinWidthHeight; |
967 | scaledDown |= 1; |
968 | } |
969 | - coloredMaterial->setShapeTexture(textureData->texture, !!scaledDown); |
970 | - texturedMaterial->setShapeTexture(textureData->texture, !!scaledDown); |
971 | + coloredMaterial->setShapeTexture(textureHandle, !!scaledDown); |
972 | + texturedMaterial->setShapeTexture(textureHandle, !!scaledDown); |
973 | |
974 | // Update the other material properties. |
975 | coloredMaterial->setColor(color_); |
976 | |
977 | === modified file 'modules/Ubuntu/Components/plugin/shapeitem.h' |
978 | --- modules/Ubuntu/Components/plugin/shapeitem.h 2013-10-18 08:56:39 +0000 |
979 | +++ modules/Ubuntu/Components/plugin/shapeitem.h 2014-05-28 18:09:57 +0000 |
980 | @@ -91,6 +91,7 @@ |
981 | |
982 | private Q_SLOTS: |
983 | void onImagePropertiesChanged(); |
984 | + void onOpenglContextDestroyed(); |
985 | |
986 | private: |
987 | enum DirtyFlags { |
988 | @@ -110,6 +111,12 @@ |
989 | | DirtyGridUnit | DirtyGeometry) |
990 | }; |
991 | |
992 | + struct TextureHandles { |
993 | + TextureHandles(): high(0), low(0) {} |
994 | + QSGTexture* high; |
995 | + QSGTexture* low; |
996 | + }; |
997 | + |
998 | QColor color_; |
999 | QColor gradientColor_; |
1000 | bool gradientColorSet_; |
1001 | @@ -124,6 +131,7 @@ |
1002 | float gridUnit_; |
1003 | QRectF geometry_; |
1004 | QFlags<DirtyFlags> dirtyFlags_; |
1005 | + static QHash<QOpenGLContext*, TextureHandles> textures_; |
1006 | |
1007 | Q_DISABLE_COPY(ShapeItem) |
1008 | }; |
1009 | |
1010 | === modified file 'modules/Ubuntu/Components/plugin/shapeitemtexture.h' |
1011 | --- modules/Ubuntu/Components/plugin/shapeitemtexture.h 2013-01-07 07:59:56 +0000 |
1012 | +++ modules/Ubuntu/Components/plugin/shapeitemtexture.h 2014-05-28 18:09:57 +0000 |
1013 | @@ -20,7 +20,6 @@ |
1014 | |
1015 | struct TextureData { |
1016 | const unsigned char* const data; |
1017 | - QSGTexture* texture; |
1018 | int width; |
1019 | int height; |
1020 | int bytesPerPixel; |
1021 | @@ -5160,7 +5159,7 @@ |
1022 | |
1023 | // High resolution shape texture. |
1024 | TextureData shapeTextureHigh __attribute__((aligned(16))) = { |
1025 | - shapeTextureHighData, NULL, 256, 128, 4, 32.0f, 64.0f, 18.0f, |
1026 | + shapeTextureHighData, 256, 128, 4, 32.0f, 64.0f, 18.0f, |
1027 | { |
1028 | { // Medium raw coords. |
1029 | { hh, 0.0f }, { 0.25f-hh, 0.0f }, { 0.25f-hh, 0.0f }, { hh, 0.0f }, |
1030 | @@ -6484,7 +6483,7 @@ |
1031 | |
1032 | // Low resolution shape texture. |
1033 | TextureData shapeTextureLow __attribute__((aligned(16))) = { |
1034 | - shapeTextureLowData, NULL, 128, 64, 4, 16.0f, 32.0f, 9.0f, |
1035 | + shapeTextureLowData, 128, 64, 4, 16.0f, 32.0f, 9.0f, |
1036 | { |
1037 | { // Medium raw coords. |
1038 | { hl, 0.0f }, { 0.25f-hl, 0.0f }, { 0.25f-hl, 0.0f }, { hl, 0.0f }, |
1039 | |
1040 | === added file 'modules/Ubuntu/Components/plugin/sortbehavior.cpp' |
1041 | --- modules/Ubuntu/Components/plugin/sortbehavior.cpp 1970-01-01 00:00:00 +0000 |
1042 | +++ modules/Ubuntu/Components/plugin/sortbehavior.cpp 2014-05-28 18:09:57 +0000 |
1043 | @@ -0,0 +1,47 @@ |
1044 | +/* |
1045 | + * Copyright (C) 2014 Canonical, Ltd. |
1046 | + * |
1047 | + * Authors: |
1048 | + * Christian Dywan <christian.dywan@canonical.com> |
1049 | + * |
1050 | + * This program is free software; you can redistribute it and/or modify |
1051 | + * it under the terms of the GNU Lesser General Public License as published by |
1052 | + * the Free Software Foundation; version 3. |
1053 | + * |
1054 | + * This program is distributed in the hope that it will be useful, |
1055 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1056 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1057 | + * GNU Lesser General Public License for more details. |
1058 | + * |
1059 | + * You should have received a copy of the GNU Lesser General Public License |
1060 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1061 | + */ |
1062 | + |
1063 | +#include "sortbehavior.h" |
1064 | + |
1065 | +QString |
1066 | +SortBehavior::property() const |
1067 | +{ |
1068 | + return m_property; |
1069 | +} |
1070 | + |
1071 | +Qt::SortOrder |
1072 | +SortBehavior::order() const |
1073 | +{ |
1074 | + return m_order; |
1075 | +} |
1076 | + |
1077 | +void |
1078 | +SortBehavior::setProperty(const QString& property) |
1079 | +{ |
1080 | + m_property = property; |
1081 | + Q_EMIT propertyChanged(); |
1082 | +} |
1083 | + |
1084 | +void |
1085 | +SortBehavior::setOrder(Qt::SortOrder order) |
1086 | +{ |
1087 | + m_order = order; |
1088 | + Q_EMIT orderChanged(); |
1089 | +} |
1090 | + |
1091 | |
1092 | === added file 'modules/Ubuntu/Components/plugin/sortbehavior.h' |
1093 | --- modules/Ubuntu/Components/plugin/sortbehavior.h 1970-01-01 00:00:00 +0000 |
1094 | +++ modules/Ubuntu/Components/plugin/sortbehavior.h 2014-05-28 18:09:57 +0000 |
1095 | @@ -0,0 +1,46 @@ |
1096 | +/* |
1097 | + * Copyright (C) 2014 Canonical, Ltd. |
1098 | + * |
1099 | + * Authors: |
1100 | + * Christian Dywan <christian.dywan@canonical.com> |
1101 | + * |
1102 | + * This program is free software; you can redistribute it and/or modify |
1103 | + * it under the terms of the GNU Lesser General Public License as published by |
1104 | + * the Free Software Foundation; version 3. |
1105 | + * |
1106 | + * This program is distributed in the hope that it will be useful, |
1107 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1108 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1109 | + * GNU Lesser General Public License for more details. |
1110 | + * |
1111 | + * You should have received a copy of the GNU Lesser General Public License |
1112 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1113 | + */ |
1114 | + |
1115 | +#ifndef SORTBEHAVIOR_H |
1116 | +#define SORTBEHAVIOR_H |
1117 | + |
1118 | +#include <QSortFilterProxyModel> |
1119 | + |
1120 | +class SortBehavior : public QObject { |
1121 | + Q_OBJECT |
1122 | + |
1123 | + Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY propertyChanged) |
1124 | + Q_PROPERTY(Qt::SortOrder order READ order WRITE setOrder NOTIFY orderChanged) |
1125 | + |
1126 | +public: |
1127 | + QString property() const; |
1128 | + void setProperty(const QString& property); |
1129 | + Qt::SortOrder order() const; |
1130 | + void setOrder(Qt::SortOrder order); |
1131 | + |
1132 | +Q_SIGNALS: |
1133 | + void propertyChanged(); |
1134 | + void orderChanged(); |
1135 | + |
1136 | +private: |
1137 | + QString m_property; |
1138 | + Qt::SortOrder m_order; |
1139 | +}; |
1140 | + |
1141 | +#endif // SORTBEHAVIOR_H |
1142 | |
1143 | === added file 'modules/Ubuntu/Components/plugin/sortfiltermodel.cpp' |
1144 | --- modules/Ubuntu/Components/plugin/sortfiltermodel.cpp 1970-01-01 00:00:00 +0000 |
1145 | +++ modules/Ubuntu/Components/plugin/sortfiltermodel.cpp 2014-05-28 18:09:57 +0000 |
1146 | @@ -0,0 +1,252 @@ |
1147 | +/* |
1148 | + * Copyright (C) 2012-2014 Canonical, Ltd. |
1149 | + * |
1150 | + * Authors: |
1151 | + * Michal Hruby <michal.hruby@canonical.com> |
1152 | + * Christian Dywan <christian.dywan@canonical.com> |
1153 | + * |
1154 | + * This program is free software; you can redistribute it and/or modify |
1155 | + * it under the terms of the GNU Lesser General Public License as published by |
1156 | + * the Free Software Foundation; version 3. |
1157 | + * |
1158 | + * This program is distributed in the hope that it will be useful, |
1159 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1160 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1161 | + * GNU Lesser General Public License for more details. |
1162 | + * |
1163 | + * You should have received a copy of the GNU Lesser General Public License |
1164 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1165 | + */ |
1166 | + |
1167 | +#include "sortfiltermodel.h" |
1168 | + |
1169 | +/*! |
1170 | + * \qmltype SortFilterModel |
1171 | + * \instantiates QSortFilterProxyModelQML |
1172 | + * \inqmlmodule Ubuntu.Components 0.1 |
1173 | + * \ingroup ubuntu |
1174 | + * \brief SortFilterModel sorts and filters rows from an existing model. |
1175 | + * |
1176 | + * The SortFilterModel takes an existing model such as a ListModel or |
1177 | + * any QAbstractItemModel implementation. The original rows and role names |
1178 | + * show up in the SortFilterModel with two basic differences. For one if |
1179 | + * \l sort.property is set all rows will be sorted. Further more if |
1180 | + * \l filter.property is set only rows matching the filter will be in the model. |
1181 | + * |
1182 | + * Example usage: |
1183 | + * \qml |
1184 | + * import QtQuick 2.0 |
1185 | + * import Ubuntu.Components 1.1 |
1186 | + * import Ubuntu.Components.ListItems 1.1 |
1187 | + * |
1188 | + * MainView { |
1189 | + * width: units.gu(80) |
1190 | + * height: units.gu(40) |
1191 | + * |
1192 | + * ListModel { |
1193 | + * id: movies |
1194 | + * ListElement { |
1195 | + * title: "Esign" |
1196 | + * producer: "Chris Larkee" |
1197 | + * } |
1198 | + * ListElement { |
1199 | + * title: "Elephants Dream" |
1200 | + * producer: "Blender" |
1201 | + * } |
1202 | + * ListElement { |
1203 | + * title: "Big Buck Bunny" |
1204 | + * producer: "Blender" |
1205 | + * } |
1206 | + * } |
1207 | + * |
1208 | + * SortFilterModel { |
1209 | + * id: sortedMovies |
1210 | + * model: movies |
1211 | + * sort.property: "title" |
1212 | + * sort.order: Qt.DescendingOrder |
1213 | + * |
1214 | + * filter.property: "producer" |
1215 | + * filter.pattern: /blender/ |
1216 | + * } |
1217 | + * |
1218 | + * ListView { |
1219 | + * model: sortedMovies |
1220 | + * anchors.fill: parent |
1221 | + * |
1222 | + * delegate: Subtitled { |
1223 | + * text: title |
1224 | + * subText: producer |
1225 | + * } |
1226 | + * |
1227 | + * section.delegate: ListItem.Header { text: i18n.tr(section) } |
1228 | + * section.property: "title" |
1229 | + * section.criteria: ViewSection.FirstCharacter |
1230 | + * } |
1231 | + * } |
1232 | + * \endqml |
1233 | + * |
1234 | + * Pay attention to the differences between the original model and the result: |
1235 | + * \list |
1236 | + * \li Big Buck Bunny will be the first row, because it's sorted by title |
1237 | + * \li Esign won't be visible, because it's from the wrong producer |
1238 | + * \endlist |
1239 | + */ |
1240 | + |
1241 | + |
1242 | +QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent) |
1243 | + : QSortFilterProxyModel(parent) |
1244 | +{ |
1245 | + // This is virtually always what you want in QML |
1246 | + setDynamicSortFilter(true); |
1247 | + connect(this, SIGNAL(modelReset()), SIGNAL(countChanged())); |
1248 | + connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SIGNAL(countChanged())); |
1249 | + connect(this, SIGNAL(rowsRemoved(QModelIndex,int,int)), SIGNAL(countChanged())); |
1250 | + connect(&m_sortBehavior, &SortBehavior::propertyChanged, this, &QSortFilterProxyModelQML::sortChangedInternal); |
1251 | + connect(&m_sortBehavior, &SortBehavior::orderChanged, this, &QSortFilterProxyModelQML::sortChangedInternal); |
1252 | + connect(&m_filterBehavior, &FilterBehavior::propertyChanged, this, &QSortFilterProxyModelQML::filterChangedInternal); |
1253 | + connect(&m_filterBehavior, &FilterBehavior::patternChanged, this, &QSortFilterProxyModelQML::filterChangedInternal); |
1254 | +} |
1255 | + |
1256 | +int |
1257 | +QSortFilterProxyModelQML::roleByName(const QString& roleName) const |
1258 | +{ |
1259 | + const QHash<int, QByteArray> roles = roleNames(); |
1260 | + for(int role = 0; role < roles.count(); role++) |
1261 | + if (roles[role] == roleName) |
1262 | + return role; |
1263 | + return 0; |
1264 | +} |
1265 | + |
1266 | +/*! |
1267 | + * \qmlproperty string SortFilterModel::sort.property |
1268 | + * |
1269 | + * If set to a valid role name, all rows will be sorted according to \l sort.order. |
1270 | + */ |
1271 | + |
1272 | +/*! |
1273 | + * \qmlproperty string SortFilterModel::sort.order |
1274 | + * |
1275 | + * The order, if \l sort.property is set. |
1276 | + * Qt::AscendingOrder sorts results from A to Z or 0 to 9. |
1277 | + * Qt::DescendingOrder sorts results from Z to A or 9 to 0. |
1278 | + */ |
1279 | + |
1280 | +SortBehavior* |
1281 | +QSortFilterProxyModelQML::sortBehavior() |
1282 | +{ |
1283 | + return &m_sortBehavior; |
1284 | +} |
1285 | + |
1286 | +/*! |
1287 | + * \qmlproperty string SortFilterModel::filter.pattern |
1288 | + * |
1289 | + * The pattern all rows must match, if \l filter.property is set. |
1290 | + * |
1291 | + * Some examples: |
1292 | + * \list |
1293 | + * \li /possible/ matches anywhere in a word, so both "impossible" and "possible". |
1294 | + * \li /^sign/ matches "sign". But not "assignment" because ^ means start. |
1295 | + * \li /vest$/ matches "safety vest" and "vest" but not "vested". |
1296 | + * \endlist |
1297 | + * |
1298 | + * For more advanced uses it's recommended to read up on Javascript regular expressions. |
1299 | + */ |
1300 | + |
1301 | +/*! |
1302 | + * \qmlproperty string SortFilterModel::filter.property |
1303 | + * |
1304 | + * If set to a valid role name, only rows matching \l filter.pattern will be in the model. |
1305 | + */ |
1306 | + |
1307 | +FilterBehavior* |
1308 | +QSortFilterProxyModelQML::filterBehavior() |
1309 | +{ |
1310 | + return &m_filterBehavior; |
1311 | +} |
1312 | + |
1313 | +void |
1314 | +QSortFilterProxyModelQML::sortChangedInternal() |
1315 | +{ |
1316 | + setSortRole(roleByName(m_sortBehavior.property())); |
1317 | + sort(sortColumn() != -1 ? sortColumn() : 0, m_sortBehavior.order()); |
1318 | + Q_EMIT sortChanged(); |
1319 | +} |
1320 | + |
1321 | +void |
1322 | +QSortFilterProxyModelQML::filterChangedInternal() |
1323 | +{ |
1324 | + setFilterRole(roleByName(m_filterBehavior.property())); |
1325 | + setFilterRegExp(m_filterBehavior.pattern()); |
1326 | + Q_EMIT filterChanged(); |
1327 | +} |
1328 | + |
1329 | +QHash<int, QByteArray> QSortFilterProxyModelQML::roleNames() const |
1330 | +{ |
1331 | + return sourceModel() ? sourceModel()->roleNames() : QHash<int, QByteArray>(); |
1332 | +} |
1333 | + |
1334 | +/*! |
1335 | + * \qmlproperty QAbstractItemModel SortFilterModel::model |
1336 | + * |
1337 | + * The source model to sort and/ or filter. |
1338 | + */ |
1339 | +void |
1340 | +QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel) |
1341 | +{ |
1342 | + if (itemModel == NULL) { |
1343 | + return; |
1344 | + } |
1345 | + |
1346 | + if (itemModel != sourceModel()) { |
1347 | + if (sourceModel() != NULL) { |
1348 | + sourceModel()->disconnect(this); |
1349 | + } |
1350 | + |
1351 | + setSourceModel(itemModel); |
1352 | + // Roles mapping to role names may change |
1353 | + setSortRole(roleByName(m_sortBehavior.property())); |
1354 | + setFilterRole(roleByName(m_filterBehavior.property())); |
1355 | + Q_EMIT modelChanged(); |
1356 | + } |
1357 | +} |
1358 | + |
1359 | +QVariantMap |
1360 | +QSortFilterProxyModelQML::get(int row) |
1361 | +{ |
1362 | + QVariantMap res; |
1363 | + const QHash<int, QByteArray> roles = roleNames(); |
1364 | + for(int role = 0; role < roles.count(); role++) |
1365 | + res.insert (roles[role], data(row, role)); |
1366 | + return res; |
1367 | +} |
1368 | + |
1369 | +QVariant |
1370 | +QSortFilterProxyModelQML::data(int row, int role) |
1371 | +{ |
1372 | + if (sourceModel() == NULL) { |
1373 | + return QVariant(); |
1374 | + } |
1375 | + |
1376 | + return index(row, 0).data(role); |
1377 | +} |
1378 | + |
1379 | +int |
1380 | +QSortFilterProxyModelQML::count() |
1381 | +{ |
1382 | + return rowCount(); |
1383 | +} |
1384 | + |
1385 | +bool |
1386 | +QSortFilterProxyModelQML::filterAcceptsRow(int sourceRow, |
1387 | + const QModelIndex &sourceParent) const |
1388 | +{ |
1389 | + if (filterRegExp().isEmpty()) { |
1390 | + return true; |
1391 | + } |
1392 | + |
1393 | + bool result = QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); |
1394 | + return result; |
1395 | +} |
1396 | + |
1397 | +#include "moc_sortfiltermodel.cpp" |
1398 | + |
1399 | |
1400 | === added file 'modules/Ubuntu/Components/plugin/sortfiltermodel.h' |
1401 | --- modules/Ubuntu/Components/plugin/sortfiltermodel.h 1970-01-01 00:00:00 +0000 |
1402 | +++ modules/Ubuntu/Components/plugin/sortfiltermodel.h 2014-05-28 18:09:57 +0000 |
1403 | @@ -0,0 +1,68 @@ |
1404 | +/* |
1405 | + * Copyright (C) 2012-2014 Canonical, Ltd. |
1406 | + * |
1407 | + * Authors: |
1408 | + * Michal Hruby <michal.hruby@canonical.com> |
1409 | + * Christian Dywan <christian.dywan@canonical.com> |
1410 | + * |
1411 | + * This program is free software; you can redistribute it and/or modify |
1412 | + * it under the terms of the GNU Lesser General Public License as published by |
1413 | + * the Free Software Foundation; version 3. |
1414 | + * |
1415 | + * This program is distributed in the hope that it will be useful, |
1416 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1417 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1418 | + * GNU Lesser General Public License for more details. |
1419 | + * |
1420 | + * You should have received a copy of the GNU Lesser General Public License |
1421 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1422 | + */ |
1423 | + |
1424 | +#ifndef QSORTFILTERPROXYMODELQML_H |
1425 | +#define QSORTFILTERPROXYMODELQML_H |
1426 | + |
1427 | +#include <QSortFilterProxyModel> |
1428 | +#include "sortbehavior.h" |
1429 | +#include "filterbehavior.h" |
1430 | + |
1431 | +class Q_DECL_EXPORT QSortFilterProxyModelQML : public QSortFilterProxyModel |
1432 | +{ |
1433 | + Q_OBJECT |
1434 | + |
1435 | + Q_PROPERTY(QAbstractItemModel* model READ sourceModel WRITE setModel NOTIFY modelChanged) |
1436 | + Q_PROPERTY(int count READ count NOTIFY countChanged) |
1437 | + Q_PROPERTY(SortBehavior* sort READ sortBehavior NOTIFY sortChanged) |
1438 | + Q_PROPERTY(FilterBehavior* filter READ filterBehavior NOTIFY filterChanged) |
1439 | + |
1440 | +public: |
1441 | + explicit QSortFilterProxyModelQML(QObject *parent = 0); |
1442 | + |
1443 | + Q_INVOKABLE QVariantMap get(int row); |
1444 | + QVariant data(int row, int role); |
1445 | + Q_INVOKABLE int count(); |
1446 | + virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; |
1447 | + |
1448 | + /* getters */ |
1449 | + QHash<int, QByteArray> roleNames() const; |
1450 | + |
1451 | + /* setters */ |
1452 | + void setFilterProperty(const QString& property); |
1453 | + void setModel(QAbstractItemModel *model); |
1454 | + |
1455 | +Q_SIGNALS: |
1456 | + void countChanged(); |
1457 | + void modelChanged(); |
1458 | + void sortChanged(); |
1459 | + void filterChanged(); |
1460 | + |
1461 | +private: |
1462 | + SortBehavior m_sortBehavior; |
1463 | + SortBehavior* sortBehavior(); |
1464 | + void sortChangedInternal(); |
1465 | + FilterBehavior m_filterBehavior; |
1466 | + FilterBehavior* filterBehavior(); |
1467 | + void filterChangedInternal(); |
1468 | + int roleByName(const QString& roleName) const; |
1469 | +}; |
1470 | + |
1471 | +#endif // QSORTFILTERPROXYMODELQML_H |
1472 | |
1473 | === modified file 'modules/Ubuntu/Components/plugin/thumbnailgenerator.cpp' |
1474 | --- modules/Ubuntu/Components/plugin/thumbnailgenerator.cpp 2014-02-25 09:14:23 +0000 |
1475 | +++ modules/Ubuntu/Components/plugin/thumbnailgenerator.cpp 2014-05-28 18:09:57 +0000 |
1476 | @@ -43,12 +43,15 @@ |
1477 | * is the only way around the issue for now. */ |
1478 | std::string src_path(QUrl(id).path().toUtf8().data()); |
1479 | std::string tgt_path; |
1480 | + const int xlarge_cutoff = 512; |
1481 | + const int large_cutoff = 256; |
1482 | + const int small_cutoff = 128; |
1483 | try { |
1484 | ThumbnailSize desiredSize; |
1485 | - const int large_cutoff = 256; |
1486 | - const int small_cutoff = 128; |
1487 | - if(requestedSize.width() > large_cutoff || requestedSize.height() > large_cutoff) { |
1488 | + if(requestedSize.width() > xlarge_cutoff || requestedSize.height() > xlarge_cutoff) { |
1489 | desiredSize = TN_SIZE_ORIGINAL; |
1490 | + } else if(requestedSize.width() > large_cutoff || requestedSize.height() > large_cutoff) { |
1491 | + desiredSize = TN_SIZE_XLARGE; |
1492 | } else if(requestedSize.width() > small_cutoff || requestedSize.height() > small_cutoff) { |
1493 | desiredSize = TN_SIZE_LARGE; |
1494 | } else { |
1495 | |
1496 | === modified file 'modules/Ubuntu/Components/plugin/ucalarm.cpp' |
1497 | --- modules/Ubuntu/Components/plugin/ucalarm.cpp 2014-04-23 08:50:20 +0000 |
1498 | +++ modules/Ubuntu/Components/plugin/ucalarm.cpp 2014-05-28 18:09:57 +0000 |
1499 | @@ -177,6 +177,21 @@ |
1500 | return result; |
1501 | } |
1502 | |
1503 | + // fix lp:1319401 - dayOfWeek omitted if set to other than AutoDetect |
1504 | + int dayOfWeek = rawData.date.date().dayOfWeek(); |
1505 | + if (!isDaySet(dayOfWeek, rawData.days)) { |
1506 | + // dayOfWeek has been set by the user, adjust the date to it |
1507 | + int nextOccurrence = nextDayOfWeek(rawData.days, dayOfWeek); |
1508 | + if (nextOccurrence < dayOfWeek) { |
1509 | + // the starting date should be moved to the next week's occurrence |
1510 | + rawData.date = rawData.date.addDays(7 - dayOfWeek + nextOccurrence); |
1511 | + } else { |
1512 | + // the starting date is still this week |
1513 | + rawData.date = rawData.date.addDays(nextOccurrence - dayOfWeek); |
1514 | + } |
1515 | + rawData.changes |= AlarmData::Date; |
1516 | + } |
1517 | + |
1518 | // start date should be later then the current date/time |
1519 | if (rawData.date <= AlarmData::normalizeDate(QDateTime::currentDateTime())) { |
1520 | return UCAlarm::EarlyDate; |
1521 | @@ -370,10 +385,6 @@ |
1522 | d->rawData.date = AlarmData::normalizeDate(date); |
1523 | d->rawData.changes |= AlarmData::Date; |
1524 | Q_EMIT dateChanged(); |
1525 | - if (d->rawData.type == UCAlarm::OneTime) { |
1526 | - // adjust dayOfWeek as well |
1527 | - setDaysOfWeek(UCAlarm::AutoDetect); |
1528 | - } |
1529 | } |
1530 | |
1531 | /*! |
1532 | |
1533 | === modified file 'modules/Ubuntu/Components/plugin/ucthemesettings.cpp' |
1534 | --- modules/Ubuntu/Components/plugin/ucthemesettings.cpp 2013-10-18 08:56:39 +0000 |
1535 | +++ modules/Ubuntu/Components/plugin/ucthemesettings.cpp 2014-05-28 18:09:57 +0000 |
1536 | @@ -21,19 +21,20 @@ |
1537 | |
1538 | #include <QtCore/QDir> |
1539 | #include <QtCore/QFile> |
1540 | +#include <QtCore/QStandardPaths> |
1541 | |
1542 | /* |
1543 | - User theme settings are stored in $HOME/.config/ubuntu-ui-toolkit/theme.ini file, which contains |
1544 | + User theme settings are stored in $XDG_CONFIG_HOME/ubuntu-ui-toolkit/theme.ini file, which contains |
1545 | the current global theme name. |
1546 | */ |
1547 | |
1548 | -const QString SETTINGS_FILE_FORMAT("%1/.config/ubuntu-ui-toolkit/theme.ini"); |
1549 | +const QString SETTINGS_FILE_FORMAT("%1/ubuntu-ui-toolkit/theme.ini"); |
1550 | const QString THEME_KEY("theme"); |
1551 | const QString DEFAULT_THEME("Ubuntu.Components.Themes.Ambiance"); |
1552 | |
1553 | UCThemeSettings::UCThemeSettings(QObject *parent) : |
1554 | QObject(parent), |
1555 | - m_settings(SETTINGS_FILE_FORMAT.arg(QDir::homePath()), QSettings::IniFormat) |
1556 | + m_settings(SETTINGS_FILE_FORMAT.arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)), QSettings::IniFormat) |
1557 | { |
1558 | // check if there is a theme settings file, if not, create one |
1559 | if (!QFile::exists(m_settings.fileName())) { |
1560 | |
1561 | === modified file 'modules/Ubuntu/Layouts/plugin/plugin.pro' |
1562 | --- modules/Ubuntu/Layouts/plugin/plugin.pro 2013-11-22 11:15:48 +0000 |
1563 | +++ modules/Ubuntu/Layouts/plugin/plugin.pro 2014-05-28 18:09:57 +0000 |
1564 | @@ -5,7 +5,7 @@ |
1565 | |
1566 | QMAKE_CXXFLAGS += -Werror |
1567 | |
1568 | -QT += quick-private |
1569 | +QT += quick-private gui-private |
1570 | QT += qml-private core-private |
1571 | |
1572 | equals(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 2) { |
1573 | |
1574 | === modified file 'modules/Ubuntu/Layouts/plugin/propertychanges.cpp' |
1575 | --- modules/Ubuntu/Layouts/plugin/propertychanges.cpp 2013-06-26 09:58:41 +0000 |
1576 | +++ modules/Ubuntu/Layouts/plugin/propertychanges.cpp 2014-05-28 18:09:57 +0000 |
1577 | @@ -145,7 +145,7 @@ |
1578 | } |
1579 | if (fromBinding) { |
1580 | QQmlAbstractBinding *revertedBinding = QQmlPropertyPrivate::setBinding(property, fromBinding); |
1581 | - if (revertedBinding && ((revertedBinding != toBinding.data()) || (revertedBinding == toBinding.data() && deleteToBinding))) { |
1582 | + if (revertedBinding && (revertedBinding != fromBinding) && ((revertedBinding != toBinding.data()) || (revertedBinding == toBinding.data() && deleteToBinding))) { |
1583 | revertedBinding->destroy(); |
1584 | } |
1585 | } else if (!toBinding.isNull() && QQmlPropertyPrivate::binding(property) == toBinding.data()) { |
1586 | @@ -222,24 +222,6 @@ |
1587 | { |
1588 | } |
1589 | |
1590 | -/****************************************************************************** |
1591 | - * ReparentChange |
1592 | - */ |
1593 | -ReparentChange::ReparentChange(QQuickItem *target, const QString &property, QQuickItem *source) |
1594 | - : PropertyChange(target, property, QVariant(), Normal) |
1595 | - , sourceProperty(source, property, qmlContext(source)) |
1596 | -{ |
1597 | - action.type = PropertyAction::Binding; |
1598 | -} |
1599 | - |
1600 | -void ReparentChange::saveState() |
1601 | -{ |
1602 | - action.toValue = sourceProperty.read(); |
1603 | - PropertyChange::saveState(); |
1604 | - if (sourceProperty.isValid()) { |
1605 | - action.setTargetBinding(QQmlPropertyPrivate::binding(sourceProperty), false); |
1606 | - } |
1607 | -} |
1608 | |
1609 | /****************************************************************************** |
1610 | * ParentChange |
1611 | @@ -304,35 +286,31 @@ |
1612 | * ItemStackBackup |
1613 | * High priority change backing up the item's stack position. |
1614 | */ |
1615 | -ItemStackBackup::ItemStackBackup(QQuickItem *item, QQuickItem *currentLayoutItem, QQuickItem *previousLayoutItem) |
1616 | +ItemStackBackup::ItemStackBackup(QQuickItem *item) |
1617 | : PropertyChange(High) |
1618 | , target(item) |
1619 | - , currentLayout(currentLayoutItem) |
1620 | - , previousLayout(previousLayoutItem) |
1621 | - , originalStackBefore(0) |
1622 | + , prevItem(0) |
1623 | { |
1624 | } |
1625 | |
1626 | void ItemStackBackup::saveState() |
1627 | { |
1628 | QQuickItem *rewindParent = target->parentItem(); |
1629 | + if (!rewindParent) { |
1630 | + return; |
1631 | + } |
1632 | // save original stack position, but detect layout objects! |
1633 | QList<QQuickItem*> children = rewindParent->childItems(); |
1634 | - for (int ii = 0; ii < children.count() - 1; ++ii) { |
1635 | - if (children.at(ii) == target) { |
1636 | - originalStackBefore = children.at(ii + 1); |
1637 | - if (originalStackBefore == currentLayout || originalStackBefore == previousLayout) { |
1638 | - originalStackBefore = 0; |
1639 | - } |
1640 | - break; |
1641 | - } |
1642 | + int index = children.indexOf(target); |
1643 | + if (index > 0) { |
1644 | + prevItem = children.at(index - 1); |
1645 | } |
1646 | } |
1647 | |
1648 | void ItemStackBackup::revert() |
1649 | { |
1650 | - if (originalStackBefore) { |
1651 | - target->stackBefore(originalStackBefore); |
1652 | + if (prevItem) { |
1653 | + target->stackAfter(prevItem); |
1654 | } |
1655 | } |
1656 | |
1657 | @@ -459,6 +437,13 @@ |
1658 | return *this; |
1659 | } |
1660 | |
1661 | +// creates two changes, one for reparenting and one for itemstack backup |
1662 | +ChangeList &ChangeList::addParentChange(QQuickItem *item, QQuickItem *newParent, bool topmostItem) |
1663 | +{ |
1664 | + return addChange(new ParentChange(item, newParent, topmostItem)) |
1665 | + .addChange(new ItemStackBackup(item)); |
1666 | +} |
1667 | + |
1668 | QList<PropertyChange*> ChangeList::unifiedChanges() |
1669 | { |
1670 | QList<PropertyChange*> list; |
1671 | |
1672 | === modified file 'modules/Ubuntu/Layouts/plugin/propertychanges_p.h' |
1673 | --- modules/Ubuntu/Layouts/plugin/propertychanges_p.h 2013-06-26 09:58:41 +0000 |
1674 | +++ modules/Ubuntu/Layouts/plugin/propertychanges_p.h 2014-05-28 18:09:57 +0000 |
1675 | @@ -104,18 +104,6 @@ |
1676 | }; |
1677 | |
1678 | |
1679 | -class ReparentChange : public PropertyChange |
1680 | -{ |
1681 | -public: |
1682 | - ReparentChange(QQuickItem *item, const QString &property, QQuickItem *source); |
1683 | - |
1684 | -protected: |
1685 | - virtual void saveState(); |
1686 | - |
1687 | - QQmlProperty sourceProperty; |
1688 | -}; |
1689 | - |
1690 | - |
1691 | class ParentChange : public PropertyChange |
1692 | { |
1693 | public: |
1694 | @@ -143,16 +131,14 @@ |
1695 | class ItemStackBackup : public PropertyChange |
1696 | { |
1697 | public: |
1698 | - ItemStackBackup(QQuickItem *item, QQuickItem *currentLayoutItem, QQuickItem *previousLayoutItem); |
1699 | + ItemStackBackup(QQuickItem *item); |
1700 | void apply() {} |
1701 | void revert(); |
1702 | |
1703 | protected: |
1704 | virtual void saveState(); |
1705 | QQuickItem *target; |
1706 | - QQuickItem *currentLayout; |
1707 | - QQuickItem *previousLayout; |
1708 | - QQuickItem *originalStackBefore; |
1709 | + QQuickItem *prevItem; |
1710 | private: |
1711 | friend class ULLayouts; |
1712 | }; |
1713 | @@ -214,6 +200,7 @@ |
1714 | void clear(); |
1715 | |
1716 | ChangeList &addChange(PropertyChange *change); |
1717 | + ChangeList &addParentChange(QQuickItem *item, QQuickItem *newParent, bool topmostItem); |
1718 | |
1719 | private: |
1720 | QList<PropertyChange*> changes[PropertyChange::MaxPriority]; |
1721 | |
1722 | === modified file 'modules/Ubuntu/Layouts/plugin/ulitemlayout.h' |
1723 | --- modules/Ubuntu/Layouts/plugin/ulitemlayout.h 2013-06-06 16:00:10 +0000 |
1724 | +++ modules/Ubuntu/Layouts/plugin/ulitemlayout.h 2014-05-28 18:09:57 +0000 |
1725 | @@ -26,7 +26,7 @@ |
1726 | Q_OBJECT |
1727 | Q_DISABLE_COPY(ULItemLayout) |
1728 | |
1729 | - Q_PROPERTY(QString item READ item WRITE setItem) |
1730 | + Q_PROPERTY(QString item READ item WRITE setItem NOTIFY itemChanged) |
1731 | |
1732 | public: |
1733 | explicit ULItemLayout(QQuickItem *parent = 0); |
1734 | @@ -35,6 +35,9 @@ |
1735 | QString item() const; |
1736 | void setItem(const QString &value); |
1737 | |
1738 | +Q_SIGNALS: |
1739 | + void itemChanged(); |
1740 | + |
1741 | private: |
1742 | QString m_itemName; |
1743 | }; |
1744 | |
1745 | === modified file 'modules/Ubuntu/Layouts/plugin/ullayouts.cpp' |
1746 | --- modules/Ubuntu/Layouts/plugin/ullayouts.cpp 2014-04-20 19:25:12 +0000 |
1747 | +++ modules/Ubuntu/Layouts/plugin/ullayouts.cpp 2014-05-28 18:09:57 +0000 |
1748 | @@ -22,15 +22,21 @@ |
1749 | #include "ulconditionallayout.h" |
1750 | #include "propertychanges_p.h" |
1751 | #include <QtQml/QQmlInfo> |
1752 | +#include <QtQuick/private/qquickitem_p.h> |
1753 | |
1754 | ULLayoutsPrivate::ULLayoutsPrivate(ULLayouts *qq) |
1755 | : QQmlIncubator(Asynchronous) |
1756 | , q_ptr(qq) |
1757 | , currentLayoutItem(0) |
1758 | , previousLayoutItem(0) |
1759 | + , contentItem(new QQuickItem) |
1760 | , currentLayoutIndex(-1) |
1761 | , ready(false) |
1762 | { |
1763 | + // hidden container for the components that are not laid out |
1764 | + // any component not subject of layout is reparented into this component |
1765 | + contentItem->setParent(qq); |
1766 | + contentItem->setParentItem(qq); |
1767 | } |
1768 | |
1769 | |
1770 | @@ -80,7 +86,6 @@ |
1771 | QQuickItem *item = static_cast<QQuickItem*>(object); |
1772 | // set disabled and invisible, and set its parent as last action |
1773 | item->setVisible(false); |
1774 | - item->setEnabled(false); |
1775 | } |
1776 | |
1777 | /* |
1778 | @@ -98,14 +103,16 @@ |
1779 | currentLayoutItem = qobject_cast<QQuickItem*>(object()); |
1780 | Q_ASSERT(currentLayoutItem); |
1781 | |
1782 | - // hide all non-laid out items first |
1783 | - hideExcludedItems(); |
1784 | - |
1785 | //reparent components to be laid out |
1786 | reparentItems(); |
1787 | // set parent item, then enable and show layout |
1788 | changes.addChange(new ParentChange(currentLayoutItem, q, false)); |
1789 | - itemActivate(currentLayoutItem, true); |
1790 | + |
1791 | + // hide default layout, then show the new one |
1792 | + // there's no need to queue these property changes as we do not need |
1793 | + // to back up their previosus states |
1794 | + contentItem->setVisible(false); |
1795 | + currentLayoutItem->setVisible(true); |
1796 | // apply changes |
1797 | changes.apply(); |
1798 | // clear previous layout |
1799 | @@ -114,18 +121,10 @@ |
1800 | |
1801 | Q_EMIT q->currentLayoutChanged(); |
1802 | } else if (status == Error) { |
1803 | - Q_Q(ULLayouts); |
1804 | error(q, errors()); |
1805 | } |
1806 | } |
1807 | |
1808 | -void ULLayoutsPrivate::hideExcludedItems() |
1809 | -{ |
1810 | - for (int i = 0; i < excludedFromLayout.count(); i++) { |
1811 | - itemActivate(excludedFromLayout[i], false); |
1812 | - } |
1813 | -} |
1814 | - |
1815 | /* |
1816 | * Re-parent items to the new layout. |
1817 | */ |
1818 | @@ -134,26 +133,32 @@ |
1819 | // create copy of items list, to keep track of which ones we change |
1820 | LaidOutItemsMap unusedItems = itemsToLayout; |
1821 | |
1822 | - // iterate through the Layout definition to find containers - those Items with |
1823 | - // ConditionalLayout.items set |
1824 | - QList<QQuickItem*> items = currentLayoutItem->findChildren<QQuickItem*>(); |
1825 | - // add the root item as that also can be the container |
1826 | - items.prepend(currentLayoutItem); |
1827 | - |
1828 | - Q_FOREACH(QQuickItem *container, items) { |
1829 | - // check whether we have ItemLayout declared |
1830 | - ULItemLayout *itemLayout = qobject_cast<ULItemLayout*>(container); |
1831 | - if (itemLayout) { |
1832 | - reparentToItemLayout(unusedItems, itemLayout); |
1833 | + // iterate through the Layout definition to find containers - ItemLayout items |
1834 | + QList<ULItemLayout*> containers = collectContainers(currentLayoutItem); |
1835 | + |
1836 | + Q_FOREACH(ULItemLayout *container, containers) { |
1837 | + reparentToItemLayout(unusedItems, container); |
1838 | + } |
1839 | +} |
1840 | + |
1841 | +QList<ULItemLayout*> ULLayoutsPrivate::collectContainers(QQuickItem *fromItem) |
1842 | +{ |
1843 | + QList<ULItemLayout*> result; |
1844 | + // check first if the fromItem is also a container |
1845 | + ULItemLayout *container = qobject_cast<ULItemLayout*>(fromItem); |
1846 | + if (container) { |
1847 | + result.append(container); |
1848 | + } |
1849 | + |
1850 | + // loop through children but exclude nested Layouts |
1851 | + QList<QQuickItem*> children = fromItem->childItems(); |
1852 | + Q_FOREACH(QQuickItem *child, children) { |
1853 | + if (qobject_cast<ULLayouts*>(child)) { |
1854 | + continue; |
1855 | } |
1856 | - } |
1857 | - |
1858 | - // hide the rest of the unused ones |
1859 | - LaidOutItemsMapIterator i(unusedItems); |
1860 | - while (i.hasNext()) { |
1861 | - i.next(); |
1862 | - itemActivate(i.value(), false); |
1863 | - } |
1864 | + result.append(collectContainers(child)); |
1865 | + } |
1866 | + return result; |
1867 | } |
1868 | |
1869 | /* |
1870 | @@ -176,8 +181,7 @@ |
1871 | } |
1872 | |
1873 | // the component fills the parent |
1874 | - changes.addChange(new ParentChange(item, fragment, true)); |
1875 | - changes.addChange(new ItemStackBackup(item, currentLayoutItem, previousLayoutItem)); |
1876 | + changes.addParentChange(item, fragment, true); |
1877 | changes.addChange(new AnchorChange(item, "fill", fragment)); |
1878 | changes.addChange(new PropertyChange(item, "anchors.margins", 0)); |
1879 | changes.addChange(new PropertyChange(item, "anchors.leftMargin", 0)); |
1880 | @@ -194,18 +198,6 @@ |
1881 | map.remove(itemName); |
1882 | } |
1883 | |
1884 | -void ULLayoutsPrivate::itemActivate(QQuickItem *item, bool activate) |
1885 | -{ |
1886 | - changes.addChange(new PropertyChange(item, "visible", activate)) |
1887 | - .addChange(new PropertyChange(item, "enabled", activate)); |
1888 | -} |
1889 | - |
1890 | -// remove the deleted item from the excluded ones |
1891 | -void ULLayoutsPrivate::_q_removeExcludedItem(QObject *excludedItem) |
1892 | -{ |
1893 | - excludedFromLayout.removeAll(static_cast<QQuickItem*>(excludedItem)); |
1894 | -} |
1895 | - |
1896 | /* |
1897 | * Validates the declared conditional layouts by checking whether they have name |
1898 | * property set and whether the value set is unique, and whether the conditional |
1899 | @@ -244,44 +236,20 @@ |
1900 | /* |
1901 | * Collect items to be laid out. |
1902 | */ |
1903 | -void ULLayoutsPrivate::getLaidOutItems() |
1904 | +void ULLayoutsPrivate::getLaidOutItems(QQuickItem *container) |
1905 | { |
1906 | - Q_Q(ULLayouts); |
1907 | - |
1908 | - QList<QQuickItem*> items = q->findChildren<QQuickItem*>(); |
1909 | - for (int i = 0; i < items.count(); i++) { |
1910 | - QQuickItem *item = items[i]; |
1911 | + Q_FOREACH(QQuickItem *child, container->childItems()) { |
1912 | + // skip nested layouts |
1913 | + if (qobject_cast<ULLayouts*>(child)) { |
1914 | + continue; |
1915 | + } |
1916 | ULLayoutsAttached *marker = qobject_cast<ULLayoutsAttached*>( |
1917 | - qmlAttachedPropertiesObject<ULLayouts>(item, false)); |
1918 | + qmlAttachedPropertiesObject<ULLayouts>(child, false)); |
1919 | if (marker && !marker->item().isEmpty()) { |
1920 | - itemsToLayout.insert(marker->item(), item); |
1921 | + itemsToLayout.insert(marker->item(), child); |
1922 | } else { |
1923 | - // the item is not marked to be laid out but one of its parents |
1924 | - // can be, therefore check |
1925 | - // check if the item's parent is included in the layout |
1926 | - QQuickItem *pl = item->parentItem(); |
1927 | - marker = 0; |
1928 | - if (!pl && item->parent()) { |
1929 | - // this may be an item instance assigned to a property |
1930 | - // like "property var anItem: Item {}" |
1931 | - // in which case we must get the parent object of it, not the parent item |
1932 | - pl = qobject_cast<QQuickItem*>(item->parent()); |
1933 | - } |
1934 | - while (pl) { |
1935 | - marker = qobject_cast<ULLayoutsAttached*>( |
1936 | - qmlAttachedPropertiesObject<ULLayouts>(pl, false)); |
1937 | - if (marker && !marker->item().isEmpty()) { |
1938 | - break; |
1939 | - } |
1940 | - pl = pl->parentItem(); |
1941 | - } |
1942 | - if (!marker || (marker && marker->item().isEmpty())) { |
1943 | - // remember theese so we hide them once we switch away from default layout |
1944 | - excludedFromLayout << item; |
1945 | - // and make sure we remove the item from excluded ones in case the item is destroyed |
1946 | - QObject::connect(item, SIGNAL(destroyed(QObject*)), |
1947 | - q, SLOT(_q_removeExcludedItem(QObject*))); |
1948 | - } |
1949 | + // continue to search in between the child's children |
1950 | + getLaidOutItems(child); |
1951 | } |
1952 | } |
1953 | } |
1954 | @@ -344,6 +312,9 @@ |
1955 | // revert and clear changes |
1956 | changes.revert(); |
1957 | changes.clear(); |
1958 | + // make contentItem visible |
1959 | + |
1960 | + contentItem->setVisible(true); |
1961 | delete currentLayoutItem; |
1962 | currentLayoutItem = 0; |
1963 | currentLayoutIndex = -1; |
1964 | @@ -606,10 +577,18 @@ |
1965 | Q_D(ULLayouts); |
1966 | d->ready = true; |
1967 | d->validateConditionalLayouts(); |
1968 | - d->getLaidOutItems(); |
1969 | + d->getLaidOutItems(d->contentItem); |
1970 | d->updateLayout(); |
1971 | } |
1972 | |
1973 | +void ULLayouts::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) |
1974 | +{ |
1975 | + Q_D(ULLayouts); |
1976 | + QQuickItem::geometryChanged(newGeometry, oldGeometry); |
1977 | + // simply update the container's width/height to the new width/height |
1978 | + d->contentItem->setSize(newGeometry.size()); |
1979 | +} |
1980 | + |
1981 | /*! |
1982 | * \qmlproperty string Layouts::currentLayout |
1983 | * The property holds the active layout name. The default layout is identified |
1984 | @@ -634,6 +613,17 @@ |
1985 | } |
1986 | |
1987 | /*! |
1988 | + * \internal |
1989 | + * Returns the contentItem for internal use. |
1990 | + */ |
1991 | +QQuickItem *ULLayouts::contentItem() const |
1992 | +{ |
1993 | + Q_D(const ULLayouts); |
1994 | + return d->contentItem; |
1995 | +} |
1996 | + |
1997 | + |
1998 | +/*! |
1999 | * \qmlproperty list<ConditionalLayout> Layouts::layouts |
2000 | * The property holds the list of different ConditionalLayout elements. |
2001 | */ |
2002 | @@ -647,4 +637,25 @@ |
2003 | &ULLayoutsPrivate::clear_layouts); |
2004 | } |
2005 | |
2006 | +/*! |
2007 | + * \internal |
2008 | + * Overrides the default data property. |
2009 | + */ |
2010 | +QQmlListProperty<QObject> ULLayouts::data() |
2011 | +{ |
2012 | + Q_D(ULLayouts); |
2013 | + return QQuickItemPrivate::get(d->contentItem)->data(); |
2014 | +} |
2015 | + |
2016 | +/*! |
2017 | + * \internal |
2018 | + * Overrides the default children property. |
2019 | + */ |
2020 | +QQmlListProperty<QQuickItem> ULLayouts::children() |
2021 | +{ |
2022 | + Q_D(ULLayouts); |
2023 | + return QQuickItemPrivate::get(d->contentItem)->children(); |
2024 | +} |
2025 | + |
2026 | + |
2027 | #include "moc_ullayouts.cpp" |
2028 | |
2029 | === modified file 'modules/Ubuntu/Layouts/plugin/ullayouts.h' |
2030 | --- modules/Ubuntu/Layouts/plugin/ullayouts.h 2014-02-18 13:27:23 +0000 |
2031 | +++ modules/Ubuntu/Layouts/plugin/ullayouts.h 2014-05-28 18:09:57 +0000 |
2032 | @@ -55,7 +55,10 @@ |
2033 | |
2034 | Q_PROPERTY(QString currentLayout READ currentLayout NOTIFY currentLayoutChanged DESIGNABLE false) |
2035 | Q_PROPERTY(QQmlListProperty<ULConditionalLayout> layouts READ layouts DESIGNABLE false) |
2036 | - |
2037 | + |
2038 | + Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false) |
2039 | + Q_PROPERTY(QQmlListProperty<QQuickItem> children READ children DESIGNABLE false) |
2040 | + Q_CLASSINFO("DefaultProperty", "data") |
2041 | public: |
2042 | explicit ULLayouts(QQuickItem *parent = 0); |
2043 | ~ULLayouts(); |
2044 | @@ -64,21 +67,23 @@ |
2045 | |
2046 | QString currentLayout() const; |
2047 | QList<ULConditionalLayout*> layoutList(); |
2048 | + QQuickItem *contentItem() const; |
2049 | |
2050 | Q_SIGNALS: |
2051 | void currentLayoutChanged(); |
2052 | |
2053 | protected: |
2054 | void componentComplete(); |
2055 | + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); |
2056 | |
2057 | private: |
2058 | QQmlListProperty<ULConditionalLayout> layouts(); |
2059 | + QQmlListProperty<QObject> data(); |
2060 | + QQmlListProperty<QQuickItem> children(); |
2061 | |
2062 | friend class ULConditionalLayout; |
2063 | Q_DECLARE_PRIVATE(ULLayouts) |
2064 | QScopedPointer<ULLayoutsPrivate> d_ptr; |
2065 | - |
2066 | - Q_PRIVATE_SLOT(d_func(), void _q_removeExcludedItem(QObject*)) |
2067 | }; |
2068 | |
2069 | QML_DECLARE_TYPE(ULLayouts) |
2070 | |
2071 | === modified file 'modules/Ubuntu/Layouts/plugin/ullayouts_p.h' |
2072 | --- modules/Ubuntu/Layouts/plugin/ullayouts_p.h 2014-02-18 13:27:23 +0000 |
2073 | +++ modules/Ubuntu/Layouts/plugin/ullayouts_p.h 2014-05-28 18:09:57 +0000 |
2074 | @@ -33,9 +33,8 @@ |
2075 | |
2076 | ULLayoutsPrivate(ULLayouts *qq); |
2077 | |
2078 | - void _q_removeExcludedItem(QObject *excludedItem); |
2079 | void validateConditionalLayouts(); |
2080 | - void getLaidOutItems(); |
2081 | + void getLaidOutItems(QQuickItem *item); |
2082 | void updateLayout(); |
2083 | |
2084 | static void error(QObject *item, const QString &message); |
2085 | @@ -51,9 +50,9 @@ |
2086 | QList<ULConditionalLayout*> layouts; |
2087 | ChangeList changes; |
2088 | LaidOutItemsMap itemsToLayout; |
2089 | - QList<QQuickItem*> excludedFromLayout; |
2090 | QQuickItem* currentLayoutItem; |
2091 | QQuickItem* previousLayoutItem; |
2092 | + QQuickItem* contentItem; |
2093 | int currentLayoutIndex; |
2094 | bool ready:1; |
2095 | |
2096 | @@ -64,10 +63,9 @@ |
2097 | static void clear_layouts(QQmlListProperty<ULConditionalLayout>*); |
2098 | |
2099 | void reLayout(); |
2100 | - void hideExcludedItems(); |
2101 | void reparentItems(); |
2102 | + QList<ULItemLayout*> collectContainers(QQuickItem *fromItem); |
2103 | void reparentToItemLayout(LaidOutItemsMap &map, ULItemLayout *fragment); |
2104 | - void itemActivate(QQuickItem *item, bool activate); |
2105 | }; |
2106 | |
2107 | #endif // ULLAYOUTS_P_H |
2108 | |
2109 | === modified file 'po/ca.po' |
2110 | --- po/ca.po 2014-05-10 07:55:56 +0000 |
2111 | +++ po/ca.po 2014-05-28 18:09:57 +0000 |
2112 | @@ -14,8 +14,8 @@ |
2113 | "MIME-Version: 1.0\n" |
2114 | "Content-Type: text/plain; charset=UTF-8\n" |
2115 | "Content-Transfer-Encoding: 8bit\n" |
2116 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2117 | -"X-Generator: Launchpad (build 16996)\n" |
2118 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2119 | +"X-Generator: Launchpad (build 17017)\n" |
2120 | |
2121 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2122 | msgid "NumberAnimation" |
2123 | |
2124 | === modified file 'po/de.po' |
2125 | --- po/de.po 2014-05-10 07:55:56 +0000 |
2126 | +++ po/de.po 2014-05-28 18:09:57 +0000 |
2127 | @@ -14,8 +14,8 @@ |
2128 | "MIME-Version: 1.0\n" |
2129 | "Content-Type: text/plain; charset=UTF-8\n" |
2130 | "Content-Transfer-Encoding: 8bit\n" |
2131 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2132 | -"X-Generator: Launchpad (build 16996)\n" |
2133 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2134 | +"X-Generator: Launchpad (build 17017)\n" |
2135 | |
2136 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2137 | msgid "NumberAnimation" |
2138 | |
2139 | === modified file 'po/es.po' |
2140 | --- po/es.po 2014-05-10 07:55:56 +0000 |
2141 | +++ po/es.po 2014-05-28 18:09:57 +0000 |
2142 | @@ -14,8 +14,8 @@ |
2143 | "MIME-Version: 1.0\n" |
2144 | "Content-Type: text/plain; charset=UTF-8\n" |
2145 | "Content-Transfer-Encoding: 8bit\n" |
2146 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2147 | -"X-Generator: Launchpad (build 16996)\n" |
2148 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2149 | +"X-Generator: Launchpad (build 17017)\n" |
2150 | |
2151 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2152 | msgid "NumberAnimation" |
2153 | |
2154 | === modified file 'po/fi.po' |
2155 | --- po/fi.po 2014-05-10 07:55:56 +0000 |
2156 | +++ po/fi.po 2014-05-28 18:09:57 +0000 |
2157 | @@ -14,8 +14,8 @@ |
2158 | "MIME-Version: 1.0\n" |
2159 | "Content-Type: text/plain; charset=UTF-8\n" |
2160 | "Content-Transfer-Encoding: 8bit\n" |
2161 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2162 | -"X-Generator: Launchpad (build 16996)\n" |
2163 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2164 | +"X-Generator: Launchpad (build 17017)\n" |
2165 | |
2166 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2167 | msgid "NumberAnimation" |
2168 | |
2169 | === modified file 'po/fr.po' |
2170 | --- po/fr.po 2014-05-10 07:55:56 +0000 |
2171 | +++ po/fr.po 2014-05-28 18:09:57 +0000 |
2172 | @@ -14,8 +14,8 @@ |
2173 | "MIME-Version: 1.0\n" |
2174 | "Content-Type: text/plain; charset=UTF-8\n" |
2175 | "Content-Transfer-Encoding: 8bit\n" |
2176 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2177 | -"X-Generator: Launchpad (build 16996)\n" |
2178 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2179 | +"X-Generator: Launchpad (build 17017)\n" |
2180 | |
2181 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2182 | msgid "NumberAnimation" |
2183 | |
2184 | === modified file 'po/gl.po' |
2185 | --- po/gl.po 2014-05-10 07:55:56 +0000 |
2186 | +++ po/gl.po 2014-05-28 18:09:57 +0000 |
2187 | @@ -14,8 +14,8 @@ |
2188 | "MIME-Version: 1.0\n" |
2189 | "Content-Type: text/plain; charset=UTF-8\n" |
2190 | "Content-Transfer-Encoding: 8bit\n" |
2191 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2192 | -"X-Generator: Launchpad (build 16996)\n" |
2193 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2194 | +"X-Generator: Launchpad (build 17017)\n" |
2195 | |
2196 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2197 | msgid "NumberAnimation" |
2198 | |
2199 | === modified file 'po/he.po' |
2200 | --- po/he.po 2014-05-10 07:55:56 +0000 |
2201 | +++ po/he.po 2014-05-28 18:09:57 +0000 |
2202 | @@ -14,8 +14,8 @@ |
2203 | "MIME-Version: 1.0\n" |
2204 | "Content-Type: text/plain; charset=UTF-8\n" |
2205 | "Content-Transfer-Encoding: 8bit\n" |
2206 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2207 | -"X-Generator: Launchpad (build 16996)\n" |
2208 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2209 | +"X-Generator: Launchpad (build 17017)\n" |
2210 | |
2211 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2212 | msgid "NumberAnimation" |
2213 | |
2214 | === modified file 'po/hu.po' |
2215 | --- po/hu.po 2014-05-10 07:55:56 +0000 |
2216 | +++ po/hu.po 2014-05-28 18:09:57 +0000 |
2217 | @@ -14,8 +14,8 @@ |
2218 | "MIME-Version: 1.0\n" |
2219 | "Content-Type: text/plain; charset=UTF-8\n" |
2220 | "Content-Transfer-Encoding: 8bit\n" |
2221 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2222 | -"X-Generator: Launchpad (build 16996)\n" |
2223 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2224 | +"X-Generator: Launchpad (build 17017)\n" |
2225 | |
2226 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2227 | msgid "NumberAnimation" |
2228 | |
2229 | === modified file 'po/ko.po' |
2230 | --- po/ko.po 2014-05-10 07:55:56 +0000 |
2231 | +++ po/ko.po 2014-05-28 18:09:57 +0000 |
2232 | @@ -14,8 +14,8 @@ |
2233 | "MIME-Version: 1.0\n" |
2234 | "Content-Type: text/plain; charset=UTF-8\n" |
2235 | "Content-Transfer-Encoding: 8bit\n" |
2236 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2237 | -"X-Generator: Launchpad (build 16996)\n" |
2238 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2239 | +"X-Generator: Launchpad (build 17017)\n" |
2240 | |
2241 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2242 | msgid "NumberAnimation" |
2243 | |
2244 | === modified file 'po/my.po' |
2245 | --- po/my.po 2014-05-10 07:55:56 +0000 |
2246 | +++ po/my.po 2014-05-28 18:09:57 +0000 |
2247 | @@ -14,8 +14,8 @@ |
2248 | "MIME-Version: 1.0\n" |
2249 | "Content-Type: text/plain; charset=UTF-8\n" |
2250 | "Content-Transfer-Encoding: 8bit\n" |
2251 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2252 | -"X-Generator: Launchpad (build 16996)\n" |
2253 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2254 | +"X-Generator: Launchpad (build 17017)\n" |
2255 | |
2256 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2257 | msgid "NumberAnimation" |
2258 | |
2259 | === modified file 'po/nl.po' |
2260 | --- po/nl.po 2014-05-10 07:55:56 +0000 |
2261 | +++ po/nl.po 2014-05-28 18:09:57 +0000 |
2262 | @@ -14,8 +14,8 @@ |
2263 | "MIME-Version: 1.0\n" |
2264 | "Content-Type: text/plain; charset=UTF-8\n" |
2265 | "Content-Transfer-Encoding: 8bit\n" |
2266 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2267 | -"X-Generator: Launchpad (build 16996)\n" |
2268 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2269 | +"X-Generator: Launchpad (build 17017)\n" |
2270 | |
2271 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2272 | msgid "NumberAnimation" |
2273 | |
2274 | === modified file 'po/oc.po' |
2275 | --- po/oc.po 2014-05-10 07:55:56 +0000 |
2276 | +++ po/oc.po 2014-05-28 18:09:57 +0000 |
2277 | @@ -14,8 +14,8 @@ |
2278 | "MIME-Version: 1.0\n" |
2279 | "Content-Type: text/plain; charset=UTF-8\n" |
2280 | "Content-Transfer-Encoding: 8bit\n" |
2281 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2282 | -"X-Generator: Launchpad (build 16996)\n" |
2283 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2284 | +"X-Generator: Launchpad (build 17017)\n" |
2285 | |
2286 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2287 | msgid "NumberAnimation" |
2288 | |
2289 | === modified file 'po/pt_BR.po' |
2290 | --- po/pt_BR.po 2014-05-10 07:55:56 +0000 |
2291 | +++ po/pt_BR.po 2014-05-28 18:09:57 +0000 |
2292 | @@ -14,8 +14,8 @@ |
2293 | "MIME-Version: 1.0\n" |
2294 | "Content-Type: text/plain; charset=UTF-8\n" |
2295 | "Content-Transfer-Encoding: 8bit\n" |
2296 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2297 | -"X-Generator: Launchpad (build 16996)\n" |
2298 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2299 | +"X-Generator: Launchpad (build 17017)\n" |
2300 | |
2301 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2302 | msgid "NumberAnimation" |
2303 | |
2304 | === modified file 'po/sv.po' |
2305 | --- po/sv.po 2014-05-10 07:55:56 +0000 |
2306 | +++ po/sv.po 2014-05-28 18:09:57 +0000 |
2307 | @@ -14,8 +14,8 @@ |
2308 | "MIME-Version: 1.0\n" |
2309 | "Content-Type: text/plain; charset=UTF-8\n" |
2310 | "Content-Transfer-Encoding: 8bit\n" |
2311 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2312 | -"X-Generator: Launchpad (build 16996)\n" |
2313 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2314 | +"X-Generator: Launchpad (build 17017)\n" |
2315 | |
2316 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2317 | msgid "NumberAnimation" |
2318 | |
2319 | === modified file 'po/uk.po' |
2320 | --- po/uk.po 2014-05-10 07:55:56 +0000 |
2321 | +++ po/uk.po 2014-05-28 18:09:57 +0000 |
2322 | @@ -14,8 +14,8 @@ |
2323 | "MIME-Version: 1.0\n" |
2324 | "Content-Type: text/plain; charset=UTF-8\n" |
2325 | "Content-Transfer-Encoding: 8bit\n" |
2326 | -"X-Launchpad-Export-Date: 2014-05-10 07:55+0000\n" |
2327 | -"X-Generator: Launchpad (build 16996)\n" |
2328 | +"X-Launchpad-Export-Date: 2014-05-22 06:44+0000\n" |
2329 | +"X-Generator: Launchpad (build 17017)\n" |
2330 | |
2331 | #: examples/ubuntu-ui-toolkit-gallery/Animations.qml:22 |
2332 | msgid "NumberAnimation" |
2333 | |
2334 | === modified file 'tests/autopilot/ubuntuuitoolkit/__init__.py' |
2335 | --- tests/autopilot/ubuntuuitoolkit/__init__.py 2014-04-25 18:39:51 +0000 |
2336 | +++ tests/autopilot/ubuntuuitoolkit/__init__.py 2014-05-28 18:09:57 +0000 |
2337 | @@ -24,14 +24,15 @@ |
2338 | 'environment', |
2339 | 'emulators', |
2340 | 'fixture_setup', |
2341 | - 'Flickable', |
2342 | 'get_keyboard', |
2343 | 'get_pointing_device', |
2344 | 'Header', |
2345 | 'listitems', |
2346 | 'MainView', |
2347 | 'OptionSelector', |
2348 | + 'pickers', |
2349 | 'popups', |
2350 | + 'QQuickFlickable', |
2351 | 'QQuickListView', |
2352 | 'TabBar', |
2353 | 'Tabs', |
2354 | @@ -53,14 +54,15 @@ |
2355 | from ubuntuuitoolkit._custom_proxy_objects import ( |
2356 | check_autopilot_version, |
2357 | CheckBox, |
2358 | - Flickable, |
2359 | get_keyboard, |
2360 | get_pointing_device, |
2361 | Header, |
2362 | listitems, |
2363 | MainView, |
2364 | OptionSelector, |
2365 | + pickers, |
2366 | popups, |
2367 | + QQuickFlickable, |
2368 | QQuickListView, |
2369 | TabBar, |
2370 | Tabs, |
2371 | |
2372 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py' |
2373 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py 2014-04-28 15:39:24 +0000 |
2374 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py 2014-05-28 18:09:57 +0000 |
2375 | @@ -20,14 +20,15 @@ |
2376 | __all__ = [ |
2377 | 'check_autopilot_version', |
2378 | 'CheckBox', |
2379 | - 'Flickable', |
2380 | 'get_keyboard', |
2381 | 'get_pointing_device', |
2382 | 'Header', |
2383 | 'listitems', |
2384 | 'MainView', |
2385 | 'OptionSelector', |
2386 | + 'pickers', |
2387 | 'popups', |
2388 | + 'QQuickFlickable', |
2389 | 'QQuickListView', |
2390 | 'TabBar', |
2391 | 'Tabs', |
2392 | @@ -45,13 +46,14 @@ |
2393 | ToolkitException, |
2394 | UbuntuUIToolkitCustomProxyObjectBase, |
2395 | ) |
2396 | -from ubuntuuitoolkit._custom_proxy_objects._flickable import Flickable |
2397 | +from ubuntuuitoolkit._custom_proxy_objects._flickable import QQuickFlickable |
2398 | from ubuntuuitoolkit._custom_proxy_objects._header import Header |
2399 | from ubuntuuitoolkit._custom_proxy_objects import listitems |
2400 | from ubuntuuitoolkit._custom_proxy_objects._mainview import MainView |
2401 | from ubuntuuitoolkit._custom_proxy_objects._optionselector import ( |
2402 | OptionSelector |
2403 | ) |
2404 | +from ubuntuuitoolkit._custom_proxy_objects import pickers |
2405 | from ubuntuuitoolkit._custom_proxy_objects import popups |
2406 | from ubuntuuitoolkit._custom_proxy_objects._qquicklistview import ( |
2407 | QQuickListView |
2408 | |
2409 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_common.py' |
2410 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_common.py 2014-04-16 21:13:39 +0000 |
2411 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_common.py 2014-05-28 18:09:57 +0000 |
2412 | @@ -16,13 +16,21 @@ |
2413 | |
2414 | """Common helpers for Ubuntu UI Toolkit Autopilot custom proxy objects.""" |
2415 | |
2416 | +import logging |
2417 | from distutils import version |
2418 | |
2419 | import autopilot |
2420 | -from autopilot import platform, input |
2421 | +from autopilot import ( |
2422 | + input, |
2423 | + logging as autopilot_logging, |
2424 | + platform |
2425 | +) |
2426 | from autopilot.introspection import dbus |
2427 | |
2428 | |
2429 | +logger = logging.getLogger(__name__) |
2430 | + |
2431 | + |
2432 | class ToolkitException(Exception): |
2433 | """Exception raised when there is an error with the emulator.""" |
2434 | |
2435 | @@ -67,3 +75,39 @@ |
2436 | check_autopilot_version() |
2437 | super(UbuntuUIToolkitCustomProxyObjectBase, self).__init__(*args) |
2438 | self.pointing_device = get_pointing_device() |
2439 | + |
2440 | + def is_flickable(self): |
2441 | + """Check if the object is flickable. |
2442 | + |
2443 | + If the object has a flicking attribute, we consider it as a flickable. |
2444 | + |
2445 | + :return: True if the object is flickable. False otherwise. |
2446 | + |
2447 | + """ |
2448 | + try: |
2449 | + self.flicking |
2450 | + return True |
2451 | + except AttributeError: |
2452 | + return False |
2453 | + |
2454 | + @autopilot_logging.log_action(logger.info) |
2455 | + def swipe_into_view(self): |
2456 | + """Make the object visible. |
2457 | + |
2458 | + Currently it works only when the object needs to be swiped vertically. |
2459 | + TODO implement horizontal swiping. --elopio - 2014-03-21 |
2460 | + |
2461 | + """ |
2462 | + flickable_parent = self._get_flickable_parent() |
2463 | + flickable_parent.swipe_child_into_view(self) |
2464 | + |
2465 | + def _get_flickable_parent(self): |
2466 | + parent = self.get_parent() |
2467 | + root = self.get_root_instance() |
2468 | + while parent.id != root.id: |
2469 | + if parent.is_flickable(): |
2470 | + return parent |
2471 | + parent = parent.get_parent() |
2472 | + raise ToolkitException( |
2473 | + "The element is not contained in a Flickable so it can't be " |
2474 | + "swiped into view.") |
2475 | |
2476 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_flickable.py' |
2477 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_flickable.py 2014-04-16 21:13:39 +0000 |
2478 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_flickable.py 2014-05-28 18:09:57 +0000 |
2479 | @@ -38,21 +38,7 @@ |
2480 | return min(containers_bottom) |
2481 | |
2482 | |
2483 | -class Flickable(_common.UbuntuUIToolkitCustomProxyObjectBase): |
2484 | - |
2485 | - @autopilot_logging.log_action(logger.info) |
2486 | - def swipe_child_into_view(self, child): |
2487 | - """Make the child visible. |
2488 | - |
2489 | - Currently it works only when the object needs to be swiped vertically. |
2490 | - TODO implement horizontal swiping. --elopio - 2014-03-21 |
2491 | - |
2492 | - """ |
2493 | - containers = self._get_containers() |
2494 | - if not self._is_child_visible(child, containers): |
2495 | - self._swipe_non_visible_child_into_view(child, containers) |
2496 | - else: |
2497 | - logger.debug('The element is already visible.') |
2498 | +class Scrollable(_common.UbuntuUIToolkitCustomProxyObjectBase): |
2499 | |
2500 | def _get_containers(self): |
2501 | """Return a list with the containers to take into account when swiping. |
2502 | @@ -68,15 +54,19 @@ |
2503 | def _get_top_container(self): |
2504 | """Return the top-most container with a globalRect.""" |
2505 | root = self.get_root_instance() |
2506 | - containers = [root] |
2507 | - while len(containers) == 1: |
2508 | - try: |
2509 | - containers[0].globalRect |
2510 | - return containers[0] |
2511 | - except AttributeError: |
2512 | - containers = containers[0].get_children() |
2513 | - |
2514 | - raise _common.ToolkitException("Couldn't find the top-most container.") |
2515 | + parent = self.get_parent() |
2516 | + top_container = None |
2517 | + while parent.id != root.id: |
2518 | + if hasattr(parent, 'globalRect'): |
2519 | + top_container = parent |
2520 | + |
2521 | + parent = parent.get_parent() |
2522 | + |
2523 | + if top_container is None: |
2524 | + raise _common.ToolkitException( |
2525 | + "Couldn't find the top-most container.") |
2526 | + else: |
2527 | + return top_container |
2528 | |
2529 | def _is_child_visible(self, child, containers): |
2530 | """Check if the center of the child is visible. |
2531 | @@ -90,8 +80,38 @@ |
2532 | return (object_center >= visible_top and |
2533 | object_center <= visible_bottom) |
2534 | |
2535 | + def _slow_drag(self, start_x, stop_x, start_y, stop_y): |
2536 | + # If we drag too fast, we end up scrolling more than what we |
2537 | + # should, sometimes missing the element we are looking for. |
2538 | + # I found that when the flickDeceleration is 1500, the rate should be |
2539 | + # 5 and that when it's 100, the rate should be 1. With those two points |
2540 | + # we can get that the following equation. |
2541 | + # XXX The deceleration might not be linear with respect to the rate, |
2542 | + # but this works for the two types of scrollables we have for now. |
2543 | + # --elopio - 2014-05-08 |
2544 | + rate = (self.flickDeceleration + 250) / 350 |
2545 | + self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate=rate) |
2546 | + |
2547 | + |
2548 | +class QQuickFlickable(Scrollable): |
2549 | + |
2550 | + @autopilot_logging.log_action(logger.info) |
2551 | + def swipe_child_into_view(self, child): |
2552 | + """Make the child visible. |
2553 | + |
2554 | + Currently it works only when the object needs to be swiped vertically. |
2555 | + TODO implement horizontal swiping. --elopio - 2014-03-21 |
2556 | + |
2557 | + """ |
2558 | + containers = self._get_containers() |
2559 | + if not self._is_child_visible(child, containers): |
2560 | + self._swipe_non_visible_child_into_view(child, containers) |
2561 | + else: |
2562 | + logger.debug('The element is already visible.') |
2563 | + |
2564 | @autopilot_logging.log_action(logger.info) |
2565 | def _swipe_non_visible_child_into_view(self, child, containers): |
2566 | + original_content_y = self.contentY |
2567 | while not self._is_child_visible(child, containers): |
2568 | # Check the direction of the swipe based on the position of the |
2569 | # child relative to the immediate flickable container. |
2570 | @@ -100,6 +120,10 @@ |
2571 | else: |
2572 | self._swipe_to_show_more_below(containers) |
2573 | |
2574 | + if self.contentY == original_content_y: |
2575 | + raise _common.ToolkitException( |
2576 | + "Couldn't swipe in the flickable.") |
2577 | + |
2578 | @autopilot_logging.log_action(logger.info) |
2579 | def _swipe_to_show_more_above(self, containers): |
2580 | if self.atYBeginning: |
2581 | @@ -124,8 +148,12 @@ |
2582 | # bottom. |
2583 | top = _get_visible_container_top(containers) + 5 |
2584 | bottom = _get_visible_container_bottom(containers) - 5 |
2585 | + |
2586 | if direction == 'below': |
2587 | - start_y = bottom |
2588 | + # Take into account that swiping from below can open the toolbar or |
2589 | + # trigger the bottom edge gesture. |
2590 | + # XXX Do this only if we are close to the bottom edge. |
2591 | + start_y = bottom - 20 |
2592 | stop_y = top |
2593 | elif direction == 'above': |
2594 | start_y = top |
2595 | @@ -137,11 +165,6 @@ |
2596 | self.dragging.wait_for(False) |
2597 | self.moving.wait_for(False) |
2598 | |
2599 | - def _slow_drag(self, start_x, stop_x, start_y, stop_y): |
2600 | - # If we drag too fast, we end up scrolling more than what we |
2601 | - # should, sometimes missing the element we are looking for. |
2602 | - self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate=5) |
2603 | - |
2604 | @autopilot_logging.log_action(logger.info) |
2605 | def _scroll_to_top(self): |
2606 | if not self.atYBeginning: |
2607 | |
2608 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py' |
2609 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py 2014-05-02 18:55:43 +0000 |
2610 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py 2014-05-28 18:09:57 +0000 |
2611 | @@ -21,6 +21,7 @@ |
2612 | |
2613 | from ubuntuuitoolkit._custom_proxy_objects import ( |
2614 | _common, |
2615 | + _mainview, |
2616 | _tabbar |
2617 | ) |
2618 | |
2619 | @@ -36,9 +37,31 @@ |
2620 | |
2621 | def __init__(self, *args): |
2622 | super(Header, self).__init__(*args) |
2623 | - self.pointing_device = _common.get_pointing_device() |
2624 | + # XXX we need a better way to keep reference to the main view. |
2625 | + # --elopio - 2014-02-26 |
2626 | + self.main_view = self.get_root_instance().select_single( |
2627 | + _mainview.MainView) |
2628 | + |
2629 | + def _show_if_not_visible(self): |
2630 | + if not self._is_visible(): |
2631 | + self._show() |
2632 | + |
2633 | + def _is_visible(self): |
2634 | + return self.y == 0 |
2635 | + |
2636 | + def _show(self): |
2637 | + # FIXME This will fail if the header is not linked to a flickable that |
2638 | + # fills the main view. The header has a flickable property but it |
2639 | + # can't be read by autopilot. See bug http://pad.lv/1318829 |
2640 | + start_x = stop_x = (self.globalRect.x + self.globalRect.width) // 2 |
2641 | + start_y = self.main_view.globalRect.y + 5 |
2642 | + stop_y = start_y + self.globalRect.height |
2643 | + self.pointing_device.drag(start_x, start_y, stop_x, stop_y) |
2644 | + self.y.wait_for(0) |
2645 | |
2646 | def click_back_button(self): |
2647 | + self._show_if_not_visible() |
2648 | + |
2649 | if self.useDeprecatedToolbar: |
2650 | raise _common.ToolkitException('Old header has no back button') |
2651 | try: |
2652 | @@ -51,6 +74,8 @@ |
2653 | self.pointing_device.click_object(back_button) |
2654 | |
2655 | def click_custom_back_button(self): |
2656 | + self._show_if_not_visible() |
2657 | + |
2658 | if self.useDeprecatedToolbar: |
2659 | raise _common.ToolkitException( |
2660 | 'Old header has no custom back button') |
2661 | @@ -79,6 +104,8 @@ |
2662 | :raise ToolkitEmulatorException: If the main view has no tabs. |
2663 | |
2664 | """ |
2665 | + self._show_if_not_visible() |
2666 | + |
2667 | if self.useDeprecatedToolbar: |
2668 | self._switch_to_next_tab_in_deprecated_tabbar() |
2669 | else: |
2670 | @@ -108,6 +135,8 @@ |
2671 | useDeprecatedToolbar is set. |
2672 | |
2673 | """ |
2674 | + self._show_if_not_visible() |
2675 | + |
2676 | if self.useDeprecatedToolbar: |
2677 | raise _common.ToolkitException( |
2678 | "Header.swtich_to_tab_by_index only works with new header") |
2679 | @@ -145,6 +174,8 @@ |
2680 | name. |
2681 | |
2682 | """ |
2683 | + self._show_if_not_visible() |
2684 | + |
2685 | button = self._get_action_button(action_object_name) |
2686 | self.pointing_device.click_object(button) |
2687 | |
2688 | |
2689 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_mainview.py' |
2690 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_mainview.py 2014-04-30 18:17:32 +0000 |
2691 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_mainview.py 2014-05-28 18:09:57 +0000 |
2692 | @@ -169,7 +169,7 @@ |
2693 | :parameter object_name: The QML objectName property of the popover. |
2694 | |
2695 | """ |
2696 | - return self.select_single( |
2697 | + return self.wait_select_single( |
2698 | popups.ActionSelectionPopover, objectName=object_name) |
2699 | |
2700 | @autopilot_logging.log_action(logger.info) |
2701 | |
2702 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_qquicklistview.py' |
2703 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_qquicklistview.py 2014-04-16 21:13:39 +0000 |
2704 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_qquicklistview.py 2014-05-28 18:09:57 +0000 |
2705 | @@ -19,22 +19,24 @@ |
2706 | from autopilot import logging as autopilot_logging |
2707 | from autopilot.introspection import dbus |
2708 | |
2709 | -from ubuntuuitoolkit._custom_proxy_objects import _flickable |
2710 | -from ubuntuuitoolkit._custom_proxy_objects import _common |
2711 | - |
2712 | +from ubuntuuitoolkit._custom_proxy_objects import _common, _flickable |
2713 | |
2714 | logger = logging.getLogger(__name__) |
2715 | |
2716 | |
2717 | -class QQuickListView(_flickable.Flickable): |
2718 | +class QQuickListView(_flickable.QQuickFlickable): |
2719 | |
2720 | @autopilot_logging.log_action(logger.info) |
2721 | - def click_element(self, object_name): |
2722 | + def click_element(self, object_name, direction=None): |
2723 | """Click an element from the list. |
2724 | |
2725 | It swipes the element into view if it's center is not visible. |
2726 | |
2727 | :parameter objectName: The objectName property of the element to click. |
2728 | + :parameter direction: The direction where the element is, it can be |
2729 | + either 'above' or 'below'. Default value is None, which means we |
2730 | + don't know where the object is and we will need to search the full |
2731 | + list. |
2732 | |
2733 | """ |
2734 | try: |
2735 | @@ -42,16 +44,31 @@ |
2736 | except dbus.StateNotFoundError: |
2737 | # The element might be on a part of the list that hasn't been |
2738 | # created yet. We have to search for it scrolling the entire list. |
2739 | - element = self._find_element(object_name) |
2740 | + element = self._find_element(object_name, direction) |
2741 | self.swipe_child_into_view(element) |
2742 | self.pointing_device.click_object(element) |
2743 | |
2744 | @autopilot_logging.log_action(logger.info) |
2745 | - def _find_element(self, object_name): |
2746 | - self._scroll_to_top() |
2747 | - while not self.atYEnd: |
2748 | - containers = self._get_containers() |
2749 | - self._swipe_to_show_more_below(containers) |
2750 | + def _find_element(self, object_name, direction=None): |
2751 | + if direction is None: |
2752 | + # We don't know where the object is so we start looking for it from |
2753 | + # the top. |
2754 | + self._scroll_to_top() |
2755 | + direction = 'below' |
2756 | + |
2757 | + if direction == 'below': |
2758 | + fail_condition = lambda: self.atYEnd |
2759 | + swipe_method = self._swipe_to_show_more_below |
2760 | + elif direction == 'above': |
2761 | + fail_condition = lambda: self.atYBeginning |
2762 | + swipe_method = self._swipe_to_show_more_above |
2763 | + else: |
2764 | + raise _common.ToolkitException( |
2765 | + 'Invalid direction: {}'.format(direction)) |
2766 | + |
2767 | + containers = self._get_containers() |
2768 | + while not fail_condition(): |
2769 | + swipe_method(containers) |
2770 | try: |
2771 | return self.select_single(objectName=object_name) |
2772 | except dbus.StateNotFoundError: |
2773 | |
2774 | === modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_textfield.py' |
2775 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_textfield.py 2014-04-16 21:13:39 +0000 |
2776 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_textfield.py 2014-05-28 18:09:57 +0000 |
2777 | @@ -81,8 +81,13 @@ |
2778 | self.keyboard.press_and_release('BackSpace') |
2779 | |
2780 | def _select_all(self): |
2781 | - self.pointing_device.click_object(self, press_duration=1) |
2782 | - root = self.get_root_instance() |
2783 | - main_view = root.select_single(_mainview.MainView) |
2784 | - popover = main_view.get_action_selection_popover('text_input_popover') |
2785 | - popover.click_button_by_text('Select All') |
2786 | + if not self._is_all_text_selected(): |
2787 | + self.pointing_device.click_object(self, press_duration=1) |
2788 | + root = self.get_root_instance() |
2789 | + main_view = root.select_single(_mainview.MainView) |
2790 | + popover = main_view.get_action_selection_popover( |
2791 | + 'text_input_popover') |
2792 | + popover.click_button_by_text('Select All') |
2793 | + |
2794 | + def _is_all_text_selected(self): |
2795 | + return self.text == self.selectedText |
2796 | |
2797 | === added file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/pickers.py' |
2798 | --- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/pickers.py 1970-01-01 00:00:00 +0000 |
2799 | +++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/pickers.py 2014-05-28 18:09:57 +0000 |
2800 | @@ -0,0 +1,255 @@ |
2801 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
2802 | +# |
2803 | +# Copyright (C) 2014 Canonical Ltd. |
2804 | +# |
2805 | +# This program is free software; you can redistribute it and/or modify |
2806 | +# it under the terms of the GNU Lesser General Public License as published by |
2807 | +# the Free Software Foundation; version 3. |
2808 | +# |
2809 | +# This program is distributed in the hope that it will be useful, |
2810 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2811 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2812 | +# GNU Lesser General Public License for more details. |
2813 | +# |
2814 | +# You should have received a copy of the GNU Lesser General Public License |
2815 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2816 | + |
2817 | +import datetime |
2818 | +import logging |
2819 | + |
2820 | +from autopilot import logging as autopilot_logging |
2821 | +from autopilot.introspection import dbus |
2822 | + |
2823 | +from ubuntuuitoolkit._custom_proxy_objects import ( |
2824 | + _common, |
2825 | + _flickable, |
2826 | + _qquicklistview |
2827 | +) |
2828 | + |
2829 | + |
2830 | +logger = logging.getLogger(__name__) |
2831 | + |
2832 | + |
2833 | +class DatePicker(_common.UbuntuUIToolkitCustomProxyObjectBase): |
2834 | + """Autopilot helper for the DatePicker component.""" |
2835 | + |
2836 | + @autopilot_logging.log_action(logger.info) |
2837 | + def pick_date(self, date): |
2838 | + """Pick a date from the date picker. |
2839 | + |
2840 | + :parameter date: The date to pick. |
2841 | + :type date: An object with year, month and day attributes, like |
2842 | + python's datetime.date. |
2843 | + :raises ubuntuuitoolkit.ToolkitException if the mode of the picker |
2844 | + doesn't let select a date. |
2845 | + |
2846 | + """ |
2847 | + if not self._is_date_picker(): |
2848 | + raise _common.ToolkitException( |
2849 | + "Can't pick date. The picker mode is: {!r}.".format(self.mode)) |
2850 | + if 'Years' in self.mode: |
2851 | + self._pick_year(date.year) |
2852 | + self.year.wait_for(date.year) |
2853 | + if 'Month' in self.mode: |
2854 | + # Python's date object starts at one. The model in the date picker |
2855 | + # at 0. |
2856 | + self._pick_month(date.month - 1) |
2857 | + self.month.wait_for(date.month - 1) |
2858 | + if 'Day' in self.mode: |
2859 | + self._pick_day(date.day) |
2860 | + self.day.wait_for(date.day) |
2861 | + |
2862 | + def _is_date_picker(self): |
2863 | + mode = self.mode |
2864 | + if 'Years' in mode or 'Months' in mode or 'Days' in mode: |
2865 | + return True |
2866 | + else: |
2867 | + return False |
2868 | + |
2869 | + @autopilot_logging.log_action(logger.info) |
2870 | + def _pick_year(self, year): |
2871 | + picker = self.select_single( |
2872 | + 'Picker', objectName='PickerRow_YearPicker') |
2873 | + list_view = picker.select_single( |
2874 | + _qquicklistview.QQuickListView, objectName='Picker_Linear') |
2875 | + self._pick_value(self.year, year, list_view) |
2876 | + |
2877 | + @autopilot_logging.log_action(logger.info) |
2878 | + def _pick_month(self, month): |
2879 | + self._pick_value_from_path_view('Month', self.month, month) |
2880 | + |
2881 | + @autopilot_logging.log_action(logger.info) |
2882 | + def _pick_day(self, day): |
2883 | + # Python's date object starts at one. The model in the date picker |
2884 | + # at 0. |
2885 | + self._pick_value_from_path_view('Day', self.day - 1, day - 1) |
2886 | + |
2887 | + def _pick_value_from_path_view(self, type_, current_value, new_value): |
2888 | + picker = self.select_single( |
2889 | + 'Picker', objectName='PickerRow_{}Picker'.format(type_)) |
2890 | + path_view = picker.select_single( |
2891 | + QQuickPathView, objectName='Picker_WrapAround') |
2892 | + self._pick_value(current_value, new_value, path_view) |
2893 | + |
2894 | + def _pick_value(self, current_value, new_value, scrollable): |
2895 | + if new_value > current_value: |
2896 | + direction = 'below' |
2897 | + elif new_value < current_value: |
2898 | + direction = 'above' |
2899 | + else: |
2900 | + logger.debug('The value is already selected.') |
2901 | + return |
2902 | + scrollable.click_element( |
2903 | + object_name='PickerRow_PickerLabel{}'.format(new_value), |
2904 | + direction=direction) |
2905 | + |
2906 | + def get_date(self): |
2907 | + """Return the currently selected date. |
2908 | + |
2909 | + :return: a python datetime.date object with the selected date. |
2910 | + |
2911 | + """ |
2912 | + # Python's date object starts at one. The model in the date picker |
2913 | + # at 0. |
2914 | + return datetime.date(self.year, self.month + 1, self.day) |
2915 | + |
2916 | + @autopilot_logging.log_action(logger.info) |
2917 | + def pick_time(self, time): |
2918 | + """Pick a time from the date picker. |
2919 | + |
2920 | + :parameter time: The time to pick. |
2921 | + :type time: An object with hour, minute and second attributes, like |
2922 | + python's datetime.time. |
2923 | + :raises ubuntuuitoolkit.ToolkitException if the mode of the picker |
2924 | + doesn't let select a time. |
2925 | + |
2926 | + """ |
2927 | + if not self._is_time_picker(): |
2928 | + raise _common.ToolkitException( |
2929 | + "Can't pick time. The picker mode is: {!r}.".format(self.mode)) |
2930 | + if 'Hours' in self.mode: |
2931 | + self._pick_hour(time.hour) |
2932 | + self.hours.wait_for(time.hour) |
2933 | + if 'Minutes' in self.mode: |
2934 | + self._pick_minute(time.minute) |
2935 | + self.minutes.wait_for(time.minute) |
2936 | + if 'Seconds' in self.mode: |
2937 | + self._pick_second(time.second) |
2938 | + self.seconds.wait_for(time.second) |
2939 | + |
2940 | + def _is_time_picker(self): |
2941 | + mode = self.mode |
2942 | + if 'Hours' in mode or 'Minutes' in mode or 'Seconds' in mode: |
2943 | + return True |
2944 | + else: |
2945 | + return False |
2946 | + |
2947 | + @autopilot_logging.log_action(logger.info) |
2948 | + def _pick_hour(self, hour): |
2949 | + self._pick_value_from_path_view('Hours', self.hours, hour) |
2950 | + |
2951 | + @autopilot_logging.log_action(logger.info) |
2952 | + def _pick_minute(self, minute): |
2953 | + self._pick_value_from_path_view('Minutes', self.minutes, minute) |
2954 | + |
2955 | + @autopilot_logging.log_action(logger.info) |
2956 | + def _pick_second(self, second): |
2957 | + self._pick_value_from_path_view('Seconds', self.seconds, second) |
2958 | + |
2959 | + def get_time(self): |
2960 | + """Return the currently selected time. |
2961 | + |
2962 | + :return: a python datetime.time object with the selected time. |
2963 | + |
2964 | + """ |
2965 | + return datetime.time(self.hours, self.minutes, self.seconds) |
2966 | + |
2967 | + |
2968 | +class QQuickPathView(_flickable.Scrollable): |
2969 | + |
2970 | + # TODO make it more general and move it to its own module. |
2971 | + # --elopio - 2014-05-06 |
2972 | + |
2973 | + @autopilot_logging.log_action(logger.info) |
2974 | + def click_element(self, object_name, direction='below'): |
2975 | + try: |
2976 | + element = self.select_single(objectName=object_name) |
2977 | + except dbus.StateNotFoundError: |
2978 | + # The element might be on a part of the list that hasn't been |
2979 | + # created yet. We have to search for it scrolling. |
2980 | + element = self._find_element(object_name, direction) |
2981 | + self.swipe_child_into_view(element) |
2982 | + self.pointing_device.click_object(element) |
2983 | + |
2984 | + @autopilot_logging.log_action(logger.info) |
2985 | + def _find_element(self, object_name, direction): |
2986 | + containers = self._get_containers() |
2987 | + for index in range(self.count): |
2988 | + if direction == 'below': |
2989 | + swipe_method = self._swipe_to_show_one_more_below |
2990 | + elif direction == 'above': |
2991 | + swipe_method = self._swipe_to_show_one_more_above |
2992 | + else: |
2993 | + raise _common.ToolkitException( |
2994 | + 'Invalid direction: {}'.format(direction)) |
2995 | + |
2996 | + swipe_method(containers) |
2997 | + |
2998 | + try: |
2999 | + return self.select_single(objectName=object_name) |
3000 | + except dbus.StateNotFoundError: |
3001 | + pass |
3002 | + raise _common.ToolkitException( |
3003 | + 'List element with objectName "{}" not found.'.format(object_name)) |
3004 | + |
3005 | + @autopilot_logging.log_action(logger.info) |
3006 | + def _swipe_to_show_one_more_above(self, containers): |
3007 | + self._swipe_to_show_one_more('above', containers) |
3008 | + |
3009 | + @autopilot_logging.log_action(logger.info) |
3010 | + def _swipe_to_show_one_more_below(self, containers): |
3011 | + self._swipe_to_show_one_more('below', containers) |
3012 | + |
3013 | + def _swipe_to_show_one_more(self, direction, containers): |
3014 | + start_x = stop_x = self.globalRect.x + (self.globalRect.width // 2) |
3015 | + center_y = self.globalRect.y + (self.globalRect.height // 2) |
3016 | + # XXX This assumes all the children are of the same height |
3017 | + child = self.get_children_by_type('PickerDelegate')[0] |
3018 | + top = center_y - (child.globalRect.height // 2) |
3019 | + bottom = center_y + (child.globalRect.height // 2) |
3020 | + if direction == 'below': |
3021 | + start_y = bottom |
3022 | + stop_y = top |
3023 | + elif direction == 'above': |
3024 | + start_y = top |
3025 | + stop_y = bottom |
3026 | + else: |
3027 | + raise _common.ToolkitException( |
3028 | + 'Invalid direction {}.'.format(direction)) |
3029 | + self._slow_drag(start_x, stop_x, start_y, stop_y) |
3030 | + self.dragging.wait_for(False) |
3031 | + self.moving.wait_for(False) |
3032 | + |
3033 | + @autopilot_logging.log_action(logger.info) |
3034 | + def swipe_child_into_view(self, child): |
3035 | + """Make the child visible. |
3036 | + |
3037 | + Currently it works only when the object needs to be swiped vertically. |
3038 | + TODO implement horizontal swiping. --elopio - 2014-03-21 |
3039 | + |
3040 | + """ |
3041 | + containers = self._get_containers() |
3042 | + if not self._is_child_visible(child, containers): |
3043 | + self._swipe_non_visible_child_into_view(child, containers) |
3044 | + else: |
3045 | + logger.debug('The element is already visible.') |
3046 | + |
3047 | + @autopilot_logging.log_action(logger.info) |
3048 | + def _swipe_non_visible_child_into_view(self, child, containers): |
3049 | + while not self._is_child_visible(child, containers): |
3050 | + # Check the direction of the swipe based on the position of the |
3051 | + # child relative to the immediate flickable container. |
3052 | + if child.globalRect.y < self.globalRect.y: |
3053 | + self._swipe_to_show_one_more_above(containers) |
3054 | + else: |
3055 | + self._swipe_to_show_one_more_below(containers) |
3056 | |
3057 | === modified file 'tests/autopilot/ubuntuuitoolkit/emulators.py' |
3058 | --- tests/autopilot/ubuntuuitoolkit/emulators.py 2014-04-25 18:39:51 +0000 |
3059 | +++ tests/autopilot/ubuntuuitoolkit/emulators.py 2014-05-28 18:09:57 +0000 |
3060 | @@ -36,12 +36,12 @@ |
3061 | 'CheckBox', |
3062 | 'ComposerSheet', |
3063 | 'Empty', |
3064 | - 'Flickable', |
3065 | 'Header', |
3066 | 'ItemSelector', |
3067 | 'MainView', |
3068 | 'MultiValue', |
3069 | 'OptionSelector', |
3070 | + 'QQuickFlickable', |
3071 | 'QQuickListView', |
3072 | 'SingleControl', |
3073 | 'SingleValue', |
3074 | @@ -61,10 +61,10 @@ |
3075 | get_keyboard, |
3076 | get_pointing_device, |
3077 | CheckBox, |
3078 | - Flickable, |
3079 | Header, |
3080 | MainView, |
3081 | OptionSelector, |
3082 | + QQuickFlickable, |
3083 | QQuickListView, |
3084 | TabBar, |
3085 | Tabs, |
3086 | |
3087 | === added file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_date_picker.py' |
3088 | --- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_date_picker.py 1970-01-01 00:00:00 +0000 |
3089 | +++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_date_picker.py 2014-05-28 18:09:57 +0000 |
3090 | @@ -0,0 +1,203 @@ |
3091 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3092 | +# |
3093 | +# Copyright (C) 2014 Canonical Ltd. |
3094 | +# |
3095 | +# This program is free software; you can redistribute it and/or modify |
3096 | +# it under the terms of the GNU Lesser General Public License as published by |
3097 | +# the Free Software Foundation; version 3. |
3098 | +# |
3099 | +# This program is distributed in the hope that it will be useful, |
3100 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3101 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3102 | +# GNU Lesser General Public License for more details. |
3103 | +# |
3104 | +# You should have received a copy of the GNU Lesser General Public License |
3105 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3106 | + |
3107 | +import datetime |
3108 | + |
3109 | +import ubuntuuitoolkit |
3110 | +from ubuntuuitoolkit import pickers, tests |
3111 | + |
3112 | + |
3113 | +class DatePickerBaseTestCase(tests.QMLStringAppTestCase): |
3114 | + |
3115 | + test_qml = (""" |
3116 | +import QtQuick 2.0 |
3117 | +import Ubuntu.Components 1.1 |
3118 | +import Ubuntu.Components.Pickers 1.0 |
3119 | + |
3120 | +MainView { |
3121 | + width: units.gu(48) |
3122 | + height: units.gu(60) |
3123 | + |
3124 | + Column { |
3125 | + DatePicker { |
3126 | + id: datePicker |
3127 | + objectName: 'datePicker' |
3128 | + mode: 'Years|Months|Days' |
3129 | + date: { |
3130 | + var d = new Date() |
3131 | + // Make sure that the picker will have higher and lower values |
3132 | + // to select. |
3133 | + d.setFullYear(d.getFullYear() + 25) |
3134 | + d.setMonth('5') |
3135 | + d.setDate('15') |
3136 | + return d |
3137 | + } |
3138 | + } |
3139 | + DatePicker { |
3140 | + id: timePicker |
3141 | + objectName: 'timePicker' |
3142 | + mode: 'Hours|Minutes|Seconds' |
3143 | + date: { |
3144 | + var d = new Date() |
3145 | + // Make sure that the picker will have higher and lower values |
3146 | + // to select. |
3147 | + d.setHours(12) |
3148 | + d.setMinutes('30') |
3149 | + d.setSeconds('30') |
3150 | + return d |
3151 | + } |
3152 | + } |
3153 | + } |
3154 | +} |
3155 | +""") |
3156 | + |
3157 | + def setUp(self): |
3158 | + super(DatePickerBaseTestCase, self).setUp() |
3159 | + self.date_picker = self.main_view.select_single( |
3160 | + pickers.DatePicker, objectName='datePicker') |
3161 | + self.time_picker = self.main_view.select_single( |
3162 | + pickers.DatePicker, objectName='timePicker') |
3163 | + |
3164 | + |
3165 | +class DatePickerTestCase(DatePickerBaseTestCase): |
3166 | + |
3167 | + def test_select_date_picker_must_return_custom_proxy_object(self): |
3168 | + self.assertIsInstance( |
3169 | + self.date_picker, pickers.DatePicker) |
3170 | + |
3171 | + def test_pick_date_on_time_picker_must_raise_exception(self): |
3172 | + error = self.assertRaises( |
3173 | + ubuntuuitoolkit.ToolkitException, self.time_picker.pick_date, |
3174 | + 'dummy') |
3175 | + self.assertEqual( |
3176 | + str(error), |
3177 | + "Can't pick date. The picker mode is: {!r}.".format( |
3178 | + self.time_picker.mode)) |
3179 | + |
3180 | + def test_pick_time_on_date_picker_must_raise_exception(self): |
3181 | + error = self.assertRaises( |
3182 | + ubuntuuitoolkit.ToolkitException, self.date_picker.pick_time, |
3183 | + 'dummy') |
3184 | + self.assertEqual( |
3185 | + str(error), |
3186 | + "Can't pick time. The picker mode is: {!r}.".format( |
3187 | + self.date_picker.mode)) |
3188 | + |
3189 | + def test_swipe_to_show_one_more_below_must_select_next_index(self): |
3190 | + """Test that we don't end up swiping more than needed. |
3191 | + |
3192 | + This would cause us to miss the element we are looking for, and to have |
3193 | + to swipe many times in order to finally click it. |
3194 | + |
3195 | + """ |
3196 | + picker = self.main_view.select_single( |
3197 | + 'Picker', objectName='PickerRow_DayPicker') |
3198 | + path_view = picker.select_single( |
3199 | + pickers.QQuickPathView, objectName='Picker_WrapAround') |
3200 | + current_index = path_view.currentIndex |
3201 | + |
3202 | + path_view._swipe_to_show_one_more_below(path_view._get_containers()) |
3203 | + |
3204 | + self.assertEqual(path_view.currentIndex, current_index + 1) |
3205 | + |
3206 | + def test_swipe_to_show_one_more_above_must_select_previous_index(self): |
3207 | + """Test that we don't end up swiping more than needed. |
3208 | + |
3209 | + This would cause us to miss the element we are looking for, and to have |
3210 | + to swipe many times in order to finally click it. |
3211 | + |
3212 | + """ |
3213 | + picker = self.main_view.select_single( |
3214 | + 'Picker', objectName='PickerRow_DayPicker') |
3215 | + path_view = picker.select_single( |
3216 | + pickers.QQuickPathView, objectName='Picker_WrapAround') |
3217 | + current_index = path_view.currentIndex |
3218 | + |
3219 | + path_view._swipe_to_show_one_more_above(path_view._get_containers()) |
3220 | + |
3221 | + self.assertEqual(path_view.currentIndex, current_index - 1) |
3222 | + |
3223 | + |
3224 | +class PickDateFromDatePickerTestCase(DatePickerBaseTestCase): |
3225 | + |
3226 | + SELECTED_YEAR = datetime.date.today().year + 25 |
3227 | + SELECTED_MONTH = 6 # June |
3228 | + SELECTED_DAY = 15 |
3229 | + |
3230 | + scenarios = [ |
3231 | + ('higher year', { |
3232 | + 'date_to_pick': datetime.date( |
3233 | + SELECTED_YEAR + 10, SELECTED_MONTH, SELECTED_DAY)}), |
3234 | + ('lower year', { |
3235 | + 'date_to_pick': datetime.date( |
3236 | + SELECTED_YEAR - 10, SELECTED_MONTH, SELECTED_DAY)}), |
3237 | + ('higher month', { |
3238 | + 'date_to_pick': datetime.date( |
3239 | + SELECTED_YEAR, SELECTED_MONTH + 4, SELECTED_DAY)}), |
3240 | + ('lower month', { |
3241 | + 'date_to_pick': datetime.date( |
3242 | + SELECTED_YEAR, SELECTED_MONTH - 4, SELECTED_DAY)}), |
3243 | + ('higher day', { |
3244 | + 'date_to_pick': datetime.date( |
3245 | + SELECTED_YEAR, SELECTED_MONTH, SELECTED_DAY + 10)}), |
3246 | + ('lower day', { |
3247 | + 'date_to_pick': datetime.date( |
3248 | + SELECTED_YEAR, SELECTED_MONTH, SELECTED_DAY - 10)}), |
3249 | + ('change all values', { |
3250 | + 'date_to_pick': datetime.date( |
3251 | + SELECTED_YEAR - 10, SELECTED_MONTH + 4, SELECTED_DAY - 10)}), |
3252 | + ] |
3253 | + |
3254 | + def test_pick_date(self): |
3255 | + """Test that picking a date updates the picker.""" |
3256 | + self.date_picker.pick_date(self.date_to_pick) |
3257 | + self.assertEqual(self.date_picker.get_date(), self.date_to_pick) |
3258 | + |
3259 | + |
3260 | +class PickTimeFromDatePickerTestCase(DatePickerBaseTestCase): |
3261 | + |
3262 | + SELECTED_HOUR = 12 |
3263 | + SELECTED_MINUTE = 30 |
3264 | + SELECTED_SECOND = 30 |
3265 | + |
3266 | + scenarios = [ |
3267 | + ('higher hour', { |
3268 | + 'time_to_pick': datetime.time( |
3269 | + SELECTED_HOUR + 6, SELECTED_MINUTE, SELECTED_SECOND)}), |
3270 | + ('lower hour', { |
3271 | + 'time_to_pick': datetime.time( |
3272 | + SELECTED_HOUR - 6, SELECTED_MINUTE, SELECTED_SECOND)}), |
3273 | + ('higher minute', { |
3274 | + 'time_to_pick': datetime.time( |
3275 | + SELECTED_HOUR, SELECTED_MINUTE + 10, SELECTED_SECOND)}), |
3276 | + ('lower minute', { |
3277 | + 'time_to_pick': datetime.time( |
3278 | + SELECTED_HOUR, SELECTED_MINUTE - 10, SELECTED_SECOND)}), |
3279 | + ('higher second', { |
3280 | + 'time_to_pick': datetime.time( |
3281 | + SELECTED_HOUR, SELECTED_MINUTE, SELECTED_SECOND + 10)}), |
3282 | + ('lower second', { |
3283 | + 'time_to_pick': datetime.time( |
3284 | + SELECTED_HOUR, SELECTED_MINUTE, SELECTED_SECOND - 10)}), |
3285 | + ('change all values', { |
3286 | + 'time_to_pick': datetime.time( |
3287 | + SELECTED_HOUR + 6, SELECTED_MINUTE - 10, |
3288 | + SELECTED_SECOND + 10)}), |
3289 | + ] |
3290 | + |
3291 | + def test_pick_time(self): |
3292 | + self.time_picker.pick_time(self.time_to_pick) |
3293 | + self.assertEqual(self.time_picker.get_time(), self.time_to_pick) |
3294 | |
3295 | === added file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_flickable.py' |
3296 | --- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_flickable.py 1970-01-01 00:00:00 +0000 |
3297 | +++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_flickable.py 2014-05-28 18:09:57 +0000 |
3298 | @@ -0,0 +1,201 @@ |
3299 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3300 | +# |
3301 | +# Copyright (C) 2014 Canonical Ltd. |
3302 | +# |
3303 | +# This program is free software; you can redistribute it and/or modify |
3304 | +# it under the terms of the GNU Lesser General Public License as published by |
3305 | +# the Free Software Foundation; version 3. |
3306 | +# |
3307 | +# This program is distributed in the hope that it will be useful, |
3308 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3309 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3310 | +# GNU Lesser General Public License for more details. |
3311 | +# |
3312 | +# You should have received a copy of the GNU Lesser General Public License |
3313 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3314 | + |
3315 | + |
3316 | +import testtools |
3317 | + |
3318 | +import ubuntuuitoolkit |
3319 | +from ubuntuuitoolkit import tests |
3320 | +from ubuntuuitoolkit._custom_proxy_objects import _common |
3321 | + |
3322 | + |
3323 | +class FlickableTestCase(testtools.TestCase): |
3324 | + |
3325 | + def test_get_unity_top_container(self): |
3326 | + """Test that we can get the top cointainer in Unity.""" |
3327 | + # This tests bug http://pad.lv/1314390 |
3328 | + # On Unity, the top container is not the first child as it is in all |
3329 | + # the apps that have a MainView. This makes the first implementation of |
3330 | + # _get_top_container fail. Instead of going from the top looking for |
3331 | + # a container, we should start from the flickable until we find the |
3332 | + # top-most container. |
3333 | + # FIXME we are faking the QML tree because we have no way to launch |
3334 | + # the app with a tree like the one in Unity8. kalikiana has a branch |
3335 | + # with an alternate launcher that will let us clean this test. |
3336 | + # --elopio - 2014-05-15. |
3337 | + RootClass = type('obj', (object,), {'id': 'root'}) |
3338 | + mock_root_instance = RootClass() |
3339 | + # We consider a container is an object with a globalRect. |
3340 | + MockNonContainerClass = type('obj', (object,), {}) |
3341 | + mock_non_container = MockNonContainerClass() |
3342 | + MockContainerClass = type( |
3343 | + 'obj', (object,), {'id': 'container', 'globalRect': 'dummy'}) |
3344 | + mock_container = MockContainerClass() |
3345 | + mock_container.get_parent = lambda: mock_root_instance |
3346 | + |
3347 | + # The root instance has two children. This exposes the bug. |
3348 | + mock_root_instance.get_children = lambda: [ |
3349 | + mock_non_container, mock_container] |
3350 | + |
3351 | + dummy_state = {'id': '10'} |
3352 | + flickable = ubuntuuitoolkit.QQuickFlickable( |
3353 | + dummy_state, '/dummy'.encode(), 'dummy') |
3354 | + |
3355 | + flickable.get_root_instance = lambda: mock_root_instance |
3356 | + # The top container of the flickable is its immediate parent. |
3357 | + flickable.get_parent = lambda: mock_container |
3358 | + |
3359 | + top_container = flickable._get_top_container() |
3360 | + self.assertEqual(top_container, mock_container) |
3361 | + |
3362 | + def test_is_flickable_with_flicking_property_must_return_true(self): |
3363 | + """is_flickable returns True if flickable property exists.""" |
3364 | + dummy_id = (0, 0) |
3365 | + dummy_flicking = (0, 'dummy') |
3366 | + state_with_flicking = {'id': dummy_id, 'flicking': dummy_flicking} |
3367 | + element = _common.UbuntuUIToolkitCustomProxyObjectBase( |
3368 | + state_with_flicking, '/dummy'.encode(), 'dummy') |
3369 | + with element.no_automatic_refreshing(): |
3370 | + self.assertTrue(element.is_flickable()) |
3371 | + |
3372 | + def test_is_flickable_without_flicking_property_must_return_false(self): |
3373 | + """is_flickable returns False if flickable property doesn't exist.""" |
3374 | + dummy_id = (0, 0) |
3375 | + state_without_flicking = {'id': dummy_id} |
3376 | + element = _common.UbuntuUIToolkitCustomProxyObjectBase( |
3377 | + state_without_flicking, '/dummy'.encode(), 'dummy') |
3378 | + with element.no_automatic_refreshing(): |
3379 | + self.assertFalse(element.is_flickable()) |
3380 | + |
3381 | + |
3382 | +class IsFlickableTestCase(tests.QMLStringAppTestCase): |
3383 | + """Functional test to check that is_flickable returns the right value. |
3384 | + |
3385 | + We already have tests for is_flickable with mocks, so here we just check |
3386 | + with some real elements. |
3387 | + |
3388 | + """ |
3389 | + |
3390 | + test_qml = (""" |
3391 | +import QtQuick 2.0 |
3392 | +import Ubuntu.Components 0.1 |
3393 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
3394 | + |
3395 | +MainView { |
3396 | + objectName: 'mainView' |
3397 | + width: units.gu(48) |
3398 | + height: units.gu(60) |
3399 | + |
3400 | + Flickable { |
3401 | + objectName: 'flickable' |
3402 | + } |
3403 | + ListView { |
3404 | + objectName: 'listView' |
3405 | + } |
3406 | + Label { |
3407 | + objectName: 'label' |
3408 | + } |
3409 | +} |
3410 | +""") |
3411 | + |
3412 | + scenarios = [ |
3413 | + ('main view', dict(object_name='mainView', is_flickable=False)), |
3414 | + ('flickable', dict(object_name='flickable', is_flickable=True)), |
3415 | + ('list view', dict(object_name='listView', is_flickable=True)), |
3416 | + ('label', dict(object_name='label', is_flickable=False)) |
3417 | + ] |
3418 | + |
3419 | + def test_is_flickable(self): |
3420 | + """Test that is_flickable identifies the elements correctly.""" |
3421 | + element = self.app.select_single(objectName=self.object_name) |
3422 | + self.assertEqual(element.is_flickable(), self.is_flickable) |
3423 | + |
3424 | + |
3425 | +class SwipeIntoViewTestCase(tests.QMLStringAppTestCase): |
3426 | + |
3427 | + test_qml = (""" |
3428 | +import QtQuick 2.0 |
3429 | +import Ubuntu.Components 0.1 |
3430 | + |
3431 | +MainView { |
3432 | + width: units.gu(48) |
3433 | + height: units.gu(60) |
3434 | + |
3435 | + Label { |
3436 | + id: clickedLabel |
3437 | + objectName: "clickedLabel" |
3438 | + text: "No element clicked." |
3439 | + } |
3440 | + |
3441 | + Flickable { |
3442 | + anchors { |
3443 | + fill: parent |
3444 | + topMargin: clickedLabel.height |
3445 | + // It can't be at the bottom, or the toolbar will be opened |
3446 | + // when we try to click it. |
3447 | + bottomMargin: units.gu(10) |
3448 | + } |
3449 | + objectName: 'flickable' |
3450 | + height: units.gu(60) |
3451 | + contentHeight: bottomButton.y + bottomButton.height |
3452 | + |
3453 | + Button { |
3454 | + id: topButton |
3455 | + objectName: 'topButton' |
3456 | + text: 'Top button' |
3457 | + onClicked: clickedLabel.text = objectName |
3458 | + } |
3459 | + Rectangle { |
3460 | + id: emptyRectangle |
3461 | + height: units.gu(80) |
3462 | + anchors.top: topButton.bottom |
3463 | + } |
3464 | + Button { |
3465 | + id: bottomButton |
3466 | + objectName: 'bottomButton' |
3467 | + text: 'Bottom button' |
3468 | + onClicked: clickedLabel.text = objectName |
3469 | + anchors.top: emptyRectangle.bottom |
3470 | + } |
3471 | + } |
3472 | +} |
3473 | +""") |
3474 | + |
3475 | + def setUp(self): |
3476 | + super(SwipeIntoViewTestCase, self).setUp() |
3477 | + self.label = self.main_view.select_single( |
3478 | + 'Label', objectName='clickedLabel') |
3479 | + self.assertEqual(self.label.text, 'No element clicked.') |
3480 | + |
3481 | + def test_swipe_to_bottom(self): |
3482 | + self.main_view.close_toolbar() |
3483 | + |
3484 | + button = self.main_view.select_single(objectName='bottomButton') |
3485 | + button.swipe_into_view() |
3486 | + |
3487 | + self.pointing_device.click_object(button) |
3488 | + self.assertEqual(self.label.text, 'bottomButton') |
3489 | + |
3490 | + def test_swipe_to_top(self): |
3491 | + self.main_view.close_toolbar() |
3492 | + bottomButton = self.main_view.select_single(objectName='bottomButton') |
3493 | + bottomButton.swipe_into_view() |
3494 | + |
3495 | + topButton = self.main_view.select_single(objectName='topButton') |
3496 | + topButton.swipe_into_view() |
3497 | + |
3498 | + self.pointing_device.click_object(topButton) |
3499 | + self.assertEqual(self.label.text, 'topButton') |
3500 | |
3501 | === modified file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_header.py' |
3502 | --- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_header.py 2014-05-10 21:52:19 +0000 |
3503 | +++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_header.py 2014-05-28 18:09:57 +0000 |
3504 | @@ -22,7 +22,7 @@ |
3505 | |
3506 | test_qml = (""" |
3507 | import QtQuick 2.0 |
3508 | -import Ubuntu.Components 0.1 |
3509 | +import Ubuntu.Components 1.1 |
3510 | |
3511 | MainView { |
3512 | width: units.gu(48) |
3513 | @@ -33,11 +33,46 @@ |
3514 | Page { |
3515 | title: "Test title" |
3516 | |
3517 | - Label { |
3518 | - id: label |
3519 | - objectName: "clicked_label" |
3520 | - anchors.centerIn: parent |
3521 | - text: "No button clicked." |
3522 | + Flickable { |
3523 | + anchors.fill: parent |
3524 | + contentHeight: units.gu(120) |
3525 | + objectName: "header_test_flickable" |
3526 | + |
3527 | + Label { |
3528 | + id: label |
3529 | + objectName: "clicked_label" |
3530 | + anchors { |
3531 | + top: parent.top |
3532 | + horizontalCenter: parent.horizontalCenter |
3533 | + } |
3534 | + text: "No button clicked." |
3535 | + } |
3536 | + |
3537 | + Button { |
3538 | + objectName: "hide_actions_button" |
3539 | + anchors { |
3540 | + top: label.bottom |
3541 | + topMargin: units.gu(5) |
3542 | + horizontalCenter: parent.horizontalCenter |
3543 | + } |
3544 | + text: "Hide some actions" |
3545 | + onClicked: { |
3546 | + cancelAction.visible = false; |
3547 | + for (var i=0; i < 3; i++) { |
3548 | + buttonRepeater.itemAt(i).action.visible = false; |
3549 | + } |
3550 | + // only three of five visible actions left |
3551 | + } |
3552 | + } |
3553 | + Label { |
3554 | + id: endLabel |
3555 | + objectName: "end_label" |
3556 | + anchors { |
3557 | + bottom: parent.bottom |
3558 | + horizontalCenter: parent.horizontalCenter |
3559 | + } |
3560 | + text: "The end." |
3561 | + } |
3562 | } |
3563 | |
3564 | tools: ToolbarItems { |
3565 | @@ -62,22 +97,6 @@ |
3566 | } |
3567 | } |
3568 | } |
3569 | - |
3570 | - Button { |
3571 | - objectName: "hide_actions_button" |
3572 | - anchors { |
3573 | - bottom: parent.bottom |
3574 | - horizontalCenter: parent.horizontalCenter |
3575 | - } |
3576 | - text: "Hide some actions" |
3577 | - onClicked: { |
3578 | - cancelAction.visible = false; |
3579 | - for (var i=0; i < 3; i++) { |
3580 | - buttonRepeater.itemAt(i).action.visible = false; |
3581 | - } |
3582 | - // only three of five visible actions left |
3583 | - } |
3584 | - } |
3585 | } |
3586 | } |
3587 | """) |
3588 | @@ -95,8 +114,8 @@ |
3589 | self.assertEqual(self.header.title, "Test title") |
3590 | |
3591 | def test_click_header_action_button(self): |
3592 | - self.header.click_action_button('action1') |
3593 | - self.assertEqual(self.label.text, 'Button 1 clicked.') |
3594 | + self.header.click_action_button('action0') |
3595 | + self.assertEqual(self.label.text, 'Button 0 clicked.') |
3596 | |
3597 | def test_click_header_overflow_action_button(self): |
3598 | # custom back button and first action button go in the header |
3599 | @@ -117,6 +136,13 @@ |
3600 | self.header.click_custom_back_button() |
3601 | self.assertEqual(self.label.text, 'Cancel button clicked.') |
3602 | |
3603 | + def test_click_header_action_button_with_hidden_header(self): |
3604 | + bottom_label = self.main_view.select_single(objectName='end_label') |
3605 | + bottom_label.swipe_into_view() |
3606 | + self.assertFalse(self.header._is_visible()) |
3607 | + self.header.click_action_button('action0') |
3608 | + self.assertEqual(self.label.text, 'Button 0 clicked.') |
3609 | + |
3610 | def test_overflow_button(self): |
3611 | # there are 5 actions plus a custom back action |
3612 | overflow_button = self.header.select_single( |
3613 | |
3614 | === modified file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_textfield.py' |
3615 | --- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_textfield.py 2014-04-17 01:06:31 +0000 |
3616 | +++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_textfield.py 2014-05-28 18:09:57 +0000 |
3617 | @@ -14,6 +14,13 @@ |
3618 | # You should have received a copy of the GNU Lesser General Public License |
3619 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
3620 | |
3621 | +try: |
3622 | + from unittest import mock |
3623 | +except ImportError: |
3624 | + import mock |
3625 | + |
3626 | +from autopilot import platform |
3627 | + |
3628 | import ubuntuuitoolkit |
3629 | from ubuntuuitoolkit import tests |
3630 | |
3631 | @@ -91,3 +98,23 @@ |
3632 | self.assertTrue(self.simple_text_field.is_empty()) |
3633 | self.simple_text_field.write('test') |
3634 | self.assertFalse(self.simple_text_field.is_empty()) |
3635 | + |
3636 | + def test_select_all_selects_all_text(self): |
3637 | + if platform.model() != 'Desktop': |
3638 | + self.skipTest('Select all is not yet implemented on the phone.') |
3639 | + self.simple_text_field.write('Text to select.') |
3640 | + self.simple_text_field._select_all() |
3641 | + |
3642 | + self.assertTrue(self.simple_text_field._is_all_text_selected()) |
3643 | + |
3644 | + def test_select_all_when_already_selected_must_do_nothing(self): |
3645 | + """Test for select all the text when it's already selected.""" |
3646 | + if platform.model() != 'Desktop': |
3647 | + self.skipTest('Select all is not yet implemented on the phone.') |
3648 | + self.simple_text_field.write('Text to select.') |
3649 | + self.simple_text_field._select_all() |
3650 | + with mock.patch.object( |
3651 | + self.simple_text_field, 'pointing_device') as mock_device: |
3652 | + self.simple_text_field._select_all() |
3653 | + |
3654 | + self.assertFalse(mock_device.called) |
3655 | |
3656 | === modified file 'tests/autopilot/ubuntuuitoolkit/tests/gallery/test_gallery.py' |
3657 | --- tests/autopilot/ubuntuuitoolkit/tests/gallery/test_gallery.py 2014-01-13 15:31:14 +0000 |
3658 | +++ tests/autopilot/ubuntuuitoolkit/tests/gallery/test_gallery.py 2014-05-28 18:09:57 +0000 |
3659 | @@ -75,6 +75,10 @@ |
3660 | # TODO: check for properties |
3661 | |
3662 | def test_ubuntushape(self): |
3663 | + # Flaky test case |
3664 | + # FIXME: https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1308979 |
3665 | + return |
3666 | + |
3667 | item = "Ubuntu Shape" |
3668 | self.loadItem(item) |
3669 | self.checkPageHeader(item) |
3670 | |
3671 | === modified file 'tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py' |
3672 | --- tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py 2013-11-08 09:19:02 +0000 |
3673 | +++ tests/autopilot/ubuntuuitoolkit/tests/gallery/test_optionselector.py 2014-05-28 18:09:57 +0000 |
3674 | @@ -1,6 +1,6 @@ |
3675 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
3676 | # |
3677 | -# Copyright (C) 2012, 2013 Canonical Ltd. |
3678 | +# Copyright (C) 2012, 2013, 2014 Canonical Ltd. |
3679 | # |
3680 | # This program is free software; you can redistribute it and/or modify |
3681 | # it under the terms of the GNU Lesser General Public License as published by |
3682 | @@ -14,85 +14,52 @@ |
3683 | # You should have received a copy of the GNU Lesser General Public License |
3684 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
3685 | |
3686 | -"""Tests for the Ubuntu UI Toolkit Gallery - OptionSelector component""" |
3687 | -import time |
3688 | -from autopilot.matchers import Eventually |
3689 | -from testtools.matchers import Equals |
3690 | -from ubuntuuitoolkit.tests import FlickDirection |
3691 | +"""Tests for the Ubuntu UI Toolkit Gallery - OptionSelector component.""" |
3692 | + |
3693 | +import ubuntuuitoolkit |
3694 | from ubuntuuitoolkit.tests.gallery import GalleryTestCase |
3695 | |
3696 | |
3697 | -class OptionSelectorTests(GalleryTestCase): |
3698 | - """Generic tests for the Gallery""" |
3699 | - |
3700 | - def test_optionselector_collapsed(self): |
3701 | - item = "Option Selector" |
3702 | - self.loadItem(item) |
3703 | - self.checkPageHeader(item) |
3704 | - collapsed = self.getObject("optionselector_collapsed") |
3705 | - styleditem = collapsed.select_single('StyledItem', |
3706 | - objectName='listContainer') |
3707 | - |
3708 | - self.assertThat(collapsed.selectedIndex, Equals(0)) |
3709 | - self.pointing_device.click_object(collapsed) |
3710 | - self.assertThat(styleditem.currentlyExpanded, Eventually(Equals(True))) |
3711 | - #try to search the following list entry few times |
3712 | - #as it may not be available immediately. |
3713 | - for t in range(0, 9): |
3714 | - try: |
3715 | - selectedValue = collapsed.select_single('Label', |
3716 | - text='Value 4') |
3717 | - self.assertIsNotNone(selectedValue) |
3718 | - except: |
3719 | - time.sleep(1) |
3720 | - |
3721 | - self.pointing_device.click_object(selectedValue) |
3722 | - self.assertThat(collapsed.selectedIndex, Eventually(Equals(3))) |
3723 | - self.assertThat(styleditem.currentlyExpanded, |
3724 | - Eventually(Equals(False))) |
3725 | - |
3726 | - def test_optionselector_expanded(self): |
3727 | - item = "Option Selector" |
3728 | - self.loadItem(item) |
3729 | - self.checkPageHeader(item) |
3730 | - expanded = self.getObject("optionselector_expanded") |
3731 | - |
3732 | - self.assertThat(expanded.selectedIndex, Equals(0)) |
3733 | - selectedValue = expanded.select_single('Label', text='Value 4') |
3734 | - self.assertIsNotNone(selectedValue) |
3735 | - self.pointing_device.click_object(selectedValue) |
3736 | - self.assertThat(expanded.selectedIndex, Eventually(Equals(3))) |
3737 | - |
3738 | - selectedValue = expanded.select_single('Label', text='Value 1') |
3739 | - self.assertIsNotNone(selectedValue) |
3740 | - self.pointing_device.click_object(selectedValue) |
3741 | - self.assertThat(expanded.selectedIndex, Eventually(Equals(0))) |
3742 | - |
3743 | - def test_optionselector_custommodel(self): |
3744 | - item = "Option Selector" |
3745 | - self.loadItem(item) |
3746 | - self.checkPageHeader(item) |
3747 | - |
3748 | - custommodel = self.getObject("optionselector_custommodel") |
3749 | - flickable = self.main_view.select_single('QQuickFlickable') |
3750 | - self.assertIsNotNone(flickable) |
3751 | - |
3752 | - #Flick upward to reveal the hidden ui element. |
3753 | - self.reveal_item_by_flick(custommodel, flickable, FlickDirection.UP) |
3754 | - self.assertThat(flickable.flicking, Eventually(Equals(False))) |
3755 | - |
3756 | - self.assertThat(custommodel.selectedIndex, Equals(0)) |
3757 | - selectedValue = custommodel.select_single('Label', text='Name 4') |
3758 | - self.assertIsNotNone(selectedValue) |
3759 | - self.pointing_device.click_object(selectedValue) |
3760 | - self.assertThat(custommodel.selectedIndex, Eventually(Equals(3))) |
3761 | - |
3762 | - selectedValue = custommodel.select_single('Label', text='Name 1') |
3763 | - self.assertIsNotNone(selectedValue) |
3764 | - self.pointing_device.click_object(selectedValue) |
3765 | - self.assertThat(custommodel.selectedIndex, Eventually(Equals(0))) |
3766 | - |
3767 | - #scroll the page downward now. |
3768 | - collapsed = self.getObject("optionselector_collapsed") |
3769 | - self.reveal_item_by_flick(collapsed, flickable, FlickDirection.DOWN) |
3770 | - self.assertThat(flickable.flicking, Eventually(Equals(False))) |
3771 | +class OptionSelectorTestCase(GalleryTestCase): |
3772 | + |
3773 | + def setUp(self): |
3774 | + super(OptionSelectorTestCase, self).setUp() |
3775 | + item = "Option Selector" |
3776 | + self.loadItem(item) |
3777 | + self.checkPageHeader(item) |
3778 | + |
3779 | + def test_select_option_from_collapsed_optionselector(self): |
3780 | + collapsed_option_selector = self.main_view.select_single( |
3781 | + ubuntuuitoolkit.OptionSelector, |
3782 | + objectName='optionselector_collapsed') |
3783 | + |
3784 | + self.assertEqual( |
3785 | + collapsed_option_selector.get_selected_text(), 'Value 1') |
3786 | + |
3787 | + collapsed_option_selector.select_option('Label', text='Value 4') |
3788 | + self.assertEqual(collapsed_option_selector.get_selected_index(), 3) |
3789 | + |
3790 | + def test_select_option_from_expanded_optionselector(self): |
3791 | + expanded_option_selector = self.main_view.select_single( |
3792 | + ubuntuuitoolkit.OptionSelector, |
3793 | + objectName='optionselector_expanded') |
3794 | + |
3795 | + self.assertEqual( |
3796 | + expanded_option_selector.get_selected_text(), 'Value 1') |
3797 | + |
3798 | + expanded_option_selector.select_option('Label', text='Value 4') |
3799 | + self.assertEqual(expanded_option_selector.get_selected_index(), 3) |
3800 | + |
3801 | + def test_select_option_from_optionselector_with_custom_model(self): |
3802 | + option_selector_with_custom_model = self.main_view.select_single( |
3803 | + ubuntuuitoolkit.OptionSelector, |
3804 | + objectName='optionselector_custommodel') |
3805 | + option_selector_with_custom_model.swipe_into_view() |
3806 | + |
3807 | + self.assertEqual( |
3808 | + option_selector_with_custom_model.get_selected_index(), 0) |
3809 | + |
3810 | + option_selector_with_custom_model.select_option( |
3811 | + 'Label', text='Name 4') |
3812 | + self.assertEqual( |
3813 | + option_selector_with_custom_model.get_selected_index(), 3) |
3814 | |
3815 | === modified file 'tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py' |
3816 | --- tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py 2014-04-28 15:39:24 +0000 |
3817 | +++ tests/autopilot/ubuntuuitoolkit/tests/test_emulators.py 2014-05-28 18:09:57 +0000 |
3818 | @@ -32,7 +32,7 @@ |
3819 | |
3820 | symbols_retaining_name = [ |
3821 | 'check_autopilot_version', 'get_keyboard', 'get_pointing_device', |
3822 | - 'CheckBox', 'Flickable', 'Header', 'MainView', 'OptionSelector', |
3823 | + 'CheckBox', 'Header', 'MainView', 'OptionSelector', 'QQuickFlickable', |
3824 | 'QQuickListView', 'TabBar', 'Tabs', 'TextField', 'Toolbar', |
3825 | ] |
3826 | |
3827 | |
3828 | === modified file 'tests/qmlapicheck.py' |
3829 | --- tests/qmlapicheck.py 2014-04-24 09:18:38 +0000 |
3830 | +++ tests/qmlapicheck.py 2014-05-28 18:09:57 +0000 |
3831 | @@ -130,10 +130,10 @@ |
3832 | if '{' in line and '}' in line: |
3833 | if filetype == 'qmltypes' and not in_builtin_type: |
3834 | print(' ' + line.strip()) |
3835 | - continue |
3836 | + continue |
3837 | |
3838 | # End of function/ signal/ Item block |
3839 | - if '}' in line: |
3840 | + if '}' in line and not '{' in line: |
3841 | in_block -= 1 |
3842 | block_meta = {} |
3843 | if in_block == 1 and in_builtin_type: |
3844 | @@ -143,7 +143,7 @@ |
3845 | # Only root "Item {" is inspected for QML, otherwise all children |
3846 | if in_block == 1 or filetype == 'qmltypes': |
3847 | # Left hand side specifies a keyword, a type and a variable name |
3848 | - declaration = line.split(':')[0] |
3849 | + declaration = line.split(':', 1)[0] |
3850 | words = declaration.strip().split(' ') |
3851 | # Skip types with prefixes considered builtin |
3852 | if filetype == 'qmltypes' and words[0] == 'name': |
3853 | @@ -175,7 +175,8 @@ |
3854 | for word in words: |
3855 | if word in keywords: |
3856 | if filetype == 'qml': |
3857 | - signature = declaration.split('{')[0].strip() |
3858 | + separator = '{' if 'function' in declaration else ':' |
3859 | + signature = declaration.split(separator, 1)[0].strip() |
3860 | if 'alias' in line: |
3861 | no_mods = signature |
3862 | for mod in ['readonly', 'default']: |
3863 | @@ -198,7 +199,7 @@ |
3864 | break |
3865 | |
3866 | # Start of function/ signal/ Item block |
3867 | - if '{' in line: |
3868 | + if '{' in line and not '}' in line: |
3869 | in_block += 1 |
3870 | block_meta = {} |
3871 | # The parent type can affect API |
3872 | |
3873 | === modified file 'tests/resources/alarm/Alarms.qml' |
3874 | --- tests/resources/alarm/Alarms.qml 2014-04-23 08:50:20 +0000 |
3875 | +++ tests/resources/alarm/Alarms.qml 2014-05-28 18:09:57 +0000 |
3876 | @@ -113,7 +113,7 @@ |
3877 | id: days |
3878 | text: "Occurence" |
3879 | values: getValues() |
3880 | - visible: recurence.selectedIndex == 2 |
3881 | + visible: recurence.selectedIndex !== 1 |
3882 | onClicked: { |
3883 | PopupUtils.open(Qt.resolvedUrl("AlarmDays.qml"), days, {"alarm": alarm}); |
3884 | } |
3885 | |
3886 | === added file 'tests/resources/toolbar/header.qml' |
3887 | --- tests/resources/toolbar/header.qml 1970-01-01 00:00:00 +0000 |
3888 | +++ tests/resources/toolbar/header.qml 2014-05-28 18:09:57 +0000 |
3889 | @@ -0,0 +1,143 @@ |
3890 | +/* |
3891 | + * Copyright (C) 2013-2014 Canonical Ltd. |
3892 | + * |
3893 | + * This program is free software; you can redistribute it and/or modify |
3894 | + * it under the terms of the GNU Lesser General Public License as published by |
3895 | + * the Free Software Foundation; version 3. |
3896 | + * |
3897 | + * This program is distributed in the hope that it will be useful, |
3898 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3899 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3900 | + * GNU Lesser General Public License for more details. |
3901 | + * |
3902 | + * You should have received a copy of the GNU Lesser General Public License |
3903 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3904 | + */ |
3905 | + |
3906 | +import QtQuick 2.0 |
3907 | +import Ubuntu.Components 1.1 |
3908 | + |
3909 | +MainView { |
3910 | + id: mainView |
3911 | + width: units.gu(40) |
3912 | + height: units.gu(50) |
3913 | + |
3914 | + PageStack { |
3915 | + id: stack |
3916 | + |
3917 | + Component.onCompleted: stack.push(tabs) |
3918 | + Tabs { |
3919 | + id: tabs |
3920 | + Tab { |
3921 | + title: "Tab 1" |
3922 | + page: Page { |
3923 | + Button { |
3924 | + anchors.centerIn: parent |
3925 | + text: "Click me" |
3926 | + onTriggered: stack.push(pageOnStack) |
3927 | + } |
3928 | + tools: ToolbarItems { |
3929 | + ToolbarButton { |
3930 | + action: Action { |
3931 | + iconName: "settings" |
3932 | + text: "Settings" |
3933 | + } |
3934 | + } |
3935 | + } |
3936 | + } |
3937 | + } |
3938 | + Tab { |
3939 | + title: "Tab 2" |
3940 | + page: Page { |
3941 | + Label { |
3942 | + anchors.centerIn: parent |
3943 | + text: "Second tab" |
3944 | + } |
3945 | + |
3946 | + tools: ToolbarItems { |
3947 | + ToolbarButton { |
3948 | + action: Action { |
3949 | + iconName: "search" |
3950 | + text: "Search" |
3951 | + } |
3952 | + } |
3953 | + ToolbarButton { |
3954 | + action: Action { |
3955 | + iconName: "contact" |
3956 | + text: "Contacts" |
3957 | + } |
3958 | + } |
3959 | + ToolbarButton { |
3960 | + action: Action { |
3961 | + iconName: "share" |
3962 | + text: "Share" |
3963 | + } |
3964 | + } |
3965 | + ToolbarButton { |
3966 | + action: Action { |
3967 | + iconName: "select" |
3968 | + text: "Select" |
3969 | + } |
3970 | + } |
3971 | + } |
3972 | + } |
3973 | + } |
3974 | + Tab { |
3975 | + title: "Tab 3" |
3976 | + page: Page { |
3977 | + Switch { |
3978 | + id: newHeaderSwitch |
3979 | + anchors.centerIn: parent |
3980 | + checked: !mainView.useDeprecatedToolbar |
3981 | + onTriggered: { |
3982 | + mainView.useDeprecatedToolbar = !checked; |
3983 | + } |
3984 | + } |
3985 | + Label { |
3986 | + anchors { |
3987 | + horizontalCenter: parent.horizontalCenter |
3988 | + bottom: newHeaderSwitch.top |
3989 | + bottomMargin: units.gu(1) |
3990 | + } |
3991 | + text: "Use new header" |
3992 | + } |
3993 | + tools: ToolbarItems { |
3994 | + ToolbarButton { |
3995 | + action: Action { |
3996 | + iconName: "camera-flip" |
3997 | + text: "hello" |
3998 | + } |
3999 | + } |
4000 | + } |
4001 | + |
4002 | + } |
4003 | + } |
4004 | + Tab { |
4005 | + title: "Tab 4" |
4006 | + page: Page { } |
4007 | + } |
4008 | + Tab { |
4009 | + title: "Tab 5" |
4010 | + page: Page { } |
4011 | + } |
4012 | + } |
4013 | + } |
4014 | + |
4015 | + Page { |
4016 | + id: pageOnStack |
4017 | + visible: false |
4018 | + title: "Stacked page" |
4019 | + Label { |
4020 | + anchors.centerIn: parent |
4021 | + text: "Use back button to return" |
4022 | + } |
4023 | + tools: ToolbarItems { |
4024 | + ToolbarButton { |
4025 | + action: Action { |
4026 | + iconName: "search" |
4027 | + text: "Search" |
4028 | + } |
4029 | + } |
4030 | + } |
4031 | + } |
4032 | +} |
4033 | |
4034 | === modified file 'tests/unit/tst_alarms/tst_alarms.cpp' |
4035 | --- tests/unit/tst_alarms/tst_alarms.cpp 2014-04-10 09:53:26 +0000 |
4036 | +++ tests/unit/tst_alarms/tst_alarms.cpp 2014-05-28 18:09:57 +0000 |
4037 | @@ -354,6 +354,7 @@ |
4038 | waitForRequest(&alarm); |
4039 | QCOMPARE(alarm.error(), (int)UCAlarm::NoError); |
4040 | QVERIFY(containsAlarm(&alarm)); |
4041 | + QSKIP("https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1322558"); |
4042 | |
4043 | alarm.setDate(alarm.date().addDays(1)); |
4044 | alarm.save(); |
4045 | @@ -456,6 +457,51 @@ |
4046 | QVERIFY(srcDate.timeZone() != dstDate.timeZone()); |
4047 | } |
4048 | |
4049 | + void test_oneTime_dow_data() { |
4050 | + QTest::addColumn<QString>("message"); |
4051 | + QTest::addColumn<int>("dow"); |
4052 | + |
4053 | + QTest::newRow("Monday") << "Monday" << (int)UCAlarm::Monday; |
4054 | + QTest::newRow("Tuesday") << "Tuesday" << (int)UCAlarm::Tuesday; |
4055 | + QTest::newRow("Wednesday") << "Wednesday" << (int)UCAlarm::Wednesday; |
4056 | + QTest::newRow("Thursday") << "Thursday" << (int)UCAlarm::Thursday; |
4057 | + QTest::newRow("Friday") << "Friday" << (int)UCAlarm::Friday; |
4058 | + QTest::newRow("Saturday") << "Saturday" << (int)UCAlarm::Saturday; |
4059 | + QTest::newRow("Sunday") << "Sunday" << (int)UCAlarm::Sunday; |
4060 | + } |
4061 | + void test_oneTime_dow() { |
4062 | + QFETCH(QString, message); |
4063 | + QFETCH(int, dow); |
4064 | + |
4065 | + UCAlarm alarm(QDateTime::currentDateTime().addSecs(3600), "test_oneTime_dow_" + message); |
4066 | + alarm.setDaysOfWeek((UCAlarm::DaysOfWeek)dow); |
4067 | + alarm.save(); |
4068 | + waitForRequest(&alarm); |
4069 | + QCOMPARE(alarm.error(), (int)UCAlarm::NoError); |
4070 | + QVERIFY(containsAlarm(&alarm)); |
4071 | + } |
4072 | + |
4073 | + void test_oneTime_setDate_does_not_change_dow_data() { |
4074 | + QTest::addColumn<QString>("message"); |
4075 | + QTest::addColumn<int>("dow"); |
4076 | + |
4077 | + QTest::newRow("Monday") << "Monday" << (int)UCAlarm::Monday; |
4078 | + QTest::newRow("Tuesday") << "Tuesday" << (int)UCAlarm::Tuesday; |
4079 | + QTest::newRow("Wednesday") << "Wednesday" << (int)UCAlarm::Wednesday; |
4080 | + QTest::newRow("Thursday") << "Thursday" << (int)UCAlarm::Thursday; |
4081 | + QTest::newRow("Friday") << "Friday" << (int)UCAlarm::Friday; |
4082 | + QTest::newRow("Saturday") << "Saturday" << (int)UCAlarm::Saturday; |
4083 | + QTest::newRow("Sunday") << "Sunday" << (int)UCAlarm::Sunday; |
4084 | + } |
4085 | + void test_oneTime_setDate_does_not_change_dow() { |
4086 | + QFETCH(QString, message); |
4087 | + QFETCH(int, dow); |
4088 | + |
4089 | + UCAlarm alarm(QDateTime::currentDateTime(), "test_oneTime_setDate_does_not_change_dow_" + message); |
4090 | + alarm.setDaysOfWeek((UCAlarm::DaysOfWeek)dow); |
4091 | + alarm.setDate(QDateTime::currentDateTime().addSecs(3600)); |
4092 | + QCOMPARE((int)alarm.daysOfWeek(), dow); |
4093 | + } |
4094 | }; |
4095 | |
4096 | QTEST_MAIN(tst_UCAlarms) |
4097 | |
4098 | === modified file 'tests/unit/tst_components/tst_label.qml' |
4099 | --- tests/unit/tst_components/tst_label.qml 2014-04-23 08:50:20 +0000 |
4100 | +++ tests/unit/tst_components/tst_label.qml 2014-05-28 18:09:57 +0000 |
4101 | @@ -44,7 +44,7 @@ |
4102 | } |
4103 | |
4104 | function test_fontWeight() { |
4105 | - compare(textCustom.font.weight, Font.Normal, "font.weight is 'normal' by default") |
4106 | + compare(textCustom.font.weight, Font.Light, "font.weight is 'light' by default") |
4107 | |
4108 | var fontWeights = [ Font.Light, Font.Normal, Font.DemiBold, Font.Bold, Font.Black ] |
4109 | |
4110 | |
4111 | === added file 'tests/unit/tst_components/tst_sortfiltermodel.qml' |
4112 | --- tests/unit/tst_components/tst_sortfiltermodel.qml 1970-01-01 00:00:00 +0000 |
4113 | +++ tests/unit/tst_components/tst_sortfiltermodel.qml 2014-05-28 18:09:57 +0000 |
4114 | @@ -0,0 +1,123 @@ |
4115 | +/* |
4116 | + * Copyright 2014 Canonical Ltd. |
4117 | + * |
4118 | + * This program is free software; you can redistribute it and/or modify |
4119 | + * it under the terms of the GNU Lesser General Public License as published by |
4120 | + * the Free Software Foundation; version 3. |
4121 | + * |
4122 | + * This program is distributed in the hope that it will be useful, |
4123 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4124 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4125 | + * GNU Lesser General Public License for more details. |
4126 | + * |
4127 | + * You should have received a copy of the GNU Lesser General Public License |
4128 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4129 | + */ |
4130 | + |
4131 | +import QtQuick 2.0 |
4132 | +import QtTest 1.0 |
4133 | +import Ubuntu.Components 1.1 |
4134 | + |
4135 | +TestCase { |
4136 | + name: "SortFilterModel" |
4137 | + |
4138 | + ListModel { |
4139 | + id: things |
4140 | + ListElement { foo: "pub"; alpha: "bee"; num: 200 } |
4141 | + ListElement { foo: "den"; alpha: "cow"; num: 300 } |
4142 | + ListElement { foo: "bar"; alpha: "ant"; num: 100 } |
4143 | + } |
4144 | + |
4145 | + SortFilterModel { |
4146 | + id: unmodified |
4147 | + model: things |
4148 | + } |
4149 | + |
4150 | + SortFilterModel { |
4151 | + id: alphabetic |
4152 | + model: things |
4153 | + sort.property: "alpha" |
4154 | + } |
4155 | + |
4156 | + SortFilterModel { |
4157 | + id: alphaSecond |
4158 | + model: things |
4159 | + sort.property: "foo" |
4160 | + } |
4161 | + |
4162 | + SortFilterModel { |
4163 | + id: alphabeticRe |
4164 | + model: things |
4165 | + sort.property: "alpha" |
4166 | + sort.order: Qt.DescendingOrder |
4167 | + } |
4168 | + |
4169 | + SortFilterModel { |
4170 | + id: numeric |
4171 | + model: things |
4172 | + sort.property: "num" |
4173 | + } |
4174 | + |
4175 | + SortFilterModel { |
4176 | + id: numericRe |
4177 | + model: things |
4178 | + sort.property: "num" |
4179 | + sort.order: Qt.DescendingOrder |
4180 | + } |
4181 | + |
4182 | + SortFilterModel { |
4183 | + id: bee |
4184 | + model: things |
4185 | + filter.property: "alpha" |
4186 | + filter.pattern: /e/ |
4187 | + } |
4188 | + |
4189 | + function test_passthrough() { |
4190 | + compare(unmodified.count, things.count) |
4191 | + } |
4192 | + |
4193 | + function test_sort() { |
4194 | + // Default is Ascending |
4195 | + compare(alphabetic.sort.order, Qt.AscendingOrder) |
4196 | + compare(alphabetic.get(0).alpha, "ant") |
4197 | + compare(alphabetic.get(1).alpha, "bee") |
4198 | + compare(alphabetic.get(2).alpha, "cow") |
4199 | + |
4200 | + // Ensure different columns work also |
4201 | + compare(alphaSecond.get(0).foo, "bar") |
4202 | + |
4203 | + // Descending |
4204 | + compare(alphabeticRe.sort.order, Qt.DescendingOrder) |
4205 | + compare(alphabeticRe.get(0).alpha, "cow") |
4206 | + compare(alphabeticRe.get(1).alpha, "bee") |
4207 | + compare(alphabeticRe.get(2).alpha, "ant") |
4208 | + |
4209 | + // Numbers |
4210 | + compare(numeric.get(0).num, 100) |
4211 | + compare(numericRe.get(0).num, 300) |
4212 | + |
4213 | + // Changing roles |
4214 | + alphabetic.sort.property = "foo" |
4215 | + compare(alphabetic.get(0).foo, "bar") |
4216 | + compare(alphabetic.get(1).foo, "den") |
4217 | + compare(alphabetic.get(2).foo, "pub") |
4218 | + // Sanity check |
4219 | + compare(alphabetic.get(1).alpha, "cow") |
4220 | + // change again |
4221 | + alphabetic.sort.property = "num" |
4222 | + compare(alphabetic.get(0).num, 100) |
4223 | + compare(alphabetic.get(1).num, 200) |
4224 | + compare(alphabetic.get(2).num, 300) |
4225 | + // Sanity check |
4226 | + compare(alphabetic.get(2).alpha, "cow") |
4227 | + } |
4228 | + |
4229 | + function test_filter() { |
4230 | + // Default is an empty pattern |
4231 | + compare(unmodified.filter.pattern, RegExp()) |
4232 | + |
4233 | + // Filter |
4234 | + compare(bee.count, 1) |
4235 | + compare(bee.get(0).alpha, "bee") |
4236 | + } |
4237 | +} |
4238 | |
4239 | === modified file 'tests/unit/tst_components/tst_toolbaritems.qml' |
4240 | --- tests/unit/tst_components/tst_toolbaritems.qml 2014-04-23 08:50:20 +0000 |
4241 | +++ tests/unit/tst_components/tst_toolbaritems.qml 2014-05-28 18:09:57 +0000 |
4242 | @@ -23,6 +23,7 @@ |
4243 | height: 200 |
4244 | |
4245 | MainView { |
4246 | + id: mainView |
4247 | anchors.fill: parent |
4248 | PageStack { |
4249 | id: pageStack0 |
4250 | @@ -37,7 +38,8 @@ |
4251 | |
4252 | Page { |
4253 | id: page1 |
4254 | - tools: ToolbarItems { |
4255 | + tools: toolbarItems |
4256 | + ToolbarItems { |
4257 | id: toolbarItems |
4258 | ToolbarButton { |
4259 | id: button |
4260 | @@ -94,5 +96,12 @@ |
4261 | pageStack0.pop(); |
4262 | compare(pageStack0.depth, 0, "pageStack is empty after popping both pages"); |
4263 | } |
4264 | + |
4265 | + function test_visible() { |
4266 | + compare(toolbarItems.visible, true, "Toolbar items are visible when in toolbar"); |
4267 | + mainView.useDeprecatedToolbar = false; |
4268 | + compare(toolbarItems.visible, false, "Toolbar items are invisible when not using deprecated toolbar"); |
4269 | + mainView.useDeprecatedToolbar = true; |
4270 | + } |
4271 | } |
4272 | } |
4273 | |
4274 | === removed directory 'tests/unit/tst_i18n/appropriate/localizedApp' |
4275 | === renamed directory 'tests/unit/tst_i18n/appropriate' => 'tests/unit/tst_i18n/localizedApp' |
4276 | === added directory 'tests/unit/tst_i18n/localizedApp/.click' |
4277 | === added file 'tests/unit/tst_i18n/localizedApp/.click/status' |
4278 | --- tests/unit/tst_i18n/localizedApp/.click/status 1970-01-01 00:00:00 +0000 |
4279 | +++ tests/unit/tst_i18n/localizedApp/.click/status 2014-05-28 18:09:57 +0000 |
4280 | @@ -0,0 +1,1 @@ |
4281 | +Package: localizedApp |
4282 | |
4283 | === added directory 'tests/unit/tst_i18n/localizedApp/share' |
4284 | === renamed directory 'tests/unit/tst_i18n/appropriate/locale' => 'tests/unit/tst_i18n/localizedApp/share/locale' |
4285 | === modified file 'tests/unit/tst_i18n/src/tst_i18n.cpp' |
4286 | --- tests/unit/tst_i18n/src/tst_i18n.cpp 2013-12-13 15:37:31 +0000 |
4287 | +++ tests/unit/tst_i18n/src/tst_i18n.cpp 2014-05-28 18:09:57 +0000 |
4288 | @@ -76,19 +76,11 @@ |
4289 | { |
4290 | // Set test locale folder in the environment |
4291 | // Using setenv because QProcessEnvironment ignores changes |
4292 | - QString wrongDataFolder(QCoreApplication::applicationDirPath() + "/diversion"); |
4293 | - QString testDataFolder(QCoreApplication::applicationDirPath() + "/appropriate"); |
4294 | - setenv("XDG_DATA_DIRS", (wrongDataFolder + ":" + testDataFolder).toUtf8(), 1); |
4295 | + QString testAppDir(QCoreApplication::applicationDirPath() + "/localizedApp"); |
4296 | + setenv("APP_DIR", testAppDir.toUtf8(), 1); |
4297 | |
4298 | // Verify that we set it correctly |
4299 | - QString dataPath(QStandardPaths::locate(QStandardPaths::GenericDataLocation, |
4300 | - "localizedApp", QStandardPaths::LocateDirectory)); |
4301 | - QDir dataDir(dataPath); |
4302 | - QVERIFY(dataDir.cdUp()); |
4303 | - QVERIFY(dataDir.cd("locale")); |
4304 | - QString doubleCheckLocalePath(dataDir.path()); |
4305 | - QCOMPARE(doubleCheckLocalePath, testDataFolder + "/locale"); |
4306 | - QVERIFY(QFileInfo(testDataFolder + "/locale/en/LC_MESSAGES/localizedApp.mo").exists()); |
4307 | + QVERIFY(QFileInfo(testAppDir + "/share/locale/en/LC_MESSAGES/localizedApp.mo").exists()); |
4308 | |
4309 | QString modules("../../../modules"); |
4310 | QVERIFY(QDir(modules).exists()); |
4311 | @@ -128,12 +120,8 @@ |
4312 | |
4313 | // Was the locale folder detected and set? |
4314 | QString boundDomain(C::bindtextdomain(i18n->domain().toUtf8(), ((const char*)0))); |
4315 | - QString dataPath(QStandardPaths::locate(QStandardPaths::GenericDataLocation, |
4316 | - i18n->domain(), QStandardPaths::LocateDirectory)); |
4317 | - QDir dataDir(dataPath); |
4318 | - QVERIFY(dataDir.cdUp()); |
4319 | - QVERIFY(dataDir.cd("locale")); |
4320 | - QString expectedLocalePath(dataDir.path()); |
4321 | + QString testAppDir(QCoreApplication::applicationDirPath() + "/localizedApp"); |
4322 | + QString expectedLocalePath(QDir(testAppDir).filePath("share/locale")); |
4323 | QCOMPARE(boundDomain, expectedLocalePath); |
4324 | // Is the domain gettext uses correct? |
4325 | QString gettextDomain(C::textdomain(((const char*)0))); |
4326 | |
4327 | === modified file 'tests/unit/tst_i18n/tst_i18n.pro' |
4328 | --- tests/unit/tst_i18n/tst_i18n.pro 2013-12-13 15:37:31 +0000 |
4329 | +++ tests/unit/tst_i18n/tst_i18n.pro 2014-05-28 18:09:57 +0000 |
4330 | @@ -2,7 +2,7 @@ |
4331 | QT += gui |
4332 | DEFINES += SRCDIR=\\\"$$PWD/\\\" |
4333 | |
4334 | -system(msgfmt po/en_US.po -o appropriate/locale/en/LC_MESSAGES/localizedApp.mo) |
4335 | +system(msgfmt po/en_US.po -o localizedApp/share/locale/en/LC_MESSAGES/localizedApp.mo) |
4336 | |
4337 | SOURCES += \ |
4338 | src\/tst_i18n.cpp |
4339 | |
4340 | === modified file 'tests/unit_x11/tst_components/tst_datepicker.qml' |
4341 | --- tests/unit_x11/tst_components/tst_datepicker.qml 2014-05-05 17:45:45 +0000 |
4342 | +++ tests/unit_x11/tst_components/tst_datepicker.qml 2014-05-28 18:09:57 +0000 |
4343 | @@ -59,7 +59,7 @@ |
4344 | function getPickerLabel(picker, name) { |
4345 | var pickerItem = findChild(picker, name); |
4346 | var pickerCurrent = findChild(pickerItem, "Picker_ViewLoader"); |
4347 | - return findChild(pickerCurrent.item.currentItem, "PickerRow_PickerLabel"); |
4348 | + return pickerCurrent.item.currentItem.children[2]; |
4349 | } |
4350 | function getPickerModel(picker, name) { |
4351 | var pickerItem = findInvisibleChild(picker, name); |
4352 | |
4353 | === added file 'tests/unit_x11/tst_layouts/NestedVisibility.qml' |
4354 | --- tests/unit_x11/tst_layouts/NestedVisibility.qml 1970-01-01 00:00:00 +0000 |
4355 | +++ tests/unit_x11/tst_layouts/NestedVisibility.qml 2014-05-28 18:09:57 +0000 |
4356 | @@ -0,0 +1,163 @@ |
4357 | +/* |
4358 | + * Copyright 2014 Canonical Ltd. |
4359 | + * |
4360 | + * This program is free software; you can redistribute it and/or modify |
4361 | + * it under the terms of the GNU Lesser General Public License as published by |
4362 | + * the Free Software Foundation; version 3. |
4363 | + * |
4364 | + * This program is distributed in the hope that it will be useful, |
4365 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4366 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4367 | + * GNU Lesser General Public License for more details. |
4368 | + * |
4369 | + * You should have received a copy of the GNU Lesser General Public License |
4370 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4371 | + */ |
4372 | + |
4373 | +import QtQuick 2.0 |
4374 | +import Ubuntu.Components 1.1 |
4375 | +import Ubuntu.Layouts 1.0 |
4376 | + |
4377 | +MainView { |
4378 | + id: main |
4379 | + objectName: "mainView" |
4380 | + applicationName: "test-app" |
4381 | + |
4382 | + /* |
4383 | + This property enables the application to change orientation |
4384 | + when the device is rotated. The default is false. |
4385 | + */ |
4386 | + automaticOrientation: true // TODO: support wide aspect ratios, esp. on prepareGamePage |
4387 | + |
4388 | + width: units.gu(40) |
4389 | + height: units.gu(75) |
4390 | + |
4391 | + function phoneLayout() { |
4392 | + width = units.gu(50); |
4393 | + } |
4394 | + function tabletPortraitLayout() { |
4395 | + width = units.gu(70); |
4396 | + } |
4397 | + function tabletLandscapeLayout() { |
4398 | + width = units.gu(100); |
4399 | + } |
4400 | + |
4401 | + PageStack { |
4402 | + Component.onCompleted: push(testPage) |
4403 | + |
4404 | + Page { |
4405 | + title: i18n.tr("Conditional Layouts with PageStack") |
4406 | + id: testPage |
4407 | + visible: false |
4408 | + |
4409 | + Layouts { |
4410 | + id: layouts |
4411 | + objectName: "mainLayout" |
4412 | + width: parent.width |
4413 | + height: parent.height |
4414 | + layouts: [ |
4415 | + ConditionalLayout { |
4416 | + name: "tabletPortrait" |
4417 | + when: main.width > units.gu(50) |
4418 | + Layouts { |
4419 | + anchors.fill: parent |
4420 | + objectName: "nestedLayout" |
4421 | + layouts: [ |
4422 | + ConditionalLayout { |
4423 | + name: "tabletLandscape" |
4424 | + when: main.width > units.gu(70) |
4425 | + Row { |
4426 | + objectName: "tabletLandscape" |
4427 | + anchors.fill: parent |
4428 | + Rectangle { |
4429 | + height: parent.height |
4430 | + color: "white" |
4431 | + width: parent.width / 5 |
4432 | + } |
4433 | + Flow { |
4434 | + spacing: units.gu(2) |
4435 | + ItemLayout { |
4436 | + objectName: "nestedMagentaContainer" |
4437 | + item: "mainMagenta" |
4438 | + width: units.gu(20) |
4439 | + height: width |
4440 | + } |
4441 | + ItemLayout { |
4442 | + objectName: "nestedGreenContainer" |
4443 | + item: "mainGreen" |
4444 | + width: units.gu(60) |
4445 | + height: width |
4446 | + } |
4447 | + } |
4448 | + } |
4449 | + } |
4450 | + ] |
4451 | + // Default layout, but can have ItemLayouts |
4452 | + // as those will belong to the previous Layouts |
4453 | + // and attaching Layouts.item we can layout it further |
4454 | + Flow { |
4455 | + objectName: "tabletPortrait" |
4456 | + anchors.fill: parent |
4457 | + ItemLayout { |
4458 | + objectName: "greenContainer" |
4459 | + item: "mainGreen" |
4460 | + width: units.gu(40) |
4461 | + height: width |
4462 | + Layouts.item: item |
4463 | + } |
4464 | + ItemLayout { |
4465 | + objectName: "magentaContainer" |
4466 | + item: "mainMagenta" |
4467 | + width: units.gu(60) |
4468 | + height: width |
4469 | + Layouts.item: item |
4470 | + } |
4471 | + } |
4472 | + } |
4473 | + } |
4474 | + ] |
4475 | + |
4476 | + // default layout for mainLayout |
4477 | + Flow { |
4478 | + objectName: "mainDefaultLayout" |
4479 | + anchors.fill: parent |
4480 | + Rectangle { |
4481 | + objectName: "mainRed" |
4482 | + width: units.gu(15) |
4483 | + height: width |
4484 | + color: "red" |
4485 | + Layouts.item: "mainRed" |
4486 | + } |
4487 | + Rectangle { |
4488 | + objectName: "mainGreen" |
4489 | + width: units.gu(15) |
4490 | + height: width |
4491 | + color: "green" |
4492 | + Layouts.item: "mainGreen" |
4493 | + } |
4494 | + Rectangle { |
4495 | + objectName: "mainBlue" |
4496 | + width: units.gu(15) |
4497 | + height: width |
4498 | + color: "blue" |
4499 | + Layouts.item: "mainBlue" |
4500 | + } |
4501 | + Rectangle { |
4502 | + objectName: "mainMagenta" |
4503 | + width: units.gu(15) |
4504 | + height: width |
4505 | + color: "magenta" |
4506 | + Layouts.item: "mainMagenta" |
4507 | + } |
4508 | + Rectangle { |
4509 | + objectName: "mainHidden" |
4510 | + width: units.gu(15) |
4511 | + height: width |
4512 | + color: "yellow" |
4513 | + visible: false |
4514 | + } |
4515 | + } |
4516 | + } |
4517 | + } |
4518 | + } |
4519 | +} |
4520 | |
4521 | === added file 'tests/unit_x11/tst_layouts/Visibility.qml' |
4522 | --- tests/unit_x11/tst_layouts/Visibility.qml 1970-01-01 00:00:00 +0000 |
4523 | +++ tests/unit_x11/tst_layouts/Visibility.qml 2014-05-28 18:09:57 +0000 |
4524 | @@ -0,0 +1,84 @@ |
4525 | +/* |
4526 | + * Copyright 2014 Canonical Ltd. |
4527 | + * |
4528 | + * This program is free software; you can redistribute it and/or modify |
4529 | + * it under the terms of the GNU Lesser General Public License as published by |
4530 | + * the Free Software Foundation; version 3. |
4531 | + * |
4532 | + * This program is distributed in the hope that it will be useful, |
4533 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4534 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4535 | + * GNU Lesser General Public License for more details. |
4536 | + * |
4537 | + * You should have received a copy of the GNU Lesser General Public License |
4538 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4539 | + */ |
4540 | + |
4541 | +import QtQuick 2.0 |
4542 | +import Ubuntu.Components 1.1 |
4543 | +import Ubuntu.Layouts 1.0 |
4544 | + |
4545 | +MainView { |
4546 | + id: main |
4547 | + objectName: "mainView" |
4548 | + applicationName: "test-app" |
4549 | + |
4550 | + /* |
4551 | + This property enables the application to change orientation |
4552 | + when the device is rotated. The default is false. |
4553 | + */ |
4554 | + automaticOrientation: true // TODO: support wide aspect ratios, esp. on prepareGamePage |
4555 | + |
4556 | + property bool boundValue: true |
4557 | + |
4558 | + width: units.gu(100) |
4559 | + height: units.gu(75) |
4560 | + |
4561 | + function portraitLayout() { |
4562 | + width = units.gu(50); |
4563 | + } |
4564 | + function landscapeLayout() { |
4565 | + width = units.gu(100); |
4566 | + } |
4567 | + |
4568 | + PageStack { |
4569 | + Component.onCompleted: push(testPage) |
4570 | + |
4571 | + Page { |
4572 | + title: i18n.tr("Conditional Layouts with PageStack") |
4573 | + id: testPage |
4574 | + visible: false |
4575 | + |
4576 | + Layouts { |
4577 | + id: layouts |
4578 | + objectName: "layoutManager" |
4579 | + width: parent.width |
4580 | + height: parent.height |
4581 | + layouts: [ |
4582 | + ConditionalLayout { |
4583 | + name: "wide" |
4584 | + when: layouts.width < units.gu(60) |
4585 | + UbuntuShape { |
4586 | + width: units.gu(20) |
4587 | + height: units.gu(20) |
4588 | + color: "red" |
4589 | + Label { text: "wide" } |
4590 | + } |
4591 | + } |
4592 | + ] |
4593 | + |
4594 | + // This is a default layout. |
4595 | + // When using a PageStack and layouts is not empty, it won't display or switch to the default layout. |
4596 | + // However it only works when putting it into the layouts list with an inversed condition. |
4597 | + UbuntuShape { |
4598 | + objectName: "DefaultLayout" |
4599 | + width: units.gu(20) |
4600 | + height: units.gu(20) |
4601 | + color: "green" |
4602 | + visible: main.boundValue |
4603 | + Label { text: "default" } |
4604 | + } |
4605 | + } |
4606 | + } |
4607 | + } |
4608 | +} |
4609 | |
4610 | === modified file 'tests/unit_x11/tst_layouts/tst_layouts.cpp' |
4611 | --- tests/unit_x11/tst_layouts/tst_layouts.cpp 2014-03-19 12:48:33 +0000 |
4612 | +++ tests/unit_x11/tst_layouts/tst_layouts.cpp 2014-05-28 18:09:57 +0000 |
4613 | @@ -72,6 +72,25 @@ |
4614 | return (children.count() > 0) ? children[0] : 0; |
4615 | } |
4616 | |
4617 | + bool hasChildItem(QQuickItem *child, QQuickItem *parent) |
4618 | + { |
4619 | + QQuickItem *pl = child->parentItem(); |
4620 | + while (pl) { |
4621 | + if (pl == parent) { |
4622 | + return true; |
4623 | + } |
4624 | + pl = pl->parentItem(); |
4625 | + } |
4626 | + return false; |
4627 | + } |
4628 | + |
4629 | + QQuickItem *prevSibling(QQuickItem *item) |
4630 | + { |
4631 | + QList<QQuickItem*> children = item->parentItem()->childItems(); |
4632 | + int index = children.indexOf(item); |
4633 | + return (index > 0) ? children.at(index - 1) : 0; |
4634 | + } |
4635 | + |
4636 | |
4637 | private Q_SLOTS: |
4638 | void initTestCase() |
4639 | @@ -419,16 +438,16 @@ |
4640 | |
4641 | void testCase_AnchorFilledReparenting() |
4642 | { |
4643 | - QScopedPointer<QQuickView> view(loadTest("AnchorFilledReparenting.qml")); |
4644 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorFilledReparenting.qml")); |
4645 | QVERIFY(view); |
4646 | QQuickItem *root = view->rootObject(); |
4647 | QVERIFY(root); |
4648 | |
4649 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4650 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4651 | QVERIFY(layout); |
4652 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4653 | |
4654 | - QQuickItem *item = testItem(root, "testItem"); |
4655 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4656 | QVERIFY(item); |
4657 | |
4658 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4659 | @@ -436,27 +455,27 @@ |
4660 | |
4661 | root->setWidth(root->width() + 100); |
4662 | layoutChangeSpy.wait(100); |
4663 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4664 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4665 | QVERIFY(testLayout); |
4666 | QCOMPARE(anchors->fill(), testLayout); |
4667 | |
4668 | root->setWidth(root->width() - 100); |
4669 | layoutChangeSpy.wait(100); |
4670 | - QCOMPARE(anchors->fill(), layout); |
4671 | + QCOMPARE(anchors->fill(), layout->contentItem()); |
4672 | } |
4673 | |
4674 | void testCase_AnchorFilledMargins() |
4675 | { |
4676 | - QScopedPointer<QQuickView> view(loadTest("AnchorFilledMargins.qml")); |
4677 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorFilledMargins.qml")); |
4678 | QVERIFY(view); |
4679 | QQuickItem *root = view->rootObject(); |
4680 | QVERIFY(root); |
4681 | |
4682 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4683 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4684 | QVERIFY(layout); |
4685 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4686 | |
4687 | - QQuickItem *item = testItem(root, "testItem"); |
4688 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4689 | QVERIFY(item); |
4690 | |
4691 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4692 | @@ -465,29 +484,29 @@ |
4693 | root->setWidth(root->width() + 100); |
4694 | layoutChangeSpy.wait(100); |
4695 | |
4696 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4697 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4698 | QVERIFY(testLayout); |
4699 | QCOMPARE(anchors->fill(), testLayout); |
4700 | QCOMPARE(anchors->margins(), 0.0); |
4701 | |
4702 | root->setWidth(root->width() - 100); |
4703 | layoutChangeSpy.wait(100); |
4704 | - QCOMPARE(anchors->fill(), layout); |
4705 | + QCOMPARE(anchors->fill(), layout->contentItem()); |
4706 | QCOMPARE(anchors->margins(), 10.0); |
4707 | } |
4708 | |
4709 | void testCase_AnchorFilledSeparateMargins() |
4710 | { |
4711 | - QScopedPointer<QQuickView> view(loadTest("AnchorFilledSeparateMargins.qml")); |
4712 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorFilledSeparateMargins.qml")); |
4713 | QVERIFY(view); |
4714 | QQuickItem *root = view->rootObject(); |
4715 | QVERIFY(root); |
4716 | |
4717 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4718 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4719 | QVERIFY(layout); |
4720 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4721 | |
4722 | - QQuickItem *item = testItem(root, "testItem"); |
4723 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4724 | QVERIFY(item); |
4725 | |
4726 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4727 | @@ -496,7 +515,7 @@ |
4728 | root->setWidth(root->width() + 100); |
4729 | layoutChangeSpy.wait(100); |
4730 | |
4731 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4732 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4733 | QVERIFY(testLayout); |
4734 | QCOMPARE(anchors->fill(), testLayout); |
4735 | QCOMPARE(anchors->margins(), 0.0); |
4736 | @@ -507,7 +526,7 @@ |
4737 | |
4738 | root->setWidth(root->width() - 100); |
4739 | layoutChangeSpy.wait(100); |
4740 | - QCOMPARE(anchors->fill(), layout); |
4741 | + QCOMPARE(anchors->fill(), layout->contentItem()); |
4742 | QCOMPARE(anchors->leftMargin(), 10.0); |
4743 | QCOMPARE(anchors->topMargin(), 20.0); |
4744 | QCOMPARE(anchors->rightMargin(), 30.0); |
4745 | @@ -516,16 +535,16 @@ |
4746 | |
4747 | void testCase_AnchorCenteredInDefault() |
4748 | { |
4749 | - QScopedPointer<QQuickView> view(loadTest("AnchorCenteredInDefault.qml")); |
4750 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorCenteredInDefault.qml")); |
4751 | QVERIFY(view); |
4752 | QQuickItem *root = view->rootObject(); |
4753 | QVERIFY(root); |
4754 | |
4755 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4756 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4757 | QVERIFY(layout); |
4758 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4759 | |
4760 | - QQuickItem *item = testItem(root, "testItem"); |
4761 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4762 | QVERIFY(item); |
4763 | |
4764 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4765 | @@ -533,335 +552,335 @@ |
4766 | |
4767 | root->setWidth(root->width() + 100); |
4768 | layoutChangeSpy.wait(100); |
4769 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4770 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4771 | QVERIFY(testLayout); |
4772 | QCOMPARE(anchors->fill(), testLayout); |
4773 | |
4774 | root->setWidth(root->width() - 100); |
4775 | layoutChangeSpy.wait(100); |
4776 | - QCOMPARE(anchors->centerIn(), layout); |
4777 | + QCOMPARE(anchors->centerIn(), layout->contentItem()); |
4778 | } |
4779 | |
4780 | void testCase_AnchorVerticalCenter() |
4781 | { |
4782 | - QScopedPointer<QQuickView> view(loadTest("AnchorVerticalCenter.qml")); |
4783 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorVerticalCenter.qml")); |
4784 | QVERIFY(view); |
4785 | QQuickItem *root = view->rootObject(); |
4786 | QVERIFY(root); |
4787 | |
4788 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4789 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4790 | QVERIFY(layout); |
4791 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4792 | |
4793 | - QQuickItem *item = testItem(root, "testItem"); |
4794 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4795 | QVERIFY(item); |
4796 | |
4797 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4798 | QVERIFY(anchors); |
4799 | |
4800 | - QCOMPARE(anchors->verticalCenter().item, layout); |
4801 | + QCOMPARE(anchors->verticalCenter().item, layout->contentItem()); |
4802 | |
4803 | root->setWidth(root->width() + 100); |
4804 | layoutChangeSpy.wait(100); |
4805 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4806 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4807 | QVERIFY(testLayout); |
4808 | QCOMPARE(anchors->fill(), testLayout); |
4809 | |
4810 | root->setWidth(root->width() - 100); |
4811 | layoutChangeSpy.wait(100); |
4812 | - QCOMPARE(anchors->verticalCenter().item, layout); |
4813 | + QCOMPARE(anchors->verticalCenter().item, layout->contentItem()); |
4814 | } |
4815 | |
4816 | void testCase_AnchorVerticalCenterOffset() |
4817 | { |
4818 | - QScopedPointer<QQuickView> view(loadTest("AnchorVerticalCenterOffset.qml")); |
4819 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorVerticalCenterOffset.qml")); |
4820 | QVERIFY(view); |
4821 | QQuickItem *root = view->rootObject(); |
4822 | QVERIFY(root); |
4823 | |
4824 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4825 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4826 | QVERIFY(layout); |
4827 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4828 | |
4829 | - QQuickItem *item = testItem(root, "testItem"); |
4830 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4831 | QVERIFY(item); |
4832 | |
4833 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4834 | QVERIFY(anchors); |
4835 | |
4836 | - QCOMPARE(anchors->verticalCenter().item, layout); |
4837 | + QCOMPARE(anchors->verticalCenter().item, layout->contentItem()); |
4838 | QCOMPARE(anchors->verticalCenterOffset(), 50.0); |
4839 | |
4840 | root->setWidth(root->width() + 100); |
4841 | layoutChangeSpy.wait(100); |
4842 | - QQuickItem *testLayout = qobject_cast<QQuickItem*>(testItem(root, "testLayout")); |
4843 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4844 | QVERIFY(testLayout); |
4845 | QCOMPARE(anchors->fill(), testLayout); |
4846 | // no need to check offset as it does not affect the fill |
4847 | |
4848 | root->setWidth(root->width() - 100); |
4849 | layoutChangeSpy.wait(100); |
4850 | - QCOMPARE(anchors->verticalCenter().item, layout); |
4851 | + QCOMPARE(anchors->verticalCenter().item, layout->contentItem()); |
4852 | QCOMPARE(anchors->verticalCenterOffset(), 50.0); |
4853 | } |
4854 | |
4855 | void testCase_AnchorHorizontalCenter() |
4856 | { |
4857 | - QScopedPointer<QQuickView> view(loadTest("AnchorHorizontalCenter.qml")); |
4858 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorHorizontalCenter.qml")); |
4859 | QVERIFY(view); |
4860 | QQuickItem *root = view->rootObject(); |
4861 | QVERIFY(root); |
4862 | |
4863 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4864 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4865 | QVERIFY(layout); |
4866 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4867 | |
4868 | - QQuickItem *item = testItem(root, "testItem"); |
4869 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4870 | QVERIFY(item); |
4871 | |
4872 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4873 | QVERIFY(anchors); |
4874 | |
4875 | - QCOMPARE(anchors->horizontalCenter().item, layout); |
4876 | + QCOMPARE(anchors->horizontalCenter().item, layout->contentItem()); |
4877 | |
4878 | root->setWidth(root->width() + 100); |
4879 | layoutChangeSpy.wait(100); |
4880 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4881 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4882 | QVERIFY(testLayout); |
4883 | QCOMPARE(anchors->fill(), testLayout); |
4884 | |
4885 | root->setWidth(root->width() - 100); |
4886 | layoutChangeSpy.wait(100); |
4887 | - QCOMPARE(anchors->horizontalCenter().item, layout); |
4888 | + QCOMPARE(anchors->horizontalCenter().item, layout->contentItem()); |
4889 | } |
4890 | |
4891 | void testCase_AnchorHorizontalCenterOffset() |
4892 | { |
4893 | - QScopedPointer<QQuickView> view(loadTest("AnchorHorizontalCenterOffset.qml")); |
4894 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorHorizontalCenterOffset.qml")); |
4895 | QVERIFY(view); |
4896 | QQuickItem *root = view->rootObject(); |
4897 | QVERIFY(root); |
4898 | |
4899 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4900 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4901 | QVERIFY(layout); |
4902 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4903 | |
4904 | - QQuickItem *item = testItem(root, "testItem"); |
4905 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4906 | QVERIFY(item); |
4907 | |
4908 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4909 | QVERIFY(anchors); |
4910 | |
4911 | - QCOMPARE(anchors->horizontalCenter().item, layout); |
4912 | + QCOMPARE(anchors->horizontalCenter().item, layout->contentItem()); |
4913 | QCOMPARE(anchors->horizontalCenterOffset(), 50.0); |
4914 | |
4915 | root->setWidth(root->width() + 100); |
4916 | layoutChangeSpy.wait(100); |
4917 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4918 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4919 | QVERIFY(testLayout); |
4920 | QCOMPARE(anchors->fill(), testLayout); |
4921 | // no need to check offset as it does not affect the fill |
4922 | |
4923 | root->setWidth(root->width() - 100); |
4924 | layoutChangeSpy.wait(100); |
4925 | - QCOMPARE(anchors->horizontalCenter().item, layout); |
4926 | + QCOMPARE(anchors->horizontalCenter().item, layout->contentItem()); |
4927 | QCOMPARE(anchors->horizontalCenterOffset(), 50.0); |
4928 | } |
4929 | |
4930 | void testCase_AnchorCenterWithOffset() |
4931 | { |
4932 | - QScopedPointer<QQuickView> view(loadTest("AnchorCenterWithOffset.qml")); |
4933 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorCenterWithOffset.qml")); |
4934 | QVERIFY(view); |
4935 | QQuickItem *root = view->rootObject(); |
4936 | QVERIFY(root); |
4937 | |
4938 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4939 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4940 | QVERIFY(layout); |
4941 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4942 | |
4943 | - QQuickItem *item = testItem(root, "testItem"); |
4944 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4945 | QVERIFY(item); |
4946 | |
4947 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4948 | QVERIFY(anchors); |
4949 | |
4950 | - QCOMPARE(anchors->centerIn(), layout); |
4951 | + QCOMPARE(anchors->centerIn(), layout->contentItem()); |
4952 | QCOMPARE(anchors->verticalCenterOffset(), 50.0); |
4953 | QCOMPARE(anchors->horizontalCenterOffset(), 40.0); |
4954 | |
4955 | root->setWidth(root->width() + 100); |
4956 | layoutChangeSpy.wait(100); |
4957 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4958 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4959 | QVERIFY(testLayout); |
4960 | QCOMPARE(anchors->fill(), testLayout); |
4961 | // no need to check offsets as it does not affect the fill |
4962 | |
4963 | root->setWidth(root->width() - 100); |
4964 | layoutChangeSpy.wait(100); |
4965 | - QCOMPARE(anchors->centerIn(), layout); |
4966 | + QCOMPARE(anchors->centerIn(), layout->contentItem()); |
4967 | QCOMPARE(anchors->verticalCenterOffset(), 50.0); |
4968 | QCOMPARE(anchors->horizontalCenterOffset(), 40.0); |
4969 | } |
4970 | |
4971 | void testCase_AnchorLeft() |
4972 | { |
4973 | - QScopedPointer<QQuickView> view(loadTest("AnchorLeft.qml")); |
4974 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("AnchorLeft.qml")); |
4975 | QVERIFY(view); |
4976 | QQuickItem *root = view->rootObject(); |
4977 | QVERIFY(root); |
4978 | |
4979 | - QQuickItem *layout = testItem(root, "layoutManager"); |
4980 | + ULLayouts *layout = view->findItem<ULLayouts*>("layoutManager"); |
4981 | QVERIFY(layout); |
4982 | QSignalSpy layoutChangeSpy(layout, SIGNAL(currentLayoutChanged())); |
4983 | |
4984 | - QQuickItem *item = testItem(root, "testItem"); |
4985 | + QQuickItem *item = view->findItem<QQuickItem*>("testItem"); |
4986 | QVERIFY(item); |
4987 | |
4988 | QQuickAnchors *anchors = item->property("anchors").value<QQuickAnchors*>(); |
4989 | QVERIFY(anchors); |
4990 | |
4991 | - QCOMPARE(anchors->left().item, layout); |
4992 | + QCOMPARE(anchors->left().item, layout->contentItem()); |
4993 | QCOMPARE(anchors->leftMargin(), 10.0); |
4994 | |
4995 | root->setWidth(root->width() + 100); |
4996 | layoutChangeSpy.wait(100); |
4997 | - QQuickItem *testLayout = testItem(root, "testLayout"); |
4998 | + QQuickItem *testLayout = view->findItem<QQuickItem*>("testLayout"); |
4999 | QVERIFY(testLayout); |
5000 | QCOMPARE(anchors->fill(), testLayout); |