on xenial help sign in
Merged trunk
commit578d8c18fc351d867c2b3e63d199b110561338cb authorAndrea Cimitan <andrea.cimitan@gmail.com> dateThu 13 Feb 2014, 17:13 (13 years ago) parent2d3c8dcd496b75
44 files changed+493−174
cmake/modules/Plugins.cmake+1 debian/changelog+36 debian/control+2 plugins/Unity/Indicators/indicatorsmanager.cpp+5−4 plugins/Unity/Indicators/indicatorsmanager.h+2−1 plugins/Unity/Indicators/indicatorsmodel.cpp+2−2 plugins/Unity/Indicators/indicatorsmodel.h+1−1 po/km.po+7−5 qml/Dash/DashContent.qml+2 qml/Dash/PreviewListView.qml+10−4 qml/Dash/Previews/Preview.qml+1 qml/Dash/Previews/PreviewActionButton.qml+2−2 qml/Dash/Previews/PreviewActionCombo.qml+2−2 qml/Dash/Previews/PreviewActions.qml+2−2 qml/Panel/Indicators.qml+3−1 qml/Panel/Indicators/VisibleIndicators.qml+2−2 qml/Panel/Indicators/client/IndicatorsClient.qml+1−2 qml/Panel/Indicators/client/IndicatorsList.qml+2−1 qml/SideStage/SideStage.qml+5 src/Panel/Indicators/client/indicatorsclient.cpp+6−1 tests/autopilot/unity8/__init__.py+16−12 tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+9−13 tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.py+116 tests/autopilot/unity8/process_helpers.py+9−7 tests/autopilot/unity8/shell/emulators/dash.py+1−1 tests/autopilot/unity8/shell/emulators/main_window.py+45−27 tests/autopilot/unity8/shell/tests/__init__.py+8−6 tests/autopilot/unity8/shell/tests/test_hud.py+4−7 tests/autopilot/unity8/shell/tests/test_notifications.py+2−3 tests/data/unity/indicators/com.canonical.indicator.fake1+4−4 tests/data/unity/indicators/com.canonical.indicator.fake2+4−4 tests/data/unity/indicators/com.canonical.indicator.fake3+4−4 tests/data/unity/indicators/com.canonical.indicator.fake4+4−4 tests/mocks/Unity/fake_scope.cpp+4−4 tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp+29−6 tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp+49−4 tests/qmltests/Dash/Previews/tst_Preview.qml+14−6 tests/qmltests/Dash/tst_Card.qml+1 tests/qmltests/Dash/tst_DashContent.qml+2 tests/qmltests/Dash/tst_GenericScopeView.qml+66−29 tests/qmltests/Panel/tst_IndicatorRow.qml+2−2 tests/qmltests/Panel/tst_Indicators.qml+1 tests/qmltests/Panel/tst_MenuContent.qml+1−1 tests/qmltests/Panel/tst_Panel.qml+4
cmake/modules/Plugins.cmake+1
@@ -24,6 +24,7 @@ macro(export_qmlfiles PLUGIN PLUGIN_SUBPATH)
2424 add_custom_target(${PLUGIN}-qmlfiles ALL
2525 COMMAND cp ${QMLFILES} ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}
2626 DEPENDS ${QMLFILES}
27+ SOURCES ${QMLFILES}
2728 )
2829
2930 # install the qmlfiles file.
debian/changelog+36
@@ -1,3 +1,39 @@
1+unity8 (7.84+14.04.20140212-0ubuntu1) trusty; urgency=low
2+
3+ [ Gerry Boland ]
4+ * Add InputFilterArea to sidestage handle to block input to mainstage
5+ app while moving sidestage (LP: #1275732)
6+
7+ [ Leo Arias ]
8+ * On the autopilot helper to open a scope, wait for the dash content
9+ list to stop moving. (LP: #1277591)
10+ * Added a test to swipe out an application started by url-dispatcher.
11+
12+ [ Nick Dedekind ]
13+ * Added a "-profile" option to the indicator-client to switch between
14+ indicator service profiles.
15+ * Fixed issue importing plugin qml files into qtcreator
16+
17+ [ Albert Astals ]
18+ * Fix test_previewCycle
19+ * Don't move the list contentY unless there's a preview to show (LP:
20+ #1271676)
21+ * Add overlay to card. Fix implicit card height. .
22+ * PreviewHeader Is just a link of the widgetData with the CardHeader
23+ * Fix tst_Preview.qml
24+ * Scopes guys want the data back
25+ * Link the pageheader scope with the current scope So that the
26+ activity indicator on search works again (LP: #1279316)
27+
28+ [ Andrea Cimitan ]
29+ * Add PreviewImage
30+ * Preview widget for video playback
31+
32+ [ CI bot ]
33+ * Add overlay to card. Fix implicit card height. .
34+
35+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 12 Feb 2014 15:15:03 +0000
36+
137unity8 (7.84+14.04.20140207.1-0ubuntu1) trusty; urgency=low
238
339 [ Ted Gould ]
debian/control+2
@@ -111,8 +111,10 @@ Depends: gir1.2-glib-2.0,
111111 python-fixtures,
112112 python-gi,
113113 python-mock,
114+ ubuntu-ui-toolkit-autopilot,
114115 unity8 (>= ${source:Version}),
115116 unity8-fake-env (>= ${source:Version}),
117+ url-dispatcher-tools,
116118 ${misc:Depends},
117119 ${python:Depends},
118120 ${shlibs:Depends},
plugins/Unity/Indicators/indicatorsmanager.cpp+5−4
@@ -26,8 +26,6 @@
2626
2727#include <paths.h>
2828
29−const QString profile = "phone";
30−
3129
3230class IndicatorsManager::IndicatorData
3331{
@@ -49,6 +47,7 @@ public:
4947IndicatorsManager::IndicatorsManager(QObject* parent)
5048 : QObject(parent)
5149 , m_loaded(false)
50+ , m_profile("phone")
5251{
5352}
5453
@@ -58,9 +57,11 @@ IndicatorsManager::~IndicatorsManager()
5857
5958}
6059
61−void IndicatorsManager::load()
60+void IndicatorsManager::load(const QString& profile)
6261{
6362 unload();
63+ m_profile = profile;
64+
6465 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
6566
6667 m_fsWatcher.reset(new QFileSystemWatcher(this));
@@ -300,7 +301,7 @@ Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
300301 Indicator::Ptr new_indicator(new Indicator(this));
301302 data->m_indicator = new_indicator;
302303 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
303− new_indicator->init(profile, data->m_fileInfo.fileName(), settings);
304+ new_indicator->init(m_profile, data->m_fileInfo.fileName(), settings);
304305 return new_indicator;
305306}
306307
plugins/Unity/Indicators/indicatorsmanager.h+2−1
@@ -38,7 +38,7 @@ public:
3838 explicit IndicatorsManager(QObject* parent = 0);
3939 ~IndicatorsManager();
4040
41− Q_INVOKABLE void load();
41+ Q_INVOKABLE void load(const QString& profile);
4242 Q_INVOKABLE void unload();
4343
4444 Indicator::Ptr indicator(const QString& indicator_name);
@@ -71,6 +71,7 @@ private:
7171 QHash<QString, IndicatorData*> m_indicatorsData;
7272 QSharedPointer<QFileSystemWatcher> m_fsWatcher;
7373 bool m_loaded;
74+ QString m_profile;
7475};
7576
7677#endif // INDICATORS_MANAGER_H
plugins/Unity/Indicators/indicatorsmodel.cpp+2−2
@@ -85,10 +85,10 @@ int IndicatorsModel::count() const
8585
8686 Load all indicators.
8787*/
88−void IndicatorsModel::load()
88+void IndicatorsModel::load(const QString& profile)
8989{
9090 m_indicators.clear();
91− m_manager->load();
91+ m_manager->load(profile);
9292}
9393
9494/*!
plugins/Unity/Indicators/indicatorsmodel.h+1−1
@@ -40,7 +40,7 @@ public:
4040 IndicatorsModel(QObject *parent=0);
4141 ~IndicatorsModel();
4242
43− Q_INVOKABLE void load();
43+ Q_INVOKABLE void load(const QString& profile);
4444 Q_INVOKABLE void unload();
4545
4646 Q_INVOKABLE QVariant data(int row, int role) const;
po/km.po+7−5
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-02-04 15:43+0000\n"
11−"PO-Revision-Date: 2013-11-20 07:34+0000\n"
11+"PO-Revision-Date: 2014-02-12 07:06+0000\n"
1212"Last-Translator: Khoem Sokhem <khoemsokhem@khmeros.info>\n"
1313"Language-Team: Khmer <km@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n"
18+"X-Launchpad-Export-Date: 2014-02-13 06:51+0000\n"
1919"X-Generator: Launchpad (build 16916)\n"
2020
2121#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -74,6 +74,8 @@ msgid ""
7474"You have now mastered the edge gestures and can start using the "
7575"phone<br><br>Tap on the screen to start"
7676msgstr ""
77+"ឥឡូវ​អ្នក​បាន​ពិនិត្យ​កាយវិការ​គែម​ "
78+"និង​អាច​ចាប់ផ្ដើម​ប្រើ​ទូរស័ព្ទ<br><br>ប៉ះ លើ​អេក្រង់​ដើម្បី​ចាប់ផ្ដើម"
7779
7880#: qml/Components/PageHeader.qml:339
7981msgid "Recent searches"
@@ -81,11 +83,11 @@ msgstr "ការ​ស្វែងរក​ថ្មី"
8183
8284#: qml/Components/SeeMore.qml:32
8385msgid "See more"
84−msgstr ""
86+msgstr "មើល​ច្រើន​ទៀត"
8587
8688#: qml/Components/SeeMore.qml:61
8789msgid "See less"
88−msgstr ""
90+msgstr "មើល​តិច​ជាង"
8991
9092#: qml/Dash/Apps/AppPreview.qml:136
9193msgid "Rate this"
@@ -159,7 +161,7 @@ msgstr "បង្ហាញ​ពាក្យ​សម្ងាត់"
159161
160162#: qml/Notifications/NotificationMenuItemFactory.qml:103
161163msgid "Please enter SIM PIN"
162−msgstr ""
164+msgstr "បញ្ចូល​កូដ PIN របស់​ស៊ីមកាត"
163165
164166#: qml/Panel/SearchIndicator.qml:27
165167msgid "Search"
qml/Dash/DashContent.qml+2
@@ -156,9 +156,11 @@ Item {
156156
157157 PageHeader {
158158 id: pageHeader
159+ objectName: "pageHeader"
159160 width: parent.width
160161 searchEntryEnabled: true
161162 searchHistory: dashContent.searchHistory
163+ scope: dashContentList.currentItem.theScope
162164
163165 childItem: TabBar {
164166 id: tabBar
qml/Dash/PreviewListView.qml+10−4
@@ -32,6 +32,7 @@ Item {
3232 property alias model: previewListView.model
3333 property alias currentIndex: previewListView.currentIndex
3434 property alias currentItem: previewListView.currentItem
35+ property alias count: previewListView.count
3536
3637 Image {
3738 objectName: "pointerArrow"
@@ -87,15 +88,19 @@ Item {
8788 id: previewDelegateMapper
8889 }
8990
90− onCurrentIndexChanged: {
91+ onCurrentIndexChanged: positionListView();
92+
93+ function positionListView() {
94+ if (!open) {
95+ return;
96+ }
97+
9198 var row = Math.floor(currentIndex / categoryDelegate.columns);
9299 if (categoryDelegate.collapsedRowCount <= row) {
93100 categoryView.expandedCategoryId = categoryId
94101 }
95102
96− if (open) {
97− categoryDelegate.highlightIndex = currentIndex
98− }
103+ categoryDelegate.highlightIndex = currentIndex
99104
100105 if (!init && model !== undefined) {
101106 var item = model.get(currentIndex)
@@ -136,6 +141,7 @@ Item {
136141 onScreen = true;
137142 categoryDelegate.highlightIndex = currentIndex;
138143 pageHeader.unfocus();
144+ positionListView();
139145 } else {
140146 // Cancel any pending preview requests or actions
141147 if (previewListView.currentItem.previewData !== undefined) {
qml/Dash/Previews/Preview.qml+1
@@ -71,6 +71,7 @@ Item {
7171 bottomMargin: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
7272
7373 model: previewModel
74+ cacheBuffer: units.gu(40)
7475
7576 Behavior on contentY { UbuntuNumberAnimation { } }
7677
qml/Dash/Previews/PreviewActionButton.qml+2−2
@@ -18,7 +18,7 @@ import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919
2020Button {
21− signal triggeredAction(string id)
21+ signal triggeredAction(var actionData)
2222
2323 property var data: null
2424 objectName: "button" + (data && data.id || "")
@@ -26,5 +26,5 @@ Button {
2626 text: data && data.label || ""
2727 iconSource: data && data.icon || ""
2828 iconPosition: "left"
29− onClicked: triggeredAction(data.id)
29+ onClicked: triggeredAction(data)
3030}
qml/Dash/Previews/PreviewActionCombo.qml+2−2
@@ -22,7 +22,7 @@ Item {
2222
2323 implicitHeight: childrenRect.height
2424
25− signal triggeredAction(string id)
25+ signal triggeredAction(var actionData)
2626
2727 property alias model: actionRepeater.model
2828
@@ -59,7 +59,7 @@ Item {
5959 delegate: PreviewActionButton {
6060 data: modelData
6161 width: implicitWidth < parent.width ? parent.width : implicitWidth
62− onClicked: root.triggeredAction(modelData.id)
62+ onClicked: root.triggeredAction(modelData)
6363 }
6464 }
6565 }
qml/Dash/Previews/PreviewActions.qml+2−2
@@ -49,7 +49,7 @@ PreviewWidget {
4949 Connections {
5050 target: loader.item
5151 onTriggeredAction: {
52− root.triggered(root.widgetId, id, null);
52+ root.triggered(root.widgetId, actionData.id, actionData);
5353 }
5454 }
5555 }
@@ -57,7 +57,7 @@ PreviewWidget {
5757 PreviewActionButton {
5858 data: visible ? row.actions[0] : null
5959 visible: row.actions && row.actions.length > 0
60− onTriggeredAction: root.triggered(root.widgetId, id, null)
60+ onTriggeredAction: root.triggered(root.widgetId, actionData.id, actionData)
6161 width: (root.width - units.gu(1)) / 2
6262 }
6363 }
qml/Panel/Indicators.qml+3−1
@@ -31,6 +31,8 @@ Showable {
3131 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
3232 property alias overFlowWidth: indicatorRow.overFlowWidth
3333 property alias showAll: indicatorRow.showAll
34+ // TODO: This should be sourced by device type (eg "desktop", "tablet", "phone"...)
35+ property string profile: "phone"
3436
3537 readonly property real hintValue: panelHeight + menuContent.headerHeight
3638 readonly property int lockThreshold: openedHeight / 2
@@ -429,6 +431,6 @@ Showable {
429431
430432 Component.onCompleted: initialise();
431433 function initialise() {
432− visibleIndicators.load();
434+ visibleIndicators.load(profile);
433435 }
434436}
qml/Panel/Indicators/VisibleIndicators.qml+2−2
@@ -78,7 +78,7 @@ Item {
7878 }
7979 }
8080
81− function load() {
82− indicatorsModel.load();
81+ function load(profile) {
82+ indicatorsModel.load(profile);
8383 }
8484}
qml/Panel/Indicators/client/IndicatorsClient.qml+1−2
@@ -33,8 +33,7 @@ Rectangle {
3333 function reset() {
3434 clear();
3535 var component = Qt.createComponent("IndicatorsList.qml");
36− var page = component.createObject(pages);
37− console.log(component.errorString());
36+ var page = component.createObject(pages, {"profile": indicatorProfile});
3837 push(page);
3938 }
4039 }
qml/Panel/Indicators/client/IndicatorsList.qml+2−1
@@ -26,12 +26,13 @@ import "../.."
2626Page {
2727 id: page
2828 anchors.fill: parent
29+ property string profile: ""
2930 title: "Plugin list"
3031
3132 Indicators.IndicatorsModel {
3233 id: indicatorsModel
3334
34− Component.onCompleted: load()
35+ Component.onCompleted: load(profile)
3536 }
3637
3738 ListView {
qml/SideStage/SideStage.qml+5
@@ -65,4 +65,9 @@ Stage {
6565 Behavior on width { NumberAnimation { easing.type: Easing.OutQuart} }
6666 z: -1
6767 }
68+
69+ InputFilterArea {
70+ anchors.fill: handle
71+ blockInput: visible
72+ }
6873}
src/Panel/Indicators/client/indicatorsclient.cpp+6−1
@@ -41,9 +41,14 @@ IndicatorsClient::IndicatorsClient(int &argc, char **argv)
4141 prependImportPaths(m_view->engine(), ::overrideImportPaths());
4242 appendImportPaths(m_view->engine(), ::fallbackImportPaths());
4343
44+ QString profile = "phone";
45+ if (args.contains(QLatin1String("-profile")) && args.size() > args.indexOf(QLatin1String("-profile")) + 1) {
46+ profile = args.at(args.indexOf(QLatin1String("-profile")) + 1);
47+ }
48+ m_view->rootContext()->setContextProperty("indicatorProfile", profile);
49+
4450 m_view->setSource(QUrl("IndicatorsClient.qml"));
4551 m_view->setResizeMode(QQuickView::SizeRootObjectToView);
46−
4752 if (args.contains(QLatin1String("-geometry")) && args.size() > args.indexOf(QLatin1String("-geometry")) + 1) {
4853 QStringList geometryArg = args.at(args.indexOf(QLatin1String("-geometry")) + 1).split('x');
4954 if (geometryArg.size() == 2) {
tests/autopilot/unity8/__init__.py+16−12
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -88,28 +88,31 @@ def get_binary_path(binary="unity8"):
8888 return binary_path
8989
9090
91−def get_data_dirs():
91+def get_data_dirs(data_dirs_mock_enabled=True):
9292 """Prepend a mock data path to XDG_DATA_DIRS."""
93+ data_dirs = _get_xdg_env_path()
94+ if data_dirs_mock_enabled:
95+ mock_data_path = _get_full_mock_data_path()
96+ if os.path.exists(mock_data_path):
97+ if data_dirs is not None:
98+ data_dirs = '{0}:{1}'.format(mock_data_path, data_dirs)
99+ else:
100+ data_dirs = mock_data_path
101+ return data_dirs
102+
103+
104+def _get_full_mock_data_path():
93105 if running_installed_tests():
94106 data_path = "/usr/share/unity8/mocks/data"
95107 else:
96108 data_path = "../../mocks/data"
97− full_data_path = os.path.abspath(
109+ return os.path.abspath(
98110 os.path.join(
99111 os.path.dirname(__file__),
100112 data_path
101113 )
102114 )
103115
104− if os.path.exists(full_data_path):
105− xdg_path = _get_xdg_env_path()
106− if xdg_path is not None:
107− return "{0}:{1}".format(full_data_path, xdg_path)
108− else:
109− return full_data_path
110− else:
111− return None
112−
113116
114117def _get_xdg_env_path():
115118 path = os.getenv("XDG_DATA_DIRS")
@@ -129,6 +132,7 @@ def _get_xdg_upstart_env():
129132 except subprocess.CalledProcessError:
130133 return None
131134
135+
132136def get_grid_size():
133137 grid_size = os.getenv('GRID_UNIT_PX')
134138 if grid_size is None:
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+9−13
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2013 Canonical
4+# Copyright (C) 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -44,9 +44,8 @@ class ApplicationLifecycleTests(UnityTestCase):
4444 self.skipTest("Test cannot be run on the desktop.")
4545
4646 def swipe_screen_from_right(self):
47− qml_view = self.main_window.get_qml_view()
48− width = qml_view.width
49− height = qml_view.height
47+ width = self.main_window.width
48+ height = self.main_window.height
5049 start_x = width
5150 start_y = int(height/2)
5251 end_x = int(width/2)
@@ -55,9 +54,6 @@ class ApplicationLifecycleTests(UnityTestCase):
5554 logger.info("Swiping screen from the right edge")
5655 self.touch.drag(start_x, start_y, end_x, end_y)
5756
58− def _get_current_focused_app_id(self):
59− return self._proxy.select_single("Shell").currentFocusedAppId
60−
6157 def _launch_app(self, app_name):
6258 """Launches the application *app_name*
6359
@@ -86,7 +82,7 @@ class ApplicationLifecycleTests(UnityTestCase):
8682
8783 self.assertThat(app, NotEquals(None))
8884 self.assertThat(
89− self._get_current_focused_app_id(),
85+ self.main_window.get_current_focused_app_id(),
9086 Eventually(Equals("messaging-app"))
9187 )
9288
@@ -98,13 +94,13 @@ class ApplicationLifecycleTests(UnityTestCase):
9894
9995 self._launch_app("messaging-app")
10096 self.assertThat(
101− self._get_current_focused_app_id(),
97+ self.main_window.get_current_focused_app_id(),
10298 Eventually(Equals("messaging-app"))
10399 )
104100
105101 self._launch_app("address-book-app")
106102 self.assertThat(
107− self._get_current_focused_app_id(),
103+ self.main_window.get_current_focused_app_id(),
108104 Eventually(Equals("address-book-app"))
109105 )
110106
@@ -119,19 +115,19 @@ class ApplicationLifecycleTests(UnityTestCase):
119115
120116 self._launch_app("messaging-app")
121117 self.assertThat(
122− self._get_current_focused_app_id(),
118+ self.main_window.get_current_focused_app_id(),
123119 Eventually(Equals("messaging-app"))
124120 )
125121
126122 self._launch_app("address-book-app")
127123 self.assertThat(
128− self._get_current_focused_app_id(),
124+ self.main_window.get_current_focused_app_id(),
129125 Eventually(Equals("address-book-app"))
130126 )
131127
132128 self.swipe_screen_from_right()
133129
134130 self.assertThat(
135− self._get_current_focused_app_id(),
131+ self.main_window.get_current_focused_app_id(),
136132 Eventually(Equals("messaging-app"))
137133 )
tests/autopilot/unity8/application_lifecycle/tests/test_url_dispatcher.pynew file+116
@@ -0,0 +1,116 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2014 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+"""Test the integration with the URL dispatcher service."""
21+
22+import os
23+import tempfile
24+
25+from autopilot import platform
26+from autopilot.matchers import Eventually
27+from testtools.matchers import Equals
28+from ubuntuuitoolkit import base as toolkit_base
29+
30+from unity8 import process_helpers
31+from unity8.shell import tests
32+
33+
34+class URLDispatcherTestCase(tests.UnityTestCase):
35+
36+ scenarios = tests._get_device_emulation_scenarios()
37+
38+ test_qml = ("""
39+import QtQuick 2.0
40+import Ubuntu.Components 0.1
41+
42+MainView {
43+ width: units.gu(48)
44+ height: units.gu(60)
45+
46+ Label {
47+ text: 'Test application.'
48+ }
49+}
50+""")
51+
52+ desktop_file_contents = ("""[Desktop Entry]
53+Type=Application
54+Name=test
55+Exec={qmlscene} {qml_file_path}
56+Icon=Not important
57+""")
58+
59+ def setUp(self):
60+ if platform.model() == 'Desktop':
61+ self.skipTest("URL dispatcher doesn't work on the desktop.")
62+ super(URLDispatcherTestCase, self).setUp()
63+ self._qml_mock_enabled = False
64+ self._data_dirs_mock_enabled = False
65+ unity_proxy = self.launch_unity()
66+ process_helpers.unlock_unity(unity_proxy)
67+
68+ def create_test_application(self):
69+ # FIXME most of this code is duplicated in the toolkit. We should
70+ # create a fixture on the toolkit for other projects to use.
71+ # http://pad.lv/1277334 --elopio - 2014-02-06
72+ qml_file_path = self._write_test_qml_file()
73+ self.addCleanup(os.remove, qml_file_path)
74+ desktop_file_path = self._write_test_desktop_file(qml_file_path)
75+ self.addCleanup(os.remove, desktop_file_path)
76+ return qml_file_path, desktop_file_path
77+
78+ def _write_test_qml_file(self):
79+ qml_file = tempfile.NamedTemporaryFile(suffix='.qml', delete=False)
80+ qml_file.write(self.test_qml.encode('utf-8'))
81+ qml_file.close()
82+ return qml_file.name
83+
84+ def _write_test_desktop_file(self, qml_file_path):
85+ desktop_file_dir = self._get_local_desktop_file_directory()
86+ if not os.path.exists(desktop_file_dir):
87+ os.makedirs(desktop_file_dir)
88+ desktop_file = tempfile.NamedTemporaryFile(
89+ suffix='.desktop', dir=desktop_file_dir, delete=False)
90+ contents = self.desktop_file_contents.format(
91+ qmlscene=toolkit_base.get_qmlscene_launch_command(),
92+ qml_file_path=qml_file_path)
93+ desktop_file.write(contents.encode('utf-8'))
94+ desktop_file.close()
95+ return desktop_file.name
96+
97+ def _get_local_desktop_file_directory(self):
98+ return os.path.join(
99+ os.environ.get('HOME'), '.local', 'share', 'applications')
100+
101+ def test_swipe_out_application_started_by_url_dispatcher(self):
102+ _, desktop_file_path = self.create_test_application()
103+ desktop_file_name = os.path.basename(desktop_file_path)
104+ application_name, _ = os.path.splitext(desktop_file_name)
105+
106+ self.assertEqual('', self.main_window.get_current_focused_app_id())
107+ self.addCleanup(os.system, 'pkill qmlscene')
108+ os.system('url-dispatcher application:///{}'.format(desktop_file_name))
109+ self.assertThat(
110+ self.main_window.get_current_focused_app_id,
111+ Eventually(Equals(application_name)))
112+
113+ self.main_window.show_dash_swiping()
114+ self.assertThat(
115+ self.main_window.get_current_focused_app_id,
116+ Eventually(Equals('')))
tests/autopilot/unity8/process_helpers.py+9−7
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Utilities
4−# Copyright (C) 2013 Canonical
4+# Copyright (C) 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -23,8 +23,8 @@ from autopilot.introspection import (
2323)
2424import logging
2525import subprocess
26−from unity8.shell.emulators import UnityEmulatorBase
27−from unity8.shell.emulators.main_window import MainWindow
26+from unity8.shell import emulators
27+from unity8.shell.emulators import main_window as main_window_emulator
2828
2929logger = logging.getLogger(__name__)
3030
@@ -54,7 +54,7 @@ def unlock_unity(unity_proxy_obj=None):
5454 try:
5555 pid = _get_unity_pid()
5656 unity = _get_unity_proxy_object(pid)
57− main_window = MainWindow(unity)
57+ main_window = unity.select_single(main_window_emulator.QQuickView)
5858 except ProcessSearchError as e:
5959 raise CannotAccessUnity(
6060 "Cannot introspect unity, make sure that it has been started "
@@ -64,7 +64,8 @@ def unlock_unity(unity_proxy_obj=None):
6464 % str(e)
6565 )
6666 else:
67− main_window = MainWindow(unity_proxy_obj)
67+ main_window = unity_proxy_obj.select_single(
68+ main_window_emulator.QQuickView)
6869
6970 greeter = main_window.get_greeter()
7071 if greeter.created == False:
@@ -110,7 +111,8 @@ def restart_unity(*args):
110111 status = _get_unity_status()
111112 if "start/" in status:
112113 try:
113− output = subprocess.check_output(['/sbin/initctl', 'stop', 'unity8'])
114+ output = subprocess.check_output(
115+ ['/sbin/initctl', 'stop', 'unity8'])
114116 logger.info(output)
115117 except subprocess.CalledProcessError as e:
116118 e.args += (
@@ -155,5 +157,5 @@ def _get_unity_pid():
155157def _get_unity_proxy_object(pid):
156158 return get_proxy_object_for_existing_process(
157159 pid=pid,
158− emulator_base=UnityEmulatorBase,
160+ emulator_base=emulators.UnityEmulatorBase,
159161 )
tests/autopilot/unity8/shell/emulators/dash.py+1−1
@@ -94,9 +94,9 @@ class Dash(emulators.UnityEmulatorBase):
9494
9595 while not scope_loader.isCurrent:
9696 scroll()
97+ self.dash_content_list.moving.wait_for(False)
9798
9899 scope = self._get_scope_from_loader(scope_loader)
99− scope.moving.wait_for(False)
100100 scope.isCurrent.wait_for(True)
101101 return scope
102102
tests/autopilot/unity8/shell/emulators/main_window.py+45−27
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -17,85 +17,103 @@
1717# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818#
1919
20+import logging
2021
22+from autopilot import logging as autopilot_logging
23+
24+from unity8.shell import emulators
2125from unity8.shell.emulators.greeter import Greeter
2226from unity8.shell.emulators.hud import Hud
2327from unity8.shell.emulators.dash import Dash
2428from unity8.shell.emulators.launcher import Launcher
2529
30+logger = logging.getLogger(__name__)
2631
27−class MainWindow(object):
28− """An emulator class that makes it easy to interact with the shell"""
29−
30− def __init__(self, app):
31− self.app = app
3232
33− def get_qml_view(self):
34− """Get the main QML view"""
35− return self.app.select_single("QQuickView")
33+class QQuickView(emulators.UnityEmulatorBase):
34+ """An emulator class that makes it easy to interact with the shell"""
3635
3736 def get_greeter(self):
38− return self.app.select_single(Greeter)
37+ return self.select_single(Greeter)
3938
4039 def get_greeter_content_loader(self):
41− return self.app.wait_select_single(
40+ return self.wait_select_single(
4241 "QQuickLoader",
4342 objectName="greeterContentLoader"
4443 )
4544
4645 def get_greeter_background(self):
47− return self.app.select_single("CrossFadeImage", objectName="greeterBackground")
46+ return self.select_single(
47+ "CrossFadeImage", objectName="greeterBackground")
4848
4949 def get_login_loader(self):
50− return self.app.select_single("QQuickLoader", objectName="loginLoader")
50+ return self.select_single("QQuickLoader", objectName="loginLoader")
5151
5252 def get_login_list(self):
53− return self.app.select_single("LoginList")
53+ return self.select_single("LoginList")
5454
5555 def get_hud(self):
56− return self.app.select_single(Hud)
56+ return self.select_single(Hud)
5757
5858 def get_hud_showable(self):
59− return self.app.select_single("Showable", objectName="hudShowable")
59+ return self.select_single("Showable", objectName="hudShowable")
6060
6161 def get_hud_show_button(self):
62− return self.app.select_single("HudButton")
62+ return self.select_single("HudButton")
6363
6464 def get_hud_edge_drag_area(self):
65− return self.app.select_single(objectName="hudDragArea")
65+ return self.select_single(objectName="hudDragArea")
6666
6767 def get_dash(self):
68− return self.app.select_single(Dash)
68+ return self.select_single(Dash)
6969
7070 def get_bottombar(self):
71− return self.app.select_single("Bottombar")
71+ return self.select_single("Bottombar")
7272
7373 def get_launcher(self):
74− return self.app.select_single(Launcher)
74+ return self.select_single(Launcher)
7575
7676 def get_pinPadLoader(self):
77− return self.app.select_single(
77+ return self.select_single(
7878 "QQuickLoader",
7979 objectName="pinPadLoader"
8080 )
8181
8282 def get_pinPadButton(self, buttonId):
83− return self.app.select_single(
83+ return self.select_single(
8484 "PinPadButton",
8585 objectName="pinPadButton%i" % buttonId
8686 )
8787
8888 def get_lockscreen(self):
89− return self.app.select_single("Lockscreen")
89+ return self.select_single("Lockscreen")
9090
9191 def get_pinentryField(self):
92− return self.app.select_single(objectName="pinentryField")
92+ return self.select_single(objectName="pinentryField")
9393
9494 def get_indicator(self, indicator_name):
95− return self.app.wait_select_single(
95+ return self.wait_select_single(
9696 'DefaultIndicatorWidget',
9797 objectName=indicator_name+'-widget'
9898 )
9999
100100 def get_shell_background(self):
101− return self.app.select_single("CrossFadeImage", objectName="backgroundImage")
101+ return self.select_single(
102+ "CrossFadeImage", objectName="backgroundImage")
103+
104+ @autopilot_logging.log_action(logger.info)
105+ def show_dash_swiping(self):
106+ """Show the dash swiping from the left."""
107+ width = self.width
108+ height = self.height
109+ start_x = 0
110+ start_y = height // 2
111+ end_x = width
112+ end_y = start_y
113+
114+ self.pointing_device.drag(start_x, start_y, end_x, end_y)
115+ return self.get_dash()
116+
117+ def get_current_focused_app_id(self):
118+ """Return the id of the focused application."""
119+ return self.select_single('Shell').currentFocusedAppId
tests/autopilot/unity8/shell/tests/__init__.py+8−6
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -43,8 +43,8 @@ from unity8 import (
4343 get_data_dirs
4444)
4545from unity8.process_helpers import restart_unity_with_testability
46+from unity8.shell.emulators import main_window as main_window_emulator
4647from unity8.shell.emulators.dash import Dash
47−from unity8.shell.emulators.main_window import MainWindow
4848
4949
5050logger = logging.getLogger(__name__)
@@ -139,10 +139,9 @@ class UnityTestCase(AutopilotTestCase):
139139 self._proxy = None
140140 self._lightdm_mock_type = None
141141 self._qml_mock_enabled = True
142+ self._data_dirs_mock_enabled = True
142143 self._environment = {}
143144
144− self._patch_data_dirs()
145−
146145 #### FIXME: This is a work around re: lp:1238417 ####
147146 if model() != "Desktop":
148147 from autopilot.input import _uinput
@@ -268,6 +267,9 @@ class UnityTestCase(AutopilotTestCase):
268267 if self._qml_mock_enabled:
269268 self._setup_extra_mock_environment_patch()
270269
270+ if self._data_dirs_mock_enabled:
271+ self._patch_data_dirs()
272+
271273 # FIXME: we shouldn't be doing this
272274 # $MIR_SOCKET, fallback to $XDG_RUNTIME_DIR/mir_socket and
273275 # /tmp/mir_socket as last resort
@@ -321,7 +323,7 @@ class UnityTestCase(AutopilotTestCase):
321323 logger.warning("Appears unity was already stopped!")
322324
323325 def _patch_data_dirs(self):
324− data_dirs = get_data_dirs()
326+ data_dirs = get_data_dirs(self._data_dirs_mock_enabled)
325327 if data_dirs is not None:
326328 self._environment['XDG_DATA_DIRS'] = data_dirs
327329
@@ -391,4 +393,4 @@ class UnityTestCase(AutopilotTestCase):
391393
392394 @property
393395 def main_window(self):
394− return MainWindow(self._proxy)
396+ return self._proxy.select_single(main_window_emulator.QQuickView)
tests/autopilot/unity8/shell/tests/test_hud.py+4−7
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -41,7 +41,6 @@ class TestHud(UnityTestCase, DragMixin):
4141 """
4242 unity_proxy = self.launch_unity()
4343 unlock_unity(unity_proxy)
44− window = self.main_window.get_qml_view()
4544 hud_show_button = self.main_window.get_hud_show_button()
4645 edge_drag_area = self.main_window.get_hud_edge_drag_area()
4746 hud = self.main_window.get_hud()
@@ -49,7 +48,7 @@ class TestHud(UnityTestCase, DragMixin):
4948 self._launch_test_app_from_app_screen()
5049
5150 swipe_coords = hud.get_button_swipe_coords(
52− window,
51+ self.main_window,
5352 hud_show_button
5453 )
5554 initialBottomMargin = int(hud_show_button.bottomMargin)
@@ -83,14 +82,13 @@ class TestHud(UnityTestCase, DragMixin):
8382 """
8483 unity_proxy = self.launch_unity()
8584 unlock_unity(unity_proxy)
86− window = self.main_window.get_qml_view()
8785 hud_show_button = self.main_window.get_hud_show_button()
8886 hud = self.main_window.get_hud()
8987
9088 self._launch_test_app_from_app_screen()
9189
9290 swipe_coords = hud.get_button_swipe_coords(
93− window,
91+ self.main_window,
9492 hud_show_button
9593 )
9694
@@ -137,7 +135,6 @@ class TestHud(UnityTestCase, DragMixin):
137135 """
138136 unity_proxy = self.launch_unity()
139137 unlock_unity(unity_proxy)
140− window = self.main_window.get_qml_view()
141138 hud = self.main_window.get_hud()
142139
143140 self._launch_test_app_from_app_screen()
@@ -146,7 +143,7 @@ class TestHud(UnityTestCase, DragMixin):
146143
147144 start_x, start_y = hud.get_close_button_coords()
148145 end_x = start_x
149− end_y = int(window.height / 2)
146+ end_y = int(self.main_window.height / 2)
150147
151148 self.touch.drag(start_x, start_y, end_x, end_y)
152149 self.assertThat(hud.shown, Eventually(Equals(False)))
tests/autopilot/unity8/shell/tests/test_notifications.py+2−3
@@ -1,7 +1,7 @@
11# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
22#
33# Unity Autopilot Test Suite
4−# Copyright (C) 2012-2013 Canonical
4+# Copyright (C) 2012, 2013, 2014 Canonical
55#
66# This program is free software: you can redistribute it and/or modify
77# it under the terms of the GNU General Public License as published by
@@ -61,8 +61,7 @@ class NotificationsBase(UnityTestCase):
6161 return os.path.dirname(__file__) + "/../../../../../qml/graphics/" + icon_name
6262
6363 def _get_notifications_list(self):
64− main_view = self.main_window.get_qml_view()
65− return main_view.select_single(
64+ return self.main_window.select_single(
6665 "Notifications",
6766 objectName='notificationList'
6867 )
tests/data/unity/indicators/com.canonical.indicator.fake1+4−4
@@ -3,8 +3,8 @@ Name=indicator-fake1
33ObjectPath=/com/canonical/indicator/fake1
44Position=1
55
6−[phone]
7−ObjectPath=/com/canonical/indicator/fake1/phone
6+[test1]
7+ObjectPath=/com/canonical/indicator/fake1/test1
88
9−[desktop]
10−ObjectPath=/com/canonical/indicator/fake1/desktop
9+[test2]
10+ObjectPath=/com/canonical/indicator/fake1/test2
tests/data/unity/indicators/com.canonical.indicator.fake2+4−4
@@ -3,8 +3,8 @@ Name=indicator-fake2
33ObjectPath=/com/canonical/indicator/fake2
44Position=0
55
6−[phone]
7−ObjectPath=/com/canonical/indicator/fake2/phone
6+[test1]
7+ObjectPath=/com/canonical/indicator/fake2/test1
88
9−[desktop]
10−ObjectPath=/com/canonical/indicator/fake2/desktop
9+[test2]
10+ObjectPath=/com/canonical/indicator/fake2/test2
tests/data/unity/indicators/com.canonical.indicator.fake3+4−4
@@ -3,8 +3,8 @@ Name=indicator-fake3
33ObjectPath=/com/canonical/indicator/fake3
44Position=3
55
6−[phone]
7−ObjectPath=/com/canonical/indicator/fake3/phone
6+[test1]
7+ObjectPath=/com/canonical/indicator/fake3/test1
88
9−[desktop]
10−ObjectPath=/com/canonical/indicator/fake3/desktop
9+[test2]
10+ObjectPath=/com/canonical/indicator/fake3/test2
tests/data/unity/indicators/com.canonical.indicator.fake4+4−4
@@ -3,8 +3,8 @@ Name=indicator-fake4
33ObjectPath=/com/canonical/indicator/fake4
44Position=2
55
6−[phone]
7−ObjectPath=/com/canonical/indicator/fake4/phone
6+[test1]
7+ObjectPath=/com/canonical/indicator/fake4/test1
88
9−[desktop]
10−ObjectPath=/com/canonical/indicator/fake4/desktop
9+[test2]
10+ObjectPath=/com/canonical/indicator/fake4/test2
tests/mocks/Unity/fake_scope.cpp+4−4
@@ -36,9 +36,9 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
3636 , m_visible(visible)
3737 , m_searching(false)
3838 , m_isActive(false)
39+ , m_previewRendererName("preview-generic")
3940 , m_categories(new Categories(this))
4041 , m_results(new DeeListModel(this))
41− , m_previewRendererName("preview-generic")
4242{
4343 DeeModel* results_model = create_results_model(20, 300);
4444 m_categories->setResultModel(results_model);
@@ -155,7 +155,6 @@ void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVari
155155 const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
156156 const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
157157{
158− Q_UNUSED(uri);
159158 Q_UNUSED(icon_hint);
160159 Q_UNUSED(category);
161160 Q_UNUSED(result_type);
@@ -165,7 +164,8 @@ void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVari
165164 Q_UNUSED(dnd_uri);
166165 Q_UNUSED(metadata);
167166
168− m_timer.start();
167+ if (uri != "uri://result.2")
168+ m_timer.start();
169169}
170170
171171void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
@@ -202,7 +202,7 @@ DeeModel* create_categories_model(unsigned category_count) {
202202 for(unsigned i = 0; i < category_count; ++i)
203203 {
204204 dee_model_append(category_model,
205− std::to_string(i).c_str(),
205+ (i == 2) ? "applications.scope" : std::to_string(i).c_str(),
206206 ("Category "+std::to_string(i)).c_str(),
207207 "gtk-apply",
208208 i % 2 == 0 ? "grid" : "carousel",
tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp+29−6
@@ -50,7 +50,7 @@ private Q_SLOTS:
5050 QVERIFY(!manager.isLoaded());
5151 QCOMPARE(manager.indicators().count(), 0);
5252
53− manager.load();
53+ manager.load("test1");
5454
5555 QVERIFY(manager.isLoaded());
5656 QCOMPARE(manager.indicators().count(), 4);
@@ -64,10 +64,10 @@ private Q_SLOTS:
6464 /*
6565 * Test the creation & initialising of the indicator data
6666 */
67− void testPluginInterface()
67+ void testPluginInterfaceProfile1()
6868 {
6969 IndicatorsManager manager;
70− manager.load();
70+ manager.load("test1");
7171
7272 Indicator::Ptr indicator = manager.indicator("indicator-fake1");
7373 QVERIFY(indicator ? true : false);
@@ -81,7 +81,30 @@ private Q_SLOTS:
8181 QCOMPARE(props["busName"].toString(), QString("com.canonical.indicator.fake1"));
8282 QCOMPARE(props["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake1"));
8383
84− QCOMPARE(props["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake1/phone"));
84+ QCOMPARE(props["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake1/test1"));
85+ }
86+
87+ /*
88+ * Test the creation & initialising of the indicator data
89+ */
90+ void testPluginInterfaceProfile2()
91+ {
92+ IndicatorsManager manager;
93+ manager.load("test2");
94+
95+ Indicator::Ptr indicator = manager.indicator("indicator-fake1");
96+ QVERIFY(indicator ? true : false);
97+
98+ QCOMPARE(indicator->identifier(), QString("indicator-fake1"));
99+ QCOMPARE(indicator->position(), 1);
100+
101+ // Check that the initial properties have been set.
102+ QVariantMap props = indicator->indicatorProperties().toMap();
103+ QCOMPARE(props.count(), 4);
104+ QCOMPARE(props["busName"].toString(), QString("com.canonical.indicator.fake1"));
105+ QCOMPARE(props["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake1"));
106+
107+ QCOMPARE(props["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake1/test2"));
85108 }
86109
87110 /*
@@ -90,7 +113,7 @@ private Q_SLOTS:
90113 void testPluginInstance()
91114 {
92115 IndicatorsManager manager;
93− manager.load();
116+ manager.load("test2");
94117
95118 Indicator::Ptr i0 = manager.indicator("indicator-fake1");
96119 Indicator::Ptr i1 = manager.indicator("indicator-fake1");
@@ -110,7 +133,7 @@ private Q_SLOTS:
110133 void testPluginInitAndShutdown()
111134 {
112135 IndicatorsManager manager;
113− manager.load();
136+ manager.load("test1");
114137
115138 QWeakPointer<Indicator> wp0;
116139 QWeakPointer<Indicator> wp1;
tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp+49−4
@@ -50,7 +50,7 @@ private Q_SLOTS:
5050
5151 QCOMPARE(model.property("count").toInt(), 0);
5252
53− model.load();
53+ model.load("test1");
5454
5555 QCOMPARE(model.property("count").toInt(), 4);
5656
@@ -61,13 +61,13 @@ private Q_SLOTS:
6161 }
6262
6363 /*
64− * Testa that the plugin data was loaded correctly
64+ * Testa that the plugin data was loaded correctly ( "test1" )
6565 */
66− void testDataAndOrder()
66+ void testDataAndOrderProfile1()
6767 {
6868 // Priority order. (2, 1, 4, 3)
6969 IndicatorsModel model;
70− model.load();
70+ model.load("test1");
7171
7272 // should be in order:
7373 // fake3, fake4, fake1, fake2
@@ -75,18 +75,63 @@ private Q_SLOTS:
7575 QCOMPARE(model.data(0, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake3"));
7676 QCOMPARE(model.data(0, IndicatorsModelRole::Position).toInt(), 3);
7777 QCOMPARE(model.data(0, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake3"));
78+ QCOMPARE(model.data(0, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake3"));
79+ QCOMPARE(model.data(0, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake3/test1"));
7880
7981 QCOMPARE(model.data(1, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake4"));
8082 QCOMPARE(model.data(1, IndicatorsModelRole::Position).toInt(), 2);
8183 QCOMPARE(model.data(1, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake4"));
84+ QCOMPARE(model.data(1, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake4"));
85+ QCOMPARE(model.data(1, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake4/test1"));
8286
8387 QCOMPARE(model.data(2, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake1"));
8488 QCOMPARE(model.data(2, IndicatorsModelRole::Position).toInt(), 1);
8589 QCOMPARE(model.data(2, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake1"));
90+ QCOMPARE(model.data(2, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake1"));
91+ QCOMPARE(model.data(2, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake1/test1"));
8692
8793 QCOMPARE(model.data(3, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake2"));
8894 QCOMPARE(model.data(3, IndicatorsModelRole::Position).toInt(), 0);
8995 QCOMPARE(model.data(3, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake2"));
96+ QCOMPARE(model.data(3, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake2"));
97+ QCOMPARE(model.data(3, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake2/test1"));
98+ }
99+
100+ /*
101+ * Testa that the plugin data was loaded correctly ( "test2" )
102+ */
103+ void testDataAndOrderProfile2()
104+ {
105+ // Priority order. (2, 1, 4, 3)
106+ IndicatorsModel model;
107+ model.load("test2");
108+
109+ // should be in order:
110+ // fake3, fake4, fake1, fake2
111+
112+ QCOMPARE(model.data(0, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake3"));
113+ QCOMPARE(model.data(0, IndicatorsModelRole::Position).toInt(), 3);
114+ QCOMPARE(model.data(0, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake3"));
115+ QCOMPARE(model.data(0, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake3"));
116+ QCOMPARE(model.data(0, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake3/test2"));
117+
118+ QCOMPARE(model.data(1, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake4"));
119+ QCOMPARE(model.data(1, IndicatorsModelRole::Position).toInt(), 2);
120+ QCOMPARE(model.data(1, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake4"));
121+ QCOMPARE(model.data(1, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake4"));
122+ QCOMPARE(model.data(1, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake4/test2"));
123+
124+ QCOMPARE(model.data(2, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake1"));
125+ QCOMPARE(model.data(2, IndicatorsModelRole::Position).toInt(), 1);
126+ QCOMPARE(model.data(2, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake1"));
127+ QCOMPARE(model.data(2, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake1"));
128+ QCOMPARE(model.data(2, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake1/test2"));
129+
130+ QCOMPARE(model.data(3, IndicatorsModelRole::Identifier).toString(), QString("indicator-fake2"));
131+ QCOMPARE(model.data(3, IndicatorsModelRole::Position).toInt(), 0);
132+ QCOMPARE(model.data(3, IndicatorsModelRole::IndicatorProperties).toMap()["busName"].toString(), QString("com.canonical.indicator.fake2"));
133+ QCOMPARE(model.data(3, IndicatorsModelRole::IndicatorProperties).toMap()["actionsObjectPath"].toString(), QString("/com/canonical/indicator/fake2"));
134+ QCOMPARE(model.data(3, IndicatorsModelRole::IndicatorProperties).toMap()["menuObjectPath"].toString(), QString("/com/canonical/indicator/fake2/test2"));
90135 }
91136};
92137
tests/qmltests/Dash/Previews/tst_Preview.qml+14−6
@@ -87,21 +87,29 @@ Rectangle {
8787
8888 function test_containOnFocus() {
8989 waitForRendering(preview);
90− var widget = findChild(preview, "widget-13");
91−
92− widget.forceActiveFocus();
90+ tryCompareFunction(function () { return findChild(preview, "widget-9") != null }, true);
91+ var widget = findChild(preview, "widget-9");
9392
9493 var bottomLeft = preview.mapFromItem(widget, 0, widget.height);
94+ verify(bottomLeft.y > preview.height);
9595
96− tryCompareFunction(function () { return bottomLeft.y <= preview.height }, true);
96+ widget.forceActiveFocus();
97+
98+ tryCompareFunction(function () {
99+ var bottomLeft = preview.mapFromItem(widget, 0, widget.height);
100+ return bottomLeft.y <= preview.height
101+ }, true);
97102 }
98103
99104 function test_containOnGrow() {
100105 waitForRendering(preview);
106+ tryCompareFunction(function () { return findChild(preview, "widget-13") != null }, true);
101107 var widget = findChild(preview, "widget-13");
102108
103− widget.forceActiveFocus();
104− widget.height += 200;
109+ var bottomLeft = preview.mapFromItem(widget, 0, widget.height);
110+ verify(bottomLeft.y > preview.height);
111+
112+ root.height += units.gu(50);
105113
106114 tryCompareFunction(function () {
107115 var bottomLeft = preview.mapFromItem(widget, 0, widget.height);
tests/qmltests/Dash/tst_Card.qml+1
@@ -85,6 +85,7 @@ Rectangle {
8585 id: cardTool
8686 template: card.template
8787 components: card.components
88+ viewWidth: units.gu(48)
8889 }
8990
9091 Card {
tests/qmltests/Dash/tst_DashContent.qml+2
@@ -250,6 +250,8 @@ Item {
250250 function test_scope_mapping(data) {
251251 dashContent.setCurrentScopeAtIndex(data.index, true, false);
252252 tryCompareFunction(get_current_item_object_name, data.objectName)
253+ var pageHeader = findChild(dashContent, "pageHeader");
254+ compare(pageHeader.scope, scopesModel.get(data.index));
253255 }
254256
255257 function test_is_active_data() {
tests/qmltests/Dash/tst_GenericScopeView.qml+66−29
@@ -32,7 +32,7 @@ Item {
3232 id: scopes
3333
3434 onLoadedChanged: {
35− genericScopeView.scope = scopes.get(0)
35+ genericScopeView.scope = scopes.get(2)
3636 }
3737 }
3838
@@ -41,17 +41,10 @@ Item {
4141 signal mainStageFocusedApplicationChanged()
4242 }
4343
44− PreviewListView {
45− id: previewListView
46− anchors.fill: parent
47− openEffect: openEffect
48− categoryView: genericScopeView.categoryView
49− scope: genericScopeView.scope
50− }
51−
5244 DashContentOpenEffect {
5345 id: openEffect
5446 previewListView: previewListView
47+ sourceItem: genericScopeView
5548 }
5649
5750 PageHeaderLabel {
@@ -101,36 +94,42 @@ Item {
10194 function test_showDash() {
10295 previewListView.open = true;
10396 tryCompare(openEffect, "live", true);
104− scopes.get(0).showDash();
97+ scopes.get(2).showDash();
10598 tryCompare(previewListView, "open", false);
10699 tryCompare(openEffect, "live", true);
107100 }
108101
109102 function test_hideDash() {
110103 previewListView.open = true;
111− scopes.get(0).hideDash();
104+ scopes.get(2).hideDash();
112105 tryCompare(previewListView, "open", false);
106+ tryCompare(openEffect, "gap", 0);
113107 }
114108
115− function openPreview() {
116− var categoryListView = findChild(genericScopeView, "categoryListView");
117− categoryListView.positionAtBeginning();
118−
109+ function openPreview(filterGridName, willOpen) {
110+ if (filterGridName === undefined)
111+ filterGridName = "0";
112+ if (willOpen === undefined)
113+ willOpen = true;
119114 tryCompareFunction(function() {
120− var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
121− return tile != undefined;
115+ var filterGrid = findChild(genericScopeView, filterGridName);
116+ if (filterGrid != null) {
117+ var tile = findChild(filterGrid, "delegate0");
118+ return tile != null;
119+ }
120+ return false;
122121 },
123122 true);
124− var tile = findChild(findChild(genericScopeView, "0"), "delegate0");
123+ var tile = findChild(findChild(genericScopeView, filterGridName), "delegate0");
125124 mouseClick(tile, tile.width / 2, tile.height / 2);
126− tryCompare(previewListView, "open", true);
127− tryCompare(openEffect, "gap", 1);
125+ tryCompare(previewListView, "open", willOpen);
126+ tryCompare(openEffect, "gap", willOpen ? 1 : 0);
128127 }
129128
130129 function checkArrowPosition(index) {
131130 tryCompareFunction(function() {
132131 var tile = findChild(findChild(genericScopeView, "0"), "delegate" + index);
133− return tile != undefined;
132+ return tile != null;
134133 },
135134 true);
136135 var tile = findChild(findChild(genericScopeView, "0"), "delegate" + index);
@@ -154,6 +153,8 @@ Item {
154153
155154 function test_previewOpenClose() {
156155 tryCompare(previewListView, "open", false);
156+ var categoryListView = findChild(genericScopeView, "categoryListView");
157+ categoryListView.positionAtBeginning();
157158
158159 openPreview();
159160
@@ -193,7 +194,11 @@ Item {
193194 }
194195
195196 function test_previewCycle() {
197+ var categoryListView = findChild(genericScopeView, "categoryListView");
198+ categoryListView.positionAtBeginning();
199+
196200 tryCompare(previewListView, "open", false);
201+ tryCompare(openEffect, "gap", 0);
197202
198203 openPreview();
199204
@@ -211,7 +216,7 @@ Item {
211216 checkArrowPosition(0);
212217
213218 // flick to the next previews
214−
219+ tryCompare(previewListView, "count", 15);
215220 for (var i = 1; i < previewListView.count; ++i) {
216221
217222 mouseFlick(previewListView, previewListView.width - units.gu(1),
@@ -246,8 +251,13 @@ Item {
246251 }
247252
248253 function test_show_spinner() {
254+ var categoryListView = findChild(genericScopeView, "categoryListView");
255+ waitForRendering(categoryListView);
256+ categoryListView.contentY = units.gu(13);
249257 openPreview();
250258 var previewLoader = findChild(previewListView, "previewLoader0");
259+ compare(previewLoader.source.toString().split("/").pop(), "DashPreviewPlaceholder.qml");
260+ compare(categoryListView.contentY, 0)
251261 tryCompare(previewLoader, "progress", 1.0);
252262 tryCompareFunction(function() { return previewLoader.item != undefined; }, true);
253263
@@ -263,13 +273,13 @@ Item {
263273 function test_changeScope() {
264274 genericScopeView.scope.searchQuery = "test"
265275 genericScopeView.scope = scopes.get(1)
266− genericScopeView.scope = scopes.get(0)
276+ genericScopeView.scope = scopes.get(2)
267277 tryCompare(genericScopeView.scope, "searchQuery", "")
268278 }
269279
270280 function test_filter_expand_collapse() {
271281 // wait for the item to be there
272− tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != undefined; }, true);
282+ tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != null; }, true);
273283
274284 var header = findChild(genericScopeView, "dashSectionHeader0")
275285 var category = findChild(genericScopeView, "dashCategory0")
@@ -306,7 +316,7 @@ Item {
306316 }
307317
308318 function test_showPreviewCarousel() {
309− tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != undefined; }, true);
319+ tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != null; }, true);
310320 var tile = findChild(genericScopeView, "carouselDelegate");
311321 mouseClick(tile, tile.width / 2, tile.height / 2);
312322 tryCompare(openEffect, "gap", 1);
@@ -332,15 +342,15 @@ Item {
332342 tryCompare(previewListView, "open", false);
333343 }
334344
335− function test_filter_expand_expand() {
345+ function test_filter_expand_expand_collapse() {
336346 // wait for the item to be there
337− tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader2") != undefined; }, true);
347+ tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeaderapplications.scope") != null; }, true);
338348
339349 var categoryListView = findChild(genericScopeView, "categoryListView");
340350 categoryListView.contentY = categoryListView.height;
341351
342− var header2 = findChild(genericScopeView, "dashSectionHeader2")
343− var category2 = findChild(genericScopeView, "dashCategory2")
352+ var header2 = findChild(genericScopeView, "dashSectionHeaderapplications.scope")
353+ var category2 = findChild(genericScopeView, "dashCategoryapplications.scope")
344354 var category2FilterGrid = category2.children[0].children[0].children[0];
345355 verify(UT.Util.isInstanceOf(category2FilterGrid, "FilterGrid"));
346356
@@ -368,11 +378,30 @@ Item {
368378 tryCompare(category0, "filtered", false);
369379 tryCompare(category2, "filtered", true);
370380 tryCompare(category2FilterGrid, "filter", true);
381+ mouseClick(header0, header0.width / 2, header0.height / 2);
382+ tryCompare(category0, "filtered", true);
383+ tryCompare(category2, "filtered", true);
384+ }
385+
386+ function test_bug1271676_no_move_y_no_preview() {
387+ waitForRendering(genericScopeView);
388+ var categoryListView = findChild(genericScopeView, "categoryListView");
389+ waitForRendering(categoryListView);
390+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategoryapplications.scope") != null; }, true);
391+ var category = findChild(genericScopeView, "dashCategoryapplications.scope")
392+ categoryListView.contentY = category.y;
393+ waitForRendering(categoryListView);
394+ var contentYBefore = categoryListView.contentY
395+ openPreview("applications.scope", false); // This actually doesn't open anything because we
396+ // have code so that the item of installed
397+ // does activate instead of preview and never shows a preview
398+ compare(categoryListView.contentY, contentYBefore);
371399 }
372400
373401 function test_narrow_delegate_ranges_expand() {
374402 tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
375403 var category = findChild(genericScopeView, "dashCategory0")
404+ tryCompare(category, "filtered", true);
376405
377406 shell.width = units.gu(20)
378407 var categoryListView = findChild(genericScopeView, "categoryListView");
@@ -386,4 +415,12 @@ Item {
386415 }
387416 }
388417 }
418+
419+ PreviewListView {
420+ id: previewListView
421+ anchors.fill: parent
422+ openEffect: openEffect
423+ categoryView: genericScopeView.categoryView
424+ scope: genericScopeView.scope
425+ }
389426}
tests/qmltests/Panel/tst_IndicatorRow.qml+2−2
@@ -32,7 +32,7 @@ Item {
3232
3333 function init_test()
3434 {
35− indicatorModel.load();
35+ indicatorModel.load("test1");
3636
3737 indicatorRow.state = "initial";
3838 indicatorRow.setCurrentItemIndex(-1);
@@ -52,7 +52,7 @@ Item {
5252
5353 indicatorsModel: indicatorModel
5454
55− Component.onCompleted: indicatorModel.load()
55+ Component.onCompleted: indicatorModel.load("test1")
5656 }
5757
5858 Indicators.IndicatorsModel {
tests/qmltests/Panel/tst_Indicators.qml+1
@@ -43,6 +43,7 @@ Item {
4343 width: (shell.width > units.gu(60)) ? units.gu(40) : shell.width
4444 y: 0
4545 shown: false
46+ profile: "test1"
4647
4748 openedHeight: parent.height - click_me.height
4849 }
tests/qmltests/Panel/tst_MenuContent.qml+1−1
@@ -41,7 +41,7 @@ Item {
4141
4242 Indicators.IndicatorsModel {
4343 id: indicatorsModel
44− Component.onCompleted: load()
44+ Component.onCompleted: load("test1")
4545 }
4646
4747 MenuContent {
tests/qmltests/Panel/tst_Panel.qml+4
@@ -40,6 +40,10 @@ Item {
4040 Panel {
4141 id: panel
4242 anchors.fill: parent
43+
44+ indicators {
45+ profile: "test1"
46+ }
4347 }
4448
4549 UT.UnityTestCase {