Merge lp:~aacid/unity8/optionselector_filter into lp:unity8
- optionselector_filter
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andrea Cimitan |
Approved revision: | 2019 |
Merged at revision: | 2296 |
Proposed branch: | lp:~aacid/unity8/optionselector_filter |
Merge into: | lp:unity8 |
Prerequisite: | lp:~aacid/unity8/new_dash_navigation |
Diff against target: |
1035 lines (+621/-30) 21 files modified
qml/Dash/DashNavigation.qml (+1/-1) qml/Dash/DashPageHeader.qml (+36/-16) qml/Dash/Filters/FilterOptionSelector.qml (+89/-0) qml/Dash/Filters/FilterWidget.qml (+29/-0) qml/Dash/Filters/FilterWidgetFactory.qml (+49/-0) qml/Dash/FiltersPopover.qml (+97/-0) qml/Dash/GenericScopeView.qml (+11/-0) qml/Dash/PageHeaderExtraPanel.qml (+20/-2) tests/mocks/Unity/fake_filters.cpp (+17/-3) tests/mocks/Unity/fake_filters.h (+9/-2) tests/mocks/Unity/fake_optionselectorfilter.cpp (+6/-0) tests/mocks/Unity/fake_optionselectorfilter.h (+8/-1) tests/mocks/Unity/fake_optionselectoroptions.cpp (+12/-0) tests/mocks/Unity/fake_optionselectoroptions.h (+5/-0) tests/mocks/Unity/fake_scope.cpp (+20/-4) tests/mocks/Unity/fake_scope.h (+8/-1) tests/mocks/Unity/fake_unity_plugin.cpp (+5/-0) tests/qmltests/CMakeLists.txt (+2/-0) tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qml (+96/-0) tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml (+55/-0) tests/qmltests/Dash/tst_DashContent.qml (+46/-0) |
To merge this branch: | bzr merge lp:~aacid/unity8/optionselector_filter |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrea Cimitan (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Review via email: mp+273194@code.launchpad.net |
Commit message
Filter implementation with Option Selector filter as the only filter
Description of the change
* Are there any related MPs required for this MP to build/function as expected?
Branches from https:/
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* Did you make sure that your branch does not contain spurious tags?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
Not yet
- 1994. By Albert Astals Cid
-
Implement Scope::
activeFiltersCo unt in the mock plugin - 1995. By Albert Astals Cid
-
Number with the active filters
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1995
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1996. By Albert Astals Cid
-
Fix whitespace
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1996
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1997. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1997
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1998. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1998
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1999. By Albert Astals Cid
-
Wrap the filters in a flickable
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1999
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2000. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2000
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2001. By Albert Astals Cid
-
Merge
- 2002. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2002
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2003. By Albert Astals Cid
-
mege
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2003
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2004. By Albert Astals Cid
-
Merge
- 2005. By Albert Astals Cid
-
Merge
- 2006. By Albert Astals Cid
-
Merge
- 2007. By Albert Astals Cid
-
Proper name
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2005
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2007
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2008. By Albert Astals Cid
-
Fix import versions
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2008
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2009. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2009
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2009
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2010. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2010
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2011. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2011
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2012. By Albert Astals Cid
-
Add "Refine your results" + "Reset" to the filter popover
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2012
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Andrea Cimitan (cimi) wrote : | # |
couple of comments for now
- 2013. By Albert Astals Cid
-
drop unneeded id
- 2014. By Albert Astals Cid
-
Better wait for it to check for growth to have stopped
Albert Astals Cid (aacid) wrote : | # |
Both fixed
- 2015. By Albert Astals Cid
-
Merge
Andrea Cimitan (cimi) wrote : | # |
Thanks! A couple more
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2013
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2015
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2016. By Albert Astals Cid
-
More reviews fixes
Albert Astals Cid (aacid) wrote : | # |
> Thanks! A couple more
Done.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2016
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2017. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2017
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2018. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2018
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 2019. By Albert Astals Cid
-
Merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2019
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Andrea Cimitan (cimi) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
yes, silo 54
* Did CI run pass? If not, please explain why.
unrelated
* Did you make sure that the branch does not contain spurious tags?
y
- 2020. By Albert Astals Cid
-
Merge
- 2021. By Albert Astals Cid
-
Merge
- 2022. By Albert Astals Cid
-
Hide popover when scope stops being current
- 2023. By Albert Astals Cid
-
Remove clicking on the scope title to trigger search
Was a bug in the prototype i ended up copying ^_^
- 2024. By Albert Astals Cid
-
Take into account OSK height for limiting the popover height
- 2025. By Albert Astals Cid
-
Give some space between the popover and the OSK
3gu decided by Patty
- 2026. By Albert Astals Cid
-
Merge
- 2027. By Albert Astals Cid
-
Merge
- 2028. By Albert Astals Cid
-
Merge
- 2029. By Albert Astals Cid
-
Merge
- 2030. By Albert Astals Cid
-
Merge
- 2031. By Albert Astals Cid
-
Merge
Preview Diff
1 | === modified file 'qml/Dash/DashNavigation.qml' |
2 | --- qml/Dash/DashNavigation.qml 2016-03-14 08:53:26 +0000 |
3 | +++ qml/Dash/DashNavigation.qml 2016-03-14 08:53:26 +0000 |
4 | @@ -35,7 +35,7 @@ |
5 | property bool isEnteringChildren: false |
6 | |
7 | visible: height != 0 |
8 | - implicitHeight: navigationListView.y + navigationListView.height |
9 | + implicitHeight: scope && scope.hasNavigation ? navigationListView.y + navigationListView.height : 0 |
10 | |
11 | function resetNavigation() { |
12 | if (navigationModel.count > 1) { |
13 | |
14 | === modified file 'qml/Dash/DashPageHeader.qml' |
15 | --- qml/Dash/DashPageHeader.qml 2016-03-14 08:53:26 +0000 |
16 | +++ qml/Dash/DashPageHeader.qml 2016-03-14 08:53:26 +0000 |
17 | @@ -17,7 +17,6 @@ |
18 | import QtQuick 2.4 |
19 | import Ubuntu.Components 1.3 |
20 | import Ubuntu.Components.Themes.Ambiance 1.3 |
21 | -import Ubuntu.Components.Popups 1.3 |
22 | import Ubuntu.Components.ListItems 1.3 |
23 | import "../Components" |
24 | |
25 | @@ -27,6 +26,8 @@ |
26 | implicitHeight: headerContainer.height + signatureLineHeight |
27 | readonly property real signatureLineHeight: showSignatureLine ? units.gu(2) : 0 |
28 | |
29 | + property int activeFiltersCount: 0 |
30 | + property bool scopeHasFilters: false |
31 | property bool showBackButton: false |
32 | property bool backIsClose: false |
33 | property string title |
34 | @@ -54,6 +55,7 @@ |
35 | signal settingsClicked() |
36 | signal favoriteClicked() |
37 | signal searchTextFieldFocused() |
38 | + signal showFiltersPopup(var item) |
39 | |
40 | onScopeStyleChanged: refreshLogo() |
41 | onSearchQueryChanged: { |
42 | @@ -204,29 +206,47 @@ |
43 | rightMargin: units.gu(1) |
44 | } |
45 | |
46 | + readonly property bool clearIsSettings: !searchTextField.focus && root.scopeHasFilters |
47 | + |
48 | primaryItem: Label { |
49 | text: root.navigationTag |
50 | } |
51 | |
52 | - secondaryItem: AbstractButton { |
53 | + secondaryItem: Row { |
54 | height: searchTextField.height |
55 | - width: height |
56 | - enabled: searchTextField.text.length > 0 || root.navigationTag != "" |
57 | - |
58 | - Image { |
59 | - objectName: "clearIcon" |
60 | - anchors.fill: parent |
61 | - anchors.margins: units.gu(.75) |
62 | - source: "image://theme/clear" |
63 | - opacity: parent.enabled |
64 | - visible: opacity > 0 |
65 | - Behavior on opacity { |
66 | - UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration } |
67 | + |
68 | + AbstractButton { |
69 | + id: clearOrSettingsButton |
70 | + height: parent.height |
71 | + width: height |
72 | + enabled: searchTextField.text.length > 0 || root.navigationTag != "" |
73 | + |
74 | + Image { |
75 | + objectName: "clearIcon" |
76 | + anchors.fill: parent |
77 | + anchors.margins: units.gu(.75) |
78 | + source: searchTextField.clearIsSettings ? "image://theme/settings" : "image://theme/clear" |
79 | + opacity: parent.enabled |
80 | + visible: opacity > 0 |
81 | + Behavior on opacity { |
82 | + UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration } |
83 | + } |
84 | + } |
85 | + |
86 | + onClicked: { |
87 | + if (searchTextField.clearIsSettings) { |
88 | + root.showFiltersPopup(clearOrSettingsButton); |
89 | + } else { |
90 | + root.clearSearch(true); |
91 | + } |
92 | } |
93 | } |
94 | |
95 | - onClicked: { |
96 | - root.clearSearch(true); |
97 | + Label { |
98 | + visible: searchTextField.clearIsSettings && root.activeFiltersCount > 0 |
99 | + height: parent.height |
100 | + text: root.activeFiltersCount |
101 | + verticalAlignment: Text.AlignVCenter |
102 | } |
103 | } |
104 | |
105 | |
106 | === added directory 'qml/Dash/Filters' |
107 | === added file 'qml/Dash/Filters/FilterOptionSelector.qml' |
108 | --- qml/Dash/Filters/FilterOptionSelector.qml 1970-01-01 00:00:00 +0000 |
109 | +++ qml/Dash/Filters/FilterOptionSelector.qml 2016-03-14 08:53:26 +0000 |
110 | @@ -0,0 +1,89 @@ |
111 | +/* |
112 | + * Copyright (C) 2015 Canonical, Ltd. |
113 | + * |
114 | + * This program is free software; you can redistribute it and/or modify |
115 | + * it under the terms of the GNU General Public License as published by |
116 | + * the Free Software Foundation; version 3. |
117 | + * |
118 | + * This program is distributed in the hope that it will be useful, |
119 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
120 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
121 | + * GNU General Public License for more details. |
122 | + * |
123 | + * You should have received a copy of the GNU General Public License |
124 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
125 | + */ |
126 | + |
127 | +import QtQuick 2.4 |
128 | +import Ubuntu.Components 1.3 |
129 | +import Ubuntu.Components.ListItems 1.3 as ListItems |
130 | + |
131 | +/*! Option Selector Filter Widget. */ |
132 | + |
133 | +FilterWidget { |
134 | + id: root |
135 | + |
136 | + implicitHeight: expandingItem.height |
137 | + |
138 | + ListItems.Expandable { |
139 | + id: expandingItem |
140 | + objectName: "expandingItem" |
141 | + |
142 | + expandedHeight: collapsedHeight + column.height |
143 | + width: parent.width |
144 | + |
145 | + onClicked: { |
146 | + expanded = !expanded; |
147 | + } |
148 | + |
149 | + Item { |
150 | + id: holder |
151 | + anchors.top: parent.top |
152 | + height: expandingItem.collapsedHeight |
153 | + width: parent.width |
154 | + |
155 | + Label { |
156 | + anchors.left: parent.left |
157 | + anchors.right: dropDown.left |
158 | + anchors.verticalCenter: parent.verticalCenter |
159 | + text: widgetData.label || "" |
160 | + } |
161 | + |
162 | + Image { |
163 | + id: dropDown |
164 | + height: units.gu(3) |
165 | + fillMode: Image.PreserveAspectFit |
166 | + anchors.right: parent.right |
167 | + anchors.verticalCenter: parent.verticalCenter |
168 | + source: expandingItem.expanded ? "image://theme/up" : "image://theme/down" |
169 | + } |
170 | + } |
171 | + |
172 | + Column { |
173 | + id: column |
174 | + anchors.top: holder.bottom |
175 | + width: parent.width |
176 | + Repeater { |
177 | + model: widgetData.options |
178 | + |
179 | + ListItems.Standard { |
180 | + text: label |
181 | + objectName: root.objectName + "label" + index; |
182 | + |
183 | + Image { |
184 | + height: units.gu(3) |
185 | + fillMode: Image.PreserveAspectFit |
186 | + anchors.right: parent.right |
187 | + anchors.verticalCenter: parent.verticalCenter |
188 | + source: "image://theme/tick" |
189 | + visible: checked |
190 | + } |
191 | + |
192 | + onClicked: { |
193 | + widgetData.options.setChecked(index, !checked); |
194 | + } |
195 | + } |
196 | + } |
197 | + } |
198 | + } |
199 | +} |
200 | |
201 | === added file 'qml/Dash/Filters/FilterWidget.qml' |
202 | --- qml/Dash/Filters/FilterWidget.qml 1970-01-01 00:00:00 +0000 |
203 | +++ qml/Dash/Filters/FilterWidget.qml 2016-03-14 08:53:26 +0000 |
204 | @@ -0,0 +1,29 @@ |
205 | +/* |
206 | + * Copyright (C) 2015 Canonical, Ltd. |
207 | + * |
208 | + * This program is free software; you can redistribute it and/or modify |
209 | + * it under the terms of the GNU General Public License as published by |
210 | + * the Free Software Foundation; version 3. |
211 | + * |
212 | + * This program is distributed in the hope that it will be useful, |
213 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
214 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
215 | + * GNU General Public License for more details. |
216 | + * |
217 | + * You should have received a copy of the GNU General Public License |
218 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
219 | + */ |
220 | + |
221 | +import QtQuick 2.4 |
222 | + |
223 | +/*! Interface for filter widgets. */ |
224 | + |
225 | +Item { |
226 | + //! The widget identifier |
227 | + property string widgetId |
228 | + |
229 | + //! Variable used to contain widget's data |
230 | + property var widgetData |
231 | + |
232 | + objectName: widgetId |
233 | +} |
234 | |
235 | === added file 'qml/Dash/Filters/FilterWidgetFactory.qml' |
236 | --- qml/Dash/Filters/FilterWidgetFactory.qml 1970-01-01 00:00:00 +0000 |
237 | +++ qml/Dash/Filters/FilterWidgetFactory.qml 2016-03-14 08:53:26 +0000 |
238 | @@ -0,0 +1,49 @@ |
239 | +/* |
240 | + * Copyright (C) 2015 Canonical, Ltd. |
241 | + * |
242 | + * This program is free software; you can redistribute it and/or modify |
243 | + * it under the terms of the GNU General Public License as published by |
244 | + * the Free Software Foundation; version 3. |
245 | + * |
246 | + * This program is distributed in the hope that it will be useful, |
247 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
248 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
249 | + * GNU General Public License for more details. |
250 | + * |
251 | + * You should have received a copy of the GNU General Public License |
252 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
253 | + */ |
254 | + |
255 | +import QtQuick 2.4 |
256 | +import Unity 0.2 |
257 | + |
258 | +//! \brief This component loads the widgets based on widgetType. |
259 | + |
260 | +Loader { |
261 | + id: root |
262 | + |
263 | + //! Identifier of the widget. |
264 | + property string widgetId: "" |
265 | + |
266 | + //! Type of the widget to display. |
267 | + property int widgetType |
268 | + |
269 | + //! Widget data, forwarded to the widget as is. |
270 | + property var widgetData: null |
271 | + |
272 | + source: widgetSource |
273 | + |
274 | + //! \cond private |
275 | + readonly property url widgetSource: { |
276 | + switch (widgetType) { |
277 | + case Filters.OptionSelectorFilter: return "FilterOptionSelector.qml"; |
278 | + default: return ""; |
279 | + } |
280 | + } |
281 | + //! \endcond |
282 | + |
283 | + onLoaded: { |
284 | + item.widgetId = Qt.binding(function() { return root.widgetId } ) |
285 | + item.widgetData = Qt.binding(function() { return root.widgetData } ) |
286 | + } |
287 | +} |
288 | |
289 | === added file 'qml/Dash/FiltersPopover.qml' |
290 | --- qml/Dash/FiltersPopover.qml 1970-01-01 00:00:00 +0000 |
291 | +++ qml/Dash/FiltersPopover.qml 2016-03-14 08:53:26 +0000 |
292 | @@ -0,0 +1,97 @@ |
293 | +/* |
294 | + * Copyright (C) 2013-2015 Canonical, Ltd. |
295 | + * |
296 | + * This program is free software; you can redistribute it and/or modify |
297 | + * it under the terms of the GNU General Public License as published by |
298 | + * the Free Software Foundation; version 3. |
299 | + * |
300 | + * This program is distributed in the hope that it will be useful, |
301 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
302 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
303 | + * GNU General Public License for more details. |
304 | + * |
305 | + * You should have received a copy of the GNU General Public License |
306 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
307 | + */ |
308 | + |
309 | +import QtQuick 2.4 |
310 | +import Ubuntu.Components 1.3 |
311 | +import Ubuntu.Components.Popups 1.3 |
312 | +import "Filters" as Filters |
313 | + |
314 | +Popover { |
315 | + id: root |
316 | + objectName: "filtersPopover" |
317 | + |
318 | + Flickable { |
319 | + id: flickable |
320 | + anchors { |
321 | + top: parent.top |
322 | + left: parent.left |
323 | + right: parent.right |
324 | + } |
325 | + height: { |
326 | + // Popover doesn't like being 75% or bigger than the screen (counting the "empty" part on top) |
327 | + var posToRootParent = flickable.mapToItem(null, 0, 0).y; |
328 | + var threeQuartersParent = root.parent.height * 3 / 4 - posToRootParent - 1; |
329 | + var parentAndKeyboard = root.parent.height - posToRootParent - (Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height + units.gu(3) : 0) |
330 | + return Math.min(parentAndKeyboard, Math.min(threeQuartersParent, column.height)); |
331 | + } |
332 | + contentHeight: column.height |
333 | + contentWidth: width |
334 | + |
335 | + Column { |
336 | + id: column |
337 | + width: parent.width |
338 | + |
339 | + Item { |
340 | + width: parent.width |
341 | + height: resetLabel.height + units.gu(3) |
342 | + |
343 | + Label { |
344 | + anchors { |
345 | + left: parent.left |
346 | + right: resetLabel.left |
347 | + margins: units.gu(2) |
348 | + verticalCenter: parent.verticalCenter |
349 | + } |
350 | + text: i18n.tr("Refine your results") |
351 | + } |
352 | + Label { |
353 | + id: resetLabel |
354 | + anchors { |
355 | + right: parent.right |
356 | + rightMargin: units.gu(2) |
357 | + verticalCenter: parent.verticalCenter |
358 | + } |
359 | + text: i18n.tr("Reset") |
360 | + |
361 | + AbstractButton { |
362 | + anchors { |
363 | + fill: parent |
364 | + rightMargin: units.gu(-2) |
365 | + leftMargin: units.gu(-2) |
366 | + topMargin: units.gu(-1) |
367 | + bottomMargin: units.gu(-1) |
368 | + } |
369 | + onClicked: { |
370 | + scopeView.scope.resetFilters(); |
371 | + } |
372 | + } |
373 | + } |
374 | + } |
375 | + |
376 | + Repeater { |
377 | + model: scopeView.scope.filters |
378 | + |
379 | + delegate: Filters.FilterWidgetFactory { |
380 | + width: parent.width |
381 | + |
382 | + widgetId: id |
383 | + widgetType: type |
384 | + widgetData: filter |
385 | + } |
386 | + } |
387 | + } |
388 | + } |
389 | +} |
390 | |
391 | === modified file 'qml/Dash/GenericScopeView.qml' |
392 | --- qml/Dash/GenericScopeView.qml 2016-03-14 08:53:26 +0000 |
393 | +++ qml/Dash/GenericScopeView.qml 2016-03-14 08:53:26 +0000 |
394 | @@ -16,6 +16,7 @@ |
395 | |
396 | import QtQuick 2.4 |
397 | import Ubuntu.Components 1.3 |
398 | +import Ubuntu.Components.Popups 1.3 |
399 | import "../Components/SearchHistoryModel" |
400 | import Utils 0.1 |
401 | import Unity 0.2 |
402 | @@ -42,6 +43,7 @@ |
403 | property alias pageHeaderTotallyVisible: categoryView.pageHeaderTotallyVisible |
404 | property var holdingList: null |
405 | property bool wasCurrentOnMoveStart: false |
406 | + property var filtersPopover: null |
407 | |
408 | property var scopeStyle: ScopeStyle { |
409 | style: scope ? scope.customizations : {} |
410 | @@ -121,6 +123,10 @@ |
411 | } |
412 | categoryView.pageHeader.resetSearch(); |
413 | subPageLoader.closeSubPage(); |
414 | + if (filtersPopover) { |
415 | + PopupUtils.close(filtersPopover) |
416 | + scopeView.filtersPopover = null; |
417 | + } |
418 | } |
419 | |
420 | Binding { |
421 | @@ -619,6 +625,8 @@ |
422 | extraPanel: peExtraPanel |
423 | searchHistory: SearchHistoryModel |
424 | searchHint: scopeView.scope && scopeView.scope.searchHint || i18n.ctr("Label: Hint for dash search line edit", "Search") |
425 | + scopeHasFilters: scopeView.scope.filters != null |
426 | + activeFiltersCount: scopeView.scope.activeFiltersCount |
427 | showBackButton: scopeView.hasBackAction |
428 | searchEntryEnabled: true |
429 | settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false |
430 | @@ -642,6 +650,9 @@ |
431 | openPopup(); |
432 | } |
433 | } |
434 | + onShowFiltersPopup: { // item |
435 | + scopeView.filtersPopover = PopupUtils.open(Qt.resolvedUrl("FiltersPopover.qml"), item, { "contentWidth": scopeView.width - units.gu(2) } ); |
436 | + } |
437 | } |
438 | |
439 | PageHeaderExtraPanel { |
440 | |
441 | === modified file 'qml/Dash/PageHeaderExtraPanel.qml' |
442 | --- qml/Dash/PageHeaderExtraPanel.qml 2016-03-14 08:53:26 +0000 |
443 | +++ qml/Dash/PageHeaderExtraPanel.qml 2016-03-14 08:53:26 +0000 |
444 | @@ -17,13 +17,14 @@ |
445 | import QtQuick 2.4 |
446 | import Ubuntu.Components 1.3 |
447 | import Ubuntu.Components.ListItems 1.3 |
448 | +import "Filters" as Filters |
449 | |
450 | Item { |
451 | id: root |
452 | |
453 | readonly property real searchesHeight: recentSearchesRepeater.count > 0 ? searchColumn.height + recentSearchesLabels.height + recentSearchesLabels.anchors.margins : 0 |
454 | |
455 | - implicitHeight: searchesHeight + dashNavigation.implicitHeight |
456 | + implicitHeight: searchesHeight + dashNavigation.implicitHeight + primaryFilter.height |
457 | |
458 | // Set by parent |
459 | property ListModel searchHistory |
460 | @@ -32,7 +33,7 @@ |
461 | property real windowHeight |
462 | |
463 | // Used by PageHeader |
464 | - readonly property bool hasContents: searchHistory.count > 0 || scope && scope.hasNavigation |
465 | + readonly property bool hasContents: searchHistory.count > 0 || scope && scope.hasNavigation || scope && scope.primaryNavigationFilter |
466 | |
467 | signal historyItemClicked(string text) |
468 | signal dashNavigationLeafClicked() |
469 | @@ -111,6 +112,23 @@ |
470 | onLeafClicked: root.dashNavigationLeafClicked(); |
471 | } |
472 | |
473 | + Filters.FilterWidgetFactory { |
474 | + id: primaryFilter |
475 | + active: scope && !scope.hasNavigation |
476 | + |
477 | + property var filter: active ? scope.primaryNavigationFilter : null |
478 | + |
479 | + anchors { |
480 | + top: recentSearchesRepeater.count > 0 ? searchColumn.bottom : parent.top |
481 | + left: parent.left |
482 | + right: parent.right |
483 | + } |
484 | + |
485 | + widgetId: filter ? filter.filterId : "" |
486 | + widgetType: filter ? filter.filterType : -1 |
487 | + widgetData: filter |
488 | + } |
489 | + |
490 | // This is outside the item |
491 | Image { |
492 | anchors { |
493 | |
494 | === modified file 'tests/mocks/Unity/fake_filters.cpp' |
495 | --- tests/mocks/Unity/fake_filters.cpp 2016-03-14 08:53:26 +0000 |
496 | +++ tests/mocks/Unity/fake_filters.cpp 2016-03-14 08:53:26 +0000 |
497 | @@ -22,9 +22,14 @@ |
498 | Filters::Filters(Scope* parent) |
499 | : unity::shell::scopes::FiltersInterface(parent) |
500 | { |
501 | - auto optionFilter1 = new FakeOptionSelectorFilter("OSF1", "Tag1", "Which Cake you like More", false, QStringList() << "cheese" << "carrot" << "chocolate", this); |
502 | - auto optionFilter2 = new FakeOptionSelectorFilter("OSF2", "Tag2", "Which Countries have you been to?", true, QStringList() << "Germany" << "UK" << "New Zealand", this); |
503 | - m_filters << optionFilter1 << optionFilter2; |
504 | + addFilter(new FakeOptionSelectorFilter("OSF1", "Tag1", "Which Cake you like More", false, QStringList() << "cheese" << "carrot" << "chocolate", this)); |
505 | + addFilter(new FakeOptionSelectorFilter("OSF2", "Tag2", "Which Countries have you been to?", true, QStringList() << "Germany" << "UK" << "New Zealand", this)); |
506 | +} |
507 | + |
508 | +void Filters::addFilter(FakeOptionSelectorFilter *f) |
509 | +{ |
510 | + connect(f, &FakeOptionSelectorFilter::isActiveChanged, this, &Filters::activeFiltersCountChanged); |
511 | + m_filters << f; |
512 | } |
513 | |
514 | int Filters::rowCount(const QModelIndex &parent) const |
515 | @@ -54,3 +59,12 @@ |
516 | return QVariant(); |
517 | } |
518 | } |
519 | + |
520 | +int Filters::activeFiltersCount() const |
521 | +{ |
522 | + int active = 0; |
523 | + Q_FOREACH(FakeOptionSelectorFilter *f, m_filters) { |
524 | + if (f->isActive()) ++active; |
525 | + } |
526 | + return active; |
527 | +} |
528 | |
529 | === modified file 'tests/mocks/Unity/fake_filters.h' |
530 | --- tests/mocks/Unity/fake_filters.h 2016-03-14 08:53:26 +0000 |
531 | +++ tests/mocks/Unity/fake_filters.h 2016-03-14 08:53:26 +0000 |
532 | @@ -18,9 +18,9 @@ |
533 | #define FAKE_FILTERS_H |
534 | |
535 | #include <unity/shell/scopes/FiltersInterface.h> |
536 | -#include <unity/shell/scopes/FilterBaseInterface.h> |
537 | |
538 | class Scope; |
539 | +class FakeOptionSelectorFilter; |
540 | |
541 | class Filters : public unity::shell::scopes::FiltersInterface |
542 | { |
543 | @@ -32,8 +32,15 @@ |
544 | int rowCount(const QModelIndex &parent) const override; |
545 | QVariant data(const QModelIndex &index, int role) const override; |
546 | |
547 | + int activeFiltersCount() const; |
548 | + |
549 | +Q_SIGNALS: |
550 | + void activeFiltersCountChanged(); |
551 | + |
552 | private: |
553 | - QVector<unity::shell::scopes::FilterBaseInterface*> m_filters; |
554 | + void addFilter(FakeOptionSelectorFilter* f); |
555 | + |
556 | + QVector<FakeOptionSelectorFilter*> m_filters; |
557 | }; |
558 | |
559 | #endif |
560 | |
561 | === modified file 'tests/mocks/Unity/fake_optionselectorfilter.cpp' |
562 | --- tests/mocks/Unity/fake_optionselectorfilter.cpp 2016-03-14 08:53:26 +0000 |
563 | +++ tests/mocks/Unity/fake_optionselectorfilter.cpp 2016-03-14 08:53:26 +0000 |
564 | @@ -26,6 +26,7 @@ |
565 | m_multiSelect(multiselect) |
566 | { |
567 | m_options = new FakeOptionSelectorOptions(optionLabels, this); |
568 | + connect(m_options, &FakeOptionSelectorOptions::anyCheckedChanged, this, &FakeOptionSelectorFilter::isActiveChanged); |
569 | } |
570 | |
571 | QString FakeOptionSelectorFilter::filterId() const |
572 | @@ -57,3 +58,8 @@ |
573 | { |
574 | return m_options; |
575 | } |
576 | + |
577 | +bool FakeOptionSelectorFilter::isActive() const |
578 | +{ |
579 | + return m_options->anyChecked(); |
580 | +} |
581 | |
582 | === modified file 'tests/mocks/Unity/fake_optionselectorfilter.h' |
583 | --- tests/mocks/Unity/fake_optionselectorfilter.h 2016-03-14 08:53:26 +0000 |
584 | +++ tests/mocks/Unity/fake_optionselectorfilter.h 2016-03-14 08:53:26 +0000 |
585 | @@ -19,6 +19,8 @@ |
586 | |
587 | #include <unity/shell/scopes/OptionSelectorFilterInterface.h> |
588 | |
589 | +class FakeOptionSelectorOptions; |
590 | + |
591 | class FakeOptionSelectorFilter : public unity::shell::scopes::OptionSelectorFilterInterface |
592 | { |
593 | Q_OBJECT |
594 | @@ -33,13 +35,18 @@ |
595 | bool multiSelect() const override; |
596 | unity::shell::scopes::OptionSelectorOptionsInterface* options() const override; |
597 | |
598 | + bool isActive() const; |
599 | + |
600 | +Q_SIGNALS: |
601 | + void isActiveChanged(); |
602 | + |
603 | private: |
604 | QString m_filterId; |
605 | QString m_filterTag; |
606 | QString m_title; |
607 | QString m_label; |
608 | bool m_multiSelect; |
609 | - unity::shell::scopes::OptionSelectorOptionsInterface* m_options; |
610 | + FakeOptionSelectorOptions* m_options; |
611 | }; |
612 | |
613 | #endif |
614 | |
615 | === modified file 'tests/mocks/Unity/fake_optionselectoroptions.cpp' |
616 | --- tests/mocks/Unity/fake_optionselectoroptions.cpp 2016-03-14 08:53:26 +0000 |
617 | +++ tests/mocks/Unity/fake_optionselectoroptions.cpp 2016-03-14 08:53:26 +0000 |
618 | @@ -56,10 +56,22 @@ |
619 | void FakeOptionSelectorOptions::setChecked(int row, bool checked) |
620 | { |
621 | if (checked) { |
622 | + if (!static_cast<FakeOptionSelectorFilter*>(parent())->multiSelect()) { |
623 | + if (!m_checkedIndexes.isEmpty()) { |
624 | + setChecked(*m_checkedIndexes.begin(), false); |
625 | + } |
626 | + Q_ASSERT(m_checkedIndexes.isEmpty()); |
627 | + } |
628 | m_checkedIndexes << row; |
629 | } else { |
630 | m_checkedIndexes.remove(row); |
631 | } |
632 | const QModelIndex idx = index(row, 0); |
633 | Q_EMIT dataChanged(idx, idx, QVector<int>() << RoleOptionChecked); |
634 | + Q_EMIT anyCheckedChanged(); |
635 | +} |
636 | + |
637 | +bool FakeOptionSelectorOptions::anyChecked() const |
638 | +{ |
639 | + return !m_checkedIndexes.isEmpty(); |
640 | } |
641 | |
642 | === modified file 'tests/mocks/Unity/fake_optionselectoroptions.h' |
643 | --- tests/mocks/Unity/fake_optionselectoroptions.h 2016-03-14 08:53:26 +0000 |
644 | +++ tests/mocks/Unity/fake_optionselectoroptions.h 2016-03-14 08:53:26 +0000 |
645 | @@ -34,6 +34,11 @@ |
646 | QVariant data(const QModelIndex &index, int role) const override; |
647 | Q_INVOKABLE void setChecked(int index, bool checked) override; |
648 | |
649 | + bool anyChecked() const; |
650 | + |
651 | +Q_SIGNALS: |
652 | + void anyCheckedChanged(); |
653 | + |
654 | private: |
655 | QStringList m_optionLabels; |
656 | QSet<int> m_checkedIndexes; |
657 | |
658 | === modified file 'tests/mocks/Unity/fake_scope.cpp' |
659 | --- tests/mocks/Unity/fake_scope.cpp 2016-03-14 08:53:26 +0000 |
660 | +++ tests/mocks/Unity/fake_scope.cpp 2016-03-14 08:53:26 +0000 |
661 | @@ -21,6 +21,7 @@ |
662 | |
663 | #include "fake_filters.h" |
664 | #include "fake_navigation.h" |
665 | +#include "fake_optionselectorfilter.h" |
666 | #include "fake_resultsmodel.h" |
667 | #include "fake_scopes.h" |
668 | #include "fake_settingsmodel.h" |
669 | @@ -38,6 +39,8 @@ |
670 | , m_searching(false) |
671 | , m_favorite(favorite) |
672 | , m_isActive(false) |
673 | + , m_hasNavigation(true) |
674 | + , m_hasPrimaryFilter(true) |
675 | , m_currentNavigationId("root") |
676 | , m_previewRendererName("preview-generic") |
677 | , m_categories(new Categories(categories, this)) |
678 | @@ -46,6 +49,8 @@ |
679 | , m_filters(new Filters(this)) |
680 | , m_returnNullPreview(returnNullPreview) |
681 | { |
682 | + m_primaryNavigationFilter = new FakeOptionSelectorFilter("OSF3", "PFTag", "Which food you like More", false, QStringList() << "meat" << "vegetables", this); |
683 | + connect(m_filters, &Filters::activeFiltersCountChanged, this, &Scope::activeFiltersCountChanged); |
684 | } |
685 | |
686 | QString Scope::id() const |
687 | @@ -230,7 +235,13 @@ |
688 | |
689 | bool Scope::hasNavigation() const |
690 | { |
691 | - return true; |
692 | + return m_hasNavigation; |
693 | +} |
694 | + |
695 | +void Scope::setHasNavigation(bool hasNavigation) |
696 | +{ |
697 | + m_hasNavigation = hasNavigation; |
698 | + Q_EMIT hasNavigationChanged(); |
699 | } |
700 | |
701 | Scope::Status Scope::status() const |
702 | @@ -303,7 +314,7 @@ |
703 | |
704 | unity::shell::scopes::FilterBaseInterface* Scope::primaryNavigationFilter() const |
705 | { |
706 | - return nullptr; |
707 | + return m_hasPrimaryFilter ? m_primaryNavigationFilter : nullptr; |
708 | } |
709 | |
710 | unity::shell::scopes::FiltersInterface* Scope::filters() const |
711 | @@ -321,8 +332,7 @@ |
712 | |
713 | int Scope::activeFiltersCount() const |
714 | { |
715 | - // TODO |
716 | - return 0; |
717 | + return m_filters->activeFiltersCount(); |
718 | } |
719 | |
720 | void Scope::resetPrimaryNavigationTag() |
721 | @@ -332,6 +342,12 @@ |
722 | } |
723 | } |
724 | |
725 | +void Scope::setHasPrimaryFilter(bool hasPrimaryFilter) |
726 | +{ |
727 | + m_hasPrimaryFilter = hasPrimaryFilter; |
728 | + Q_EMIT primaryNavigationFilterChanged(); |
729 | +} |
730 | + |
731 | void Scope::performQuery(const QString& query) |
732 | { |
733 | Q_EMIT queryPerformed(query); |
734 | |
735 | === modified file 'tests/mocks/Unity/fake_scope.h' |
736 | --- tests/mocks/Unity/fake_scope.h 2016-03-14 08:53:26 +0000 |
737 | +++ tests/mocks/Unity/fake_scope.h 2016-03-14 08:53:26 +0000 |
738 | @@ -24,7 +24,9 @@ |
739 | |
740 | #include <QTimer> |
741 | |
742 | +class Filters; |
743 | class Scopes; |
744 | +class FakeOptionSelectorFilter; |
745 | |
746 | class Scope : public unity::shell::scopes::ScopeInterface |
747 | { |
748 | @@ -70,12 +72,14 @@ |
749 | bool hasNavigation() const override; |
750 | Q_INVOKABLE unity::shell::scopes::NavigationInterface* getNavigation(QString const& navigationId) override; |
751 | Q_INVOKABLE void setNavigationState(const QString &navigationId) override; |
752 | + Q_INVOKABLE void setHasNavigation(bool hasNavigation); // This is not invokable in the Interface, here for testing benefits |
753 | |
754 | unity::shell::scopes::FilterBaseInterface* primaryNavigationFilter() const override; |
755 | unity::shell::scopes::FiltersInterface* filters() const override; |
756 | QString primaryNavigationTag() const override; |
757 | int activeFiltersCount() const override; |
758 | Q_INVOKABLE void resetPrimaryNavigationTag() override; |
759 | + Q_INVOKABLE void setHasPrimaryFilter(bool hasPrimaryFilter); // This is not invokable in the Interface, here for testing benefits |
760 | |
761 | void performQuery(const QString& query) override; |
762 | |
763 | @@ -105,6 +109,8 @@ |
764 | bool m_searching; |
765 | bool m_favorite; |
766 | bool m_isActive; |
767 | + bool m_hasNavigation; |
768 | + bool m_hasPrimaryFilter; |
769 | QString m_currentNavigationId; |
770 | |
771 | QString m_previewRendererName; |
772 | @@ -112,7 +118,8 @@ |
773 | unity::shell::scopes::CategoriesInterface* m_categories; |
774 | unity::shell::scopes::ScopeInterface* m_openScope; |
775 | unity::shell::scopes::SettingsModelInterface* m_settings; |
776 | - unity::shell::scopes::FiltersInterface* m_filters; |
777 | + Filters* m_filters; |
778 | + FakeOptionSelectorFilter* m_primaryNavigationFilter; |
779 | |
780 | bool m_returnNullPreview; |
781 | }; |
782 | |
783 | === modified file 'tests/mocks/Unity/fake_unity_plugin.cpp' |
784 | --- tests/mocks/Unity/fake_unity_plugin.cpp 2016-02-19 11:42:42 +0000 |
785 | +++ tests/mocks/Unity/fake_unity_plugin.cpp 2016-03-14 08:53:26 +0000 |
786 | @@ -22,7 +22,9 @@ |
787 | // local |
788 | #include "fake_scopes.h" |
789 | #include "fake_categories.h" |
790 | +#include "fake_filters.h" |
791 | #include "fake_navigation.h" |
792 | +#include "fake_optionselectoroptions.h" |
793 | #include "fake_previewmodel.h" |
794 | #include "fake_previewwidgetmodel.h" |
795 | #include "fake_resultsmodel.h" |
796 | @@ -52,4 +54,7 @@ |
797 | qmlRegisterType<ResultsModel>(uri, 0, 2, "FakeResultsModel"); |
798 | qmlRegisterType<PreviewModel>(uri, 0, 2, "FakePreviewModel"); |
799 | qmlRegisterUncreatableType<PreviewWidgetModel>(uri, 0, 2, "PreviewWidgetModel", "Can't create new PreviewWidgetModel in QML. Get them from PreviewModel instance."); |
800 | + qmlRegisterUncreatableType<unity::shell::scopes::FiltersInterface>(uri, 0, 2, "Filters", "Can't create Filters object in QML. Get them from Scope instance."); |
801 | + qmlRegisterUncreatableType<unity::shell::scopes::FilterBaseInterface>(uri, 0, 2, "Filter", "Can't create Filter object in QML. Get them from Scope instance."); |
802 | + qmlRegisterUncreatableType<unity::shell::scopes::OptionSelectorOptionsInterface>(uri, 0, 2, "OptionSelectorOptions", "Can't create Filters object in QML. Get them from OptionSelector instance."); |
803 | } |
804 | |
805 | === modified file 'tests/qmltests/CMakeLists.txt' |
806 | --- tests/qmltests/CMakeLists.txt 2016-03-10 22:41:38 +0000 |
807 | +++ tests/qmltests/CMakeLists.txt 2016-03-14 08:53:26 +0000 |
808 | @@ -53,6 +53,8 @@ |
809 | add_unity8_qmltest(Dash/Previews PreviewVideoPlayback) |
810 | add_unity8_qmltest(Dash/Previews PreviewWidgetFactory) |
811 | add_unity8_qmltest(Dash/Previews PreviewZoomableImage) |
812 | +add_unity8_qmltest(Dash/Filters FilterOptionSelector) |
813 | +add_unity8_qmltest(Dash/Filters FilterWidgetFactory) |
814 | add_unity8_qmltest(Dash/ScopeSettings ScopeSettingBoolean) |
815 | add_unity8_qmltest(Dash/ScopeSettings ScopeSettingList) |
816 | add_unity8_qmltest(Dash/ScopeSettings ScopeSettingNumber) |
817 | |
818 | === added directory 'tests/qmltests/Dash/Filters' |
819 | === added file 'tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qml' |
820 | --- tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qml 1970-01-01 00:00:00 +0000 |
821 | +++ tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qml 2016-03-14 08:53:26 +0000 |
822 | @@ -0,0 +1,96 @@ |
823 | +/* |
824 | + * Copyright 2015 Canonical Ltd. |
825 | + * |
826 | + * This program is free software; you can redistribute it and/or modify |
827 | + * it under the terms of the GNU General Public License as published by |
828 | + * the Free Software Foundation; version 3. |
829 | + * |
830 | + * This program is distributed in the hope that it will be useful, |
831 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
832 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
833 | + * GNU General Public License for more details. |
834 | + * |
835 | + * You should have received a copy of the GNU General Public License |
836 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
837 | + */ |
838 | + |
839 | +import QtQuick 2.4 |
840 | +import QtTest 1.0 |
841 | +import "../../../../qml/Dash/Filters" |
842 | +import Unity.Test 0.1 as UT |
843 | +import Unity 0.2 |
844 | +import Ubuntu.Components 1.3 |
845 | + |
846 | +Rectangle { |
847 | + id: root |
848 | + width: units.gu(60) |
849 | + height: units.gu(80) |
850 | + color: theme.palette.selected.background |
851 | + |
852 | + property var singleSelectionWidgetData |
853 | + |
854 | + ListModel { |
855 | + id: optionsSingleSelect |
856 | + ListElement { |
857 | + label: "A" |
858 | + checked: false |
859 | + } |
860 | + ListElement { |
861 | + label: "B" |
862 | + checked: false |
863 | + } |
864 | + ListElement { |
865 | + label: "C" |
866 | + checked: false |
867 | + } |
868 | + |
869 | + function setChecked(index, checked) { |
870 | + for (var i = 0; i < optionsSingleSelect.count; ++i) |
871 | + optionsSingleSelect.setProperty(i, "checked", false); |
872 | + optionsSingleSelect.setProperty(index, "checked", checked); |
873 | + } |
874 | + } |
875 | + |
876 | + Component.onCompleted: { |
877 | + singleSelectionWidgetData = { label: "Hola", options: optionsSingleSelect } |
878 | + } |
879 | + |
880 | + FilterWidgetFactory { |
881 | + id: factory |
882 | + widgetId: "testOptionSelectorFilter" |
883 | + widgetType: Filters.OptionSelectorFilter |
884 | + widgetData: singleSelectionWidgetData |
885 | + anchors { |
886 | + left: parent.left |
887 | + right: parent.right |
888 | + } |
889 | + } |
890 | + |
891 | + UT.UnityTestCase { |
892 | + name: "FilterOptionSelector" |
893 | + when: windowShown |
894 | + |
895 | + function test_optionSelector() { |
896 | + var expandingItem = findChild(factory, "expandingItem"); |
897 | + // Open the selector |
898 | + mouseClick(factory); |
899 | + // wait for it to stop growing |
900 | + tryCompare(factory, "implicitHeight", expandingItem.expandedHeight); |
901 | + |
902 | + // Check the first option |
903 | + var option0 = findChild(factory, "testOptionSelectorFilterlabel0"); |
904 | + mouseClick(option0); |
905 | + verify(optionsSingleSelect.get(0).checked); |
906 | + |
907 | + // Check the second option |
908 | + var option1 = findChild(factory, "testOptionSelectorFilterlabel1"); |
909 | + mouseClick(option1); |
910 | + verify(!optionsSingleSelect.get(0).checked); |
911 | + verify(optionsSingleSelect.get(1).checked); |
912 | + |
913 | + // Uncheck the second option |
914 | + mouseClick(option1); |
915 | + verify(!optionsSingleSelect.get(1).checked); |
916 | + } |
917 | + } |
918 | +} |
919 | |
920 | === added file 'tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml' |
921 | --- tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml 1970-01-01 00:00:00 +0000 |
922 | +++ tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qml 2016-03-14 08:53:26 +0000 |
923 | @@ -0,0 +1,55 @@ |
924 | +/* |
925 | + * Copyright 2015 Canonical Ltd. |
926 | + * |
927 | + * This program is free software; you can redistribute it and/or modify |
928 | + * it under the terms of the GNU General Public License as published by |
929 | + * the Free Software Foundation; version 3. |
930 | + * |
931 | + * This program is distributed in the hope that it will be useful, |
932 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
933 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
934 | + * GNU General Public License for more details. |
935 | + * |
936 | + * You should have received a copy of the GNU General Public License |
937 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
938 | + */ |
939 | + |
940 | +import QtQuick 2.4 |
941 | +import QtTest 1.0 |
942 | +import "../../../../qml/Dash/Filters" |
943 | +import Unity.Test 0.1 as UT |
944 | +import Unity 0.2 |
945 | +import Ubuntu.Components 1.3 |
946 | + |
947 | +Rectangle { |
948 | + id: root |
949 | + width: units.gu(60) |
950 | + height: units.gu(80) |
951 | + color: theme.palette.selected.background |
952 | + |
953 | + FilterWidgetFactory { |
954 | + id: factory |
955 | + anchors { |
956 | + left: parent.left |
957 | + right: parent.right |
958 | + } |
959 | + } |
960 | + |
961 | + UT.UnityTestCase { |
962 | + name: "FilterWidgetFactory" |
963 | + when: windowShown |
964 | + |
965 | + function test_mapping_data() { |
966 | + return [ |
967 | + { tag: "OptionSelector", type: Filters.OptionSelectorFilter, source: "FilterOptionSelector.qml" } |
968 | + ]; |
969 | + } |
970 | + |
971 | + function test_mapping(data) { |
972 | + factory.widgetData = {}; |
973 | + factory.widgetType = data.type; |
974 | + |
975 | + verify((String(factory.source)).indexOf(data.source) != -1); |
976 | + } |
977 | + } |
978 | +} |
979 | |
980 | === modified file 'tests/qmltests/Dash/tst_DashContent.qml' |
981 | --- tests/qmltests/Dash/tst_DashContent.qml 2016-03-14 08:53:26 +0000 |
982 | +++ tests/qmltests/Dash/tst_DashContent.qml 2016-03-14 08:53:26 +0000 |
983 | @@ -513,6 +513,52 @@ |
984 | tryCompare(peExtraPanel, "visible", true); |
985 | } |
986 | |
987 | + function test_navigationShowFilterButton() { |
988 | + goToSecondLevel(); |
989 | + |
990 | + var dashContentList = findChild(dashContent, "dashContentList"); |
991 | + var searchTextField = findChild(dashContentList.currentItem, "searchTextField"); |
992 | + |
993 | + verify(!searchTextField.focus) |
994 | + verify(searchTextField.clearIsSettings) |
995 | + |
996 | + mouseClick(searchTextField) |
997 | + |
998 | + verify(searchTextField.focus) |
999 | + verify(!searchTextField.clearIsSettings) |
1000 | + } |
1001 | + |
1002 | + function test_navigationShowFilterPopup() { |
1003 | + goToSecondLevel(); |
1004 | + |
1005 | + var dashContentList = findChild(dashContent, "dashContentList"); |
1006 | + var searchTextField = findChild(dashContentList.currentItem, "searchTextField"); |
1007 | + var clearIcon = findChild(searchTextField, "clearIcon"); |
1008 | + |
1009 | + var filtersPopover = findChild(shell, "filtersPopover") |
1010 | + verify(!filtersPopover); |
1011 | + |
1012 | + mouseClick(clearIcon); |
1013 | + |
1014 | + filtersPopover = findChild(shell, "filtersPopover") |
1015 | + |
1016 | + verify(filtersPopover); |
1017 | + } |
1018 | + |
1019 | + function test_primaryFilter() { |
1020 | + var dashContentList = findChild(dashContent, "dashContentList"); |
1021 | + tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true); |
1022 | + dashContentList.currentItem.item.scope.setHasNavigation(false); |
1023 | + var peExtraPanel = findChild(dashContentList.currentItem, "peExtraPanel"); |
1024 | + var searchButton = findChild(dashContentList.currentItem, "search_action_button"); |
1025 | + |
1026 | + compare(peExtraPanel.visible, false); |
1027 | + mouseClick(searchButton); |
1028 | + tryCompare(peExtraPanel, "visible", true); |
1029 | + |
1030 | + tryCompareFunction(function() { return findChild(peExtraPanel, "OSF3") != null; }, true); |
1031 | + } |
1032 | + |
1033 | function test_searchHint() { |
1034 | var dashContentList = findChild(dashContent, "dashContentList"); |
1035 | verify(dashContentList !== null); |
FAILED: Continuous integration, rev:1992 jenkins. qa.ubuntu. com/job/ unity8- ci/6457/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 4615/console jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- wily-touch/ 839/console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- vivid/1169/ console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- wily/488/ console jenkins. qa.ubuntu. com/job/ unity8- vivid-amd64- ci/1064/ console jenkins. qa.ubuntu. com/job/ unity8- vivid-i386- ci/1065/ console jenkins. qa.ubuntu. com/job/ unity8- wily-amd64- ci/696/ console jenkins. qa.ubuntu. com/job/ unity8- wily-i386- ci/697/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 4612/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- wily-armhf/ 839/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity8- ci/6457/ rebuild
http://