Merge lp:~tpeeters/ubuntu-ui-toolkit/noPrivateHeader into lp:~bzoltan/ubuntu-ui-toolkit/landing_140514

Proposed by Tim Peeters
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
Reviewer Review Type Date Requested Status
Zoltan Balogh Pending
Review via email: mp+221280@code.launchpad.net

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).

To post a comment you must log in.

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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'
467Binary 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);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: