on xenial help sign in
More autopilot for indicators
commit8c60ce99f342a93d2540a4481f27c458296ed113 authorNick Dedekind <nicholas.dedekind@gmail.com> dateFri 7 Jun 2013, 14:48 (13 years ago) parent4c4b83e
19 files changed+199−27
plugins/IndicatorsClient/client/indicatorsclient.cpp+2−2 plugins/IndicatorsClient/client/indicatorsclient.qrc+3−3 plugins/IndicatorsClient/client/qml/indicatorsclient.qml → plugins/IndicatorsClient/client/qml/IndicatorsClient.qml+9−1 plugins/IndicatorsClient/client/qml/indicatorslist.qml → plugins/IndicatorsClient/client/qml/IndicatorsList.qml+4−3 plugins/IndicatorsClient/client/qml/indicatorspage.qml → plugins/IndicatorsClient/client/qml/IndicatorsPage.qml+3−2 plugins/IndicatorsClient/indicatorclientinterface.h+8−1 plugins/IndicatorsClient/indicators/common/indicatorclient_common.cpp+14 plugins/IndicatorsClient/indicators/common/indicatorclient_common.h+5 plugins/IndicatorsClient/indicatorsmodel.cpp+16−2 plugins/IndicatorsClient/indicatorsmodel.h+3−1 plugins/IndicatorsClient/qml/FactoryMenu.qml+1 plugins/IndicatorsClient/qml/Menu.qml+1−1 plugins/IndicatorsClient/qml/ProgressMenu.qml+2 plugins/IndicatorsClient/qml/SwitchMenu.qml+4 tests/autopilot/indicators_client/emulators/__init__.py+25 tests/autopilot/indicators_client/emulators/common.py+14 tests/autopilot/indicators_client/emulators/main_window.py+15−4 tests/autopilot/indicators_client/tests/__init__.py+22−7 tests/autopilot/indicators_client/tests/test_power.py+48
plugins/IndicatorsClient/client/indicatorsclient.cpp+2−2
@@ -45,7 +45,7 @@ void IndicatorsClient::setupUI()
4545{
4646 m_view = new QQuickView;
4747
48− m_view->setSource(QUrl("qrc:qml/indicatorsclient.qml"));
48+ m_view->setSource(QUrl("qrc:qml/IndicatorsClient.qml"));
4949 m_view->setResizeMode(QQuickView::SizeRootObjectToView);
5050
5151 //Usable size on desktop
@@ -55,6 +55,6 @@ void IndicatorsClient::setupUI()
5555int IndicatorsClient::run()
5656{
5757 setupUI();
58− m_view->showMaximized();
58+ m_view->show();
5959 return m_application->exec();
6060}
plugins/IndicatorsClient/client/indicatorsclient.qrc+3−3
@@ -1,7 +1,7 @@
11<RCC>
22 <qresource prefix="/">
3− <file>qml/indicatorsclient.qml</file>
4− <file>qml/indicatorslist.qml</file>
5− <file>qml/indicatorspage.qml</file>
3+ <file>qml/IndicatorsClient.qml</file>
4+ <file>qml/IndicatorsList.qml</file>
5+ <file>qml/IndicatorsPage.qml</file>
66 </qresource>
77</RCC>
plugins/IndicatorsClient/client/qml/indicatorsclient.qml → plugins/IndicatorsClient/client/qml/IndicatorsClient.qmlrenamed+9−1
@@ -23,10 +23,18 @@ import Ubuntu.Components.ListItems 0.1 as ListItem
2323
2424Rectangle {
2525 color: "black"
26+ id: root
27+
2628 PageStack {
2729 id: pages
2830
2931 anchors.fill: parent
30− Component.onCompleted: push(Qt.createComponent("indicatorslist.qml"))
32+ Component.onCompleted: root.reset()
33+ }
34+
35+ function reset() {
36+ pages.clear();
37+ var component = Qt.createComponent("IndicatorsList.qml")
38+ pages.push(component.createObject(pages));
3139 }
3240}
plugins/IndicatorsClient/client/qml/indicatorslist.qml → plugins/IndicatorsClient/client/qml/IndicatorsList.qmlrenamed+4−3
@@ -35,6 +35,7 @@ Page {
3535
3636 ListView {
3737 id: mainMenu
38+ objectName: "mainMenu"
3839 anchors.fill: parent
3940 model: indicators
4041
@@ -43,7 +44,7 @@ Page {
4344 anchors.right: parent.right
4445 height: implicitHeight
4546 progression: isValid
46− objectName: title
47+ objectName: identifier
4748
4849 // Used basic components instead of 'ListItem.Standard' properties because it does not support image resize
4950 Image {
@@ -68,8 +69,8 @@ Page {
6869 var props = model.initialProperties
6970 props["widgetsMap"] = indicators.widgetsMap
7071
71− var page = Qt.createComponent("indicatorspage.qml")
72− pages.push(page, {"initialProperties" : props, "component" : model.component})
72+ var page = Qt.createComponent("IndicatorsPage.qml")
73+ pages.push(page.createObject(pages), {"initialProperties" : props, "component" : model.component})
7374 }
7475 }
7576 }
plugins/IndicatorsClient/client/qml/indicatorspage.qml → plugins/IndicatorsClient/client/qml/IndicatorsPage.qmlrenamed+3−2
@@ -25,12 +25,13 @@ Page {
2525
2626 title: initialProperties && initialProperties.title ? initialProperties.title : ""
2727 property variant initialProperties
28− property alias component : _loader.sourceComponent
28+ property alias component : page_loader.sourceComponent
2929
3030 anchors.fill: parent
3131
3232 Loader {
33− id: _loader
33+ id: page_loader
34+ objectName: "page_loader"
3435
3536 anchors.fill: parent
3637
plugins/IndicatorsClient/indicatorclientinterface.h+8−1
@@ -56,6 +56,14 @@ public:
5656 */
5757 virtual void shutdown() = 0;
5858
59+ /**
60+ * @brief Used to retrieve the current plugin identifier
61+ * @return The identifier
62+ *
63+ * This function can be used to retrieve the indicator identifier
64+ */
65+ virtual QString identifier() const = 0;
66+
5967 /**
6068 * @brief Used to retrieve the current plugin icon
6169 * @return The icon url
@@ -64,7 +72,6 @@ public:
6472 */
6573 virtual QUrl icon() const = 0;
6674
67−
6875 /**
6976 * @brief Used to retrieve the current plugin title
7077 * @return The title
plugins/IndicatorsClient/indicators/common/indicatorclient_common.cpp+14
@@ -57,6 +57,7 @@ void IndicatorClientCommon::init(const QSettings& settings)
5757{
5858 Q_INIT_RESOURCE(indicatorclient_common);
5959
60+ setId(settings.value("Indicator Service/Name").toString());
6061 QString dbusService = settings.value("Indicator Service/DBusName").toString();
6162 QString objectPath = settings.value("Indicator Service/ObjectPath").toString();
6263
@@ -165,6 +166,19 @@ void IndicatorClientCommon::shutdown()
165166 m_actionGroup = 0;
166167}
167168
169+QString IndicatorClientCommon::identifier() const
170+{
171+ return m_identifier;
172+}
173+
174+void IndicatorClientCommon::setId(const QString &identifier)
175+{
176+ if (identifier != m_identifier) {
177+ m_identifier = identifier;
178+ Q_EMIT identifierChanged(m_identifier);
179+ }
180+}
181+
168182QUrl IndicatorClientCommon::icon() const
169183{
170184 if (!m_icon.isEmpty() && m_icon.scheme().isEmpty()) {
plugins/IndicatorsClient/indicators/common/indicatorclient_common.h+5
@@ -31,6 +31,7 @@ class QStateAction;
3131class IndicatorClientCommon : public QObject, public IndicatorClientInterface
3232{
3333 Q_OBJECT
34+ Q_PROPERTY(QString identifier READ identifier NOTIFY identifierChanged)
3435 Q_PROPERTY(QString title READ title NOTIFY titleChanged)
3536 Q_PROPERTY(QString label READ label NOTIFY labelChanged)
3637 Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
@@ -46,6 +47,7 @@ public:
4647 void init(const QSettings& settings);
4748 void shutdown();
4849
50+ QString identifier() const;
4951 QUrl icon() const;
5052 QString title() const;
5153 bool visible() const;
@@ -59,6 +61,7 @@ public:
5961 WidgetsMap widgets();
6062
6163Q_SIGNALS:
64+ void identifierChanged(const QString &identifier);
6265 void iconChanged(const QUrl &icon);
6366 void titleChanged(const QString &title);
6467 void visibleChanged(bool visible);
@@ -70,6 +73,7 @@ Q_SIGNALS:
7073protected:
7174 PropertiesMap m_initialProperties;
7275
76+ void setId(const QString &id);
7377 void setIcon(const QUrl &icon);
7478 void setTitle(const QString &title);
7579 void setDescription(const QString &description);
@@ -86,6 +90,7 @@ private Q_SLOTS:
8690 void updateState(const QVariant &state);
8791
8892private:
93+ QString m_identifier;
8994 QUrl m_icon;
9095 QString m_title;
9196 QString m_description;
plugins/IndicatorsClient/indicatorsmodel.cpp+16−2
@@ -70,8 +70,9 @@ IndicatorsModel::IndicatorsModel(QObject *parent)
7070/*! \internal */
7171IndicatorsModel::~IndicatorsModel()
7272{
73− delete m_widgetsMap;
74− delete m_manager;
73+ disconnect(m_manager, 0, 0, 0);
74+ m_manager->deleteLater();
75+ m_widgetsMap->deleteLater();
7576}
7677
7778/*!
@@ -155,6 +156,7 @@ void IndicatorsModel::onIndicatorLoaded(const QString& indicator)
155156 QObject* obj = dynamic_cast<QObject*>(plugin.get());
156157 if (obj)
157158 {
159+ QObject::connect(obj, SIGNAL(idChanged(const QString&)), this, SLOT(onIdChanged()));
158160 QObject::connect(obj, SIGNAL(iconChanged(const QUrl&)), this, SLOT(onIconChanged()));
159161 QObject::connect(obj, SIGNAL(titleChanged(const QString&)), this, SLOT(onTitleChanged()));
160162 QObject::connect(obj, SIGNAL(labelChanged(const QString&)), this, SLOT(onLabelChanged()));
@@ -189,6 +191,12 @@ void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator)
189191
190192}
191193
194+/*! \internal */
195+void IndicatorsModel::onIdChanged()
196+{
197+ notifyDataChanged(QObject::sender(), Identifier);
198+}
199+
192200/*! \internal */
193201void IndicatorsModel::onIconChanged()
194202{
@@ -233,6 +241,7 @@ QHash<int, QByteArray> IndicatorsModel::roleNames() const
233241{
234242 static QHash<int, QByteArray> roles;
235243 if (roles.isEmpty()) {
244+ roles[Identifier] = "identifier";
236245 roles[Title] = "title";
237246 roles[IconSource] = "iconSource";
238247 roles[Label] = "label";
@@ -261,6 +270,11 @@ QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
261270 IndicatorClientInterface::Ptr plugin = m_plugins[index.row()];
262271
263272 switch (role) {
273+ case Identifier:
274+ if (plugin) {
275+ attribute = QVariant(plugin->identifier());
276+ }
277+ break;
264278 case Title:
265279 if (plugin) {
266280 attribute = QVariant(plugin->title());
plugins/IndicatorsClient/indicatorsmodel.h+3−1
@@ -37,7 +37,8 @@ class IndicatorsModel : public QAbstractListModel
3737
3838public:
3939 enum ModelRoles {
40− Title = 0,
40+ Identifier = 0,
41+ Title,
4142 IconSource,
4243 Label,
4344 Description,
@@ -68,6 +69,7 @@ Q_SIGNALS:
6869 void countChanged();
6970
7071private Q_SLOTS:
72+ void onIdChanged();
7173 void onIconChanged();
7274 void onTitleChanged();
7375 void onLabelChanged();
plugins/IndicatorsClient/qml/FactoryMenu.qml+1
@@ -40,6 +40,7 @@ Item {
4040 if (!__menuFactory.menu || !__menuFactory.menu.extra || !__menuFactory.widgetsMap) {
4141 return ''
4242 }
43+
4344 var widgetType = __menuFactory.menu.extra.canonical_type
4445 var sourceFile = null
4546 if (widgetType) {
plugins/IndicatorsClient/qml/Menu.qml+1−1
@@ -23,7 +23,7 @@ import Ubuntu.Components.ListItems 0.1 as ListItem
2323
2424BasicMenu {
2525 id: __menu
26−
26+ objectName: menu ? menu.action : ""
2727 progression: menu && (menu.linkSubMenu !== undefined)
2828 text: menu && menu.label ? menu.label : ""
2929 color: "#221e1c"
plugins/IndicatorsClient/qml/ProgressMenu.qml+2
@@ -22,6 +22,8 @@ import Ubuntu.Components 0.1
2222
2323Menu {
2424
25+ property alias value : progressBar.value
26+
2527 // TODO: Replace this with the official ProgressBar component as soon as
2628 // it is available. For now, this rebuilds the Mockup as close as possible.
2729 UbuntuShape {
plugins/IndicatorsClient/qml/SwitchMenu.qml+4
@@ -21,6 +21,10 @@ import QtQuick 2.0
2121import Ubuntu.Components 0.1
2222
2323Menu {
24+ id: _switchMenu
25+
26+ property alias checked: switcher.checked
27+
2428 control: Switch {
2529 id: switcher
2630
tests/autopilot/indicators_client/emulators/__init__.py+25
@@ -4,3 +4,28 @@
44# This program is free software: you can redistribute it and/or modify it
55# under the terms of the GNU General Public License version 3, as published
66# by the Free Software Foundation.
7+
8+from autopilot.introspection.dbus import DBusIntrospectionObject
9+from autopilot.input import Mouse, Touch, Pointer
10+from autopilot.platform import model
11+
12+from time import sleep
13+
14+from autopilot.introspection.dbus import IntrospectableObjectMetaclass
15+
16+class IndicatorsIntrospectionObject(DBusIntrospectionObject):
17+
18+ """A common class that provides introspection and other helpers to indictors."""
19+
20+ if model() == 'Desktop':
21+ scenarios = [
22+ ('with mouse', dict(input_device_class=Mouse)),
23+ ]
24+ else:
25+ scenarios = [
26+ ('with touch', dict(input_device_class=Touch)),
27+ ]
28+
29+ def setUp(self):
30+ self.pointing_device = Pointer(self.input_device_class.create())
31+ super(IndicatorsTestCase, self).setUp()
tests/autopilot/indicators_client/emulators/common.pynew file+14
@@ -0,0 +1,14 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+# Copyright 2013 Canonical
3+#
4+# This program is free software: you can redistribute it and/or modify it
5+# under the terms of the GNU General Public License version 3, as published
6+# by the Free Software Foundation.
7+
8+from indicators_client.emulators import IndicatorsIntrospectionObject
9+
10+class SwitchMenu(IndicatorsIntrospectionObject):
11+ """A switch menu control."""
12+
13+ def get_checked(self):
14+ return self.checked
tests/autopilot/indicators_client/emulators/main_window.py+15−4
@@ -5,14 +5,25 @@
55# under the terms of the GNU General Public License version 3, as published
66# by the Free Software Foundation.
77
8+from indicators_client.emulators import IndicatorsIntrospectionObject
9+
810class MainWindow(object):
911 """An emulator class that makes it easy to interact with the shell"""
1012
1113 def __init__(self, app):
1214 self.app = app
1315
14− def get_panel(self):
15− return self.app.select_single("Panel")
16+ def get_qml_view(self):
17+ """Get the main QML view"""
18+ return self.app.select_single("QQuickView")
19+
20+ def get_indicators_client(self):
21+ return self.app.select_single("IndicatorsClient")
22+
23+ def get_page_stack(self):
24+ """Get the page stack"""
25+ return self.app.select_single("PageStack")
1626
17− def get_indicator(self):
18− return self.app.select_single("Indicator")
27+ def get_power_menu(self):
28+ """Get the power menu from the list"""
29+ return self.app.select_single("BasicMenu", objectName="indicator-power");
tests/autopilot/indicators_client/tests/__init__.py+22−7
@@ -9,29 +9,44 @@
99
1010import os.path
1111
12+from autopilot.input import Mouse, Touch, Pointer
1213from autopilot.testcase import AutopilotTestCase
1314from autopilot.matchers import Eventually
1415from autopilot.platform import model
1516from testtools.matchers import Equals
1617
1718from indicators_client.emulators.main_window import MainWindow
19+from logging import getLogger
20+import sys
21+from time import sleep
22+
23+log = getLogger(__name__)
1824
1925class FormFactors(object):
2026 Phone, Tablet, Desktop = range(3)
2127
2228class IndicatorsTestCase(AutopilotTestCase):
2329
24− """A common test case class that provides several useful methods for shell tests."""
30+ """A common test case class that provides several useful methods for indicator tests."""
31+
32+ if model() == 'Desktop':
33+ scenarios = [
34+ ('with mouse', dict(input_device_class=Mouse)),
35+ ]
36+ else:
37+ scenarios = [
38+ ('with touch', dict(input_device_class=Touch)),
39+ ]
2540
26− def setUp(self, geometry, grid_size):
27− super(ShellTestCase, self).setUp()
28− self.launch_test_local(geometry)
41+ def setUp(self):
42+ self.pointing_device = Pointer(self.input_device_class.create())
43+ self.launch_test_local()
44+ super(IndicatorsTestCase, self).setUp()
2945
30− def launch_test_local(self, geometry):
46+ def launch_test_local(self):
3147 os.environ['LD_LIBRARY_PATH'] = "../../../unity_build/build/lib"
3248 os.environ['QML2_IMPORT_PATH'] = "../../builddir/plugins:../../builddir/tests/mocks"
33− self.app = self.launch_test_application(
34− "../../builddir/plugins/IndicatorsClient/client/indicators-client")
49+ self.app = self.launch_test_application("../../builddir/plugins/IndicatorsClient/client/indicators-client")
3550
3651 def skipWrapper(*args, **kwargs):
3752 pass
tests/autopilot/indicators_client/tests/test_power.pynew file+48
@@ -0,0 +1,48 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+# Copyright 2013 Canonical
3+#
4+# This program is free software: you can redistribute it and/or modify it
5+# under the terms of the GNU General Public License version 3, as published
6+# by the Free Software Foundation.
7+
8+"""Add tests here if you want to ensure the behaviour of the power indicator menus are correct"""
9+
10+from testtools.matchers import Equals, NotEquals
11+from autopilot.matchers import Eventually
12+
13+from indicators_client.tests import IndicatorsTestCase
14+from indicators_client.emulators.common import SwitchMenu
15+from time import sleep
16+
17+class TestDisplayMenus(IndicatorsTestCase):
18+ def setUp(self):
19+ super(TestDisplayMenus, self).setUp()
20+
21+ # This opens the messaging menu so you don't have to do that in
22+ # every test case
23+ power = self.main_window.get_power_menu()
24+ self.pointing_device.move_to_object(power)
25+ self.pointing_device.click()
26+
27+ self.page = self.app.select_single("IndicatorsPage");
28+ page_loader = self.app.select_single("IndicatorsPage/QQuickLoader", objectName="page_loader");
29+ self.assertThat(page_loader.progress, Eventually(Equals(1.0)))
30+
31+ def tearDown(self):
32+ # self.main_window.get_indicators_client().reset()
33+ super(TestDisplayMenus, self).tearDown()
34+
35+ def test_auto_bright_switch(self):
36+ """Test the auto-bright switch"""
37+
38+ auto_brightness = self.app.select_single("SwitchMenu", objectName="auto-brightness")
39+ self.assertThat(auto_brightness, NotEquals(None))
40+
41+ old_value = auto_brightness.checked
42+
43+ print auto_brightness.get_checked()
44+
45+
46+
47+
48+