on xenial help sign in
Merge from trunk
46cee69Michael Terry
ApplicationArguments.hnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+
20+#ifndef APPLICATION_ARGUMENTS_H
21+#define APPLICATION_ARGUMENTS_H
22+
23+#include <QObject>
24+#include <QSize>
25+#include <QStringList>
26+
27+class ApplicationArguments : public QObject
28+{
29+ Q_OBJECT
30+public:
31+ ApplicationArguments(const QStringList& args) {
32+ if (args.contains(QLatin1String("-geometry")) && args.size() > args.indexOf(QLatin1String("-geometry")) + 1) {
33+ QStringList geometryArg = args.at(args.indexOf(QLatin1String("-geometry")) + 1).split('x');
34+ if (geometryArg.size() == 2) {
35+ m_size.rwidth() = geometryArg.at(0).toInt();
36+ m_size.rheight() = geometryArg.at(1).toInt();
37+ }
38+ }
39+ }
40+
41+ Q_INVOKABLE bool hasGeometry() const { return m_size.isValid(); }
42+ Q_INVOKABLE int width() const { return m_size.width(); }
43+ Q_INVOKABLE int height() const { return m_size.height(); }
44+
45+private:
46+ QSize m_size;
47+};
48+
49+#endif // APPLICATION_ARGUMENTS_H
Applications/applications.js+2−2
@@ -70,10 +70,10 @@ var __availableApplications = {
70 'exec': '/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml',
70 'exec': '/usr/bin/qmlscene /usr/share/notes-app/NotesApp.qml',
71 'stage': SideStage
71 'stage': SideStage
72 },
72 },
73− '/usr/share/applications/ubuntu-calendar-app.desktop': {
73+ '/usr/share/applications/calendar-app.desktop': {
74 'name': i18n.tr("Calendar"),
74 'name': i18n.tr("Calendar"),
75 'icon': 'calendar',
75 'icon': 'calendar',
76− 'exec': '/usr/bin/qmlscene /usr/share/ubuntu-calendar-app/calendar.qml',
76+ 'exec': '/usr/bin/qmlscene /usr/share/calendar-app/calendar.qml',
77 'stage': SideStage
77 'stage': SideStage
78 },
78 },
79 '/usr/share/applications/mediaplayer-app.desktop': {
79 '/usr/share/applications/mediaplayer-app.desktop': {
CMakeLists.txt+1
@@ -101,6 +101,7 @@ set(shell_app_HDRS
101
101
102add_executable(${SHELL_APP}
102add_executable(${SHELL_APP}
103 ${shellapplication_MOC_SRCS}
103 ${shellapplication_MOC_SRCS}
104+ ApplicationArguments.h
104 main.cpp
105 main.cpp
105 MouseTouchAdaptor.cpp
106 MouseTouchAdaptor.cpp
106 )
107 )
Components/ApplicationManagerWrapper.qml+8−1
@@ -121,9 +121,16 @@ Item {
121 desktopFile = "/usr/share/applications/share-app.desktop"
121 desktopFile = "/usr/share/applications/share-app.desktop"
122 } else if (favoriteApplication == ApplicationManager.BrowserApplication) {
122 } else if (favoriteApplication == ApplicationManager.BrowserApplication) {
123 desktopFile = "/usr/share/applications/webbrowser-app.desktop"
123 desktopFile = "/usr/share/applications/webbrowser-app.desktop"
124− } else if (favoriteApplication == 4) { // ApplicationManager.PhoneApplication
124+ } else if (favoriteApplication == ApplicationManager.PhoneApplication) {
125 desktopFile = "/usr/share/applications/phone-app.desktop"
125 desktopFile = "/usr/share/applications/phone-app.desktop"
126+ } else if (favoriteApplication == ApplicationManager.DialerApplication) {
127+ desktopFile = "/usr/share/applications/dialer-app.desktop"
128+ } else if (favoriteApplication == ApplicationManager.MessagingApplication) {
129+ desktopFile = "/usr/share/applications/messaging-app.desktop"
130+ } else if (favoriteApplication == ApplicationManager.AddressbookApplication) {
131+ desktopFile = "/usr/share/applications/address-book-app.desktop"
126 }
132 }
133+
127 applicationManager.focusRequested(desktopFile);
134 applicationManager.focusRequested(desktopFile);
128 }
135 }
129 }
136 }
Components/ApplicationScreenshot.qml+1−1
@@ -46,7 +46,7 @@ Item {
46 Rectangle {
46 Rectangle {
47 id: background
47 id: background
48 anchors.fill: parent
48 anchors.fill: parent
49− color: "white"
49+ color: "white" // FIXME should use normal background color of Suru theme
50 visible: applicationScreenshot.withBackground
50 visible: applicationScreenshot.withBackground
51 }
51 }
52
52
Components/Carousel.qml+38−1
@@ -52,6 +52,12 @@ Item {
52 /// @param itemY is y of the clicked delegate
52 /// @param itemY is y of the clicked delegate
53 signal clicked(int index, var delegateItem, real itemY)
53 signal clicked(int index, var delegateItem, real itemY)
54
54
55+ /// Emitted when the user pressed and held on an item
56+ /// @param index is the index of the held item
57+ /// @param delegateItem is the held component/delegate itself
58+ /// @param itemY is y of the held delegate
59+ signal pressAndHold(int index, var delegateItem, real itemY)
60+
55 implicitHeight: listView.tileHeight * selectedItemScaleFactor
61 implicitHeight: listView.tileHeight * selectedItemScaleFactor
56
62
57 /* Basic idea behind the carousel effect is to move the items of the delegates (compacting /stuffing them).
63 /* Basic idea behind the carousel effect is to move the items of the delegates (compacting /stuffing them).
@@ -159,6 +165,30 @@ Item {
159 newContentXAnimation.start()
165 newContentXAnimation.start()
160 }
166 }
161
167
168+ function itemPressAndHold(index, delegateItem) {
169+ var x = CarouselJS.getXFromContinuousIndex(index,
170+ realWidth,
171+ realContentWidth,
172+ tileWidth,
173+ gapToMiddlePhase,
174+ gapToEndPhase,
175+ carousel.drawBuffer);
176+
177+ if (Math.abs(x - contentX) < 1) {
178+ /* We're pressAndHold the selected item and
179+ we're in the neighbourhood of radius 1 pixel from it.
180+ Let's emit the pressAndHold signal. */
181+ carousel.pressAndHold(index, delegateItem, delegateItem.y);
182+ return;
183+ }
184+
185+ stepAnimation.stop();
186+ newContentXAnimation.stop();
187+
188+ newContentX = x;
189+ newContentXAnimation.start();
190+ }
191+
162 onMovementStarted: {
192 onMovementStarted: {
163 stepAnimation.stop()
193 stepAnimation.stop()
164 newContentXAnimation.stop()
194 newContentXAnimation.stop()
@@ -279,7 +309,14 @@ Item {
279
309
280 anchors.fill: parent
310 anchors.fill: parent
281
311
312+ onClicked: {
282− onClicked: listView.itemClicked(index, item)
313+ listView.itemClicked(index, item)
314+ }
315+
316+ onPressAndHold: {
317+ listView.itemPressAndHold(index, item)
318+ }
319+
283 }
320 }
284 }
321 }
285 }
322 }
Components/FilterGrid.qml+2−2
@@ -99,7 +99,7 @@ Item {
99
99
100 UbuntuShape {
100 UbuntuShape {
101 anchors.fill: parent
101 anchors.fill: parent
102− color: "#33ffffff"
102+ color: "#33ffffff" // FIXME no palette
103 radius: "small"
103 radius: "small"
104 }
104 }
105
105
@@ -123,7 +123,7 @@ Item {
123 }
123 }
124 text: (filter) ? "+ View all (" + model.count + ")" : "- Show fewer"
124 text: (filter) ? "+ View all (" + model.count + ")" : "- Show fewer"
125 fontSize: "small"
125 fontSize: "small"
126− color: "#f3f3e7"
126+ color: Theme.palette.selected.backgroundText
127 opacity: 0.6
127 opacity: 0.6
128 style: Text.Raised
128 style: Text.Raised
129 styleColor: "black"
129 styleColor: "black"
Components/ListItems/Header.qml+1−1
@@ -45,7 +45,7 @@ Item {
45 verticalCenter: parent.verticalCenter
45 verticalCenter: parent.verticalCenter
46 }
46 }
47
47
48− color: "#f3f3e7" //at 60%
48+ color: Theme.palette.selected.backgroundText //at 60%
49 opacity: 0.6
49 opacity: 0.6
50 font.family: "Ubuntu"
50 font.family: "Ubuntu"
51 fontSize: "medium"
51 fontSize: "medium"
Components/PageHeader.qml+1−1
@@ -90,7 +90,7 @@ Item {
90 verticalCenter: parent.verticalCenter
90 verticalCenter: parent.verticalCenter
91 }
91 }
92
92
93− color: "#f3f3e7"
93+ color: Theme.palette.selected.backgroundText
94 opacity: 0.8
94 opacity: 0.8
95 font.family: "Ubuntu"
95 font.family: "Ubuntu"
96 font.weight: Font.Light
96 font.weight: Font.Light
Components/Stage.qml+14
@@ -39,6 +39,7 @@ Showable {
39 type == ApplicationInfo.MainStage ? applicationManager.mainStageApplications
39 type == ApplicationInfo.MainStage ? applicationManager.mainStageApplications
40 : applicationManager.sideStageApplications
40 : applicationManager.sideStageApplications
41 property bool fullyShown: false
41 property bool fullyShown: false
42+ property bool fullyHidden: true
42 readonly property var focusedApplication:
43 readonly property var focusedApplication:
43 type == ApplicationInfo.MainStage ? applicationManager.mainStageFocusedApplication
44 type == ApplicationInfo.MainStage ? applicationManager.mainStageFocusedApplication
44 : applicationManager.sideStageFocusedApplication
45 : applicationManager.sideStageFocusedApplication
@@ -249,6 +250,19 @@ Showable {
249 }
250 }
250 }
251 }
251
252
253+ Connections {
254+ target: stage.applications
255+ onCountChanged: { __discardObsoleteScreenshots(); }
256+ ignoreUnknownSignals: true
257+ }
258+ onFullyHiddenChanged: { __discardObsoleteScreenshots(); }
259+ function __discardObsoleteScreenshots() {
260+ if (stage.fullyHidden && stage.applications && stage.applications.count == 0) {
261+ stage.focusedApplicationWhenUsingScreenshots = undefined;
262+ stage.__hideScreenshots();
263+ }
264+ }
265+
252
266
253 SequentialAnimation {
267 SequentialAnimation {
254 id: showStartingApplicationAnimation
268 id: showStartingApplicationAnimation
Components/Tile.qml+1−1
@@ -75,7 +75,7 @@ AbstractButton {
75 rightMargin: units.gu(1)
75 rightMargin: units.gu(1)
76 }
76 }
77
77
78− color: "#f3f3e7"
78+ color: Theme.palette.selected.backgroundText
79 opacity: 0.9
79 opacity: 0.9
80 style: Text.Raised
80 style: Text.Raised
81 styleColor: "black"
81 styleColor: "black"
Dash/Apps/RunningApplicationTile.qml+1−1
@@ -113,7 +113,7 @@ AbstractButton {
113 }
113 }
114 text: (application) ? application.name : ""
114 text: (application) ? application.name : ""
115
115
116− color: "#f3f3e7"
116+ color: Theme.palette.selected.backgroundText
117 opacity: 0.9
117 opacity: 0.9
118 style: Text.Raised
118 style: Text.Raised
119 styleColor: "black"
119 styleColor: "black"
Dash/Dash.qml−3
@@ -27,9 +27,6 @@ Showable {
27 property string showScopeOnLoaded: "home.scope"
27 property string showScopeOnLoaded: "home.scope"
28 property real contentScale: 1.0
28 property real contentScale: 1.0
29
29
30− width: units.gu(40)
31− height: units.gu(71)
32−
33 function setCurrentScope(scopeId, animate, reset) {
30 function setCurrentScope(scopeId, animate, reset) {
34 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
31 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
35
32
Dash/DashApps.qml+1−1
@@ -87,7 +87,7 @@ ScopeView {
87 model: scopeView.scope.categories
87 model: scopeView.scope.categories
88
88
89 delegate: Item {
89 delegate: Item {
90− Component.onCompleted: if (index == 3) scopeView.installedModel = Qt.binding(function() { return model.results; });
90+ Component.onCompleted: if (categoryId == "installed") scopeView.installedModel = Qt.binding(function() { return model.results; });
91 }
91 }
92 }
92 }
93
93
Dash/DashBar.qml+1−1
@@ -117,7 +117,7 @@ Item {
117
117
118 Rectangle {
118 Rectangle {
119 id: highlightLine
119 id: highlightLine
120− color: "#dd4814"
120+ color: Theme.palette.selected.foreground
121 height: parent.height
121 height: parent.height
122 anchors.bottom: parent.bottom
122 anchors.bottom: parent.bottom
123 z: 1
123 z: 1
Dash/DashContent.qml+5−2
@@ -20,8 +20,6 @@ import Unity 0.1
20
20
21Item {
21Item {
22 id: dashContent
22 id: dashContent
23− width: units.gu(40)
24− height: units.gu(71)
25
23
26 property var model: null
24 property var model: null
27 property var scopes: null
25 property var scopes: null
@@ -117,6 +115,11 @@ Item {
117 asynchronous: true
115 asynchronous: true
118 source: scopeMapper.map(scope.id)
116 source: scopeMapper.map(scope.id)
119
117
118+ // these are needed for autopilot tests
119+ readonly property string scopeId: scope.id
120+ readonly property bool isCurrent: ListView.isCurrentItem
121+ readonly property bool isLoaded: status == Loader.Ready
122+
120 onLoaded: {
123 onLoaded: {
121 item.scope = Qt.binding(function() { return scope })
124 item.scope = Qt.binding(function() { return scope })
122 item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
125 item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
Dash/DashHome.qml+1
@@ -26,6 +26,7 @@ import "Music"
26
26
27ScopeView {
27ScopeView {
28 id: root
28 id: root
29+ objectName: "DashHome"
29
30
30 onMovementStarted: listView.showHeader()
31 onMovementStarted: listView.showHeader()
31
32
Dash/DashMusic.qml+2−2
@@ -52,7 +52,7 @@ ScopeView {
52
52
53 function getRenderer(categoryId) {
53 function getRenderer(categoryId) {
54 switch (categoryId) {
54 switch (categoryId) {
55− case 1: return "Music/MusicCarousel.qml"
55+ case "featured": return "Music/MusicCarousel.qml"
56 default: return "Music/MusicFilterGrid.qml"
56 default: return "Music/MusicFilterGrid.qml"
57 }
57 }
58 }
58 }
@@ -69,7 +69,7 @@ ScopeView {
69 id: base
69 id: base
70 highlightWhenPressed: false
70 highlightWhenPressed: false
71
71
72− property int categoryId: id
72+ property string categoryId: model.categoryId
73
73
74 Loader {
74 Loader {
75 anchors { top: parent.top; left: parent.left; right: parent.right }
75 anchors { top: parent.top; left: parent.left; right: parent.right }
Dash/DashPreview.qml+1−1
@@ -92,7 +92,7 @@ Rectangle {
92 elide: Text.ElideRight
92 elide: Text.ElideRight
93 fontSize: "x-large"
93 fontSize: "x-large"
94 font.weight: Font.Light
94 font.weight: Font.Light
95− color: "#f3f3e7"
95+ color: Theme.palette.selected.backgroundText
96 opacity: 0.9
96 opacity: 0.9
97 text: root.title
97 text: root.title
98 style: Text.Raised
98 style: Text.Raised
Dash/DashVideos.qml+2−3
@@ -53,7 +53,7 @@ ScopeView {
53
53
54 function getRenderer(categoryId) {
54 function getRenderer(categoryId) {
55 switch (categoryId) {
55 switch (categoryId) {
56− case 1: return "Video/VideosCarousel.qml"
56+ case "featured": return "Video/VideosCarousel.qml"
57 default: return "Video/VideosFilterGrid.qml"
57 default: return "Video/VideosFilterGrid.qml"
58 }
58 }
59 }
59 }
@@ -102,8 +102,7 @@ ScopeView {
102 delegate: ListItems.Base {
102 delegate: ListItems.Base {
103 id: base
103 id: base
104 highlightWhenPressed: false
104 highlightWhenPressed: false
105− property int categoryIndex: index
105+ property string categoryId: model.categoryId
106− property int categoryId: id
107
106
108 Loader {
107 Loader {
109 id: loader
108 id: loader
Dash/Generic/GenericCarousel.qmlnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+import "../../Components"
20+import "../../Components/IconUtil.js" as IconUtil
21+
22+Carousel {
23+ id: genericCarousel
24+
25+ tileAspectRatio: 198 / 288
26+ minimumTileWidth: units.gu(13)
27+ itemComponent: carouselDelegateGeneric
28+ selectedItemScaleFactor: 1.14
29+ cacheBuffer: 1404 // 18px * 13gu * 6
30+ height: implicitHeight + units.gu(6)
31+
32+ Component {
33+ id: carouselDelegateGeneric
34+
35+ BaseCarouselDelegate {
36+ id: item
37+
38+ UbuntuShape {
39+ anchors.fill: parent
40+ radius: "medium"
41+ borderSource: ""
42+ image: Image {
43+ asynchronous: true
44+ sourceSize { width: item.width; height: item.height }
45+ source: model ? IconUtil.from_gicon(model.icon) : ""
46+ }
47+ }
48+
49+ BorderImage {
50+ anchors.centerIn: parent
51+ opacity: 0.6
52+ source: "../../Components/graphics/non-selected.sci"
53+ width: parent.width + units.gu(1.5)
54+ height: parent.height + units.gu(1.5)
55+ }
56+ }
57+ }
58+}
Dash/Generic/GenericFilterGrid.qmlnew file+59
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import "../../Components"
19+import "../../Components/IconUtil.js" as IconUtil
20+
21+FilterGrid {
22+ id: filtergrid
23+
24+ filter: false
25+ minimumHorizontalSpacing: units.gu(0.5)
26+ delegateWidth: units.gu(11)
27+ delegateHeight: units.gu(9.5)
28+ verticalSpacing: units.gu(2)
29+
30+ property int iconWidth: units.gu(8)
31+ property int iconHeight: units.gu(7.5)
32+
33+ signal clicked(int index, var delegateItem, real itemY)
34+ signal pressAndHold(int index, var delegateItem, real itemY)
35+
36+ delegate: Tile {
37+ id: tile
38+ objectName: "delegate" + index
39+ width: filtergrid.cellWidth
40+ height: filtergrid.cellHeight
41+ text: model.title
42+ imageWidth: filtergrid.iconWidth
43+ imageHeight: filtergrid.iconHeight
44+
45+ source: IconUtil.from_gicon(model.icon)
46+
47+ fillMode: Image.PreserveAspectCrop
48+
49+ onClicked: {
50+ var data = { model: model }
51+ filtergrid.clicked(index, data, tile.y)
52+ }
53+
54+ onPressAndHold: {
55+ var data = { model: model }
56+ filtergrid.pressAndHold(index, data, tile.y)
57+ }
58+ }
59+}
Panel/Menus/IndicatorMenuWindow.qml → Dash/Generic/GenericFilterGridPotrait.qmlrenamed+9−14
@@ -15,21 +15,16 @@
15 */
15 */
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18+import "../../Components"
18
19
19−Item {
20+GenericFilterGrid {
20− id: menuWindow
21+ id: filtergrid
21
22
22− property bool shown: false
23+ minimumHorizontalSpacing: units.gu(0.5)
23− property int contentHeight: height
24+ delegateWidth: units.gu(11)
24− property string headingText: name
25+ delegateHeight: units.gu(18)
25− property string name
26+ verticalSpacing: units.gu(2)
26
27
27− enabled: shown
28+ iconWidth: (width / columns) * 0.8
28− opacity: shown ? 1.0 : 0.0
29+ iconHeight: iconWidth * 16 / 11
29− Behavior on opacity { NumberAnimation {duration: shown ? 300 : 150 } }
30−
31− // don't pass any events under this screen
32− MouseArea {
33− anchors.fill: parent
34− }
35}
30}
Dash/GenericScopeView.qml+55−41
@@ -56,53 +56,45 @@ ScopeView {
56 delegate: ListItems.Base {
56 delegate: ListItems.Base {
57 highlightWhenPressed: false
57 highlightWhenPressed: false
58
58
59− FilterGrid {
59+ Loader {
60− id: filtergrid
60+ id: rendererLoader
61− model: results
62−
63 anchors {
61 anchors {
64 top: parent.top
62 top: parent.top
65 left: parent.left
63 left: parent.left
66 right: parent.right
64 right: parent.right
67 }
65 }
68
66
69− filter: false
67+ source: getRenderer(model.renderer, model.contentType)
70− minimumHorizontalSpacing: units.gu(0.5)
68+
71− delegateWidth: units.gu(11)
69+ onLoaded: {
72− delegateHeight: units.gu(18)
70+ item.model = results
73− verticalSpacing: units.gu(2)
71+ }
74−
72+
75− delegate: Tile {
73+ Connections {
76− width: filtergrid.cellWidth
74+ target: rendererLoader.item
77− height: filtergrid.cellHeight
78− text: title
79− imageWidth: units.gu(11)
80− imageHeight: units.gu(16)
81−
82− source: IconUtil.from_gicon(icon)
83−
84− MouseArea {
85− anchors {
86− fill: parent
87− }
88− onClicked: {
75+ onClicked: {
89− mouse.accepted = true
90− effect.positionPx = mapToItem(categoryView, 0, 0).y
76+ effect.positionPx = mapToItem(categoryView, 0, itemY).y
91− scopeView.scope.activate(uri, icon,
77+ scopeView.scope.activate(delegateItem.model.uri,
78+ delegateItem.model.icon,
92− category, 0,
79+ delegateItem.model.category,
80+ 0,
93− mimetype, title,
81+ delegateItem.model.mimetype,
94− comment, dndUri,
82+ delegateItem.model.title,
83+ delegateItem.model.comment,
84+ delegateItem.model.dndUri,
95− metadata)
85+ delegateItem.model.metadata)
96− }
86+ }
97− onPressAndHold: {
87+ onPressAndHold: {
98− mouse.accepted = true
99− effect.positionPx = mapToItem(categoryView, 0, 0).y
88+ effect.positionPx = mapToItem(categoryView, 0, itemY).y
100− scopeView.scope.preview(uri, icon,
89+ scopeView.scope.preview( delegateItem.model.uri,
90+ delegateItem.model.icon,
101− category, 0,
91+ delegateItem.model.category,
92+ 0,
102− mimetype, title,
93+ delegateItem.model.mimetype,
103− comment, dndUri,
94+ delegateItem.model.title,
95+ delegateItem.model.comment,
96+ delegateItem.model.dndUri,
104− metadata)
97+ delegateItem.model.metadata)
105− }
106 }
98 }
107 }
99 }
108 }
100 }
@@ -122,6 +114,28 @@ ScopeView {
122 }
114 }
123 }
115 }
124
116
117+ function getDefaultRendererId(contentType) {
118+ switch (contentType) {
119+ default: return "grid";
120+ }
121+ }
122+
123+ function getRenderer(rendererId, contentType) {
124+ if (rendererId == "default") {
125+ rendererId = getDefaultRendererId(contentType);
126+ }
127+ switch (rendererId) {
128+ case "grid": {
129+ switch (contentType) {
130+ case "video": return "Generic/GenericFilterGridPotrait.qml";
131+ default: return "Generic/GenericFilterGrid.qml";
132+ }
133+ }
134+ case "carousel": return "Generic/GenericCarousel.qml";
135+ default: return "Generic/GenericFilterGrid.qml";
136+ }
137+ }
138+
125 OpenEffect {
139 OpenEffect {
126 id: effect
140 id: effect
127 anchors {
141 anchors {
Dash/Music/AlbumTile.qml+2−2
@@ -69,7 +69,7 @@ AbstractButton {
69 rightMargin: units.gu(1)
69 rightMargin: units.gu(1)
70 }
70 }
71
71
72− color: "#f3f3e7"
72+ color: Theme.palette.selected.backgroundText
73 opacity: 0.9
73 opacity: 0.9
74 style: Text.Raised
74 style: Text.Raised
75 styleColor: "black"
75 styleColor: "black"
@@ -97,7 +97,7 @@ AbstractButton {
97 rightMargin: units.gu(1)
97 rightMargin: units.gu(1)
98 }
98 }
99
99
100− color: "#f3f3e7"
100+ color: Theme.palette.selected.backgroundText
101 opacity: 0.9
101 opacity: 0.9
102 style: Text.Raised
102 style: Text.Raised
103 styleColor: "black"
103 styleColor: "black"
Dash/Video/VideoPreview.qml+3−3
@@ -48,7 +48,7 @@ DashPreview {
48 property int buttonWidth: Math.min(units.gu(22), (width - spacing) / 2)
48 property int buttonWidth: Math.min(units.gu(22), (width - spacing) / 2)
49 Button {
49 Button {
50 width: parent.buttonWidth
50 width: parent.buttonWidth
51− color: "#dd4814"
51+ color: Theme.palette.selected.foreground
52 text: nfo.ready && nfo.video.buyPrice != "" ? "Buy for " + nfo.video.buyPrice : ""
52 text: nfo.ready && nfo.video.buyPrice != "" ? "Buy for " + nfo.video.buyPrice : ""
53 visible: text != ""
53 visible: text != ""
54 iconSource: "graphics/icon_button_amazon.png"
54 iconSource: "graphics/icon_button_amazon.png"
@@ -56,7 +56,7 @@ DashPreview {
56 }
56 }
57 Button {
57 Button {
58 width: parent.buttonWidth
58 width: parent.buttonWidth
59− color: "#dd4814"
59+ color: Theme.palette.selected.foreground
60 text: nfo.ready && nfo.video.buyPrice != "" ? "Rent for " + nfo.video.rentPrice : ""
60 text: nfo.ready && nfo.video.buyPrice != "" ? "Rent for " + nfo.video.rentPrice : ""
61 visible: text != ""
61 visible: text != ""
62 iconSource: "graphics/icon_button_u1.png"
62 iconSource: "graphics/icon_button_u1.png"
@@ -73,7 +73,7 @@ DashPreview {
73
73
74 Label {
74 Label {
75 text: nfo.ready ? nfo.video.plot : ""
75 text: nfo.ready ? nfo.video.plot : ""
76− color: "#f3f3e7"
76+ color: Theme.palette.selected.backgroundText
77 opacity: .6
77 opacity: .6
78 fontSize: "medium"
78 fontSize: "medium"
79 width: parent.width
79 width: parent.width
Notifications/Notification.qml+6−5
@@ -28,6 +28,7 @@ UbuntuShape {
28 property var actions
28 property var actions
29 property var notificationId
29 property var notificationId
30 property var type
30 property var type
31+ property var hints
31 property var notification
32 property var notification
32
33
33 objectName: "background"
34 objectName: "background"
@@ -117,7 +118,7 @@ UbuntuShape {
117 }
118 }
118 fontSize: "medium"
119 fontSize: "medium"
119 font.bold: true
120 font.bold: true
120− color: "#f3f3e7"
121+ color: Theme.palette.selected.backgroundText
121 elide: Text.ElideRight
122 elide: Text.ElideRight
122 }
123 }
123
124
@@ -131,7 +132,7 @@ UbuntuShape {
131 }
132 }
132 visible: body != ""
133 visible: body != ""
133 fontSize: "small"
134 fontSize: "small"
134− color: "#f3f3e7"
135+ color: Theme.palette.selected.backgroundText
135 opacity: 0.6
136 opacity: 0.6
136 wrapMode: Text.WordWrap
137 wrapMode: Text.WordWrap
137 maximumLineCount: 10
138 maximumLineCount: 10
@@ -164,7 +165,7 @@ UbuntuShape {
164 bottom: parent.bottom
165 bottom: parent.bottom
165 }
166 }
166 text: notification.type == Notification.SnapDecision && actionRepeater.count >= 2 ? actionRepeater.itemAt(1).actionLabel : ""
167 text: notification.type == Notification.SnapDecision && actionRepeater.count >= 2 ? actionRepeater.itemAt(1).actionLabel : ""
167− color: "#cdcdcb"
168+ gradient: UbuntuColors.greyGradient
168 onClicked: {
169 onClicked: {
169 if (actionRepeater.count > 2) {
170 if (actionRepeater.count > 2) {
170 buttonRow.expanded = !buttonRow.expanded
171 buttonRow.expanded = !buttonRow.expanded
@@ -194,7 +195,7 @@ UbuntuShape {
194 top: parent.top
195 top: parent.top
195 bottom: parent.bottom
196 bottom: parent.bottom
196 }
197 }
197− color: "#d85317"
198+ gradient: notification.hints == Notification.ButtonTint ? UbuntuColors.orangeGradient : UbuntuColors.greyGradient
198 visible: width > 0
199 visible: width > 0
199 onClicked: notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
200 onClicked: notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
200 }
201 }
@@ -241,7 +242,7 @@ UbuntuShape {
241
242
242 text: loader.actionLabel
243 text: loader.actionLabel
243 height: units.gu(4)
244 height: units.gu(4)
244− color: "#cdcdcb"
245+ gradient: UbuntuColors.greyGradient
245 onClicked: notification.notification.invokeAction(loader.actionId)
246 onClicked: notification.notification.invokeAction(loader.actionId)
246 }
247 }
247 }
248 }
Notifications/Notifications.qml+1
@@ -32,6 +32,7 @@ ListView {
32 right: parent.right
32 right: parent.right
33 }
33 }
34 type: model.type
34 type: model.type
35+ hints: model.hints
35 iconSource: model.icon
36 iconSource: model.icon
36 secondaryIconSource: model.secondaryIcon
37 secondaryIconSource: model.secondaryIcon
37 summary: model.summary
38 summary: model.summary
Panel/IndicatorItem.qml+6−1
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Unity.Indicators 0.1 as Indicators
19import Unity.Indicators 0.1 as Indicators
20+import "../Components"
20
21
21Item {
22Item {
22 id: indicatorItem
23 id: indicatorItem
@@ -27,6 +28,7 @@ Item {
27 property var indicatorProperties: undefined
28 property var indicatorProperties: undefined
28
29
29 opacity: dimmed ? 0.4 : 1
30 opacity: dimmed ? 0.4 : 1
31+ Behavior on opacity { StandardAnimation {} }
30
32
31 // only visible when non-empty
33 // only visible when non-empty
32 visible: loader.item != undefined && loader.status == Loader.Ready ? loader.item.enabled : false
34 visible: loader.item != undefined && loader.status == Loader.Ready ? loader.item.enabled : false
@@ -47,11 +49,14 @@ Item {
47 }
49 }
48
50
49 Rectangle {
51 Rectangle {
50− color: "#dd4814"
52+ color: Theme.palette.selected.foreground
51 objectName: "highlight"
53 objectName: "highlight"
52 height: units.dp(2)
54 height: units.dp(2)
53 width: parent.width
55 width: parent.width
54 anchors.top: parent.bottom
56 anchors.top: parent.bottom
55 visible: highlighted
57 visible: highlighted
58+
59+ opacity: highlighted ? 1 : 0
60+ Behavior on opacity { StandardAnimation {} }
56 }
61 }
57}
62}
Panel/IndicatorRow.qml+34−49
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import "../Components"
19
20
20Item {
21Item {
21 id: indicatorRow
22 id: indicatorRow
@@ -24,23 +25,19 @@ Item {
24 readonly property int currentItemIndex: currentItem ? currentItem.ownIndex : -1
25 readonly property int currentItemIndex: currentItem ? currentItem.ownIndex : -1
25 property alias row: row
26 property alias row: row
26 property QtObject indicatorsModel: null
27 property QtObject indicatorsModel: null
27− property bool overviewActive: false // "state of the menu"
28−
29− Behavior on y {NumberAnimation {duration: 300; easing.type: Easing.OutCubic} }
30
28
31 width: units.gu(40)
29 width: units.gu(40)
32 height: units.gu(3)
30 height: units.gu(3)
33
31
34− Component.onCompleted: setDefaultItem()
35−
36 function setDefaultItem() {
32 function setDefaultItem() {
37 // The leftmost indicator
33 // The leftmost indicator
38− var defaultItemIndex = 0
34+ setCurrentItem(0);
39− setItem(defaultItemIndex)
40 }
35 }
41
36
42− function setItem(index) {
37+ function setCurrentItem(index) {
38+ if (currentItemIndex !== index) {
43− currentItem = rowRepeater.itemAt(index)
39+ currentItem = rowRepeater.itemAt(index);
40+ }
44 }
41 }
45
42
46 Row {
43 Row {
@@ -55,51 +52,39 @@ Item {
55 objectName: "rowRepeater"
52 objectName: "rowRepeater"
56 model: indicatorsModel ? indicatorsModel : undefined
53 model: indicatorsModel ? indicatorsModel : undefined
57
54
58− IndicatorItem {
55+ Item {
59− id: indicatorItem
56+ id: itemWrapper
57+ height: indicatorRow.height
58+ width: childrenRect.width
60
59
61− property int ownIndex: index
60+ property int ownIndex: index
61+ property alias highlighted: indicatorItem.highlighted
62+ property alias dimmed: indicatorItem.dimmed
62
63
64+ IndicatorItem {
65+ id: indicatorItem
66+ height: parent.height
67+
68+ highlighted: indicatorRow.state != "initial" ? itemWrapper.ownIndex == indicatorRow.currentItemIndex : false
69+ dimmed: indicatorRow.state != "initial" ? itemWrapper.ownIndex != indicatorRow.currentItemIndex : false
70+
63− widgetSource: model.widgetSource
71+ widgetSource: model.widgetSource
72+ indicatorProperties : model.indicatorProperties
73+ }
64
74
65− indicatorProperties : model.indicatorProperties
75+ opacity: {
66− highlighted: indicatorRow.state == "reveal" || indicatorRow.state == "locked" || indicatorRow.state == "commit" ? ownIndex == indicatorRow.currentItemIndex : false
67− dimmed: { //See FIXME in Indicators regarding the "states" change
68− if (indicatorRow.state == "initial" || indicatorRow.state == "") {
69− return false;
70− } else if (indicatorRow.state == "hint") {
71− return true
72− } else {
73− return ownIndex != indicatorRow.currentItemIndex
74− }
75− }
76− height: indicatorRow.height
77− y: {
78− //FIXME: all indicators will be initial for now.
79− if (!highlighted && !overviewActive && (indicatorRow.state == "locked" || indicatorRow.state == "commit")) {
76+ if (!indicatorItem.highlighted && (indicatorRow.state == "locked" || indicatorRow.state == "commit")) {
80− return -indicatorRow.height
77+ return 0.0;
81− } else {
78+ } else {
82− return 0
83− }
84− }
85− Behavior on y {
86− NumberAnimation{
87− duration: {
88− if (index == 0) {
89− return 250
79+ return 1.0;
90− } else if (index == 1) {
91− return 150
92− } else if (index == 2) {
93− return 550
94− } else if (index == 3) {
95− return 400
96− } else {
97− return 100 + Math.random() * 200
98− }
99− }
100− easing.type: Easing.OutCubic
101 }
80 }
102 }
81 }
82+ Behavior on opacity {
83+ StandardAnimation {
84+ // flow away from current index
85+ duration: (rowRepeater.count - Math.abs(indicatorRow.currentItemIndex - index)) * (500/rowRepeater.count)
86+ }
87+ }
103 }
88 }
104 }
89 }
105 }
90 }
Panel/Indicators.qml+102−137
@@ -25,16 +25,15 @@ import "../Components/Math.js" as MathLocal
25Showable {
25Showable {
26 id: indicators
26 id: indicators
27
27
28− property int referenceOpenedHeight: units.gu(71)
28+ property real openedHeight: units.gu(71)
29− property real openedHeight: pinnedMode ? referenceOpenedHeight - panelHeight
30− : referenceOpenedHeight
31 property int panelHeight: units.gu(3)
29 property int panelHeight: units.gu(3)
32 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
30 property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
33
31
34 property int hintValue
32 property int hintValue
35− readonly property int lockThreshold: referenceOpenedHeight / 2
33+ readonly property int lockThreshold: openedHeight / 2
36 property bool fullyOpened: height == openedHeight
34 property bool fullyOpened: height == openedHeight
37 property bool partiallyOpened: height > panelHeight && !fullyOpened
35 property bool partiallyOpened: height > panelHeight && !fullyOpened
36+ property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
38
37
39 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
38 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
40 // use its own values. Need to ask design about this.
39 // use its own values. Need to ask design about this.
@@ -43,6 +42,13 @@ Showable {
43 duration: 350
42 duration: 350
44 to: openedHeight
43 to: openedHeight
45 easing.type: Easing.OutCubic
44 easing.type: Easing.OutCubic
45+
46+ // Re-size if we've changed the openHeight while shown.
47+ onToChanged: {
48+ if (indicators.shown) {
49+ indicators.show();
50+ }
51+ }
46 }
52 }
47
53
48 hideAnimation: StandardAnimation {
54 hideAnimation: StandardAnimation {
@@ -56,44 +62,32 @@ Showable {
56
62
57 onHeightChanged: {
63 onHeightChanged: {
58 // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
64 // need to use handle.get_height(). As the handle height depends on indicators.height changes (but this is called first!)
59− var contentProgress = indicators.height - handle.get_height()
65+ var revealProgress = indicators.height - panelHeight
60 if (!showAnimation.running && !hideAnimation.running) {
66 if (!showAnimation.running && !hideAnimation.running) {
61− if (contentProgress <= hintValue && indicators.state == "reveal") {
67+ if (revealProgress == 0) {
68+ indicators.state = "initial";
69+ } else if (revealProgress <= hintValue) {
62− indicators.state = "hint"
70+ indicators.state = "hint";
63− menuContent.hideAll()
64− } else if (contentProgress > hintValue && contentProgress < lockThreshold) {
71+ } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
65− menuContent.showMenu()
66− indicators.state = "reveal"
72+ indicators.state = "reveal";
67− } else if (contentProgress >= lockThreshold && lockThreshold > 0) {
73+ } else if (revealProgress >= lockThreshold && lockThreshold > 0) {
68− // If we've shown the overview and are closing the view with progress changes (revealer handle),
69− // we dont want to switch to a indicator menu until we hit reveal state.
70− if (menuContent.overviewActive) {
71− menuContent.showOverview()
72− } else {
73− menuContent.showMenu()
74− }
75− indicators.state = "locked"
74+ indicators.state = "locked";
76 }
75 }
77 }
76 }
78
77
79− if (contentProgress == 0) {
78+ if (revealProgress == 0) {
80− menuContent.releaseContent()
79+ menuContent.releaseContent();
81 }
80 }
82 }
81 }
83
82
84− function openOverview() {
85− indicatorRow.currentItem = null
86− menuContent.showOverview()
87− }
88−
89 function calculateCurrentItem(xValue, useBuffer) {
83 function calculateCurrentItem(xValue, useBuffer) {
90− var rowCoordinates
84+ var rowCoordinates;
91− var itemCoordinates
85+ var itemCoordinates;
92− var currentItem
86+ var currentItem;
93− var distanceFromRightEdge
87+ var distanceFromRightEdge;
94− var bufferExceeded = false
88+ var bufferExceeded = false;
95
89
96− if (indicators.state == "commit" || indicators.state == "locked" || showAnimation.running || hideAnimation.running) return
90+ if (indicators.state == "commit" || indicators.state == "locked" || showAnimation.running || hideAnimation.running) return;
97
91
98 /*
92 /*
99 If user drags the indicator handle bar down a distance hintValue or less, this is 0.
93 If user drags the indicator handle bar down a distance hintValue or less, this is 0.
@@ -102,14 +96,22 @@ Showable {
102 */
96 */
103 var verticalProgress =
97 var verticalProgress =
104 MathLocal.clamp((indicators.height - handle.height - hintValue) /
98 MathLocal.clamp((indicators.height - handle.height - hintValue) /
105− (lockThreshold - hintValue), 0, 1)
99+ (lockThreshold - hintValue), 0, 1);
100+
101+ /*
102+ Vertical velocity check. Don't change the indicator if we're moving too quickly.
103+ */
104+ var verticalSpeed = Math.abs(yVelocityCalculator.calculate());
105+ if (verticalSpeed >= 0.05 && indicatorRow.currentItem!=null) {
106+ return;
107+ }
106
108
107 /*
109 /*
108 Percentage of an indicator icon's width the user's press can stray horizontally from the
110 Percentage of an indicator icon's width the user's press can stray horizontally from the
109 focused icon before we change focus to another icon. E.g. a value of 0.5 means you must
111 focused icon before we change focus to another icon. E.g. a value of 0.5 means you must
110 go right a distance of half an icon's width before focus moves to the icon on the right
112 go right a distance of half an icon's width before focus moves to the icon on the right
111 */
113 */
112− var maxBufferThreshold = 0.5
114+ var maxBufferThreshold = 0.5;
113
115
114 /*
116 /*
115 To help users find the indicator of their choice while opening the indicators, we add logic to add a
117 To help users find the indicator of their choice while opening the indicators, we add logic to add a
@@ -124,19 +126,21 @@ Showable {
124 currentItem = indicatorRow.row.childAt(rowCoordinates.x, 0);
126 currentItem = indicatorRow.row.childAt(rowCoordinates.x, 0);
125 if (currentItem && currentItem != indicatorRow.currentItem ) {
127 if (currentItem && currentItem != indicatorRow.currentItem ) {
126 itemCoordinates = indicatorRow.row.mapToItem(currentItem, rowCoordinates.x, 0);
128 itemCoordinates = indicatorRow.row.mapToItem(currentItem, rowCoordinates.x, 0);
127− distanceFromRightEdge = (currentItem.width - itemCoordinates.x) / (currentItem.width)
129+ distanceFromRightEdge = (currentItem.width - itemCoordinates.x) / (currentItem.width);
128 if (Math.abs(currentItem.ownIndex - indicatorRow.currentItemIndex) > 1) {
130 if (Math.abs(currentItem.ownIndex - indicatorRow.currentItemIndex) > 1) {
129− bufferExceeded = true
131+ bufferExceeded = true;
130 } else {
132 } else {
131 if (indicatorRow.currentItemIndex < currentItem.ownIndex && distanceFromRightEdge < (1 - effectiveBufferThreshold)) {
133 if (indicatorRow.currentItemIndex < currentItem.ownIndex && distanceFromRightEdge < (1 - effectiveBufferThreshold)) {
132− bufferExceeded = true
134+ bufferExceeded = true;
133 } else if (indicatorRow.currentItemIndex > currentItem.ownIndex && distanceFromRightEdge > effectiveBufferThreshold) {
135 } else if (indicatorRow.currentItemIndex > currentItem.ownIndex && distanceFromRightEdge > effectiveBufferThreshold) {
134− bufferExceeded = true
136+ bufferExceeded = true;
135 }
137 }
136 }
138 }
137 if ((!useBuffer || (useBuffer && bufferExceeded)) || indicatorRow.currentItem < 0 || indicatorRow.currentItem == null) {
139 if ((!useBuffer || (useBuffer && bufferExceeded)) || indicatorRow.currentItem < 0 || indicatorRow.currentItem == null) {
138 indicatorRow.currentItem = currentItem;
140 indicatorRow.currentItem = currentItem;
139 }
141 }
142+ } else if (!currentItem) {
143+ indicatorRow.setDefaultItem();
140 }
144 }
141 }
145 }
142
146
@@ -169,14 +173,20 @@ Showable {
169 left: parent.left
173 left: parent.left
170 right: parent.right
174 right: parent.right
171 top: indicatorRow.bottom
175 top: indicatorRow.bottom
172− bottom: parent.bottom
176+ bottom: handle.top
173 }
177 }
174 indicatorsModel: indicatorsModel
178 indicatorsModel: indicatorsModel
175− animate: false
176− clip: indicators.partiallyOpened
179+ clip: !indicators.fullyOpened
177
180
178− onMenuSelected: {
181+ Connections {
179− indicatorRow.setItem(index)
182+ target: indicatorRow
183+ onCurrentItemIndexChanged: menuContent.updateCurrentMenu();
184+ }
185+
186+ function updateCurrentMenu() {
187+ if (currentMenuIndex != indicatorRow.currentItemIndex) {
188+ currentMenuIndex = indicatorRow.currentItemIndex;
189+ }
180 }
190 }
181
191
182 //small shadow gradient at bottom of menu
192 //small shadow gradient at bottom of menu
@@ -203,13 +213,13 @@ Showable {
203 anchors {
213 anchors {
204 left: parent.left
214 left: parent.left
205 right: parent.right
215 right: parent.right
206− top: menuContent.bottom
216+ bottom: parent.bottom
207 }
217 }
208 height: get_height()
218 height: get_height()
209 clip: height < handleImage.height
219 clip: height < handleImage.height
210
220
211 function get_height() {
221 function get_height() {
212− return Math.max(Math.min(handleImage.height, indicators.height - handleImage.height), 0)
222+ return Math.max(Math.min(handleImage.height, indicators.height - handleImage.height), 0);
213 }
223 }
214
224
215 BorderImage {
225 BorderImage {
@@ -227,33 +237,14 @@ Showable {
227 }
237 }
228 }
238 }
229
239
230− PanelSeparatorLine {
231− id: indicatorsSeparatorLine
232− visible: true
233− anchors {
234− top: handle.bottom
235− left: indicators.left
236− right: indicators.right
237− }
238− }
239−
240− BorderImage {
241− id: dropShadow
242− anchors {
243− top: indicators.top
244− bottom: indicatorsSeparatorLine.bottom
245− left: indicators.left
246− right: indicators.right
247− margins: -units.gu(1)
248− }
249− visible: indicators.height > panelHeight
250− source: "graphics/rectangular_dropshadow.sci"
251− }
252−
253 PanelBackground {
240 PanelBackground {
254 anchors.fill: indicatorRow
241 anchors.fill: indicatorRow
255 }
242 }
256
243
244+ IndicatorsDataModel {
245+ id: indicatorsModel
246+ }
247+
257 IndicatorRow {
248 IndicatorRow {
258 id: indicatorRow
249 id: indicatorRow
259 objectName: "indicatorRow"
250 objectName: "indicatorRow"
@@ -264,63 +255,46 @@ Showable {
264 height: indicators.panelHeight
255 height: indicators.panelHeight
265 indicatorsModel: indicatorsModel
256 indicatorsModel: indicatorsModel
266 state: indicators.state
257 state: indicators.state
267− overviewActive: menuContent.overviewActive
268−
269− onCurrentItemIndexChanged: menuContent.currentIndex = currentItemIndex
270
258
271− }
259+ Connections {
272−
260+ target: menuContent
273− IndicatorsDataModel {
261+ onCurrentMenuIndexChanged: {
274− id: indicatorsModel
262+ indicatorRow.setCurrentItem(menuContent.currentMenuIndex);
263+ }
264+ }
275 }
265 }
276
266
277 Connections {
267 Connections {
278− target: hideAnimation
268+ target: showAnimation
279 onRunningChanged: {
269 onRunningChanged: {
280− if (hideAnimation.running) {
270+ if (showAnimation.running) {
281− indicators.state = "initial"
271+ indicators.state = "commit";
282− menuContent.hideAll()
283− } else {
284− if (state == "initial") indicatorRow.setDefaultItem()
285 }
272 }
286 }
273 }
287 }
274 }
275+
288 Connections {
276 Connections {
289− target: showAnimation
277+ target: hideAnimation
290 onRunningChanged: {
278 onRunningChanged: {
291− if (showAnimation.running) {
279+ if (hideAnimation.running) {
292− if (indicators.state == "initial") {
280+ indicators.state = "initial";
293− openOverview()
281+ indicatorRow.currentItem = null;
294− } else {
295− indicators.calculateCurrentItem(dragHandle.touchX, false)
296− menuContent.showMenu()
297− }
298− indicators.state = "commit"
299 }
282 }
300 }
283 }
301 }
284 }
302
285
286+ property var activeDragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle.dragging ? hideDragHandle : null
287+ // connections to the active drag handle
303 Connections {
288 Connections {
304− target: dragHandle
289+ target: activeDragHandle
305 onTouchXChanged: {
290 onTouchXChanged: {
306− var buffer = dragHandle.dragging ? true : false
307− indicators.calculateCurrentItem(dragHandle.touchX, buffer)
291+ indicators.calculateCurrentItem(activeDragHandle.touchX, true);
292+ }
293+ onTouchSceneYChanged: {
294+ yVelocityCalculator.trackedPosition = activeDragHandle.touchSceneY;
308 }
295 }
309 }
296 }
310
297
311− // We start with pinned states. (default pinnedMode: true)
312− states: pinnedModeStates
313− // because of dynamic assignment of states, we need to assign state after completion.
314− Component.onCompleted: state = "initial"
315−
316− // changing states will reset state to "".
317− onPinnedModeChanged: {
318− var last_state = state;
319− states = (pinnedMode) ? pinnedModeStates : offScreenModeStates;
320− state = last_state;
321− }
322−
323− property var dragHandle: showDragHandle.dragging ? showDragHandle : hideDragHandle
324 DragHandle {
298 DragHandle {
325 id: showDragHandle
299 id: showDragHandle
326 anchors.bottom: parent.bottom
300 anchors.bottom: parent.bottom
@@ -334,42 +308,52 @@ Showable {
334 hintDisplacement: pinnedMode ? indicators.hintValue : 0
308 hintDisplacement: pinnedMode ? indicators.hintValue : 0
335 autoCompleteDragThreshold: maxTotalDragDistance / 2
309 autoCompleteDragThreshold: maxTotalDragDistance / 2
336 stretch: true
310 stretch: true
337− maxTotalDragDistance: openedHeight - handle.height
311+ maxTotalDragDistance: openedHeight - panelHeight
338 distanceThreshold: pinnedMode ? 0 : units.gu(3)
312 distanceThreshold: pinnedMode ? 0 : units.gu(3)
339
313
340 onStatusChanged: {
314 onStatusChanged: {
341 if (status === DirectionalDragArea.Recognized) {
315 if (status === DirectionalDragArea.Recognized) {
342− menuContent.hideAll()
343− menuContent.activateContent()
316+ menuContent.activateContent();
344 }
317 }
345 }
318 }
346 }
319 }
347 DragHandle {
320 DragHandle {
348 id: hideDragHandle
321 id: hideDragHandle
349 anchors.fill: handle
322 anchors.fill: handle
350− height: panelHeight
351 direction: Direction.Upwards
323 direction: Direction.Upwards
352 enabled: indicators.shown && indicators.available
324 enabled: indicators.shown && indicators.available
353− hintDisplacement: units.gu(2)
325+ hintDisplacement: indicators.hintValue
354 autoCompleteDragThreshold: maxTotalDragDistance / 6
326 autoCompleteDragThreshold: maxTotalDragDistance / 6
355 stretch: true
327 stretch: true
356− maxTotalDragDistance: referenceOpenedHeight - 2*panelHeight
328+ maxTotalDragDistance: openedHeight - panelHeight
357 distanceThreshold: 0
329 distanceThreshold: 0
358 }
330 }
359
331
360− property list<State> offScreenModeStates: [
332+ AxisVelocityCalculator {
333+ id: yVelocityCalculator
334+ }
335+
336+ states: [
361 State {
337 State {
362 name: "initial"
338 name: "initial"
363 },
339 },
364 State {
340 State {
365 name: "hint"
341 name: "hint"
342+ PropertyChanges {
366− PropertyChanges { target: indicatorRow; y: panelHeight }
343+ target: indicatorRow;
344+ y: pinnedMode ? 0 : panelHeight
345+ }
346+ StateChangeScript {
347+ script: {
348+ if (activeDragHandle) {
349+ calculateCurrentItem(activeDragHandle.touchX, false);
350+ }
351+ }
352+ }
367 },
353 },
368 State {
354 State {
369 name: "reveal"
355 name: "reveal"
370 extend: "hint"
356 extend: "hint"
371− PropertyChanges { target: menuContent; animate: true }
372− StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
373 },
357 },
374 State {
358 State {
375 name: "locked"
359 name: "locked"
@@ -380,26 +364,7 @@ Showable {
380 extend: "hint"
364 extend: "hint"
381 }
365 }
382 ]
366 ]
383−
384− property list<State> pinnedModeStates: [
385− State {
386− name: "initial"
367+ state: "initial"
387− },
388− State {
389− name: "hint"
390− },
391− State {
392− name: "reveal"
393− PropertyChanges { target: menuContent; animate: true }
394− StateChangeScript { script: calculateCurrentItem(dragHandle.touchX, false); }
395− },
396− State {
397− name: "locked"
398− },
399− State {
400− name: "commit"
401− }
402− ]
403
368
404 transitions: [
369 transitions: [
405 Transition {
370 Transition {
Panel/Indicators/DatetimeIndicatorPage.qml+2−2
@@ -54,7 +54,7 @@ Flickable {
54 }
54 }
55
55
56 text: ""
56 text: ""
57− color: "#f3f3e7"
57+ color: Theme.palette.selected.backgroundText
58 font.weight: Font.Light
58 font.weight: Font.Light
59 font.pixelSize: units.gu(6)
59 font.pixelSize: units.gu(6)
60 }
60 }
@@ -69,7 +69,7 @@ Flickable {
69 bottomMargin: units.gu(1.5)
69 bottomMargin: units.gu(1.5)
70 }
70 }
71 text: ""
71 text: ""
72− color: "#f3f3e7"
72+ color: Theme.palette.selected.backgroundText
73 fontSize: "small"
73 fontSize: "small"
74 }
74 }
75 }
75 }
Panel/Indicators/DatetimeIndicatorWidget.qml+1−1
@@ -31,7 +31,7 @@ Indicators.IndicatorWidget {
31 Label {
31 Label {
32 id: timeLabel
32 id: timeLabel
33 objectName: "timeLabel"
33 objectName: "timeLabel"
34− color: "#f3f3e7"
34+ color: Theme.palette.selected.backgroundText
35 opacity: 0.8
35 opacity: 0.8
36 font.family: "Ubuntu"
36 font.family: "Ubuntu"
37 fontSize: "medium"
37 fontSize: "medium"
Panel/Indicators/DefaultIndicatorWidget.qml+1−1
@@ -52,7 +52,7 @@ Indicators.IndicatorWidget {
52 Label {
52 Label {
53 id: itemLabel
53 id: itemLabel
54 objectName: "itemLabel"
54 objectName: "itemLabel"
55− color: "#f3f3e7"
55+ color: Theme.palette.selected.backgroundText
56 opacity: 0.8
56 opacity: 0.8
57 font.family: "Ubuntu"
57 font.family: "Ubuntu"
58 fontSize: "medium"
58 fontSize: "medium"
Panel/MenuContent.qml+22−71
@@ -17,50 +17,31 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Unity.Indicators 0.1 as Indicators
19import Unity.Indicators 0.1 as Indicators
20−import "Menus"
21import "../Components"
20import "../Components"
22
21
23Rectangle {
22Rectangle {
24 id: content
23 id: content
25
24
26 property QtObject indicatorsModel: null
25 property QtObject indicatorsModel: null
27− property bool animate: true // FIXME: Remove. This doesnt seem to be being used and it's referenced in Indicators.
28− property bool overviewActive: true // "state of the menu"
29− property bool __shown: false
30 property bool __contentActive: false
26 property bool __contentActive: false
31− property alias currentIndex : menus.currentIndex
27+ property alias currentMenuIndex : menus.currentIndex
32− property color backgroundColor: "#221e1c"
28+ property color backgroundColor: "#221e1c" // FIXME not in palette yet
33 property int contentReleaseInterval: 20000
29 property int contentReleaseInterval: 20000
34
30
35 width: units.gu(40)
31 width: units.gu(40)
36 height: units.gu(42)
32 height: units.gu(42)
37 color: backgroundColor
33 color: backgroundColor
38− enabled: __shown
39
34
40 signal menuSelected(int index)
35 signal menuSelected(int index)
41
36
42− function showMenu() {
43− __shown = true
44− overviewActive = false
45− }
46−
47− function showOverview() {
48− __shown = true
49− overviewActive = true
50− }
51−
52− function hideAll() {
53− __shown = false
54− }
55−
56 function activateContent() {
37 function activateContent() {
57− contentReleaseTimer.stop()
38+ contentReleaseTimer.stop();
58− __contentActive = true
39+ __contentActive = true;
59 }
40 }
60
41
61 function releaseContent() {
42 function releaseContent() {
62 if (__contentActive)
43 if (__contentActive)
63− contentReleaseTimer.restart()
44+ contentReleaseTimer.restart();
64 }
45 }
65
46
66 ListView {
47 ListView {
@@ -72,7 +53,6 @@ Rectangle {
72 width: parent.width
53 width: parent.width
73
54
74 spacing: units.gu(0.5)
55 spacing: units.gu(0.5)
75− opacity: !overviewActive && __shown ? 1 : 0
76 enabled: opacity != 0
56 enabled: opacity != 0
77 orientation: ListView.Horizontal
57 orientation: ListView.Horizontal
78 model: indicatorsModel
58 model: indicatorsModel
@@ -83,24 +63,23 @@ Rectangle {
83
63
84 delegate: Loader {
64 delegate: Loader {
85 clip: true
65 clip: true
86− property bool contentActive: content.__contentActive
66+ property bool contentActive: content.__contentActive && menuActivator.content[index].active
87
67
88 onContentActiveChanged: {
68 onContentActiveChanged: {
89 if (contentActive && item) {
69 if (contentActive && item) {
90− item.start()
70+ item.start();
91 } else if (!contentActive && item) {
71 } else if (!contentActive && item) {
92− item.stop()
72+ item.stop();
93 }
73 }
94 }
74 }
95
75
96 width: menus.width
76 width: menus.width
97 height: menus.height
77 height: menus.height
98 source: pageSource
78 source: pageSource
99− visible: content.__shown
100 onVisibleChanged: {
79 onVisibleChanged: {
101 // Reset the indicator states
80 // Reset the indicator states
102 if (!visible && item && item["reset"]) {
81 if (!visible && item && item["reset"]) {
103− item.reset()
82+ item.reset();
104 }
83 }
105 }
84 }
106 asynchronous: true
85 asynchronous: true
@@ -108,11 +87,11 @@ Rectangle {
108 onLoaded: {
87 onLoaded: {
109 for(var pName in indicatorProperties) {
88 for(var pName in indicatorProperties) {
110 if (item.hasOwnProperty(pName)) {
89 if (item.hasOwnProperty(pName)) {
111− item[pName] = indicatorProperties[pName]
90+ item[pName] = indicatorProperties[pName];
112 }
91 }
113 }
92 }
114 if (contentActive && menus.visible) {
93 if (contentActive && menus.visible) {
115− item.start()
94+ item.start();
116 }
95 }
117 }
96 }
118
97
@@ -124,40 +103,6 @@ Rectangle {
124 value: handle.height
103 value: handle.height
125 }
104 }
126 }
105 }
127−
128− Behavior on opacity { NumberAnimation {duration: 200} }
129− }
130−
131− Overview {
132− id: overview
133− objectName: "overview"
134−
135− anchors.top: header.bottom
136− anchors.bottom: parent.bottom
137− // FIXME: Dont know why we're using handle height (introduces dep).. Check with design about bottom margin
138− anchors.bottomMargin: handle.height
139−
140− width: content.width
141− indicatorsModel: content.indicatorsModel
142− enabled: content.overviewActive && content.__shown
143− opacity: content.overviewActive && content.__shown ? 1 : 0
144− Behavior on opacity {NumberAnimation{duration: 200}}
145− visible: opacity != 0
146−
147− onMenuSelected: {
148− var storedDuration = menus.highlightMoveDuration
149− var storedVelocity = menus.highlightMoveVelocity
150− menus.highlightMoveDuration = 0
151− menus.highlightMoveVelocity = 100000
152−
153− menus.currentIndex = modelIndex
154− content.overviewActive = false
155−
156− menus.highlightMoveDuration = storedDuration
157− menus.highlightMoveVelocity = storedVelocity
158−
159− content.menuSelected(modelIndex)
160− }
161 }
106 }
162
107
163 Rectangle {
108 Rectangle {
@@ -181,14 +126,10 @@ Rectangle {
181 right: parent.right
126 right: parent.right
182 }
127 }
183 text: {
128 text: {
184− if (content.overviewActive)
185− return i18n.tr("Device");
186 if (indicatorsModel && menus.currentIndex >= 0 && menus.currentIndex < indicatorsModel.count)
129 if (indicatorsModel && menus.currentIndex >= 0 && menus.currentIndex < indicatorsModel.count)
187 return indicatorsModel.data(menus.currentIndex, Indicators.IndicatorsModelRole.Title);
130 return indicatorsModel.data(menus.currentIndex, Indicators.IndicatorsModelRole.Title);
188 return "";
131 return "";
189 }
132 }
190− opacity: __shown ? 1 : 0
191− Behavior on opacity {NumberAnimation{duration: 100}}
192 }
133 }
193 }
134 }
194
135
@@ -196,6 +137,16 @@ Rectangle {
196 id: contentReleaseTimer
137 id: contentReleaseTimer
197
138
198 interval: contentReleaseInterval
139 interval: contentReleaseInterval
140+ onTriggered: {
199− onTriggered: __contentActive = false
141+ __contentActive = false;
142+ menuActivator.clear();
143+ }
144+ }
145+
146+ Indicators.MenuContentActivator {
147+ id: menuActivator
148+ running: content.__contentActive
149+ baseIndex: content.currentMenuIndex
150+ count: indicatorsModel.count
200 }
151 }
201}
152}
Panel/Menus/Overview.qmldeleted−70
@@ -1,70 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import "../../Components/ListItems" as ListItems
20−import "Overview"
21−
22−IndicatorMenuWindow {
23− id: overview
24−
25− property QtObject indicatorsModel: null
26−
27− signal menuSelected(int modelIndex)
28−
29− VisualItemModel {
30− id: itemModel
31−
32− FlightModeWidget {
33− anchors {
34− left: parent ? parent.left : undefined
35− right: parent ? parent.right : undefined
36− }
37− height: units.gu(8)
38−
39− ListItems.ThinDivider {
40− anchors {
41− bottom: parent.bottom
42− bottomMargin: -units.dp(1)
43− }
44− }
45− }
46−
47− VolumeWidget {
48− anchors {
49− left: parent ? parent.left : undefined
50− right: parent ? parent.right : undefined
51− }
52− height: units.gu(10)
53− }
54−
55− OverviewGrid {
56− model: indicatorsModel
57− anchors {
58− left: parent ? parent.left : undefined
59− right: parent ? parent.right : undefined
60− }
61− }
62− }
63−
64− ListView {
65− id: listView
66− anchors.fill: parent
67− model: itemModel
68− interactive: false
69− }
70−}
Panel/Menus/Overview/FlightModeWidget.qmldeleted−60
@@ -1,60 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−
20−Item {
21− id: flightModeWidget
22−
23− Image {
24− id: flightIcon
25− source: "graphics/plane_icon.png"
26− anchors {
27− left: parent.left
28− leftMargin: units.gu(2)
29− verticalCenter: parent.verticalCenter
30− }
31− width: units.gu(4)
32− height: units.gu(4)
33− }
34−
35− Label {
36− anchors {
37− left: flightIcon.right
38− right: flightModeSwitch.left
39− margins: units.gu(2)
40− verticalCenter: parent.verticalCenter
41− }
42− text: i18n.tr("Flight mode")
43− color: "#f3f3e7"
44− style: Text.Raised
45− styleColor: "black"
46− opacity: 0.6;
47− fontSize: "medium"
48− elide: Text.ElideRight
49− horizontalAlignment: Text.AlignLeft
50− }
51−
52− Switch {
53− id: flightModeSwitch
54− anchors {
55− right: parent.right
56− rightMargin: units.gu(2)
57− verticalCenter: parent.verticalCenter
58− }
59− }
60−}
Panel/Menus/Overview/OverviewGrid.qmldeleted−135
@@ -1,135 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−
20−import "../../../Components/ListItems" as ListItems
21−
22−Item {
23− id: overviewGrid
24−
25− height: childrenRect.height
26−
27− property var model
28−
29− UbuntuShape {
30− id: gridBackground
31− anchors.fill: grid
32− color: "#282421"
33− radius: "medium"
34− }
35−
36− GridView {
37− id: grid
38− objectName: "overviewGrid"
39−
40− property int columnCount: 3
41− property int rowCount: Math.ceil(model.count / columnCount)
42−
43− anchors {
44− top: parent.top
45− left: parent.left
46− right: parent.right
47− topMargin: units.gu(3)
48− leftMargin: units.gu(2)
49− rightMargin: units.gu(2)
50− }
51− height: cellWidth * rowCount
52− cellWidth: Math.floor((width) / columnCount)
53− cellHeight: cellWidth
54− model: overviewGrid.model
55− visible: opacity != 0
56− interactive: false
57− delegate:
58− AbstractButton {
59− objectName: "overviewGridButton" + index
60− width: grid.cellWidth
61− height: grid.cellHeight
62−
63− Loader {
64− id: loader
65− source: widgetSource
66−
67− width: units.gu(5)
68− height: units.gu(5)
69− anchors.centerIn: parent
70− anchors.verticalCenterOffset: -units.gu(1)
71−
72− onLoaded: {
73− for(var pName in indicatorProperties) {
74− if (item.hasOwnProperty(pName)) {
75− item[pName] = indicatorProperties[pName]
76− }
77− }
78− }
79− }
80−
81− Label {
82− text: title
83− color: "#f3f3e7"
84− fontSize: "small"
85− anchors {
86− left: parent.left
87− right: parent.right
88− bottom: parent.bottom
89− leftMargin: units.gu(0.5)
90− rightMargin: units.gu(0.5)
91− bottomMargin: units.gu(1.5)
92− }
93− elide: Text.ElideRight
94− horizontalAlignment: Text.AlignHCenter
95−
96− }
97− onClicked: overview.menuSelected(index)
98− }
99− }
100−
101− Item {
102− id: gridOverlay
103− anchors.fill: grid
104−
105− Column {
106− anchors {
107− left: parent.left
108− right: parent.right
109− }
110− spacing: grid.cellHeight
111− y: grid.cellHeight - units.dp(1)
112− Repeater {
113− model: grid.rowCount - 1
114− ListItems.ThinDivider {
115− anchors.margins: units.dp(1)
116− }
117− }
118− }
119−
120− Row {
121− anchors {
122− top: parent.top
123− bottom: parent.bottom
124− }
125− spacing: grid.cellWidth - units.dp(1)
126− x: grid.cellWidth - units.dp(1)
127− Repeater {
128− model: grid.columnCount - 1
129− ListItems.VerticalThinDivider {
130− anchors.margins: units.dp(1)
131− }
132− }
133− }
134− }
135−}
Panel/Menus/Overview/VolumeWidget.qmldeleted−88
@@ -1,88 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import "../../../Components/"
20−
21−Item {
22− id: volumeWidget
23−
24− Image {
25− id: minVolumeIcon
26− objectName: "minVolumeIcon"
27− source: "graphics/sound_off_icon.png"
28− anchors {
29− left: parent.left
30− leftMargin: units.gu(2)
31− verticalCenter: parent.verticalCenter
32− }
33− width: units.gu(4)
34− height: units.gu(4)
35−
36− MouseArea {
37− anchors.fill: parent
38− onClicked: volumeControl.volumeDown();
39− }
40− }
41−
42− Slider {
43− id: slider
44− objectName: "volumeSlider"
45− anchors {
46− left: minVolumeIcon.right
47− right: maxVolumeIcon.left
48− margins: units.gu(1)
49− verticalCenter: parent.verticalCenter
50− }
51− live: false
52− minimumValue: 0
53− maximumValue: 100
54− value: 50
55−
56− onValueChanged: {
57− volumeControl.volume = value;
58− }
59−
60− Binding {
61− target: slider
62− property: "value"
63− value: volumeControl.volume
64− }
65−
66− function formatValue(v) {
67− return ""
68− }
69− }
70−
71− Image {
72− id: maxVolumeIcon
73− objectName: "maxVolumeIcon"
74− source: "graphics/sound_on_icon.png"
75− anchors {
76− right: parent.right
77− rightMargin: units.gu(2)
78− verticalCenter: parent.verticalCenter
79− }
80− width: units.gu(4)
81− height: units.gu(4)
82−
83− MouseArea {
84− anchors.fill: parent
85− onClicked: volumeControl.volumeUp();
86− }
87− }
88−}
Panel/Menus/Overview/graphics/plane_icon@18.pngdeleted

Binary file not shown.

Panel/Menus/Overview/graphics/sound_off_icon@18.pngdeleted

Binary file not shown.

Panel/Menus/Overview/graphics/sound_on_icon@18.pngdeleted

Binary file not shown.

Panel/Panel.qml+28−9
@@ -39,11 +39,8 @@ Item {
39 }
39 }
40 height: __panelMinusSeparatorLineHeight
40 height: __panelMinusSeparatorLineHeight
41 y: 0
41 y: 0
42− onYChanged: indicatorsMenu.y = y;
43
42
44− Behavior on y {
43+ Behavior on y { StandardAnimation {} }
45− NumberAnimation { duration: 200 }
46− }
47 }
44 }
48
45
49 PanelSeparatorLine {
46 PanelSeparatorLine {
@@ -78,18 +75,40 @@ Item {
78 id: indicatorsMenu
75 id: indicatorsMenu
79
76
80 anchors.right: parent.right
77 anchors.right: parent.right
81− y: 0
78+ y: panelBackground.y
82 width: root.indicatorsMenuWidth
79 width: root.indicatorsMenuWidth
83 shown: false
80 shown: false
84 hintValue: __panelMinusSeparatorLineHeight * 3
81 hintValue: __panelMinusSeparatorLineHeight * 3
85 panelHeight: __panelMinusSeparatorLineHeight
82 panelHeight: __panelMinusSeparatorLineHeight
86− referenceOpenedHeight: parent.height
83+ openedHeight: parent.height + (pinnedMode ? 0 : root.panelHeight)
87−
88 pinnedMode: !fullscreenMode
84 pinnedMode: !fullscreenMode
89
85
90 property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
86 property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
91 }
87 }
92
88
89+ PanelSeparatorLine {
90+ id: indicatorsSeparatorLine
91+ visible: true
92+ anchors {
93+ left: indicatorsMenu.left
94+ right: indicatorsMenu.right
95+ }
96+ y: indicatorsMenu.visualBottom
97+ }
98+
99+ BorderImage {
100+ id: dropShadow
101+ anchors {
102+ top: indicators.top
103+ bottom: indicatorsSeparatorLine.bottom
104+ left: indicators.left
105+ right: indicators.right
106+ margins: -units.gu(1)
107+ }
108+ visible: indicatorsMenu.height > indicatorsMenu.panelHeight
109+ source: "graphics/rectangular_dropshadow.sci"
110+ }
111+
93 SearchIndicator {
112 SearchIndicator {
94 id: search
113 id: search
95 objectName: "search"
114 objectName: "search"
@@ -98,14 +117,14 @@ Item {
98 state: {
117 state: {
99 if (parent.width < indicatorsMenu.width + width) {
118 if (parent.width < indicatorsMenu.width + width) {
100 if (indicatorsMenu.state != "initial") {
119 if (indicatorsMenu.state != "initial") {
101− return "hiddenUp";
120+ return "hidden";
102 }
121 }
103 }
122 }
104 if (root.searchVisible) {
123 if (root.searchVisible) {
105 return "visible";
124 return "visible";
106 }
125 }
107
126
108− return "hiddenUp";
127+ return "hidden";
109 }
128 }
110
129
111 width: units.gu(13)
130 width: units.gu(13)
Panel/SearchIndicator.qml+3−5
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import "../Components"
19
20
20Item {
21Item {
21 id: search
22 id: search
@@ -40,8 +41,7 @@ Item {
40 width: parent.width
41 width: parent.width
41 height: parent.height
42 height: parent.height
42
43
43− Behavior on opacity {NumberAnimation {}}
44+ Behavior on opacity { StandardAnimation {} }
44− Behavior on y {NumberAnimation {duration: 300; easing.type: Easing.OutCubic}}
45
45
46 Image {
46 Image {
47 id: icon
47 id: icon
@@ -67,15 +67,13 @@ Item {
67 name: "visible"
67 name: "visible"
68 PropertyChanges {
68 PropertyChanges {
69 target: container
69 target: container
70− y: 0
71 opacity: 1
70 opacity: 1
72 }
71 }
73 },
72 },
74 State {
73 State {
75− name: "hiddenUp"
74+ name: "hidden"
76 PropertyChanges {
75 PropertyChanges {
77 target: container
76 target: container
78− y: -height
79 opacity: 0
77 opacity: 0
80 }
78 }
81 }
79 }
Shell.qml+27−9
@@ -37,8 +37,8 @@ FocusScope {
37
37
38 // this is only here to select the width / height of the window if not running fullscreen
38 // this is only here to select the width / height of the window if not running fullscreen
39 property bool tablet: false
39 property bool tablet: false
40− width: tablet ? units.gu(160) : units.gu(40)
40+ width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
41− height: tablet ? units.gu(100) : units.gu(71)
41+ height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
42
42
43 property real edgeSize: units.gu(2)
43 property real edgeSize: units.gu(2)
44 property url default_background: shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg"
44 property url default_background: shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg"
@@ -76,6 +76,8 @@ FocusScope {
76 property var applicationManager: ApplicationManagerWrapper {}
76 property var applicationManager: ApplicationManagerWrapper {}
77
77
78 Component.onCompleted: {
78 Component.onCompleted: {
79+ Theme.name = "Ubuntu.Components.Themes.SuruGradient"
80+
79 applicationManager.sideStageEnabled = Qt.binding(function() { return sideStage.enabled })
81 applicationManager.sideStageEnabled = Qt.binding(function() { return sideStage.enabled })
80
82
81 // FIXME: if application focused before shell starts, shell draws on top of it only.
83 // FIXME: if application focused before shell starts, shell draws on top of it only.
@@ -141,11 +143,20 @@ FocusScope {
141
143
142 Item {
144 Item {
143 id: underlay
145 id: underlay
146+ objectName: "underlay"
144 anchors.fill: parent
147 anchors.fill: parent
148+
149+ // Whether the underlay is fully covered by opaque UI elements.
145− visible: !(panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
150+ property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
146− && (stages.fullyHidden
151+
152+ // Whether the user should see the topmost application surface (if there's one at all).
153+ property bool applicationSurfaceShouldBeSeen:
154+ (mainStage.applications && mainStage.applications.count > 0)
147− || (stages.fullyShown && mainStage.usingScreenshots)
155+ && (!stages.fullyHidden && !mainStage.usingScreenshots)
148− || !stages.fullyShown && (mainStage.usingScreenshots || (sideStage.shown && sideStage.usingScreenshots)))
156+
157+ // NB! Application surfaces are stacked behing the shell one. So they can only be seen by the user
158+ // through the translucent parts of the shell surface.
159+ visible: !fullyCovered && !applicationSurfaceShouldBeSeen
149
160
150 Image {
161 Image {
151 id: backgroundImage
162 id: backgroundImage
@@ -163,6 +174,7 @@ FocusScope {
163
174
164 Dash {
175 Dash {
165 id: dash
176 id: dash
177+ objectName: "dash"
166
178
167 available: !greeter.shown && !lockscreen.shown
179 available: !greeter.shown && !lockscreen.shown
168 hides: [stages, launcher, panel.indicators]
180 hides: [stages, launcher, panel.indicators]
@@ -190,7 +202,7 @@ FocusScope {
190 }
202 }
191 }
203 }
192
204
193− // FIXME: only necessary because stagesRevealer.animatedProgress and
205+ // FIXME: only necessary because stagesOuterContainer.showProgress and
194 // greeterRevealer.animatedProgress are not animated
206 // greeterRevealer.animatedProgress are not animated
195 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
207 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
196 }
208 }
@@ -259,6 +271,7 @@ FocusScope {
259
271
260 Showable {
272 Showable {
261 id: stages
273 id: stages
274+ objectName: "stages"
262
275
263 x: width
276 x: width
264
277
@@ -315,6 +328,7 @@ FocusScope {
315
328
316 anchors.fill: parent
329 anchors.fill: parent
317 fullyShown: stages.fullyShown
330 fullyShown: stages.fullyShown
331+ fullyHidden: stages.fullyHidden
318 shouldUseScreenshots: !fullyShown
332 shouldUseScreenshots: !fullyShown
319 rightEdgeEnabled: !sideStage.enabled
333 rightEdgeEnabled: !sideStage.enabled
320
334
@@ -399,7 +413,7 @@ FocusScope {
399 }
413 }
400
414
401 DragHandle {
415 DragHandle {
402− id: stagesRevealer
416+ id: stagesDragHandle
403
417
404 anchors.top: parent.top
418 anchors.top: parent.top
405 anchors.bottom: parent.bottom
419 anchors.bottom: parent.bottom
@@ -407,7 +421,11 @@ FocusScope {
407
421
408 width: shell.edgeSize
422 width: shell.edgeSize
409 direction: Direction.Leftwards
423 direction: Direction.Leftwards
410− enabled: mainStage.applications.count > 0 || sideStage.applications.count > 0
424+ property bool haveApps: mainStage.applications.count > 0 || sideStage.applications.count > 0
425+
426+ maxTotalDragDistance: haveApps ? parent.width : parent.width * 0.7
427+ // Make autocompletion impossible when !haveApps
428+ edgeDragEvaluator.minDragDistance: haveApps ? maxTotalDragDistance * 0.1 : Number.MAX_VALUE
411 }
429 }
412 }
430 }
413 }
431 }
cmake/modules/Plugins.cmake+25−15
@@ -1,17 +1,12 @@
1−# Creates targets for copying and installing qmlfiles and generating the qmltypes file for a plugin
1+# Creates target for copying and installing qmlfiles
2#
2#
3−# export_qmlplugin(plugin version sub_path [TARGETS target1 [target2 ...]])
3+# export_qmlfiles(plugin sub_path)
4#
4#
5−# TARGETS additional install targets (eg the plugin shared object)
6#
5#
7−# Two targets will be created:
6+# Target to be created:
8# - plugin-qmlfiles - Copies the qml files (*.qml, *.js, qmldir) into the shadow build folder.
7# - plugin-qmlfiles - Copies the qml files (*.qml, *.js, qmldir) into the shadow build folder.
9−# - plugin-qmltypes - Generates the qmltypes file in the shadow build folder.
10−
11
8
12−macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
9+macro(export_qmlfiles PLUGIN PLUGIN_SUBPATH)
13− set(multi_value_keywords TARGETS)
14− cmake_parse_arguments(qmlplugin "" "" "${multi_value_keywords}" ${ARGN})
15
10
16 file(GLOB QMLFILES
11 file(GLOB QMLFILES
17 *.qml
12 *.qml
@@ -25,17 +20,32 @@ macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
25 DEPENDS ${QMLFILES}
20 DEPENDS ${QMLFILES}
26 )
21 )
27
22
23+ # install the qmlfiles file.
24+ install(FILES ${QMLFILES}
25+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
26+ )
27+endmacro(export_qmlfiles)
28+
29+
30+# Creates target for generating the qmltypes file for a plugin and installs plugin files
31+#
32+# export_qmlplugin(plugin version sub_path [TARGETS target1 [target2 ...]])
33+#
34+# TARGETS additional install targets (eg the plugin shared object)
35+#
36+# Target to be created:
37+# - plugin-qmltypes - Generates the qmltypes file in the shadow build folder.
38+
39+macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
40+ set(multi_value_keywords TARGETS)
41+ cmake_parse_arguments(qmlplugin "" "" "${multi_value_keywords}" ${ARGN})
42+
28 # create the plugin.qmltypes file
43 # create the plugin.qmltypes file
29 add_custom_target(${PLUGIN}-qmltypes ALL
44 add_custom_target(${PLUGIN}-qmltypes ALL
30 COMMAND qmlplugindump -notrelocatable ${PLUGIN} ${VERSION} ${CMAKE_BINARY_DIR}/plugins > ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
45 COMMAND qmlplugindump -notrelocatable ${PLUGIN} ${VERSION} ${CMAKE_BINARY_DIR}/plugins > ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
31 )
46 )
32 add_dependencies(${PLUGIN}-qmltypes ${PLUGIN}-qmlfiles ${qmlplugin_TARGETS})
47 add_dependencies(${PLUGIN}-qmltypes ${PLUGIN}-qmlfiles ${qmlplugin_TARGETS})
33
48
34− # install the qmldir file.
35− install(FILES ${QMLFILES}
36− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
37− )
38−
39 # install the qmltypes file.
49 # install the qmltypes file.
40 install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
50 install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
41 DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
51 DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
@@ -45,4 +55,4 @@ macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
45 install(TARGETS ${qmlplugin_TARGETS}
55 install(TARGETS ${qmlplugin_TARGETS}
46 DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
56 DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
47 )
57 )
48−endmacro(export_qmlplugin)
58+endmacro(export_qmlplugin)
cmake/modules/autopilot.cmake+2−1
@@ -2,8 +2,9 @@ add_custom_target(autopilot)
2
2
3function(declare_autopilot_test TEST_NAME TEST_SUITE WORKING_DIR)
3function(declare_autopilot_test TEST_NAME TEST_SUITE WORKING_DIR)
4 add_custom_target(autopilot-${TEST_NAME}
4 add_custom_target(autopilot-${TEST_NAME}
5− COMMAND autopilot run ${TEST_SUITE}
5+ COMMAND LANG=C UBUNTU_ICON_THEME=ubuntu-mobile QML2_IMPORT_PATH=${SHELL_PRIVATE_LIBDIR}/qml/mocks autopilot run ${TEST_SUITE}
6 WORKING_DIRECTORY ${WORKING_DIR}
6 WORKING_DIRECTORY ${WORKING_DIR}
7+ DEPENDS install
7 )
8 )
8
9
9 add_dependencies(autopilot autopilot-${TEST_NAME})
10 add_dependencies(autopilot autopilot-${TEST_NAME})
debian/changelog+130
@@ -1,3 +1,133 @@
1+unity8 (7.81.3+13.10.20130730ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2+
3+ [ Michał Sawicz ]
4+ * Adapt to Qt 5.1.
5+
6+ [ Albert Astals ]
7+ * Adapt to Qt 5.1.
8+
9+ [ Ubuntu daily release ]
10+ * Automatic snapshot from revision 143 (ubuntu-unity/next)
11+
12+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 30 Jul 2013 02:33:12 +0000
13+
14+unity8 (7.81.3+13.10.20130729ubuntu.unity.next-0ubuntu1) saucy; urgency=low
15+
16+ [ Michal Hruby ]
17+ * Remove the variant conversions methods as they were moved to dee-qt.
18+
19+ [ Michał Sawicz ]
20+ * Re-enable passphrase tests under UInput.
21+ * Use the new string categoryIds in custom video and music scope
22+ views. (LP: #1199322)
23+
24+ [ Nick Dedekind ]
25+ * Behavioural changes for indicators - Part 1 - Use standard
26+ animations. - Search bar animation less distracting. - Hinting
27+ animation shows header. - Vertical velocity detector to reduce
28+ accidental menu switches in dragging phase.
29+
30+ [ Gustavo Pichorim Boiko ]
31+ * Add entries to the new applications resulted from the split of the
32+ phone-app.
33+
34+ [ Ubuntu daily release ]
35+ * Automatic snapshot from revision 141 (ubuntu-unity/next)
36+
37+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 29 Jul 2013 03:41:07 +0000
38+
39+unity8 (7.81.3+13.10.20130726ubuntu.unity.next-0ubuntu1) saucy; urgency=low
40+
41+ [ Michal Hruby ]
42+ * Expose real category ids and not just indices.
43+ * Provide fallbacks for default renderer.
44+
45+ [ Daniel d'Andrada ]
46+ * Give a visual feedback on right-edge drag with no running apps (LP:
47+ #1116207). (LP: #1116207)
48+
49+ [ Albert Astals ]
50+ * Update m_firstVisibleIndex if there's no visible items anymore Also
51+ remove the check for m_visibleItems.isEmpty() on insert, the
52+ m_firstVisibleIndex == 0 already protects us against that.
53+
54+ [ Christopher Lee ]
55+ * Tests now use a default lightdm mock if not decorated. (LP:
56+ #1204772)
57+
58+ [ Ubuntu daily release ]
59+ * Automatic snapshot from revision 135 (ubuntu-unity/next)
60+
61+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 26 Jul 2013 07:06:08 +0000
62+
63+unity8 (7.81.3+13.10.20130725ubuntu.unity.next-0ubuntu1) saucy; urgency=low
64+
65+ [ Michal Hruby ]
66+ * Fix adding items into an empty LVWPH.
67+
68+ [ Michał Sawicz ]
69+ * Move to using upstart in run_on_device.
70+ * Added heeding and qmltest for button-tint hint.
71+ * Refactoring and cleanup of the Unity8 Autopilot tests.
72+ * Hide the Unity launcher during autopiloting and skip battery tests
73+ if unavailable.
74+
75+ [ Ying-Chun Liu ]
76+ * Let GenericScope support loading different renderers.
77+
78+ [ Nick Dedekind ]
79+ * Removed overview from indicators.
80+ * Menus for indicators is now created prioritised by distance from
81+ current item to speed up user experience.
82+ * Add ApplicationArguments to know the geometry from start.
83+
84+ [ Mirco Müller ]
85+ * Added heeding and qmltest for button-tint hint.
86+
87+ [ Christopher Lee ]
88+ * Refactoring and cleanup of the Unity8 Autopilot tests.
89+
90+ [ Thomi Richards ]
91+ * Refactoring and cleanup of the Unity8 Autopilot tests.
92+
93+ [ Ubuntu daily release ]
94+ * Automatic snapshot from revision 129 (ubuntu-unity/next)
95+
96+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 25 Jul 2013 03:02:12 +0000
97+
98+unity8 (7.81.3+13.10.20130718ubuntu.unity.next-0ubuntu1) saucy; urgency=low
99+
100+ [ Andrea Cimitan ]
101+ * Add support for the colour palette.
102+
103+ [ Omer Akram ]
104+ * fix the calendar icon in the launcher. (LP: #1201905)
105+
106+ [ Nick Dedekind ]
107+ * Export indicator plugin symbols using Q_DECL_EXPORT.
108+
109+ [ Ying-Chun Liu ]
110+ * Don't include .moc in previewbindingstest.cpp.
111+
112+ [ Ubuntu daily release ]
113+ * Automatic snapshot from revision 118 (ubuntu-unity/next)
114+
115+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 18 Jul 2013 06:07:00 +0000
116+
117+unity8 (7.81.3+13.10.20130717ubuntu.unity.next-0ubuntu1) saucy; urgency=low
118+
119+ [ Daniel d'Andrada ]
120+ * Remove dead code: Showable::showWithoutAnimation.
121+
122+ [ Nick Dedekind ]
123+ * Split Plugins export macro into export_qmlfiles and
124+ export_qmlplugins. Added qmltypes to indicators plugin.
125+
126+ [ Ubuntu daily release ]
127+ * Automatic snapshot from revision 112 (ubuntu-unity/next)
128+
129+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 17 Jul 2013 03:14:49 +0000
130+
1unity8 (7.81.3+13.10.20130716ubuntu.unity.next-0ubuntu1) saucy; urgency=low
131unity8 (7.81.3+13.10.20130716ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2
132
3 [ Pete Woods ]
133 [ Pete Woods ]
debian/control+3−1
@@ -5,7 +5,7 @@ Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5Build-Depends: cmake,
5Build-Depends: cmake,
6 dbus-test-runner,
6 dbus-test-runner,
7 debhelper (>= 9),
7 debhelper (>= 9),
8− libdee-qt5-dev (>= 3.0),
8+ libdee-qt5-dev (>= 3.2),
9 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
9 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
10 libgl1-mesa-dri,
10 libgl1-mesa-dri,
11 libgles2-mesa-dev[armhf],
11 libgles2-mesa-dev[armhf],
@@ -89,6 +89,8 @@ Depends: indicators-client (>= ${source:Version}),
89 ${misc:Depends},
89 ${misc:Depends},
90 ${python:Depends},
90 ${python:Depends},
91 ${shlibs:Depends},
91 ${shlibs:Depends},
92+Recommends: gir1.2-glib-2.0,
93+ python-gi,
92Description: Test package for Unity 8 shell
94Description: Test package for Unity 8 shell
93 Autopilot tests for the unity8 package
95 Autopilot tests for the unity8 package
94
96
main.cpp+4−6
@@ -18,6 +18,7 @@
18 */
18 */
19
19
20// Qt
20// Qt
21+#include <QtQml>
21#include <QtQuick/QQuickView>
22#include <QtQuick/QQuickView>
22#include <QtGui/QIcon>
23#include <QtGui/QIcon>
23#include <QtGui/QGuiApplication>
24#include <QtGui/QGuiApplication>
@@ -30,6 +31,7 @@
30// local
31// local
31#include "paths.h"
32#include "paths.h"
32#include "MouseTouchAdaptor.h"
33#include "MouseTouchAdaptor.h"
34+#include "ApplicationArguments.h"
33
35
34namespace {
36namespace {
35
37
@@ -86,6 +88,7 @@ int main(int argc, char** argv)
86 resolveIconTheme();
88 resolveIconTheme();
87
89
88 QStringList args = application.arguments();
90 QStringList args = application.arguments();
91+ ApplicationArguments qmlArgs(args);
89
92
90 // The testability driver is only loaded by QApplication but not by QGuiApplication.
93 // The testability driver is only loaded by QApplication but not by QGuiApplication.
91 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
94 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
@@ -110,6 +113,7 @@ int main(int argc, char** argv)
110 view->setResizeMode(QQuickView::SizeRootObjectToView);
113 view->setResizeMode(QQuickView::SizeRootObjectToView);
111 view->setTitle("Qml Phone Shell");
114 view->setTitle("Qml Phone Shell");
112 view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()));
115 view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()));
116+ view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
113 if (args.contains(QLatin1String("-frameless"))) {
117 if (args.contains(QLatin1String("-frameless"))) {
114 view->setFlags(Qt::FramelessWindowHint);
118 view->setFlags(Qt::FramelessWindowHint);
115 }
119 }
@@ -141,12 +145,6 @@ int main(int argc, char** argv)
141 if (qgetenv("QT_QPA_PLATFORM") == "ubuntu" || args.contains(QLatin1String("-fullscreen"))) {
145 if (qgetenv("QT_QPA_PLATFORM") == "ubuntu" || args.contains(QLatin1String("-fullscreen"))) {
142 view->showFullScreen();
146 view->showFullScreen();
143 } else {
147 } else {
144− if (args.contains(QLatin1String("-geometry")) && args.size() > args.indexOf(QLatin1String("-geometry")) + 1) {
145− QStringList geometryArg = args.at(args.indexOf(QLatin1String("-geometry")) + 1).split('x');
146− if (geometryArg.size() == 2) {
147− view->resize(geometryArg.at(0).toInt(), geometryArg.at(1).toInt());
148− }
149− }
150 view->show();
148 view->show();
151 }
149 }
152
150
plugins/HudClient/CMakeLists.txt+2−1
@@ -38,5 +38,6 @@ target_link_libraries(HudClientQml
38
38
39qt5_use_modules(HudClientQml Qml)
39qt5_use_modules(HudClientQml Qml)
40
40
41−# export the qmldir and qmltypes files
41+# export the qmldir qmltypes and plugin files
42+export_qmlfiles(HudClient HudClient)
42export_qmlplugin(HudClient 0.1 HudClient TARGETS HudClientQml)
43export_qmlplugin(HudClient 0.1 HudClient TARGETS HudClientQml)
plugins/LightDM/CMakeLists.txt+2−1
@@ -35,5 +35,6 @@ target_link_libraries(LightDM-qml
35
35
36qt5_use_modules(LightDM-qml Gui Qml)
36qt5_use_modules(LightDM-qml Gui Qml)
37
37
38−# export the qmldir and qmltypes files
38+# export the qmldir qmltypes and plugin files
39+export_qmlfiles(LightDM LightDM)
39export_qmlplugin(LightDM 0.1 LightDM TARGETS LightDM-qml)
40export_qmlplugin(LightDM 0.1 LightDM TARGETS LightDM-qml)
plugins/ListViewWithPageHeader/CMakeLists.txt+7−2
@@ -4,7 +4,11 @@ include(Plugins)
4# There's no cmake var for v8 include path :-/
4# There's no cmake var for v8 include path :-/
5# so create one
5# so create one
6LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
6LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
7+if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
7−SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
8+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
9+else()
10+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
11+endif()
8
12
9include_directories(
13include_directories(
10 ${CMAKE_CURRENT_SOURCE_DIR}
14 ${CMAKE_CURRENT_SOURCE_DIR}
@@ -33,5 +37,6 @@ target_link_libraries(ListViewWithPageHeader-qml
33
37
34qt5_use_modules(ListViewWithPageHeader-qml Qml Quick)
38qt5_use_modules(ListViewWithPageHeader-qml Qml Quick)
35
39
36−# export the qmldir and qmltypes files
40+# export the qmldir qmltypes and plugin files
41+export_qmlfiles(ListViewWithPageHeader ListViewWithPageHeader)
37export_qmlplugin(ListViewWithPageHeader 0.1 ListViewWithPageHeader TARGETS ListViewWithPageHeader-qml)
42export_qmlplugin(ListViewWithPageHeader 0.1 ListViewWithPageHeader TARGETS ListViewWithPageHeader-qml)
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+70−4
@@ -96,7 +96,11 @@
96#include <qqmlengine.h>
96#include <qqmlengine.h>
97#pragma GCC diagnostic push
97#pragma GCC diagnostic push
98#pragma GCC diagnostic ignored "-pedantic"
98#pragma GCC diagnostic ignored "-pedantic"
99+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
99#include <private/qquickvisualdatamodel_p.h>
100#include <private/qquickvisualdatamodel_p.h>
101+#else
102+#include <private/qqmldelegatemodel_p.h>
103+#endif
100#include <private/qqmlglobal_p.h>
104#include <private/qqmlglobal_p.h>
101#include <private/qquickitem_p.h>
105#include <private/qquickitem_p.h>
102#include <private/qquickanimation_p.h>
106#include <private/qquickanimation_p.h>
@@ -183,10 +187,17 @@ void ListViewWithPageHeader::setModel(QAbstractItemModel *model)
183 if (!m_delegateModel) {
187 if (!m_delegateModel) {
184 createDelegateModel();
188 createDelegateModel();
185 } else {
189 } else {
190+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
186 disconnect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
191 disconnect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
187 }
192 }
188 m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
193 m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
189 connect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
194 connect(m_delegateModel, SIGNAL(modelUpdated(QQuickChangeSet,bool)), this, SLOT(onModelUpdated(QQuickChangeSet,bool)));
195+#else
196+ disconnect(m_delegateModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(onModelUpdated(QQmlChangeSet,bool)));
197+ }
198+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
199+ connect(m_delegateModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(onModelUpdated(QQmlChangeSet,bool)));
200+#endif
190 Q_EMIT modelChanged();
201 Q_EMIT modelChanged();
191 // TODO?
202 // TODO?
192// Q_EMIT contentHeightChanged();
203// Q_EMIT contentHeightChanged();
@@ -446,8 +457,13 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
446
457
447void ListViewWithPageHeader::createDelegateModel()
458void ListViewWithPageHeader::createDelegateModel()
448{
459{
460+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
449 m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
461 m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
450 connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
462 connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
463+#else
464+ m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
465+ connect(m_delegateModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(itemCreated(int,QObject*)));
466+#endif
451 if (isComponentComplete())
467 if (isComponentComplete())
452 m_delegateModel->componentComplete();
468 m_delegateModel->componentComplete();
453 updateWatchedRoles();
469 updateWatchedRoles();
@@ -528,8 +544,13 @@ bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool
528void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
544void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
529{
545{
530 QQuickItem *item = listItem->m_item;
546 QQuickItem *item = listItem->m_item;
547+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
531 QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item);
548 QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item);
532 if (flags & QQuickVisualModel::Destroyed) {
549 if (flags & QQuickVisualModel::Destroyed) {
550+#else
551+ QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
552+ if (flags & QQmlDelegateModel::Destroyed) {
553+#endif
533 item->setParentItem(nullptr);
554 item->setParentItem(nullptr);
534 }
555 }
535 delete listItem->m_sectionItem;
556 delete listItem->m_sectionItem;
@@ -658,9 +679,27 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
658 return nullptr;
679 return nullptr;
659
680
660 m_asyncRequestedIndex = -1;
681 m_asyncRequestedIndex = -1;
682+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
661 QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
683 QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
684+#else
685+ QObject* object = m_delegateModel->object(modelIndex, asynchronous);
686+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
687+#endif
662 if (!item) {
688 if (!item) {
689+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
663 m_asyncRequestedIndex = modelIndex;
690 m_asyncRequestedIndex = modelIndex;
691+#else
692+ if (object) {
693+ m_delegateModel->release(object);
694+ if (!m_delegateValidated) {
695+ m_delegateValidated = true;
696+ QObject* delegateObj = delegate();
697+ qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
698+ }
699+ } else {
700+ m_asyncRequestedIndex = modelIndex;
701+ }
702+#endif
664 return 0;
703 return 0;
665 } else {
704 } else {
666// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
705// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
@@ -711,8 +750,18 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
711 }
750 }
712}
751}
713
752
753+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
714void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
754void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
715{
755{
756+#else
757+void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
758+{
759+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
760+ if (!item) {
761+ qWarning() << "ListViewWithPageHeader::itemCreated got a non item for index" << modelIndex;
762+ return;
763+ }
764+#endif
716// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
765// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
717
766
718 item->setParentItem(m_clipItem);
767 item->setParentItem(m_clipItem);
@@ -747,13 +796,22 @@ void ListViewWithPageHeader::onHeightChanged()
747 polish();
796 polish();
748}
797}
749
798
799+
800+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
750void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bool /*reset*/)
801void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bool /*reset*/)
802+#else
803+void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool /*reset*/)
804+#endif
751{
805{
752 // TODO Do something with reset
806 // TODO Do something with reset
753// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
807// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
754 const auto oldFirstVisibleIndex = m_firstVisibleIndex;
808 const auto oldFirstVisibleIndex = m_firstVisibleIndex;
755
809
810+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
756 Q_FOREACH(const QQuickChangeSet::Remove &remove, changeSet.removes()) {
811 Q_FOREACH(const QQuickChangeSet::Remove &remove, changeSet.removes()) {
812+#else
813+ Q_FOREACH(const QQmlChangeSet::Remove &remove, changeSet.removes()) {
814+#endif
757// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
815// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
758 if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
816 if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
759 const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
817 const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
@@ -785,10 +843,14 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
785 }
843 }
786 if (growDown) {
844 if (growDown) {
787 adjustMinYExtent();
845 adjustMinYExtent();
788− } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
846+ } else if (remove.index <= m_firstVisibleIndex) {
847+ if (!m_visibleItems.isEmpty()) {
789− // We removed the first item that is the one that positions the rest
848+ // We removed the first item that is the one that positions the rest
790− // position the new first item correctly
849+ // position the new first item correctly
791− m_visibleItems.first()->setY(oldFirstValidIndexPos);
850+ m_visibleItems.first()->setY(oldFirstValidIndexPos);
851+ } else {
852+ m_firstVisibleIndex = -1;
853+ }
792 }
854 }
793 } else if (remove.index + remove.count <= m_firstVisibleIndex) {
855 } else if (remove.index + remove.count <= m_firstVisibleIndex) {
794 m_firstVisibleIndex -= remove.count;
856 m_firstVisibleIndex -= remove.count;
@@ -803,7 +865,11 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
803 }
865 }
804 }
866 }
805
867
868+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
806 Q_FOREACH(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
869 Q_FOREACH(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
870+#else
871+ Q_FOREACH(const QQmlChangeSet::Insert &insert, changeSet.inserts()) {
872+#endif
807// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
873// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
808 const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
874 const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
809 const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
875 const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
plugins/ListViewWithPageHeader/listviewwithpageheader.h+18−1
@@ -24,9 +24,14 @@
24#pragma GCC diagnostic pop
24#pragma GCC diagnostic pop
25
25
26class QAbstractItemModel;
26class QAbstractItemModel;
27−class QQuickChangeSet;
28class QQuickNumberAnimation;
27class QQuickNumberAnimation;
28+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
29+class QQuickChangeSet;
29class QQuickVisualDataModel;
30class QQuickVisualDataModel;
31+#else
32+class QQmlChangeSet;
33+class QQmlDelegateModel;
34+#endif
30
35
31
36
32/**
37/**
@@ -100,11 +105,19 @@ protected:
100 void updatePolish();
105 void updatePolish();
101
106
102private Q_SLOTS:
107private Q_SLOTS:
108+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
103 void itemCreated(int modelIndex, QQuickItem *item);
109 void itemCreated(int modelIndex, QQuickItem *item);
110+#else
111+ void itemCreated(int modelIndex, QObject *object);
112+#endif
104 void onContentHeightChanged();
113 void onContentHeightChanged();
105 void onContentWidthChanged();
114 void onContentWidthChanged();
106 void onHeightChanged();
115 void onHeightChanged();
116+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
107 void onModelUpdated(const QQuickChangeSet &changeSet, bool reset);
117 void onModelUpdated(const QQuickChangeSet &changeSet, bool reset);
118+#else
119+ void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
120+#endif
108 void onShowHeaderAnimationFinished();
121 void onShowHeaderAnimationFinished();
109
122
110private:
123private:
@@ -141,7 +154,11 @@ private:
141 QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
154 QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
142 QQuickItem *getSectionItem(const QString &sectionText);
155 QQuickItem *getSectionItem(const QString &sectionText);
143
156
157+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
144 QQuickVisualDataModel *m_delegateModel;
158 QQuickVisualDataModel *m_delegateModel;
159+#else
160+ QQmlDelegateModel *m_delegateModel;
161+#endif
145
162
146 // Index we are waiting because we requested it asynchronously
163 // Index we are waiting because we requested it asynchronously
147 int m_asyncRequestedIndex;
164 int m_asyncRequestedIndex;
plugins/Ubuntu/Gestures/CMakeLists.txt+2−1
@@ -23,5 +23,6 @@ qt5_use_modules(UbuntuGestureQml Core Quick)
23# So that Foo.cpp can #include "Foo.moc"
23# So that Foo.cpp can #include "Foo.moc"
24include_directories(${CMAKE_CURRENT_BINARY_DIR})
24include_directories(${CMAKE_CURRENT_BINARY_DIR})
25
25
26−# export the qmldir and qmltypes files
26+# export the qmldir qmltypes and plugin files
27+export_qmlfiles(Ubuntu.Gestures Ubuntu/Gestures)
27export_qmlplugin(Ubuntu.Gestures 0.1 Ubuntu/Gestures TARGETS UbuntuGestureQml)
28export_qmlplugin(Ubuntu.Gestures 0.1 Ubuntu/Gestures TARGETS UbuntuGestureQml)
plugins/Unity/CMakeLists.txt+3−2
@@ -5,7 +5,7 @@ add_subdirectory(Indicators)
5
5
6# Dependencies
6# Dependencies
7include(FindPkgConfig)
7include(FindPkgConfig)
8−pkg_check_modules(QTDEE REQUIRED libdee-qt5)
8+pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)
9pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
9pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
10
10
11include_directories(
11include_directories(
@@ -48,7 +48,8 @@ target_link_libraries(Unity-qml
48
48
49qt5_use_modules(Unity-qml Qml)
49qt5_use_modules(Unity-qml Qml)
50
50
51−# export the qmldir and qmltypes files
51+# export the qmldir qmltypes and plugin files
52+export_qmlfiles(Unity Unity)
52export_qmlplugin(Unity 0.1 Unity TARGETS Unity-qml)
53export_qmlplugin(Unity 0.1 Unity TARGETS Unity-qml)
53
54
54add_subdirectory(Launcher)
55add_subdirectory(Launcher)
plugins/Unity/Indicators/CMakeLists.txt+7−8
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
1project(IndicatorsQml)
4project(IndicatorsQml)
2
5
3pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
6pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
@@ -20,8 +23,10 @@ set(IndicatorsQML_SOURCES
20 indicators.h
23 indicators.h
21 indicatorsmanager.cpp
24 indicatorsmanager.cpp
22 indicatorsmodel.cpp
25 indicatorsmodel.cpp
26+ menucontentactivator.cpp
23 plugin.cpp
27 plugin.cpp
24)
28)
29+add_definitions(-DUNITYINDICATORS_LIBRARY)
25
30
26set(IndicatorsQML_RESOURCES
31set(IndicatorsQML_RESOURCES
27 resources/indicators.qrc
32 resources/indicators.qrc
@@ -35,11 +40,6 @@ add_library(IndicatorsQml SHARED
35 ${IndicatorsQML_RESOURCES_RCC}
40 ${IndicatorsQML_RESOURCES_RCC}
36 ${IndicatorsQML_SOURCES}
41 ${IndicatorsQML_SOURCES}
37)
42)
38−# Because this is an internal support library, we want
39−# to expose all symbols in it. Consider changing this
40−# either to a static library or just using the
41−# files directly in targets.
42−set_target_properties(IndicatorsQml PROPERTIES COMPILE_FLAGS -fvisibility=default)
43
43
44target_link_libraries(IndicatorsQml
44target_link_libraries(IndicatorsQml
45 ${QMENUMODEL_LDFLAGS}
45 ${QMENUMODEL_LDFLAGS}
@@ -47,6 +47,5 @@ target_link_libraries(IndicatorsQml
47
47
48qt5_use_modules(IndicatorsQml Core Qml Quick)
48qt5_use_modules(IndicatorsQml Core Qml Quick)
49
49
50+# export the qmltypes and plugin files
50−install(TARGETS IndicatorsQml
51+export_qmlplugin(Unity.Indicators 0.1 Unity/Indicators TARGETS IndicatorsQml)
51− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity/Indicators
52− )
plugins/Unity/Indicators/Messaging/qml/CMakeLists.txt+4−14
@@ -1,15 +1,5 @@
1−file(GLOB IndicatorsMessaging_QMLFILES
1+# export_qmlfiles macro
2− *.qml
2+include(Plugins)
3− *.js
4− qmldir
5−)
6
3
7−# copy qml & qmldir files into build directory for shadow builds
4+# export the qmldir, *.qml files.
8−add_custom_target(UnityIndicatorsMessagingQmlFiles ALL
5+export_qmlfiles(Unity.Indicators.Messaging Unity/Indicators/Messaging)
9− COMMAND cp ${IndicatorsMessaging_QMLFILES} ${CMAKE_BINARY_DIR}/plugins/Unity/Indicators/Messaging
10− DEPENDS ${IndicatorsMessaging_QMLFILES}
11−)
12−
13−install(FILES ${IndicatorsMessaging_QMLFILES}
14− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity/Indicators/Messaging
15−)
plugins/Unity/Indicators/Network/CMakeLists.txt+6−3
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
1project(IndicatorsNetworkQml)
4project(IndicatorsNetworkQml)
2
5
3pkg_check_modules(GLIB glib-2.0>=2.32)
6pkg_check_modules(GLIB glib-2.0>=2.32)
@@ -32,9 +35,9 @@ if(LIBNM_GLIB_FOUND AND LIBNM_UTIL_FOUND AND GLIB_FOUND)
32 ${LIBNM_UTIL_LIBRARIES}
35 ${LIBNM_UTIL_LIBRARIES}
33 )
36 )
34
37
38+ # export the qmltypes and plugin files
35− install(TARGETS IndicatorsNetworkQml
39+ export_qmlplugin(Unity.Indicators.Network 0.1 Unity/Indicators/Network TARGETS IndicatorsNetworkQml)
36− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity/Indicators/Network
40+
37− )
38else()
41else()
39 message(WARNING "Missing glib or libnm dependency for the network plugin, not building")
42 message(WARNING "Missing glib or libnm dependency for the network plugin, not building")
40endif()
43endif()
plugins/Unity/Indicators/Network/qml/CMakeLists.txt+4−14
@@ -1,15 +1,5 @@
1−file(GLOB IndicatorsNetwork_QMLFILES
1+# export_qmlplugin macro
2− *.qml
2+include(Plugins)
3− *.js
4− qmldir
5−)
6
3
7−# copy qml & qmldir files into build directory for shadow builds
4+# export the qmldir, *.qml files.
8−add_custom_target(UnityIndicatorsNetworkQmlFiles ALL
5+export_qmlfiles(Unity.Indicators.Network Unity/Indicators/Network)
9− COMMAND cp ${IndicatorsNetwork_QMLFILES} ${CMAKE_BINARY_DIR}/plugins/Unity/Indicators/Network
10− DEPENDS ${IndicatorsNetwork_QMLFILES}
11−)
12−
13−install(FILES ${IndicatorsNetwork_QMLFILES}
14− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity/Indicators/Network
15−)
plugins/Unity/Indicators/Network/qml/qmldir+1
@@ -1,5 +1,6 @@
1module Unity.Indicators.Network
1module Unity.Indicators.Network
2plugin IndicatorsNetworkQml
2plugin IndicatorsNetworkQml
3+typeinfo plugin.qmltypes
3
4
4NetworkPage 0.1 NetworkPage.qml
5NetworkPage 0.1 NetworkPage.qml
5AccessPoint 0.1 AccessPoint.qml
6AccessPoint 0.1 AccessPoint.qml
plugins/Unity/Indicators/flatmenuproxymodel.h+3−1
@@ -20,12 +20,14 @@
20#ifndef FLATMENUPROXYMODEL_H
20#ifndef FLATMENUPROXYMODEL_H
21#define FLATMENUPROXYMODEL_H
21#define FLATMENUPROXYMODEL_H
22
22
23+#include "unityindicatorsglobal.h"
24+
23#include <QAbstractProxyModel>
25#include <QAbstractProxyModel>
24#include <qdbusmenumodel.h>
26#include <qdbusmenumodel.h>
25
27
26class SectionInfo;
28class SectionInfo;
27
29
28−class FlatMenuProxyModel : public QAbstractProxyModel
30+class UNITYINDICATORS_EXPORT FlatMenuProxyModel : public QAbstractProxyModel
29{
31{
30 Q_OBJECT
32 Q_OBJECT
31 Q_PROPERTY(int count READ count NOTIFY countChanged)
33 Q_PROPERTY(int count READ count NOTIFY countChanged)
plugins/Unity/Indicators/indicator.h+3−1
@@ -21,10 +21,12 @@
21#ifndef INDICATOR_H
21#ifndef INDICATOR_H
22#define INDICATOR_H
22#define INDICATOR_H
23
23
24+#include "unityindicatorsglobal.h"
25+
24#include <QObject>
26#include <QObject>
25#include <QSettings>
27#include <QSettings>
26
28
27−class Indicator : public QObject
29+class UNITYINDICATORS_EXPORT Indicator : public QObject
28{
30{
29 Q_OBJECT
31 Q_OBJECT
30 Q_PROPERTY(QString identifier READ identifier NOTIFY identifierChanged)
32 Q_PROPERTY(QString identifier READ identifier NOTIFY identifierChanged)
plugins/Unity/Indicators/indicators.h+7−5
@@ -19,9 +19,11 @@
19#ifndef INDICATORS_H
19#ifndef INDICATORS_H
20#define INDICATORS_H
20#define INDICATORS_H
21
21
22+#include "unityindicatorsglobal.h"
23+
22#include <QObject>
24#include <QObject>
23
25
24−class ActionState : public QObject
26+class UNITYINDICATORS_EXPORT ActionState : public QObject
25{
27{
26 Q_OBJECT
28 Q_OBJECT
27public:
29public:
@@ -36,7 +38,7 @@ public:
36 ActionState(QObject*parent=0):QObject(parent) {}
38 ActionState(QObject*parent=0):QObject(parent) {}
37};
39};
38
40
39−class NetworkActionState : public QObject
41+class UNITYINDICATORS_EXPORT NetworkActionState : public QObject
40{
42{
41 Q_OBJECT
43 Q_OBJECT
42public:
44public:
@@ -49,7 +51,7 @@ public:
49 NetworkActionState(QObject*parent=0):QObject(parent) {}
51 NetworkActionState(QObject*parent=0):QObject(parent) {}
50};
52};
51
53
52−class NetworkConnection : public QObject
54+class UNITYINDICATORS_EXPORT NetworkConnection : public QObject
53{
55{
54 Q_OBJECT
56 Q_OBJECT
55public:
57public:
@@ -64,7 +66,7 @@ public:
64 NetworkConnection(QObject*parent=0):QObject(parent) {}
66 NetworkConnection(QObject*parent=0):QObject(parent) {}
65};
67};
66
68
67−class IndicatorsModelRole : public QObject
69+class UNITYINDICATORS_EXPORT IndicatorsModelRole : public QObject
68{
70{
69 Q_OBJECT
71 Q_OBJECT
70public:
72public:
@@ -83,7 +85,7 @@ public:
83 IndicatorsModelRole(QObject*parent=0):QObject(parent) {}
85 IndicatorsModelRole(QObject*parent=0):QObject(parent) {}
84};
86};
85
87
86−class FlatMenuProxyModelRole : public QObject
88+class UNITYINDICATORS_EXPORT FlatMenuProxyModelRole : public QObject
87{
89{
88 Q_OBJECT
90 Q_OBJECT
89public:
91public:
plugins/Unity/Indicators/indicatorsmanager.h+4−3
@@ -19,15 +19,16 @@
19#ifndef INDICATORS_MANAGER_H
19#ifndef INDICATORS_MANAGER_H
20#define INDICATORS_MANAGER_H
20#define INDICATORS_MANAGER_H
21
21
22+#include "indicator.h"
23+#include "unityindicatorsglobal.h"
24+
22#include <QObject>
25#include <QObject>
23#include <QFileSystemWatcher>
26#include <QFileSystemWatcher>
24#include <QDir>
27#include <QDir>
25#include <QHash>
28#include <QHash>
26#include <QSharedPointer>
29#include <QSharedPointer>
27
30
28−#include "indicator.h"
29−
30−class IndicatorsManager : public QObject
31+class UNITYINDICATORS_EXPORT IndicatorsManager : public QObject
31{
32{
32 Q_OBJECT
33 Q_OBJECT
33 Q_PROPERTY(bool loaded READ isLoaded NOTIFY loadedChanged)
34 Q_PROPERTY(bool loaded READ isLoaded NOTIFY loadedChanged)
plugins/Unity/Indicators/indicatorsmodel.h+2−1
@@ -22,13 +22,14 @@
22#define INDICATORSMODEL_H
22#define INDICATORSMODEL_H
23
23
24#include "indicator.h"
24#include "indicator.h"
25+#include "unityindicatorsglobal.h"
25
26
26#include <QAbstractListModel>
27#include <QAbstractListModel>
27#include <QQmlEngine>
28#include <QQmlEngine>
28
29
29class IndicatorsManager;
30class IndicatorsManager;
30
31
31−class IndicatorsModel : public QAbstractListModel
32+class UNITYINDICATORS_EXPORT IndicatorsModel : public QAbstractListModel
32{
33{
33 Q_OBJECT
34 Q_OBJECT
34 Q_ENUMS(Roles)
35 Q_ENUMS(Roles)
plugins/Unity/Indicators/menucontentactivator.cppnew file+345
@@ -0,0 +1,345 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+ #include "menucontentactivator.h"
20+
21+// Essentially a QTimer wrapper
22+class ContentTimer : public UnityIndicators::AbstractTimer
23+{
24+ Q_OBJECT
25+public:
26+ ContentTimer(QObject *parent) : UnityIndicators::AbstractTimer(parent) {
27+ m_timer.setSingleShot(false);
28+ connect(&m_timer, &QTimer::timeout,
29+ this, &UnityIndicators::AbstractTimer::timeout);
30+ }
31+ virtual int interval() const { return m_timer.interval(); }
32+ virtual void setInterval(int msecs) { m_timer.setInterval(msecs); }
33+ virtual void start() { m_timer.start(); UnityIndicators::AbstractTimer::start(); }
34+ virtual void stop() { m_timer.stop(); UnityIndicators::AbstractTimer::stop(); }
35+private:
36+ QTimer m_timer;
37+};
38+
39+class MenuContentActivatorPrivate : public QObject
40+{
41+ Q_OBJECT
42+public:
43+ MenuContentActivatorPrivate(MenuContentActivator* parent)
44+ : m_running(false),
45+ m_baseIndex(0),
46+ m_delta(0),
47+ m_count(0),
48+ m_timer(NULL),
49+ q(parent)
50+ {}
51+
52+ ~MenuContentActivatorPrivate()
53+ {
54+ qDeleteAll(m_content);
55+ m_content.clear();
56+ }
57+
58+ int findNextInactiveDelta(bool* finished = NULL);
59+
60+ static int content_count(QQmlListProperty<MenuContentState> *prop);
61+ static MenuContentState* content_at(QQmlListProperty<MenuContentState> *prop, int index);
62+
63+ bool m_running;
64+ int m_baseIndex;
65+ int m_delta;
66+ int m_count;
67+ UnityIndicators::AbstractTimer* m_timer;
68+ QMap<int, MenuContentState*> m_content;
69+ MenuContentActivator* q;
70+};
71+
72+MenuContentActivator::MenuContentActivator(QObject* parent)
73+ : QObject(parent),
74+ d(new MenuContentActivatorPrivate(this))
75+{
76+ qRegisterMetaType<QQmlListProperty<MenuContentState> > ("QQmlListProperty<MenuContentState>");
77+
78+ setContentTimer(new ContentTimer(this));
79+ d->m_timer->setInterval(75);
80+}
81+
82+MenuContentActivator::~MenuContentActivator()
83+{
84+ delete d;
85+}
86+
87+void MenuContentActivator::restart()
88+{
89+ // when we start, make sure we have the base index in the list.
90+ setMenuContentState(d->m_baseIndex, true);
91+ setDelta(0);
92+
93+ // check if we've finished before starting the timer.
94+ bool finished = false;
95+ d->findNextInactiveDelta(&finished);
96+ if (!finished) {
97+ d->m_timer->start();
98+ } else {
99+ d->m_timer->stop();
100+ }
101+
102+ if (!d->m_running) {
103+ d->m_running = true;
104+ Q_EMIT runningChanged(true);
105+ }
106+}
107+
108+void MenuContentActivator::stop()
109+{
110+ d->m_timer->stop();
111+ if (!d->m_running) {
112+ d->m_running = false;
113+ Q_EMIT runningChanged(false);
114+ }
115+}
116+
117+void MenuContentActivator::clear()
118+{
119+ qDeleteAll(d->m_content);
120+ d->m_content.clear();
121+
122+ setDelta(0);
123+ d->m_timer->stop();
124+
125+ Q_EMIT contentChanged();
126+}
127+
128+bool MenuContentActivator::isMenuContentActive(int index) const
129+{
130+ if (d->m_content.contains(index))
131+ return d->m_content[index]->isActive();
132+ return false;
133+}
134+
135+void MenuContentActivator::setRunning(bool running)
136+{
137+ if (running) {
138+ restart();
139+ } else {
140+ stop();
141+ }
142+}
143+
144+bool MenuContentActivator::isRunning() const
145+{
146+ return d->m_running;
147+}
148+
149+void MenuContentActivator::setBaseIndex(int index)
150+{
151+ if (d->m_baseIndex != index) {
152+ d->m_baseIndex = index;
153+
154+ if (isRunning()) {
155+ restart();
156+ }
157+
158+ Q_EMIT baseIndexChanged(index);
159+ }
160+}
161+
162+int MenuContentActivator::baseIndex() const
163+{
164+ return d->m_baseIndex;
165+}
166+
167+void MenuContentActivator::setCount(int count)
168+{
169+ if (d->m_count != count) {
170+ d->m_count = count;
171+ Q_EMIT countChanged(count);
172+
173+ if (isRunning()) {
174+ restart();
175+ }
176+ }
177+}
178+
179+int MenuContentActivator::count() const
180+{
181+ return d->m_count;
182+}
183+
184+void MenuContentActivator::setDelta(int delta)
185+{
186+ if (d->m_delta != delta) {
187+ d->m_delta = delta;
188+ Q_EMIT deltaChanged(d->m_delta);
189+ }
190+}
191+
192+int MenuContentActivator::delta() const
193+{
194+ return d->m_delta;
195+}
196+
197+QQmlListProperty<MenuContentState> MenuContentActivator::content()
198+{
199+ return QQmlListProperty<MenuContentState>(this,
200+ 0,
201+ MenuContentActivatorPrivate::content_count,
202+ MenuContentActivatorPrivate::content_at);
203+}
204+
205+void MenuContentActivator::onTimeout()
206+{
207+ bool finished = false;
208+ int tempDelta = d->findNextInactiveDelta(&finished);
209+ if (!finished) {
210+ setMenuContentState(d->m_baseIndex + tempDelta, true);
211+ setDelta(tempDelta);
212+ }
213+
214+ if (finished) {
215+ d->m_timer->stop();
216+ }
217+}
218+
219+void MenuContentActivator::setContentTimer(UnityIndicators::AbstractTimer *timer)
220+{
221+ int interval = 0;
222+ bool timerWasRunning = false;
223+
224+ // can be null when called from the constructor
225+ if (d->m_timer) {
226+ interval = d->m_timer->interval();
227+ timerWasRunning = d->m_timer->isRunning();
228+ if (d->m_timer->parent() == this) {
229+ delete d->m_timer;
230+ }
231+ }
232+
233+ d->m_timer = timer;
234+ timer->setInterval(interval);
235+ connect(timer, &UnityIndicators::AbstractTimer::timeout,
236+ this, &MenuContentActivator::onTimeout);
237+ if (timerWasRunning) {
238+ d->m_timer->start();
239+ }
240+}
241+
242+void MenuContentActivator::setMenuContentState(int index, bool active)
243+{
244+ if (d->m_content.contains(index)) {
245+ d->m_content[index]->setActive(active);
246+ } else {
247+ d->m_content[index] = new MenuContentState(active);
248+ Q_EMIT contentChanged();
249+ }
250+}
251+
252+int MenuContentActivatorPrivate::findNextInactiveDelta(bool* finished)
253+{
254+ if (m_count == 0 || m_baseIndex >= m_count) {
255+ if (finished) *finished = true;
256+ return 0;
257+ }
258+
259+ int tmpDelta = m_delta;
260+ bool topReached = false, bottomReached = false;
261+ while(true) {
262+
263+ // prechecks for bottom and top limits.
264+ if (tmpDelta > 0 && bottomReached) tmpDelta = -tmpDelta;
265+ if (tmpDelta < 0 && topReached) tmpDelta = (-tmpDelta) + 1;
266+
267+ if (tmpDelta > 0) {
268+ // negative of baseIndex
269+ tmpDelta = -tmpDelta;
270+ // reached the bottom?
271+ if (m_baseIndex + tmpDelta < 0) {
272+ bottomReached = true;
273+ // if we've reached the top as well, then we know we're done.
274+ if (topReached) {
275+ if (finished) *finished = true;
276+ return 0;
277+ }
278+ continue;
279+ }
280+ } else {
281+ // positive of baseIndex
282+ tmpDelta = (-tmpDelta) + 1;
283+ // reached the top?
284+ if (m_baseIndex + tmpDelta >= m_count) {
285+ topReached = true;
286+ // if we've reached the bottom as well, then we know we're done.
287+ if (bottomReached) {
288+ if (finished) *finished = true;
289+ return 0;
290+ }
291+ continue;
292+ }
293+ }
294+
295+ if (q->isMenuContentActive(m_baseIndex + tmpDelta)) {
296+ continue;
297+ }
298+ break;
299+ }
300+ if (finished) *finished = false;
301+ return tmpDelta;
302+}
303+
304+int MenuContentActivatorPrivate::content_count(QQmlListProperty<MenuContentState> *prop)
305+{
306+ MenuContentActivator *p = qobject_cast<MenuContentActivator*>(prop->object);
307+ // we'll create MenuContentState on demand.
308+ return p->count();
309+}
310+
311+MenuContentState* MenuContentActivatorPrivate::content_at(QQmlListProperty<MenuContentState> *prop, int index)
312+{
313+ MenuContentActivator *p = qobject_cast<MenuContentActivator*>(prop->object);
314+ MenuContentActivatorPrivate *d = p->d;
315+
316+ if (!d->m_content.contains(index)) {
317+ MenuContentState* content = new MenuContentState(false);
318+ d->m_content[index] = content;
319+ Q_EMIT p->contentChanged();
320+ return content;
321+ }
322+
323+ return d->m_content[index];
324+}
325+
326+MenuContentState::MenuContentState(bool active)
327+ : m_active(active)
328+{
329+}
330+
331+bool MenuContentState::isActive() const
332+{
333+ return m_active;
334+}
335+
336+void MenuContentState::setActive(bool active)
337+{
338+ if (m_active != active) {
339+ m_active = active;
340+ Q_EMIT activeChanged();
341+ }
342+}
343+
344+// Because we are defining a new QObject-based class (ContentTimer) here.
345+#include "menucontentactivator.moc"
plugins/Unity/Indicators/menucontentactivator.hnew file+117
@@ -0,0 +1,117 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MENUCONTENTACTIVATOR_H
20+#define MENUCONTENTACTIVATOR_H
21+
22+#include "unityindicatorsglobal.h"
23+
24+#include <QObject>
25+#include <QTimer>
26+#include <QQmlListProperty>
27+
28+
29+namespace UnityIndicators {
30+/* Defines an interface for a Timer. */
31+class UNITYINDICATORS_EXPORT AbstractTimer : public QObject {
32+ Q_OBJECT
33+public:
34+ AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {}
35+ virtual int interval() const = 0;
36+ virtual void setInterval(int msecs) = 0;
37+ virtual void start() { m_isRunning = true; };
38+ virtual void stop() { m_isRunning = false; }
39+ bool isRunning() const { return m_isRunning; }
40+Q_SIGNALS:
41+ void timeout();
42+private:
43+ bool m_isRunning;
44+};
45+}
46+
47+/* Defines a object to express the active state of a menu. */
48+class UNITYINDICATORS_EXPORT MenuContentState : public QObject
49+{
50+ Q_OBJECT
51+ Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
52+public:
53+ MenuContentState(bool active);
54+
55+ bool isActive() const;
56+ void setActive(bool active);
57+
58+Q_SIGNALS:
59+ void activeChanged();
60+private:
61+ bool m_active;
62+};
63+
64+class MenuContentActivatorPrivate;
65+
66+class UNITYINDICATORS_EXPORT MenuContentActivator : public QObject
67+{
68+ Q_OBJECT
69+ Q_PROPERTY(int baseIndex READ baseIndex WRITE setBaseIndex NOTIFY baseIndexChanged)
70+ Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged)
71+ Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
72+ Q_PROPERTY(QQmlListProperty<MenuContentState> content READ content NOTIFY contentChanged DESIGNABLE false)
73+public:
74+ MenuContentActivator(QObject* parent = NULL);
75+ ~MenuContentActivator();
76+
77+ Q_INVOKABLE void restart();
78+ Q_INVOKABLE void stop();
79+ Q_INVOKABLE void clear();
80+ Q_INVOKABLE bool isMenuContentActive(int index) const;
81+
82+ void setRunning(bool running);
83+ bool isRunning() const;
84+
85+ void setBaseIndex(int index);
86+ int baseIndex() const;
87+
88+ void setCount(int index);
89+ int count() const;
90+
91+ void setDelta(int index);
92+ int delta() const;
93+
94+ QQmlListProperty<MenuContentState> content();
95+
96+ // Replaces the existing Timer with the given one.
97+ //
98+ // Useful for providing a fake timer when testing.
99+ void setContentTimer(UnityIndicators::AbstractTimer *timer);
100+ void setMenuContentState(int index, bool active);
101+
102+Q_SIGNALS:
103+ void baseIndexChanged(int baseIndex);
104+ void deltaChanged(int delta);
105+ void runningChanged(bool running);
106+ void countChanged(int count);
107+ void contentChanged();
108+
109+private Q_SLOTS:
110+ void onTimeout();
111+
112+private:
113+ MenuContentActivatorPrivate* d;
114+ friend class MenuContentActivatorPrivate;
115+};
116+
117+#endif // MENUCONTENTACTIVATOR_H
plugins/Unity/Indicators/plugin.cpp+3
@@ -27,6 +27,7 @@
27#include "indicatorsmanager.h"
27#include "indicatorsmanager.h"
28#include "indicatorsmodel.h"
28#include "indicatorsmodel.h"
29#include "indicators.h"
29#include "indicators.h"
30+#include "menucontentactivator.h"
30
31
31void IndicatorsPlugin::registerTypes(const char *uri)
32void IndicatorsPlugin::registerTypes(const char *uri)
32{
33{
@@ -35,7 +36,9 @@ void IndicatorsPlugin::registerTypes(const char *uri)
35 qmlRegisterType<IndicatorsManager>(uri, 0, 1, "IndicatorsManager");
36 qmlRegisterType<IndicatorsManager>(uri, 0, 1, "IndicatorsManager");
36 qmlRegisterType<FlatMenuProxyModel>(uri, 0, 1, "FlatMenuProxyModel");
37 qmlRegisterType<FlatMenuProxyModel>(uri, 0, 1, "FlatMenuProxyModel");
37 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
38 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
39+ qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
38
40
41+ qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
39 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
42 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
40 qmlRegisterUncreatableType<NetworkActionState>(uri, 0, 1, "NetworkActionState", "Can't create NetworkActionState class");
43 qmlRegisterUncreatableType<NetworkActionState>(uri, 0, 1, "NetworkActionState", "Can't create NetworkActionState class");
41 qmlRegisterUncreatableType<NetworkConnection>(uri, 0, 1, "NetworkConnection", "Can't create NetworkConnection class");
44 qmlRegisterUncreatableType<NetworkConnection>(uri, 0, 1, "NetworkConnection", "Can't create NetworkConnection class");
plugins/Unity/Indicators/qml/CMakeLists.txt+4−13
@@ -1,14 +1,5 @@
1−file(GLOB Indicators_QMLFILES
1+# export_qmlplugin macro
2− *.qml
2+include(Plugins)
3− qmldir
4−)
5
3
6−# copy qml & qmldir files into build directory for shadow builds
4+# export the qmldir, *.qml files.
7−add_custom_target(UnityIndicatorsQmlFiles ALL
5+export_qmlfiles(Unity.Indicators Unity/Indicators)
8− COMMAND cp ${Indicators_QMLFILES} ${CMAKE_BINARY_DIR}/plugins/Unity/Indicators
9− DEPENDS ${Indicators_QMLFILES}
10−)
11−
12−install(FILES ${Indicators_QMLFILES}
13− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity/Indicators
14−)
plugins/Unity/Indicators/qml/IndicatorPage.qml−6
@@ -188,10 +188,4 @@ IndicatorBase {
188 mainMenu.currentIndex = -1;
188 mainMenu.currentIndex = -1;
189 mainMenu.positionViewAtBeginning();
189 mainMenu.positionViewAtBeginning();
190 }
190 }
191−
192− Component.onCompleted: {
193− if ((busType != 0) && (busName != "") && (deviceMenuObjectPath != "")) {
194− start();
195− }
196− }
197}
191}
plugins/Unity/Indicators/qml/qmldir+1
@@ -1,5 +1,6 @@
1module Unity.Indicators
1module Unity.Indicators
2plugin IndicatorsQml
2plugin IndicatorsQml
3+typeinfo plugin.qmltypes
3
4
4BasicMenuItem 0.1 BasicMenuItem.qml
5BasicMenuItem 0.1 BasicMenuItem.qml
5ButtonMenuItem 0.1 ButtonMenuItem.qml
6ButtonMenuItem 0.1 ButtonMenuItem.qml
plugins/Unity/Indicators/unityindicatorsglobal.hnew file+23
@@ -0,0 +1,23 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <QtCore/QtGlobal>
18+
19+#if defined(UNITYINDICATORS_LIBRARY)
20+# define UNITYINDICATORS_EXPORT Q_DECL_EXPORT
21+#else
22+# define UNITYINDICATORS_EXPORT Q_DECL_IMPORT
23+#endif
plugins/Unity/Launcher/CMakeLists.txt+1
@@ -24,4 +24,5 @@ add_library(UnityLauncher-qml MODULE
24qt5_use_modules(UnityLauncher-qml Qml)
24qt5_use_modules(UnityLauncher-qml Qml)
25
25
26# export the qmldir and qmltypes files
26# export the qmldir and qmltypes files
27+export_qmlfiles(Unity.Launcher Unity/Launcher)
27export_qmlplugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
28export_qmlplugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
plugins/Unity/Launcher/backend/launcherbackend.cpp+3−3
@@ -37,7 +37,7 @@ LauncherBackend::LauncherBackend(QObject *parent):
37 QLatin1String("gmail-webapp.desktop") <<
37 QLatin1String("gmail-webapp.desktop") <<
38 QLatin1String("ubuntu-weather-app.desktop") <<
38 QLatin1String("ubuntu-weather-app.desktop") <<
39 QLatin1String("notes-app.desktop") <<
39 QLatin1String("notes-app.desktop") <<
40− QLatin1String("ubuntu-calendar-app.desktop");
40+ QLatin1String("calendar-app.desktop");
41
41
42 // TODO: get stuff from desktop files instead this hardcoded map
42 // TODO: get stuff from desktop files instead this hardcoded map
43 m_displayNameMap.insert("phone-app.desktop", "Phone");
43 m_displayNameMap.insert("phone-app.desktop", "Phone");
@@ -49,7 +49,7 @@ LauncherBackend::LauncherBackend(QObject *parent):
49 m_displayNameMap.insert("gmail-webapp.desktop", "GMail");
49 m_displayNameMap.insert("gmail-webapp.desktop", "GMail");
50 m_displayNameMap.insert("ubuntu-weather-app.desktop", "Weather");
50 m_displayNameMap.insert("ubuntu-weather-app.desktop", "Weather");
51 m_displayNameMap.insert("notes-app.desktop", "Notes");
51 m_displayNameMap.insert("notes-app.desktop", "Notes");
52− m_displayNameMap.insert("ubuntu-calendar-app.desktop", "Calendar");
52+ m_displayNameMap.insert("calendar-app.desktop", "Calendar");
53
53
54 // TODO: get stuff from desktop files instead this hardcoded map
54 // TODO: get stuff from desktop files instead this hardcoded map
55 m_iconMap.insert("phone-app.desktop", "phone-app");
55 m_iconMap.insert("phone-app.desktop", "phone-app");
@@ -61,7 +61,7 @@ LauncherBackend::LauncherBackend(QObject *parent):
61 m_iconMap.insert("gmail-webapp.desktop", "gmail");
61 m_iconMap.insert("gmail-webapp.desktop", "gmail");
62 m_iconMap.insert("ubuntu-weather-app.desktop", "weather");
62 m_iconMap.insert("ubuntu-weather-app.desktop", "weather");
63 m_iconMap.insert("notes-app.desktop", "notepad");
63 m_iconMap.insert("notes-app.desktop", "notepad");
64− m_iconMap.insert("ubuntu-calendar-app.desktop", "calendar");
64+ m_iconMap.insert("calendar-app.desktop", "calendar");
65
65
66}
66}
67
67
plugins/Unity/Launcher/qmldir+1
@@ -1,2 +1,3 @@
1module Unity.Launcher
1module Unity.Launcher
2plugin UnityLauncher-qml
2plugin UnityLauncher-qml
3+typeinfo plugin.qmltypes
plugins/Unity/categories.cpp+6−3
@@ -34,7 +34,7 @@ enum CategoryColumn {
34Categories::Categories(QObject* parent)
34Categories::Categories(QObject* parent)
35 : DeeListModel(parent)
35 : DeeListModel(parent)
36{
36{
37− m_roles[Categories::RoleId] = "id";
37+ m_roles[Categories::RoleCategoryId] = "categoryId";
38 m_roles[Categories::RoleName] = "name";
38 m_roles[Categories::RoleName] = "name";
39 m_roles[Categories::RoleIcon] = "icon";
39 m_roles[Categories::RoleIcon] = "icon";
40 m_roles[Categories::RoleRenderer] = "renderer";
40 m_roles[Categories::RoleRenderer] = "renderer";
@@ -42,6 +42,7 @@ Categories::Categories(QObject* parent)
42 m_roles[Categories::RoleHints] = "hints";
42 m_roles[Categories::RoleHints] = "hints";
43 m_roles[Categories::RoleResults] = "results";
43 m_roles[Categories::RoleResults] = "results";
44 m_roles[Categories::RoleCount] = "count";
44 m_roles[Categories::RoleCount] = "count";
45+ m_roles[Categories::RoleCategoryIndex] = "categoryIndex";
45
46
46 // TODO This should not be needed but accumulatting the count changes
47 // TODO This should not be needed but accumulatting the count changes
47 // makes the visualization more stable and also makes crashes on fast
48 // makes the visualization more stable and also makes crashes on fast
@@ -130,8 +131,8 @@ Categories::data(const QModelIndex& index, int role) const
130 }
131 }
131
132
132 switch (role) {
133 switch (role) {
133− case RoleId:
134+ case RoleCategoryId:
134− return QVariant::fromValue(index.row());
135+ return DeeListModel::data(index, CategoryColumn::ID);
135 case RoleName:
136 case RoleName:
136 return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
137 return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
137 case RoleIcon:
138 case RoleIcon:
@@ -149,6 +150,8 @@ Categories::data(const QModelIndex& index, int role) const
149 return QVariant::fromValue(getResults(index.row()));
150 return QVariant::fromValue(getResults(index.row()));
150 case RoleCount:
151 case RoleCount:
151 return QVariant::fromValue(getResults(index.row())->rowCount());
152 return QVariant::fromValue(getResults(index.row())->rowCount());
153+ case RoleCategoryIndex:
154+ return QVariant::fromValue(index.row());
152 default:
155 default:
153 return QVariant();
156 return QVariant();
154 }
157 }
plugins/Unity/categories.h+3−2
@@ -42,14 +42,15 @@ public:
42 explicit Categories(QObject* parent = 0);
42 explicit Categories(QObject* parent = 0);
43
43
44 enum Roles {
44 enum Roles {
45− RoleId,
45+ RoleCategoryId,
46 RoleName,
46 RoleName,
47 RoleIcon,
47 RoleIcon,
48 RoleRenderer,
48 RoleRenderer,
49 RoleContentType,
49 RoleContentType,
50 RoleHints,
50 RoleHints,
51 RoleResults,
51 RoleResults,
52− RoleCount
52+ RoleCount,
53+ RoleCategoryIndex
53 };
54 };
54
55
55 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
56 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
plugins/Unity/previewinfohint.cpp+2−2
@@ -17,9 +17,9 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
18 */
19
19
20+#include <deelistmodel.h>
20// local
21// local
21#include "previewinfohint.h"
22#include "previewinfohint.h"
22−#include "variantutils.h"
23
23
24PreviewInfoHint::PreviewInfoHint(QObject *parent):
24PreviewInfoHint::PreviewInfoHint(QObject *parent):
25 QObject(parent),
25 QObject(parent),
@@ -61,7 +61,7 @@ QString PreviewInfoHint::iconHint() const
61QVariant PreviewInfoHint::value() const
61QVariant PreviewInfoHint::value() const
62{
62{
63 if (m_unityInfoHint) {
63 if (m_unityInfoHint) {
64− return QVariantFromGVariant(m_unityInfoHint->value);
64+ return DeeListModel::VariantForData(m_unityInfoHint->value);
65 }
65 }
66 return QVariant();
66 return QVariant();
67}
67}
plugins/Unity/variantutils.cpp+2−118
@@ -17,131 +17,15 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
18 */
19
19
20+#include <deelistmodel.h>
20#include "variantutils.h"
21#include "variantutils.h"
21
22
22−/* Returns floating ref */
23−GVariant* GVariantFromQVariant(const QVariant &var)
24−{
25− GVariant *gv = nullptr;
26−
27− switch (var.type()) {
28− case QVariant::String:
29− gv = g_variant_new_string(var.toString().toUtf8());
30− break;
31− case QVariant::UInt:
32− gv = g_variant_new_uint32(var.toUInt());
33− break;
34− case QVariant::Int:
35− gv = g_variant_new_int32(var.toInt());
36− break;
37− case QVariant::LongLong:
38− gv = g_variant_new_int64(var.toLongLong());
39− break;
40− case QVariant::ULongLong:
41− gv = g_variant_new_uint64(var.toULongLong());
42− break;
43− case QVariant::Double:
44− gv = g_variant_new_double(var.toDouble());
45− break;
46− case QVariant::Bool:
47− gv = g_variant_new_boolean(var.toBool());
48− break;
49− case QVariant::Hash: {
50− const auto hash = var.toHash();
51− GVariant **children = new GVariant*[hash.size()];
52− int cnt = 0;
53− QHash<QString, QVariant>::const_iterator it = hash.constBegin();
54− while (it != hash.constEnd()) {
55− GVariant *key = g_variant_new_string(it.key().toUtf8());
56− children[cnt++] = g_variant_new_dict_entry(key, g_variant_new_variant(GVariantFromQVariant(it.value())));
57− ++it;
58− }
59− gv = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, hash.size());
60− delete [] children;
61− break;
62− }
63− default:
64− break;
65− }
66− return gv;
67−}
68−
69−// implementation of this conversion taken from libdee-qt private utility function.
70−QVariant QVariantFromGVariant(GVariant *value)
71−{
72− /* We need to special-case a{sv} here as G_VARIANT_CLASS_ARRAY handles simple arrays;
73− we need to create QVariantHash, not a list */
74− if (g_variant_is_of_type(value, G_VARIANT_TYPE_VARDICT)) {
75− const gsize nChildren = g_variant_n_children(value);
76− QVariantHash hash;
77− for (gsize i = 0; i < nChildren; ++i)
78− {
79− GVariant* dict_entry = g_variant_get_child_value(value, i);
80−
81− gchar* dict_key;
82− GVariant *dict_var;
83− g_variant_get(dict_entry, "{&sv}", &dict_key, &dict_var);
84− hash.insert(QString::fromUtf8(dict_key), QVariantFromGVariant(dict_var));
85− g_variant_unref(dict_var);
86− g_variant_unref(dict_entry);
87− }
88− return hash;
89− }
90−
91− switch (g_variant_classify(value)) {
92− case G_VARIANT_CLASS_BOOLEAN:
93− return QVariant((bool) g_variant_get_boolean(value));
94− case G_VARIANT_CLASS_BYTE:
95− return QVariant((uchar) g_variant_get_byte(value));
96− case G_VARIANT_CLASS_INT16:
97− return QVariant((qint16) g_variant_get_int16(value));
98− case G_VARIANT_CLASS_UINT16:
99− return QVariant((quint16) g_variant_get_uint16(value));
100− case G_VARIANT_CLASS_INT32:
101− return QVariant((qint32) g_variant_get_int32(value));
102− case G_VARIANT_CLASS_UINT32:
103− return QVariant((quint32) g_variant_get_uint32(value));
104− case G_VARIANT_CLASS_INT64:
105− return QVariant((qint64) g_variant_get_int64(value));
106− case G_VARIANT_CLASS_UINT64:
107− return QVariant((quint64) g_variant_get_uint64(value));
108− case G_VARIANT_CLASS_DOUBLE:
109− return QVariant(g_variant_get_double(value));
110− case G_VARIANT_CLASS_STRING:
111− return QVariant(QString::fromUtf8(g_variant_get_string(value, NULL)));
112− case G_VARIANT_CLASS_ARRAY:
113− case G_VARIANT_CLASS_TUPLE:
114− {
115− const gsize nChildren = g_variant_n_children(value);
116− QList<QVariant> array;
117− for (gsize i = 0; i < nChildren; ++i)
118− {
119− GVariant* gvariant = g_variant_get_child_value(value, i);
120− array << QVariantFromGVariant(gvariant);
121− g_variant_unref(gvariant);
122− }
123− return array;
124− }
125− default:
126− /* Fallback on an empty QVariant.
127− FIXME: Missing conversion of following GVariant types:
128− - G_VARIANT_CLASS_HANDLE
129− - G_VARIANT_CLASS_OBJECT_PATH
130− - G_VARIANT_CLASS_SIGNATURE
131− - G_VARIANT_CLASS_VARIANT
132− - G_VARIANT_CLASS_MAYBE
133− - G_VARIANT_CLASS_DICT_ENTRY
134− */
135− return QVariant();
136− }
137−}
138−
139unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
23unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val)
140{
24{
141 unity::glib::HintsMap hintsMap;
25 unity::glib::HintsMap hintsMap;
142 QHash<QString, QVariant>::const_iterator it = val.constBegin();
26 QHash<QString, QVariant>::const_iterator it = val.constBegin();
143 while (it != val.constEnd()) {
27 while (it != val.constEnd()) {
144− hintsMap[it.key().toStdString()] = GVariantFromQVariant(it.value());
28+ hintsMap[it.key().toStdString()] = DeeListModel::DataFromVariant(it.value());
145 ++it;
29 ++it;
146 }
30 }
147 return hintsMap;
31 return hintsMap;
plugins/Unity/variantutils.h−2
@@ -26,8 +26,6 @@
26// libunity-core
26// libunity-core
27#include <UnityCore/Variant.h>
27#include <UnityCore/Variant.h>
28
28
29−GVariant* GVariantFromQVariant(const QVariant &value);
30−QVariant QVariantFromGVariant(GVariant *value);
31unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
29unity::glib::HintsMap convertToHintsMap(const QHash<QString, QVariant> &val);
32unity::glib::HintsMap convertToHintsMap(const QVariant &var);
30unity::glib::HintsMap convertToHintsMap(const QVariant &var);
33
31
plugins/Utils/CMakeLists.txt+2−1
@@ -23,5 +23,6 @@ set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
23
23
24qt5_use_modules(Utils-qml Qml Quick)
24qt5_use_modules(Utils-qml Qml Quick)
25
25
26−# export the qmldir and qmltypes files
26+# export the qmldir qmltypes and plugin files
27+export_qmlfiles(Utils Utils)
27export_qmlplugin(Utils 0.1 Utils TARGETS Utils-qml)
28export_qmlplugin(Utils 0.1 Utils TARGETS Utils-qml)
po/ar.po+3−27
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-22 16:15+0000\n"
11+"PO-Revision-Date: 2013-06-26 23:26+0000\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
13"Language-Team: Arabic <ar@li.org>\n"
13"Language-Team: Arabic <ar@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,27 +218,3 @@ msgstr "عذراً، لا يوجد ما يطابق بحثك."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "أشخاص"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "الشاشة الرئيسية"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "الأشخاص المفضلون"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "أشخاص كانوا على اتصال مؤخرا"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "Recently in touch"
238−#~ msgstr "على اتصال موخرا"
239−
240−#~ msgid "New Contacts"
241−#~ msgstr "أشخاص جدد"
242−
243−#~ msgid "Favourites"
244−#~ msgstr "المفضلات"
po/az.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-26 23:48+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
13"Language-Team: Azerbaijani <az@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "İnsanlar"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Əsas Ekran"
po/bg.po+3−15
@@ -8,15 +8,15 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-19 15:47+0000\n"
11+"PO-Revision-Date: 2013-06-27 00:06+0000\n"
12"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
12"Last-Translator: Miroslav E. Hadzhiev (Хаджиев) "
13"<miroslav.hadzhiev@gmail.com>\n"
13"<miroslav.hadzhiev@gmail.com>\n"
14"Language-Team: Bulgarian <bg@li.org>\n"
14"Language-Team: Bulgarian <bg@li.org>\n"
15"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
18+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
19−"X-Generator: Launchpad (build 16681)\n"
19+"X-Generator: Launchpad (build 16696)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -219,15 +219,3 @@ msgstr "Съжаляваме, няма нищо, което да отговар
219#, qt-format
219#, qt-format
220msgid "Please enter %1"
220msgid "Please enter %1"
221msgstr ""
221msgstr ""
222−
223−#~ msgid "Favourites"
224−#~ msgstr "Любими"
225−
226−#~ msgid "People"
227−#~ msgstr "Хора"
228−
229−#~ msgid "A-Z"
230−#~ msgstr "А-Я"
231−
232−#~ msgid "Home screen"
233−#~ msgstr "Начален екран"
po/ca.po+4−16
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 00:24+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Catalan <ca@li.org>\n"
13"Language-Team: Catalan <ca@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,15 +218,3 @@ msgstr "No hi ha res que coincideixi amb la cerca"
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Gent"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Pantalla d'inici"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Gent preferida"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Gent amb qui heu parlat"
po/de.po+5−29
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-29 12:53+0000\n"
11+"PO-Revision-Date: 2013-06-27 00:37+0000\n"
12−"Last-Translator: Phillip Sz <Unknown>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: German <de@li.org>\n"
13"Language-Team: German <de@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16692)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -217,28 +217,4 @@ msgstr "Entschuldigung, es wurden keine Treffer erzielt."
217#: Shell.qml:383
217#: Shell.qml:383
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220−msgstr "Bitte geben Sie %1 ein"
220+msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Personen"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Startseite"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Lieblingspersonen"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Zuletzt kontaktierte Personen"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "Recently in touch"
238−#~ msgstr "Kürzlich im Gespräch"
239−
240−#~ msgid "New Contacts"
241−#~ msgstr "Neue Kontakte"
242−
243−#~ msgid "Favourites"
244−#~ msgstr "Favoriten"
po/el.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 00:53+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Greek <el@li.org>\n"
13"Language-Team: Greek <el@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να τ
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Πρόσωπα"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Αρχική οθόνη"
po/en_AU.po+3−27
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-18 20:36+0000\n"
11+"PO-Revision-Date: 2013-06-27 01:13+0000\n"
12"Last-Translator: Jackson Doak <Doak.jackson@gmail.com>\n"
12"Last-Translator: Jackson Doak <Doak.jackson@gmail.com>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
13"Language-Team: English (Australia) <en_AU@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,27 +218,3 @@ msgstr "Sorry, there is nothing that matches your search."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "People"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Home screen"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Favourite People"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "People Recently in Touch"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "Recently in touch"
238−#~ msgstr "Recently in touch"
239−
240−#~ msgid "New Contacts"
241−#~ msgstr "New Contacts"
242−
243−#~ msgid "Favourites"
244−#~ msgstr "Favourites"
po/en_GB.po+4−28
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-27 00:22+0000\n"
11+"PO-Revision-Date: 2013-06-27 08:53+0000\n"
12−"Last-Translator: Andi Chandler <Unknown>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
13"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,27 +218,3 @@ msgstr "Sorry, there is nothing that matches your search."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr "Please enter %1"
220msgstr "Please enter %1"
221−
222−#~ msgid "Favourite People"
223−#~ msgstr "Favourite People"
224−
225−#~ msgid "People Recently in Touch"
226−#~ msgstr "People Recently in Touch"
227−
228−#~ msgid "People"
229−#~ msgstr "People"
230−
231−#~ msgid "A-Z"
232−#~ msgstr "A-Z"
233−
234−#~ msgid "Recently in touch"
235−#~ msgstr "Recently in touch"
236−
237−#~ msgid "New Contacts"
238−#~ msgstr "New Contacts"
239−
240−#~ msgid "Favourites"
241−#~ msgstr "Favourites"
242−
243−#~ msgid "Home screen"
244−#~ msgstr "Home screen"
po/eo.po+3−3
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-26 22:35+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
13"Language-Team: Esperanto <eo@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/es.po+1−1
@@ -14,7 +14,7 @@ msgstr ""
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-07-09 06:13+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18"X-Generator: Launchpad (build 16696)\n"
18"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
po/fi.po+4−25
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-10 16:19+0000\n"
11+"PO-Revision-Date: 2013-06-27 02:43+0000\n"
12−"Last-Translator: Jiri Grönroos <Unknown>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Finnish <fi@li.org>\n"
13"Language-Team: Finnish <fi@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,24 +218,3 @@ msgstr "Hakuun täsmääviä tuloksia ei löydy."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Ihmiset"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Kotinäyttö"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Suosikkihenkilöt"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Viimeksi yhteydessä olleet henkilöt"
233−
234−#~ msgid "Favourites"
235−#~ msgstr "Suosikit"
236−
237−#~ msgid "Recently in touch"
238−#~ msgstr "Viimeksi yhteydessä"
239−
240−#~ msgid "New Contacts"
241−#~ msgstr "Uudet yhteystiedot"
po/fo.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 02:57+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Faroese <fo@li.org>\n"
13"Language-Team: Faroese <fo@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Fólk"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Heimaskíggi"
po/fr.po+40−61
@@ -8,62 +8,62 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-26 15:11+0000\n"
11+"PO-Revision-Date: 2013-06-27 03:21+0000\n"
12−"Last-Translator: Anne <anneonyme017@gmail.com>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: French <fr@li.org>\n"
13"Language-Team: French <fr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
22−msgstr "Téléphone"
22+msgstr ""
23
23
24#: Applications/applications.js:29
24#: Applications/applications.js:29
25msgid "Camera"
25msgid "Camera"
26−msgstr "Appareil photo"
26+msgstr ""
27
27
28#: Applications/applications.js:35
28#: Applications/applications.js:35
29msgid "Gallery"
29msgid "Gallery"
30−msgstr "Galerie"
30+msgstr ""
31
31
32#: Applications/applications.js:40
32#: Applications/applications.js:40
33msgid "Facebook"
33msgid "Facebook"
34−msgstr "Facebook"
34+msgstr ""
35
35
36#: Applications/applications.js:46
36#: Applications/applications.js:46
37msgid "Browser"
37msgid "Browser"
38−msgstr "Navigateur"
38+msgstr ""
39
39
40#: Applications/applications.js:51
40#: Applications/applications.js:51
41msgid "Twitter"
41msgid "Twitter"
42−msgstr "Twitter"
42+msgstr ""
43
43
44#: Applications/applications.js:57
44#: Applications/applications.js:57
45msgid "GMail"
45msgid "GMail"
46−msgstr "GMail"
46+msgstr ""
47
47
48#: Applications/applications.js:62
48#: Applications/applications.js:62
49msgid "Weather"
49msgid "Weather"
50−msgstr "Météo"
50+msgstr ""
51
51
52#: Applications/applications.js:68
52#: Applications/applications.js:68
53msgid "Notepad"
53msgid "Notepad"
54−msgstr "Bloc-notes"
54+msgstr ""
55
55
56#: Applications/applications.js:74
56#: Applications/applications.js:74
57msgid "Calendar"
57msgid "Calendar"
58−msgstr "Agenda"
58+msgstr ""
59
59
60#: Applications/applications.js:80
60#: Applications/applications.js:80
61msgid "Media Player"
61msgid "Media Player"
62−msgstr "Lecteur multimédia"
62+msgstr ""
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
66−msgstr "Evernote"
66+msgstr ""
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
@@ -71,27 +71,27 @@ msgstr ""
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
74−msgstr "Pinterest"
74+msgstr ""
75
75
76#: Applications/applications.js:101
76#: Applications/applications.js:101
77msgid "SoundCloud"
77msgid "SoundCloud"
78−msgstr "SoundCloud"
78+msgstr ""
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
82−msgstr "Wikipédia"
82+msgstr ""
83
83
84#: Applications/applications.js:111
84#: Applications/applications.js:111
85msgid "YouTube"
85msgid "YouTube"
86−msgstr "YouTube"
86+msgstr ""
87
87
88#: Components/PageHeader.qml:300
88#: Components/PageHeader.qml:300
89msgid "Recent searches"
89msgid "Recent searches"
90−msgstr "Recherches récentes"
90+msgstr ""
91
91
92#: Dash/DashApps.qml:65
92#: Dash/DashApps.qml:65
93msgid "Running apps"
93msgid "Running apps"
94−msgstr "Applications en cours d’exécution"
94+msgstr ""
95
95
96#: Dash/DashApps.qml:68
96#: Dash/DashApps.qml:68
97msgid "Frequently used"
97msgid "Frequently used"
@@ -99,7 +99,7 @@ msgstr ""
99
99
100#: Dash/DashApps.qml:71
100#: Dash/DashApps.qml:71
101msgid "Installed"
101msgid "Installed"
102−msgstr "Installées"
102+msgstr ""
103
103
104#: Dash/DashApps.qml:74
104#: Dash/DashApps.qml:74
105msgid "Available for download"
105msgid "Available for download"
@@ -111,19 +111,19 @@ msgstr "Applications"
111
111
112#: Dash/DashHome.qml:40
112#: Dash/DashHome.qml:40
113msgid "Frequent Apps"
113msgid "Frequent Apps"
114−msgstr "Applications fréquemment utilisées"
114+msgstr ""
115
115
116#: Dash/DashHome.qml:43
116#: Dash/DashHome.qml:43
117msgid "Recent Music"
117msgid "Recent Music"
118−msgstr "Musique récente"
118+msgstr ""
119
119
120#: Dash/DashHome.qml:46
120#: Dash/DashHome.qml:46
121msgid "Videos Popular Online"
121msgid "Videos Popular Online"
122−msgstr "Vidéos populaires en ligne"
122+msgstr ""
123
123
124#: Dash/DashHome.qml:175
124#: Dash/DashHome.qml:175
125msgid "Home"
125msgid "Home"
126−msgstr "Accueil"
126+msgstr ""
127
127
128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
129msgid "Featured"
129msgid "Featured"
@@ -135,7 +135,7 @@ msgstr ""
135
135
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
137msgid "New Releases"
137msgid "New Releases"
138−msgstr "Nouveautés"
138+msgstr ""
139
139
140#: Dash/DashMusic.qml:30
140#: Dash/DashMusic.qml:30
141msgid "Top Charting"
141msgid "Top Charting"
@@ -155,15 +155,15 @@ msgstr "Vidéos"
155
155
156#: Dash/Video/VideoPreview.qml:98
156#: Dash/Video/VideoPreview.qml:98
157msgid "Directed by:"
157msgid "Directed by:"
158−msgstr "Réalisé par :"
158+msgstr ""
159
159
160#: Dash/Video/VideoPreview.qml:121
160#: Dash/Video/VideoPreview.qml:121
161msgid "Starring:"
161msgid "Starring:"
162−msgstr "Acteurs :"
162+msgstr ""
163
163
164#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
165msgid "Author:"
165msgid "Author:"
166−msgstr "Auteur :"
166+msgstr ""
167
167
168#: Greeter/Lockscreen.qml:133
168#: Greeter/Lockscreen.qml:133
169msgid "Emergency call"
169msgid "Emergency call"
@@ -172,27 +172,27 @@ msgstr ""
172#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
173#, qt-format
173#, qt-format
174msgid "Hello %1"
174msgid "Hello %1"
175−msgstr "Bonjour %1"
175+msgstr ""
176
176
177#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
178msgid "Hello"
178msgid "Hello"
179−msgstr "Bonjour"
179+msgstr ""
180
180
181#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
182msgid "Confirm"
182msgid "Confirm"
183−msgstr "Confirmer"
183+msgstr ""
184
184
185#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
185#: Hud/Hud.qml:61 Hud/Hud.qml:99 Hud/Hud.qml:372
186msgid "Type or say a command"
186msgid "Type or say a command"
187−msgstr "Entrez ou dictez une commande"
187+msgstr ""
188
188
189#: Hud/Hud.qml:84
189#: Hud/Hud.qml:84
190msgid "Loading. Please Wait..."
190msgid "Loading. Please Wait..."
191−msgstr "Chargement. Veuillez patienter..."
191+msgstr ""
192
192
193#: Hud/Hud.qml:89
193#: Hud/Hud.qml:89
194msgid "Speak Now..."
194msgid "Speak Now..."
195−msgstr "Parlez maintenant..."
195+msgstr ""
196
196
197#: Hud/Hud.qml:94
197#: Hud/Hud.qml:94
198msgid "Speaking..."
198msgid "Speaking..."
@@ -204,38 +204,17 @@ msgstr ""
204
204
205#: Panel/Menus/Overview/FlightModeWidget.qml:42
205#: Panel/Menus/Overview/FlightModeWidget.qml:42
206msgid "Flight mode"
206msgid "Flight mode"
207−msgstr "Mode avion"
207+msgstr ""
208
208
209#: Panel/SearchIndicator.qml:26
209#: Panel/SearchIndicator.qml:26
210msgid "Search"
210msgid "Search"
211−msgstr "Rechercher"
211+msgstr ""
212
212
213#: plugins/Unity/scope.cpp:268
213#: plugins/Unity/scope.cpp:268
214msgid "Sorry, there is nothing that matches your search."
214msgid "Sorry, there is nothing that matches your search."
215−msgstr "Désolé, aucun résultat ne correspond à votre recherche."
215+msgstr ""
216
216
217#: Shell.qml:383
217#: Shell.qml:383
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "Home screen"
223−#~ msgstr "Écran d’accueil"
224−
225−#~ msgid "People"
226−#~ msgstr "Contacts"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Contacts favoris"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Contacts récents"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "New Contacts"
238−#~ msgstr "Nouveaux contacts"
239−
240−#~ msgid "Favourites"
241−#~ msgstr "Favoris"
po/gl.po+4−16
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 03:38+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Galician <gl@li.org>\n"
13"Language-Team: Galician <gl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,15 +218,3 @@ msgstr "Sentímolo, non hai nada que coincida con esta busca."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Persoas"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Pantalla de inicio"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Xente favorita"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Xente contactada recentemente"
po/he.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 03:54+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Hebrew <he@li.org>\n"
13"Language-Team: Hebrew <he@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "אנשים"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "מסך הבית"
po/hr.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 04:14+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Croatian <hr@li.org>\n"
13"Language-Team: Croatian <hr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Osobe"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Početni zaslon"
po/hu.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 04:28+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Elnézést, nincs találat a keresésre."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Emberek"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Kezdőképernyő"
po/hy.po+3−15
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-07 12:42+0000\n"
11+"PO-Revision-Date: 2013-06-27 04:43+0000\n"
12"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
12"Last-Translator: iAbaS <sosabazyan@yandex.ru>\n"
13"Language-Team: Armenian <hy@li.org>\n"
13"Language-Team: Armenian <hy@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,15 +218,3 @@ msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People Recently in Touch"
223−#~ msgstr "Վերջին մարդիկ"
224−
225−#~ msgid "Favourite People"
226−#~ msgstr "Ֆավորիտներ"
227−
228−#~ msgid "People"
229−#~ msgstr "Մարդիկ"
230−
231−#~ msgid "Home screen"
232−#~ msgstr "Տուն"
po/id.po+3−3
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-26 22:35+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Indonesian <id@li.org>\n"
13"Language-Team: Indonesian <id@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/it.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 05:14+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Italian <it@li.org>\n"
13"Language-Team: Italian <it@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Nessun risultato corrispondente alla ricerca."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Contatti"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Home"
po/ja.po+3−3
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-15 14:12+0000\n"
11+"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Japanese <ja@li.org>\n"
13"Language-Team: Japanese <ja@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/kn.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 05:43+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Kannada <kn@li.org>\n"
13"Language-Team: Kannada <kn@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯ
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "ಜನರು"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "ಹೋಮ್ ಸ್ಕ್ರೀನ್"
po/ko.po+4−4
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 05:59+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Korean <ko@li.org>\n"
13"Language-Team: Korean <ko@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/ky.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 06:17+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
13"Language-Team: Kirghiz <ky@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Тилекке каршы, сиздин издөөңүзгө эч нер
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Адамдар"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Башкы экран"
po/lv.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 06:31+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Latvian <lv@li.org>\n"
13"Language-Team: Latvian <lv@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Cilvēki"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Mājas ekrāns"
po/my.po+4−7
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 06:47+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Burmese <my@li.org>\n"
13"Language-Team: Burmese <my@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,6 +218,3 @@ msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "လူ"
po/nb.po+3−9
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-17 09:10+0000\n"
11+"PO-Revision-Date: 2013-06-27 07:02+0000\n"
12"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
12"Last-Translator: Joakim Langvand <jlangvand@gmail.com>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
13"Language-Team: Norwegian Bokmal <nb@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Søket ga ingen treff."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Personer"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Hjemmeskjerm"
po/nl.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 07:19+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Dutch <nl@li.org>\n"
13"Language-Team: Dutch <nl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:15+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Mensen"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Startscherm"
po/pl.po+8−32
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:43+0000\n"
11+"PO-Revision-Date: 2013-06-27 08:52+0000\n"
12−"Last-Translator: Piotr Merski <Unknown>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Polish <pl@li.org>\n"
13"Language-Team: Polish <pl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -167,16 +167,16 @@ msgstr "Autor:"
167
167
168#: Greeter/Lockscreen.qml:133
168#: Greeter/Lockscreen.qml:133
169msgid "Emergency call"
169msgid "Emergency call"
170−msgstr ""
170+msgstr "Telefon alarmowy"
171
171
172#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
173#, qt-format
173#, qt-format
174msgid "Hello %1"
174msgid "Hello %1"
175−msgstr ""
175+msgstr "Witaj %1"
176
176
177#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
178msgid "Hello"
178msgid "Hello"
179−msgstr ""
179+msgstr "Witaj"
180
180
181#: Hud/HudParametrizedActionsPage.qml:132
181#: Hud/HudParametrizedActionsPage.qml:132
182msgid "Confirm"
182msgid "Confirm"
@@ -217,28 +217,4 @@ msgstr "Nie znaleziono pasujących wyników."
217#: Shell.qml:383
217#: Shell.qml:383
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220−msgstr ""
220+msgstr "Wprowadź %1"
221−
222−#~ msgid "Home screen"
223−#~ msgstr "Ekran domowy"
224−
225−#~ msgid "People"
226−#~ msgstr "Ludzie"
227−
228−#~ msgid "People Recently in Touch"
229−#~ msgstr "Osoby ostatnio w kontakcie"
230−
231−#~ msgid "Favourite People"
232−#~ msgstr "Ulubione kontakty"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "Recently in touch"
238−#~ msgstr "Ostatnio w kontakcie"
239−
240−#~ msgid "New Contacts"
241−#~ msgstr "Nowe kontakty"
242−
243−#~ msgid "Favourites"
244−#~ msgstr "Ulubione"
po/pt_BR.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 07:39+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
13"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Pessoas"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Tela inicial"
po/ro.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 07:53+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Romanian <ro@li.org>\n"
13"Language-Team: Romanian <ro@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -219,9 +219,3 @@ msgstr ""
219#, qt-format
219#, qt-format
220msgid "Please enter %1"
220msgid "Please enter %1"
221msgstr ""
221msgstr ""
222−
223−#~ msgid "People"
224−#~ msgstr "Persoane"
225−
226−#~ msgid "Home screen"
227−#~ msgstr "Ecran principal"
po/ru.po+22−37
@@ -8,58 +8,58 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-21 10:08+0000\n"
11+"PO-Revision-Date: 2013-06-28 06:40+0000\n"
12−"Last-Translator: Andrey Dedikov <iamawesome.ndr@gmail.com>\n"
12+"Last-Translator: Eugene Marshal <Unknown>\n"
13"Language-Team: Russian <ru@li.org>\n"
13"Language-Team: Russian <ru@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
22−msgstr ""
22+msgstr "Телефон"
23
23
24#: Applications/applications.js:29
24#: Applications/applications.js:29
25msgid "Camera"
25msgid "Camera"
26−msgstr ""
26+msgstr "Камера"
27
27
28#: Applications/applications.js:35
28#: Applications/applications.js:35
29msgid "Gallery"
29msgid "Gallery"
30−msgstr ""
30+msgstr "Галерея"
31
31
32#: Applications/applications.js:40
32#: Applications/applications.js:40
33msgid "Facebook"
33msgid "Facebook"
34−msgstr ""
34+msgstr "Facebook"
35
35
36#: Applications/applications.js:46
36#: Applications/applications.js:46
37msgid "Browser"
37msgid "Browser"
38−msgstr ""
38+msgstr "Обозреватель"
39
39
40#: Applications/applications.js:51
40#: Applications/applications.js:51
41msgid "Twitter"
41msgid "Twitter"
42−msgstr ""
42+msgstr "Twitter"
43
43
44#: Applications/applications.js:57
44#: Applications/applications.js:57
45msgid "GMail"
45msgid "GMail"
46−msgstr ""
46+msgstr "GMail"
47
47
48#: Applications/applications.js:62
48#: Applications/applications.js:62
49msgid "Weather"
49msgid "Weather"
50−msgstr ""
50+msgstr "Погода"
51
51
52#: Applications/applications.js:68
52#: Applications/applications.js:68
53msgid "Notepad"
53msgid "Notepad"
54−msgstr ""
54+msgstr "Блокнот"
55
55
56#: Applications/applications.js:74
56#: Applications/applications.js:74
57msgid "Calendar"
57msgid "Calendar"
58−msgstr ""
58+msgstr "Календарь"
59
59
60#: Applications/applications.js:80
60#: Applications/applications.js:80
61msgid "Media Player"
61msgid "Media Player"
62−msgstr ""
62+msgstr "Медиапроигрыватель"
63
63
64#: Applications/applications.js:86
64#: Applications/applications.js:86
65msgid "Evernote"
65msgid "Evernote"
@@ -67,7 +67,7 @@ msgstr "Evernote"
67
67
68#: Applications/applications.js:91
68#: Applications/applications.js:91
69msgid "Map"
69msgid "Map"
70−msgstr ""
70+msgstr "Карта"
71
71
72#: Applications/applications.js:96
72#: Applications/applications.js:96
73msgid "Pinterest"
73msgid "Pinterest"
@@ -79,11 +79,11 @@ msgstr "SoundCloud"
79
79
80#: Applications/applications.js:106
80#: Applications/applications.js:106
81msgid "Wikipedia"
81msgid "Wikipedia"
82−msgstr ""
82+msgstr "Википедия"
83
83
84#: Applications/applications.js:111
84#: Applications/applications.js:111
85msgid "YouTube"
85msgid "YouTube"
86−msgstr ""
86+msgstr "YouTube"
87
87
88#: Components/PageHeader.qml:300
88#: Components/PageHeader.qml:300
89msgid "Recent searches"
89msgid "Recent searches"
@@ -131,7 +131,7 @@ msgstr ""
131
131
132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
133msgid "Recent"
133msgid "Recent"
134−msgstr ""
134+msgstr "Недавние"
135
135
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
136#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
137msgid "New Releases"
137msgid "New Releases"
@@ -163,11 +163,11 @@ msgstr "В главных ролях"
163
163
164#: Dash/Video/VideoPreview.qml:144
164#: Dash/Video/VideoPreview.qml:144
165msgid "Author:"
165msgid "Author:"
166−msgstr ""
166+msgstr "Автор:"
167
167
168#: Greeter/Lockscreen.qml:133
168#: Greeter/Lockscreen.qml:133
169msgid "Emergency call"
169msgid "Emergency call"
170−msgstr ""
170+msgstr "Экстренный вызов"
171
171
172#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
173#, qt-format
173#, qt-format
@@ -217,19 +217,4 @@ msgstr "Извините, поиск не дал результатов."
217#: Shell.qml:383
217#: Shell.qml:383
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220−msgstr ""
220+msgstr "Пожалуйста, введите %1"
221−
222−#~ msgid "People"
223−#~ msgstr "Люди"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Главный экран"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Избранные контакты"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Недавние контакты"
233−
234−#~ msgid "New Contacts"
235−#~ msgstr "Новые контакты"
po/si.po+3−3
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
13"Language-Team: Sinhalese <si@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/sl.po+1−1
@@ -14,7 +14,7 @@ msgstr ""
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-07-06 08:44+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18"X-Generator: Launchpad (build 16696)\n"
18"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
po/sr.po+4−10
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 09:19+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Serbian <sr@li.org>\n"
13"Language-Team: Serbian <sr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,9 +218,3 @@ msgstr "Нажалост, претрага није наишла на икакв
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Људи"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Почетни екран"
po/sv.po+3−3
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-26 22:36+0000\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Language-Team: Swedish <sv@li.org>\n"
13"Language-Team: Swedish <sv@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/te.po+4−4
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 09:57+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Telugu <te@li.org>\n"
13"Language-Team: Telugu <te@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
po/tr.po+3−24
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-24 17:24+0000\n"
11+"PO-Revision-Date: 2013-06-27 10:08+0000\n"
12"Last-Translator: Adar Cem EREN <adarcemeren34@gmail.com>\n"
12"Last-Translator: Adar Cem EREN <adarcemeren34@gmail.com>\n"
13"Language-Team: Turkish <tr@li.org>\n"
13"Language-Team: Turkish <tr@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,24 +218,3 @@ msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Kişiler"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Başlangıç ekranı"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Favori Kişiler"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "En Son Konuşulan Kişiler"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "New Contacts"
238−#~ msgstr "Yeni Kişiler"
239−
240−#~ msgid "Favourites"
241−#~ msgstr "Favoriler"
po/ug.po+6−27
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-28 04:36+0000\n"
11+"PO-Revision-Date: 2013-06-27 11:02+0000\n"
12−"Last-Translator: Gheyret T.Kenji <Unknown>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16692)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -172,7 +172,7 @@ msgstr "جىددىي تېلېفون"
172#: Greeter/PassphraseLockscreen.qml:59
172#: Greeter/PassphraseLockscreen.qml:59
173#, qt-format
173#, qt-format
174msgid "Hello %1"
174msgid "Hello %1"
175−msgstr "سالام %1"
175+msgstr ""
176
176
177#: Greeter/PassphraseLockscreen.qml:59
177#: Greeter/PassphraseLockscreen.qml:59
178msgid "Hello"
178msgid "Hello"
@@ -217,25 +217,4 @@ msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپ
217#: Shell.qml:383
217#: Shell.qml:383
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220−msgstr "%1 نى كىرگۈزۈڭ"
220+msgstr ""
221−
222−#~ msgid "Favourite People"
223−#~ msgstr "ھەمىشە ئالاقە قىلىدىغان كىشىلەر"
224−
225−#~ msgid "People Recently in Touch"
226−#~ msgstr "يېقىندا ئالاقە قىلغان كىشىلەر"
227−
228−#~ msgid "People"
229−#~ msgstr "كىشىلەر"
230−
231−#~ msgid "Home screen"
232−#~ msgstr "ماكان ئېكران"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "A-Z"
236−
237−#~ msgid "Recently in touch"
238−#~ msgstr "يېقىندا ئالاقە قىلغانلار"
239−
240−#~ msgid "New Contacts"
241−#~ msgstr "يېڭى ئالاقەداشلار"
po/uk.po+4−28
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-29 14:27+0000\n"
11+"PO-Revision-Date: 2013-07-21 05:47+0000\n"
12−"Last-Translator: Roman Koshkin <mar2008m@rambler.ru>\n"
12+"Last-Translator: Ярослав Смук <Smuk.Slavko@yandex.ua>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
13"Language-Team: Ukrainian <uk@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-22 06:19+0000\n"
18−"X-Generator: Launchpad (build 16692)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,27 +218,3 @@ msgstr "Вибачте, для вказаних вами ключових слі
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr "Будь ласка, введіть %1"
220msgstr "Будь ласка, введіть %1"
221−
222−#~ msgid "People"
223−#~ msgstr "Люди"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Екран домівки"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Вибрані контакти"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Недавні контакти"
233−
234−#~ msgid "A-Z"
235−#~ msgstr "А-Я"
236−
237−#~ msgid "New Contacts"
238−#~ msgstr "Нові контакти"
239−
240−#~ msgid "Favourites"
241−#~ msgstr "Улюблене"
242−
243−#~ msgid "Recently in touch"
244−#~ msgstr "Нещодавні контакти"
po/zh_CN.po+3−27
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-22 21:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 10:33+0000\n"
12"Last-Translator: Anthony Wong <anthony.wong@canonical.com>\n"
12"Last-Translator: Anthony Wong <anthony.wong@canonical.com>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
13"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,27 +218,3 @@ msgstr "对不起,没有找到您想要的结果。"
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "Home screen"
223−#~ msgstr "主页"
224−
225−#~ msgid "Favourite People"
226−#~ msgstr "常用联系人"
227−
228−#~ msgid "People Recently in Touch"
229−#~ msgstr "近期联系人"
230−
231−#~ msgid "People"
232−#~ msgstr "联系人"
233−
234−#~ msgid "Recently in touch"
235−#~ msgstr "最近联系"
236−
237−#~ msgid "New Contacts"
238−#~ msgstr "新建联系人"
239−
240−#~ msgid "Favourites"
241−#~ msgstr "最爱"
242−
243−#~ msgid "A-Z"
244−#~ msgstr "A-Z"
po/zh_TW.po+4−16
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
10"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-05 22:20+0000\n"
11+"PO-Revision-Date: 2013-06-27 10:24+0000\n"
12−"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12+"Last-Translator: Michał Sawicz <michal.sawicz@canonical.com>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
13"Language-Team: Chinese (Traditional) <zh_TW@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
17+"X-Launchpad-Export-Date: 2013-07-17 07:49+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
18+"X-Generator: Launchpad (build 16696)\n"
19
19
20#: Applications/applications.js:23
20#: Applications/applications.js:23
21msgid "Phone"
21msgid "Phone"
@@ -218,15 +218,3 @@ msgstr "很抱歉,找不到符合您想搜尋的結果。"
218#, qt-format
218#, qt-format
219msgid "Please enter %1"
219msgid "Please enter %1"
220msgstr ""
220msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "朋友"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "家屋畫面"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "喜歡的朋友"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "最近接觸的朋友"
run_on_device+3−19
@@ -33,7 +33,7 @@ usage() {
33}
33}
34
34
35exec_with_ssh() {
35exec_with_ssh() {
36− ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t $USER@$TARGET_IP -p $TARGET_SSH_PORT "bash -ic \"$@\""
36+ ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t $USER@$TARGET_IP -p $TARGET_SSH_PORT sudo -u $USER -i bash -ic \"$@\"
37}
37}
38
38
39exec_with_adb() {
39exec_with_adb() {
@@ -83,17 +83,6 @@ build() {
83}
83}
84
84
85run() {
85run() {
86− SERVICEFILE="${CHROOT_PREFIX}/etc/device-services"
87− adb shell "egrep '$BINARY' $SERVICEFILE"
88− CONTAINS_SHELL=$?
89− if [ $CONTAINS_SHELL -eq 0 ]; then
90− echo "Modifying $SERVICEFILE on device. Old contents will be saved in $SERVICEFILE.backup"
91− adb shell cp $SERVICEFILE $SERVICEFILE.backup
92− adb shell sed -i "/$BINARY/d" $SERVICEFILE
93− if $FLIPPED; then exec_with_adb /usr/bin/service ubuntu-touch-session restart
94− else exec_with_adb /usr/bin/service ubuntu-session restart; fi
95− fi
96− adb shell pkill $BINARY
97 ARGS="--nomousetouch"
86 ARGS="--nomousetouch"
98 if $GDB; then
87 if $GDB; then
99 ARGS="$ARGS --gdb"
88 ARGS="$ARGS --gdb"
@@ -105,14 +94,9 @@ run() {
105 ARGS="$ARGS -k"
94 ARGS="$ARGS -k"
106 fi
95 fi
107
96
97+ exec_with_ssh "stop unity8"
108 exec_with_ssh "cd $CODE_DIR/ && ./run $ARGS -- $RUN_OPTIONS"
98 exec_with_ssh "cd $CODE_DIR/ && ./run $ARGS -- $RUN_OPTIONS"
109−
99+ exec_with_ssh "start unity8"
110− if [ $CONTAINS_SHELL -eq 0 ]; then
111− echo "Restoring $SERVICEFILE on device from $SERVICEFILE.backup"
112− adb shell cp $SERVICEFILE.backup $SERVICEFILE
113− if $FLIPPED; then exec_with_adb /usr/bin/service ubuntu-touch-session restart
114− else exec_with_adb /usr/bin/service ubuntu-session restart; fi
115− fi
116}
100}
117
101
118set -- `getopt -n$0 -u -a --longoptions="setup,gdb,pinlock,keylock,help" "sgpkh" "$@"`
102set -- `getopt -n$0 -u -a --longoptions="setup,gdb,pinlock,keylock,help" "sgpkh" "$@"`
tests/autopilot/setup.py+17−6
@@ -1,11 +1,22 @@
1#!/usr/bin/python
1#!/usr/bin/python
2−
3# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
4−# Copyright 2013 Canonical
5#
3#
4+# Unity Autopilot Test Suite
5+# Copyright (C) 2012-2013 Canonical
6+#
6−# This program is free software: you can redistribute it and/or modify it
7+# This program is free software: you can redistribute it and/or modify
7−# under the terms of the GNU General Public License version 3, as published
8+# it under the terms of the GNU General Public License as published by
8−# by the Free Software Foundation.
9+# the Free Software Foundation, either version 3 of the License, or
10+# (at your option) any later version.
11+#
12+# This program is distributed in the hope that it will be useful,
13+# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+# GNU General Public License for more details.
16+#
17+# You should have received a copy of the GNU General Public License
18+# along with this program. If not, see <http://www.gnu.org/licenses/>.
19+#
9
20
10
21
11from distutils.core import setup
22from distutils.core import setup
@@ -14,7 +25,7 @@ from setuptools import find_packages
14setup(
25setup(
15 name='unity',
26 name='unity',
16 version='8.0',
27 version='8.0',
17− description='Unity 8 autopilot tests.',
28+ description='Unity autopilot tests.',
18 url='https://launchpad.net/unity',
29 url='https://launchpad.net/unity',
19 license='GPLv3',
30 license='GPLv3',
20 packages=find_packages(),
31 packages=find_packages(),
tests/autopilot/unity8/__init__.py+90−5
@@ -1,8 +1,93 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2−# Copyright 2013 Canonical
3#
2#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
4−# This program is free software: you can redistribute it and/or modify it
6+# This program is free software: you can redistribute it and/or modify
5−# under the terms of the GNU General Public License version 3, as published
7+# it under the terms of the GNU General Public License as published by
6−# by the Free Software Foundation.
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+"""unity autopilot tests and emulators - top level package."""
21+import os
22+import os.path
23+import subprocess
24+import sysconfig
25+
26+
27+def running_installed_tests():
28+ binary_path = get_binary_path()
29+ return binary_path.startswith('/usr')
30+
31+
32+def get_lib_path():
33+ """Return the library path to use in this test run."""
34+ if running_installed_tests():
35+ lib_path = os.path.join(
36+ "/usr/lib/",
37+ sysconfig.get_config_var('MULTIARCH'),
38+ "unity8"
39+ )
40+ else:
41+ binary_path = get_binary_path()
42+ lib_path = os.path.dirname(binary_path)
43+ return lib_path
44+
45+
46+def get_default_extra_mock_libraries():
47+ mocks_path = get_mocks_library_path()
48+ return os.path.join(mocks_path, 'libusermetrics')
49+
50+
51+def get_mocks_library_path():
52+ if running_installed_tests():
53+ mock_path = "qml/mocks/"
54+ else:
55+ mock_path = "../lib/x86_64-linux-gnu/unity8/qml/mocks/"
56+ lib_path = get_lib_path()
57+ ld_library_path = os.path.abspath(
58+ os.path.join(
59+ lib_path,
60+ mock_path,
61+ )
62+ )
63+
64+ if not os.path.exists(ld_library_path):
65+ raise RuntimeError(
66+ "Expected library path does not exists: %s." % (ld_library_path)
67+ )
68+ return ld_library_path
69+
70+
71+def get_binary_path(binary="unity8"):
72+ """Return the path to the specified binary."""
73+ binary_path = os.path.abspath(
74+ os.path.join(
75+ os.path.dirname(__file__),
76+ "../../../builddir/install/bin/%s" % binary
77+ )
78+ )
79+ if not os.path.exists(binary_path):
80+ try:
81+ binary_path = subprocess.check_output(['which', binary]).strip()
82+ except subprocess.CalledProcessError as e:
83+ raise RuntimeError("Unable to locate %s binary: %r" % (binary, e))
84+ return binary_path
85+
7
86
8−"""unity8 autopilot tests and emulators - top level package."""
87+def get_grid_size():
88+ grid_size = os.getenv('GRID_UNIT_PX')
89+ if grid_size is None:
90+ raise RuntimeError(
91+ "Environment variable GRID_UNIT_PX has not been set."
92+ )
93+ return int(grid_size)
tests/autopilot/unity8/indicators_client/__init__.py+1−1
@@ -5,4 +5,4 @@
5# under the terms of the GNU General Public License version 3, as published
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
6# by the Free Software Foundation.
7
7
8−"""unity8 indicators-client autopilot tests and emulators - sub level package."""
8+"""unity indicators-client autopilot tests and emulators - sub level package."""
tests/autopilot/unity8/indicators_client/tests/__init__.py+13−9
@@ -5,7 +5,7 @@
5# under the terms of the GNU General Public License version 3, as published
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
6# by the Free Software Foundation.
7
7
8−"""qml-phone-shell autopilot tests."""
8+"""indicators-client autopilot tests."""
9
9
10import os.path
10import os.path
11
11
@@ -15,6 +15,7 @@ from autopilot.matchers import Eventually
15from autopilot.platform import model
15from autopilot.platform import model
16from testtools.matchers import Equals
16from testtools.matchers import Equals
17
17
18+from unity8 import get_binary_path
18from unity8.indicators_client.emulators.main_window import MainWindow
19from unity8.indicators_client.emulators.main_window import MainWindow
19from logging import getLogger
20from logging import getLogger
20import sys
21import sys
@@ -29,9 +30,12 @@ class IndicatorsTestCase(AutopilotTestCase):
29
30
30 """A common test case class that provides several useful methods for indicator tests."""
31 """A common test case class that provides several useful methods for indicator tests."""
31
32
33+ geometry = None
34+ grid_unit = None
35+
32 if model() == 'Desktop':
36 if model() == 'Desktop':
33 scenarios = [
37 scenarios = [
34− ('with mouse', dict(input_device_class=Mouse)),
38+ ('with mouse', dict(input_device_class=Mouse, geometry="400x800", grid_unit="12")),
35 ]
39 ]
36 else:
40 else:
37 scenarios = [
41 scenarios = [
@@ -41,11 +45,11 @@ class IndicatorsTestCase(AutopilotTestCase):
41 def setUp(self, geometry, grid_size):
45 def setUp(self, geometry, grid_size):
42 self.pointing_device = Pointer(self.input_device_class.create())
46 self.pointing_device = Pointer(self.input_device_class.create())
43 super(IndicatorsTestCase, self).setUp()
47 super(IndicatorsTestCase, self).setUp()
44− if grid_size != "0":
48+ if grid_size is not None:
45− os.environ['GRID_UNIT_PX'] = grid_size
49+ self.patch_environment("GRID_UNIT_PX", str(grid_size))
46 self.grid_size = int(grid_size)
50 self.grid_size = int(grid_size)
47 else:
51 else:
48− self.grid_size = int(os.environ['GRID_UNIT_PX'])
52+ self.grid_size = int(os.getenv('GRID_UNIT_PX'))
49
53
50 if os.path.realpath(__file__).startswith("/usr/"):
54 if os.path.realpath(__file__).startswith("/usr/"):
51 self.launch_test_installed(geometry)
55 self.launch_test_installed(geometry)
@@ -53,15 +57,15 @@ class IndicatorsTestCase(AutopilotTestCase):
53 self.launch_test_local(geometry)
57 self.launch_test_local(geometry)
54
58
55 def launch_test_local(self, geometry):
59 def launch_test_local(self, geometry):
56− if geometry != "0x0":
60+ if geometry is None:
57− self.app = self.launch_test_application("../../builddir/src/Panel/Indicators/client/indicators-client",
61+ self.app = self.launch_test_application(get_binary_path("indicators-client"),
58 "-geometry", geometry, app_type='qt')
62 "-geometry", geometry, app_type='qt')
59 else:
63 else:
60− self.app = self.launch_test_application("../../builddir/src/Panel/Indicators/client/indicators-client",
64+ self.app = self.launch_test_application(get_binary_path("indicators-client"),
61 app_type='qt')
65 app_type='qt')
62
66
63 def launch_test_installed(self, geometry):
67 def launch_test_installed(self, geometry):
64− if geometry != "0x0":
68+ if geometry is not None:
65 self.app = self.launch_test_application("indicators-client", "-geometry", geometry, app_type='qt')
69 self.app = self.launch_test_application("indicators-client", "-geometry", geometry, app_type='qt')
66 else:
70 else:
67 self.app = self.launch_test_application("indicators-client", app_type='qt')
71 self.app = self.launch_test_application("indicators-client", app_type='qt')
tests/autopilot/unity8/indicators_client/tests/test_battery.py+14−3
@@ -8,6 +8,7 @@
8"""Add tests here if you want to ensure the behaviour of the power indicator menus are correct"""
8"""Add tests here if you want to ensure the behaviour of the power indicator menus are correct"""
9
9
10from testtools.matchers import Equals, NotEquals
10from testtools.matchers import Equals, NotEquals
11+from autopilot.input import Touch
11from autopilot.matchers import Eventually
12from autopilot.matchers import Eventually
12
13
13from unity8.indicators_client.tests import IndicatorsTestCase
14from unity8.indicators_client.tests import IndicatorsTestCase
@@ -17,7 +18,7 @@ import math
17
18
18class TestDisplayMenus(IndicatorsTestCase):
19class TestDisplayMenus(IndicatorsTestCase):
19 def setUp(self):
20 def setUp(self):
20− super(TestDisplayMenus, self).setUp("400x800", "12")
21+ super(TestDisplayMenus, self).setUp(self.geometry, self.grid_unit)
21
22
22 # This opens the messaging menu so you don't have to do that in
23 # This opens the messaging menu so you don't have to do that in
23 # every test case
24 # every test case
@@ -69,7 +70,11 @@ class TestDisplayMenus(IndicatorsTestCase):
69
70
70 # wait for the switch menu item
71 # wait for the switch menu item
71 fn_auto_brightness = lambda: self.app.select_single("SwitchMenuItem", objectName="auto-brightness");
72 fn_auto_brightness = lambda: self.app.select_single("SwitchMenuItem", objectName="auto-brightness");
73+ # FIXME: this should go away when we switch to indicator-power
74+ try:
72− self.assertThat(fn_auto_brightness, Eventually(NotEquals(None)));
75+ self.assertThat(fn_auto_brightness, Eventually(NotEquals(None)));
76+ except AssertionError:
77+ self.skipTest("WARNING: test skipped due to missing indicator-battery")
73 auto_brightness = fn_auto_brightness();
78 auto_brightness = fn_auto_brightness();
74
79
75 old_ab_value = auto_brightness.checked
80 old_ab_value = auto_brightness.checked
@@ -82,8 +87,14 @@ class TestDisplayMenus(IndicatorsTestCase):
82 def test_brightness_slider(self):
87 def test_brightness_slider(self):
83 """Test the auto-bright switch"""
88 """Test the auto-bright switch"""
84
89
90+ if self.input_device_class is Touch:
91+ self.skipTest("Dragging is broken with Touch input (LP: #1203808).")
85 fn_brightness_menu = lambda: self.app.select_single("SliderMenuItem", objectName="brightness");
92 fn_brightness_menu = lambda: self.app.select_single("SliderMenuItem", objectName="brightness");
93+ # FIXME: this should go away when we switch to indicator-power
94+ try:
86− self.assertThat(fn_brightness_menu, Eventually(NotEquals(None)));
95+ self.assertThat(fn_brightness_menu, Eventually(NotEquals(None)));
96+ except AssertionError:
97+ self.skipTest("WARNING: test skipped due to missing indicator-battery")
87 brightness_menu = fn_brightness_menu();
98 brightness_menu = fn_brightness_menu();
88
99
89 old_ab_value = brightness_menu.value
100 old_ab_value = brightness_menu.value
tests/autopilot/unity8/shell/__init__.py+35−5
@@ -1,8 +1,38 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2−# Copyright 2013 Canonical
3#
2#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
4−# This program is free software: you can redistribute it and/or modify it
6+# This program is free software: you can redistribute it and/or modify
5−# under the terms of the GNU General Public License version 3, as published
7+# it under the terms of the GNU General Public License as published by
6−# by the Free Software Foundation.
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+"""unity shell autopilot tests and emulators - sub level package."""
21+
22+from functools import wraps
23+import logging
24+
25+
26+logger = logging.getLogger(__name__)
27+
7
28
8−"""unity8 shell autopilot tests and emulators - sub level package."""
29+def with_lightdm_mock(mock_type):
30+ """A simple decorator that sets up the LightDM mock for a single test."""
31+ def with_lightdm_mock_internal(fn):
32+ @wraps(fn)
33+ def wrapper(*args, **kwargs):
34+ tests_self = args[0]
35+ tests_self.patch_lightdm_mock(mock_type)
36+ return fn(*args, **kwargs)
37+ return wrapper
38+ return with_lightdm_mock_internal
tests/autopilot/unity8/shell/emulators/__init__.py+23−4
@@ -1,6 +1,25 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2−# Copyright 2013 Canonical
3#
2#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
4−# This program is free software: you can redistribute it and/or modify it
6+# This program is free software: you can redistribute it and/or modify
5−# under the terms of the GNU General Public License version 3, as published
7+# it under the terms of the GNU General Public License as published by
6−# by the Free Software Foundation.
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+
21+from autopilot.introspection import CustomEmulatorBase
22+
23+
24+class UnityEmulatorBase(CustomEmulatorBase):
25+ """A base class for all unity emulators."""
tests/autopilot/unity8/shell/emulators/dash.pynew file+52
@@ -0,0 +1,52 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 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+from unity8.shell.emulators import UnityEmulatorBase
21+
22+
23+class Dash(UnityEmulatorBase):
24+
25+ """An emulator that understands the Dash."""
26+
27+ def get_home_applications_grid(self):
28+ return self.select_single(
29+ "ApplicationsFilterGrid",
30+ objectName="dashHomeApplicationsGrid"
31+ )
32+
33+ def get_application_icon(self, text):
34+ """Returns a 'Tile' icon that has the text 'text' from the application
35+ grid.
36+
37+ Will return None if the icon isn't found.
38+
39+ :param text: String containing the text of the icon to search for.
40+
41+ """
42+ app_grid = self.get_home_applications_grid()
43+ resp_grid = app_grid.select_single('ResponsiveGridView')
44+ return resp_grid.select_single('Tile', text=text)
45+
46+ def get_scope(self, scope_name='home'):
47+ dash_content = self.select_single(
48+ 'QQuickListView',
49+ objectName='dashContentList'
50+ )
51+ scope_id = "%s.scope" % scope_name
52+ return dash_content.select_single('QQuickLoader', scopeId=scope_id)
tests/autopilot/unity8/shell/emulators/greeter.pynew file+40
@@ -0,0 +1,40 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 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+from unity8.shell.emulators import UnityEmulatorBase
21+from autopilot.input import Touch
22+
23+
24+class Greeter(UnityEmulatorBase):
25+
26+ """An emulator that understands the greeter screen."""
27+
28+ def unlock(self):
29+ """Swipe the greeter screen away."""
30+ self.created.wait_for(True)
31+ touch = Touch.create()
32+
33+ rect = self.globalRect
34+ start_x = rect[0] + rect[2] - 3
35+ start_y = int(rect[1] + rect[3] / 2)
36+ stop_x = int(rect[0] + rect[2] * 0.2)
37+ stop_y = start_y
38+ touch.drag(start_x, start_y, stop_x, stop_y)
39+
40+ self.created.wait_for(False)
tests/autopilot/unity8/shell/emulators/hud.pynew file+83
@@ -0,0 +1,83 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 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+from collections import namedtuple
21+
22+from unity8 import get_grid_size
23+from unity8.shell.emulators import UnityEmulatorBase
24+from autopilot.input import Touch
25+
26+
27+SwipeCoords = namedtuple('SwipeCoords', 'start_x end_x start_y end_y')
28+
29+
30+class Hud(UnityEmulatorBase):
31+
32+ """An emulator that understands the Hud."""
33+
34+ def show(self):
35+ """Swipes open the Hud."""
36+ touch = Touch.create()
37+
38+ window = self.get_root_instance().select_single('QQuickView')
39+ hud_show_button = window.select_single("HudButton")
40+
41+ start_x = int(window.x + (window.width / 2))
42+ end_x = start_x
43+ start_y = window.y + window.height
44+ end_y = int(hud_show_button.y + (hud_show_button.height/2))
45+
46+ touch.press(start_x, start_y)
47+ touch._finger_move(end_x, end_y)
48+ try:
49+ hud_show_button.opacity.wait_for(1.0)
50+ touch.release()
51+ self.shown.wait_for(True)
52+ except AssertionError:
53+ raise
54+ finally:
55+ if touch._touch_finger is not None:
56+ touch.release()
57+
58+ def dismiss(self):
59+ """Closes the open Hud."""
60+ # Ensure that the Hud is actually open
61+ self.shown.wait_for(True)
62+ touch = Touch.create()
63+ x, y = self.get_close_button_coords()
64+ touch.tap(x, y)
65+ self.y.wait_for(self.height)
66+
67+ def get_close_button_coords(self):
68+ """Returns the coordinates of the Huds close button bar."""
69+ rect = self.globalRect
70+ x = int(rect[0] + rect[2] / 2)
71+ y = rect[1] + get_grid_size()
72+ return x, y
73+
74+ def get_button_swipe_coords(self, main_view, hud_show_button):
75+ """Returns the coords both start and end x,y for swiping to make the
76+ 'hud show' button appear.
77+ """
78+ start_x = int(main_view.x + (main_view.width / 2))
79+ end_x = start_x
80+ start_y = main_view.y + (main_view.height - 3)
81+ end_y = int(hud_show_button.y + (hud_show_button.height/2))
82+
83+ return SwipeCoords(start_x, end_x, start_y, end_y)
tests/autopilot/unity8/shell/emulators/launcher.pynew file+38
@@ -0,0 +1,38 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 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+from unity8.shell.emulators import UnityEmulatorBase
21+from autopilot.input import Touch
22+
23+
24+class Launcher(UnityEmulatorBase):
25+
26+ """An emulator that understands the Launcher."""
27+
28+ def show(self):
29+ """Swipes open the launcher."""
30+ touch = Touch.create()
31+
32+ view = self.get_root_instance().select_single('QQuickView')
33+ start_x = view.x + 1
34+ start_y = view.y + view.height / 2
35+ stop_x = start_x + self.panelWidth + 1
36+ stop_y = start_y
37+ touch.drag(start_x, start_y, stop_x, stop_y)
38+ self.shown.wait_for(True)
tests/autopilot/unity8/shell/emulators/main_window.py+43−12
@@ -1,9 +1,28 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2−# Copyright 2013 Canonical
3#
2#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
4−# This program is free software: you can redistribute it and/or modify it
6+# This program is free software: you can redistribute it and/or modify
5−# under the terms of the GNU General Public License version 3, as published
7+# it under the terms of the GNU General Public License as published by
6−# by the Free Software Foundation.
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+
21+from unity8.shell.emulators.greeter import Greeter
22+from unity8.shell.emulators.hud import Hud
23+from unity8.shell.emulators.dash import Dash
24+from unity8.shell.emulators.launcher import Launcher
25+
7
26
8class MainWindow(object):
27class MainWindow(object):
9 """An emulator class that makes it easy to interact with the shell"""
28 """An emulator class that makes it easy to interact with the shell"""
@@ -16,10 +35,13 @@ class MainWindow(object):
16 return self.app.select_single("QQuickView")
35 return self.app.select_single("QQuickView")
17
36
18 def get_greeter(self):
37 def get_greeter(self):
19− return self.app.select_single("Greeter")
38+ return self.app.select_single(Greeter)
20
39
21 def get_greeter_content_loader(self):
40 def get_greeter_content_loader(self):
41+ return self.app.select_single(
42+ "QQuickLoader",
22− return self.app.select_single("QQuickLoader", objectName="greeterContentLoader")
43+ objectName="greeterContentLoader"
44+ )
23
45
24 def get_login_loader(self):
46 def get_login_loader(self):
25 return self.app.select_single("QQuickLoader", objectName="loginLoader")
47 return self.app.select_single("QQuickLoader", objectName="loginLoader")
@@ -28,7 +50,7 @@ class MainWindow(object):
28 return self.app.select_single("LoginList")
50 return self.app.select_single("LoginList")
29
51
30 def get_hud(self):
52 def get_hud(self):
31− return self.app.select_single("Hud")
53+ return self.app.select_single(Hud)
32
54
33 def get_hud_showable(self):
55 def get_hud_showable(self):
34 return self.app.select_single("Showable", objectName="hudShowable")
56 return self.app.select_single("Showable", objectName="hudShowable")
@@ -37,22 +59,31 @@ class MainWindow(object):
37 return self.app.select_single("HudButton")
59 return self.app.select_single("HudButton")
38
60
39 def get_dash(self):
61 def get_dash(self):
40− return self.app.select_single("Dash")
62+ return self.app.select_single(Dash)
41
63
42 def get_dash_home_applications_grid(self):
64 def get_dash_home_applications_grid(self):
65+ return self.app.select_single(
66+ "ApplicationsFilterGrid",
43− return self.app.select_single("ApplicationsFilterGrid", objectName="dashHomeApplicationsGrid")
67+ objectName="dashHomeApplicationsGrid"
68+ )
44
69
45 def get_bottombar(self):
70 def get_bottombar(self):
46 return self.app.select_single("Bottombar")
71 return self.app.select_single("Bottombar")
47
72
48 def get_launcher(self):
73 def get_launcher(self):
49− return self.app.select_single("Launcher")
74+ return self.app.select_single(Launcher)
50
75
51 def get_pinPadLoader(self):
76 def get_pinPadLoader(self):
52− return self.app.select_single("QQuickLoader", objectName="pinPadLoader")
77+ return self.app.select_single(
78+ "QQuickLoader",
79+ objectName="pinPadLoader"
80+ )
53
81
54 def get_pinPadButton(self, buttonId):
82 def get_pinPadButton(self, buttonId):
83+ return self.app.select_single(
84+ "PinPadButton",
55− return self.app.select_single("PinPadButton", objectName="pinPadButton%i" % buttonId)
85+ objectName="pinPadButton%i" % buttonId
86+ )
56
87
57 def get_lockscreen(self):
88 def get_lockscreen(self):
58 return self.app.select_single("Lockscreen")
89 return self.app.select_single("Lockscreen")
tests/autopilot/unity8/shell/tests/__init__.py+216−58
@@ -1,81 +1,239 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2−# Copyright 2013 Canonical
3#
2#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 Canonical
5+#
4−# This program is free software: you can redistribute it and/or modify it
6+# This program is free software: you can redistribute it and/or modify
5−# under the terms of the GNU General Public License version 3, as published
7+# it under the terms of the GNU General Public License as published by
6−# by the Free Software Foundation.
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+#
7
19
8−"""unity8 autopilot tests."""
20+"""unity autopilot tests."""
9
21
10−import os.path
22+try:
11−import sysconfig
23+ from gi.repository import Gio
24+except ImportError:
25+ Gio = None
12
26
27+from autopilot.platform import model
13from autopilot.testcase import AutopilotTestCase
28from autopilot.testcase import AutopilotTestCase
14from autopilot.matchers import Eventually
29from autopilot.matchers import Eventually
15−from autopilot.platform import model
30+from autopilot.input import Touch
31+from autopilot.display import Display
32+import logging
33+import os.path
16−from testtools.matchers import Equals
34+from testtools.matchers import Equals, NotEquals
17
35
36+from unity8 import (
37+ get_lib_path,
38+ get_binary_path,
39+ get_mocks_library_path,
40+ get_default_extra_mock_libraries,
41+)
42+from unity8.shell.emulators import UnityEmulatorBase
43+from unity8.shell.emulators.dash import Dash
18from unity8.shell.emulators.main_window import MainWindow
44from unity8.shell.emulators.main_window import MainWindow
19
45
20−class FormFactors(object):
21− Phone, Tablet, Desktop = range(3)
22
46
23−class ShellTestCase(AutopilotTestCase):
47+logger = logging.getLogger(__name__)
24
48
25− """A common test case class that provides several useful methods for shell tests."""
49+UNITYSHELL_GSETTINGS_SCHEMA = "org.compiz.unityshell"
50+UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
51+UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
52+UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
26
53
27− libdir = "/usr/lib/{0}/unity8".format(sysconfig.get_config_var('MULTIARCH'))
54+def _get_device_emulation_scenarios():
28− lightdm_mock = "full"
55+ if model() == 'Desktop':
56+ return [
57+ (
58+ 'Desktop Nexus 4',
59+ dict(app_width=768, app_height=1280, grid_unit_px=18)
60+ ),
61+ (
62+ 'Desktop Nexus 10',
63+ dict(app_width=2560, app_height=1600, grid_unit_px=20)
64+ ),
65+ ]
66+ else:
67+ return [
68+ (
69+ 'Native Device',
70+ dict(app_width=0, app_height=0, grid_unit_px=0)
71+ )
72+ ]
29
73
74+
75+class UnityTestCase(AutopilotTestCase):
76+
77+ """A test case base class for the Unity shell tests."""
78+
30− def setUp(self, geometry, grid_size):
79+ def setUp(self):
31− super(ShellTestCase, self).setUp()
80+ super(UnityTestCase, self).setUp()
32− # Lets assume we are installed system wide if this file is somewhere in /usr
81+ if Gio is not None and UNITYSHELL_GSETTINGS_SCHEMA in Gio.Settings.list_relocatable_schemas():
33− if grid_size != "0":
82+ # Hide Unity launcher
34− os.environ['GRID_UNIT_PX'] = grid_size
83+ self._unityshell_schema = Gio.Settings.new_with_path(UNITYSHELL_GSETTINGS_SCHEMA, UNITYSHELL_GSETTINGS_PATH)
35− self.grid_size = int(grid_size)
84+ self._launcher_hide_mode = self._unityshell_schema.get_int(UNITYSHELL_LAUNCHER_KEY)
36− else:
85+ self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, UNITYSHELL_LAUNCHER_MODE)
37− self.grid_size = int(os.environ['GRID_UNIT_PX'])
86+ self.addCleanup(self._reset_launcher)
38− if os.path.realpath(__file__).startswith("/usr/"):
87+
39− self.launch_test_installed(geometry)
88+ self._proxy = None
89+ self._lightdm_mock_type = None
90+ self.touch = Touch.create()
91+ self._setup_display_details()
92+
93+ def _reset_launcher(self):
94+ """Reset Unity launcher hide mode"""
95+ self._unityshell_schema.set_int(UNITYSHELL_LAUNCHER_KEY, self._launcher_hide_mode)
96+
97+ def _setup_display_details(self):
98+ scale_divisor = self._determine_geometry()
99+ self._setup_grid_size(scale_divisor)
100+
101+ def _determine_geometry(self):
102+ """Use the geometry that may be supplied or use the default."""
103+ width = getattr(self, 'app_width', 0)
104+ height = getattr(self, 'app_height', 0)
105+ scale_divisor = 1
106+ if width == 0 and width == 0:
107+ self.unity_geometry_args = ['-fullscreen']
40 else:
108 else:
41− self.launch_test_local(geometry)
109+ if self._geo_larger_than_display(width, height):
42−
110+ scale_divisor = self._get_scaled_down_geo(width, height)
43− def launch_test_local(self, geometry):
111+ width = width / scale_divisor
44− os.environ['LD_LIBRARY_PATH'] = "../../builddir/tests/mocks/libusermetrics:../../builddir/tests/mocks/LightDM" + self.lightdm_mock
112+ height = height / scale_divisor
45− os.environ['QML2_IMPORT_PATH'] = "../../builddir/tests/mocks"
113+ logger.info(
46− if geometry != "0x0":
114+ "Geometry larger than display, scaled down to: %dx%d",
47− self.app = self.launch_test_application(
115+ width,
48− "../../builddir/unity8", "-geometry", geometry, "-frameless", app_type='qt')
116+ height
117+ )
118+ geo_string = "%dx%d" % (width, height)
119+ self.unity_geometry_args = [
120+ '-geometry',
121+ geo_string,
122+ '-frameless',
123+ '-mousetouch'
124+ ]
125+ return scale_divisor
126+
127+ def _setup_grid_size(self, scale_divisor):
128+ """Use the grid size that may be supplied or use the default."""
129+ if getattr(self, 'grid_unit_px', 0) == 0:
130+ self.grid_size = int(os.getenv('GRID_UNIT_PX'))
49 else:
131 else:
50− self.app = self.launch_test_application(
132+ self.grid_size = int(self.grid_unit_px / scale_divisor)
51− "../../builddir/unity8", "-fullscreen", app_type='qt')
133+ self.patch_environment("GRID_UNIT_PX", str(self.grid_size))
52−
134+
53− def launch_test_installed(self, geometry):
135+ def _geo_larger_than_display(self, width, height):
54− os.environ['LD_LIBRARY_PATH'] = "{0}/qml/mocks/libusermetrics:{0}/qml/mocks/LightDM/{1}".format(self.libdir, self.lightdm_mock)
136+ should_scale = getattr(self, 'scale_geo', True)
55− os.environ['QML2_IMPORT_PATH'] = "{0}/qml/mocks".format(self.libdir)
137+ if should_scale:
56− if model() == 'Desktop' and geometry != "0x0":
138+ screen = Display.create()
57− self.app = self.launch_test_application(
139+ screen_width = screen.get_screen_width()
58− "unity8", "-geometry", geometry, "-frameless", app_type='qt')
140+ screen_height = screen.get_screen_height()
141+ return (width > screen_width) or (height > screen_height)
59 else:
142 else:
143+ return False
144+
145+ def _get_scaled_down_geo(self, width, height):
146+ divisor = 1
147+ while self._geo_larger_than_display(width / divisor, height / divisor):
148+ divisor = divisor * 2
149+ return divisor
150+
151+ def launch_unity(self):
152+ """Launch the unity shell, return a proxy object for it."""
153+ binary_path = get_binary_path()
154+ lib_path = get_lib_path()
155+
156+ logger.info(
157+ "Lib path is '%s', binary path is '%s'",
158+ lib_path,
159+ binary_path
160+ )
161+
162+ if self._lightdm_mock_type is None:
163+ self.patch_lightdm_mock()
164+ self._setup_extra_mock_environment_patch()
165+
60− self.app = self.launch_test_application(
166+ app_proxy = self.launch_test_application(
167+ binary_path,
168+ *self.unity_geometry_args,
61− "unity8", "-fullscreen", app_type='qt')
169+ app_type='qt',
170+ emulator_base=UnityEmulatorBase
171+ )
172+ self._set_proxy(app_proxy)
173+
174+ # Ensure that the dash is visible before we return:
175+ logger.debug("Unity started, waiting for it to be ready.")
176+ self.assertUnityReady()
177+ logger.debug("Unity loaded and ready.")
178+
179+ return app_proxy
180+
181+ def patch_lightdm_mock(self, mock_type='single'):
182+ self._lightdm_mock_type = mock_type
183+ logger.info("Setting up LightDM mock type '%s'", mock_type)
184+ new_ld_library_path = "%s:%s" % (
185+ get_default_extra_mock_libraries(),
186+ self._get_lightdm_mock_path(mock_type)
187+ )
188+ logger.info("New library path: %s", new_ld_library_path)
189+
190+ self.patch_environment('LD_LIBRARY_PATH', new_ld_library_path)
191+
192+ def _get_lightdm_mock_path(self, mock_type):
193+ lib_path = get_mocks_library_path()
194+ lightdm_mock_path = os.path.abspath(
195+ os.path.join(lib_path, "LightDM", mock_type)
196+ )
197+
198+ if not os.path.exists(lightdm_mock_path):
199+ raise RuntimeError(
200+ "LightDM mock '%s' does not exist at path '%s'."
201+ % (mock_type, lightdm_mock_path)
202+ )
203+ return lightdm_mock_path
204+
205+ def _setup_extra_mock_environment_patch(self):
206+ mocks_library_path = get_mocks_library_path()
207+ self.patch_environment('QML2_IMPORT_PATH', mocks_library_path)
208+
209+ def _set_proxy(self, proxy):
210+ """Keep a copy of the proxy object, so we can use it to get common
211+ parts of the shell later on.
212+
213+ """
214+ self._proxy = proxy
215+ self.addCleanup(self._clear_proxy)
216+
217+ def _clear_proxy(self):
218+ self._proxy = None
62
219
63− def skipWrapper(*args, **kwargs):
220+ def assertUnityReady(self):
64− pass
221+ dash = self.get_dash()
222+ home_scope = dash.get_scope('home')
65
223
66− def form_factor(self):
224+ # FIXME! There is a huge timeout here for when we're doing CI on
67− return FormFactors.Desktop
225+ # VMs. See lp:1203715
226+ self.assertThat(
227+ home_scope.isLoaded,
228+ Eventually(Equals(True), timeout=60)
229+ )
230+ self.assertThat(home_scope.isCurrent, Eventually(Equals(True)))
68
231
69− def __getattribute__(self, attr_name):
232+ def get_dash(self):
70− attr = object.__getattribute__(self, attr_name);
233+ dash = self._proxy.select_single(Dash)
71− if attr_name.startswith("test_"):
234+ self.assertThat(dash, NotEquals(None))
72− try:
73− if self.form_factor() in attr.blacklist:
74− return self.skipWrapper
75− except:
76− pass
77− return attr
235+ return dash
78
236
79 @property
237 @property
80 def main_window(self):
238 def main_window(self):
81− return MainWindow(self.app)
239+ return MainWindow(self._proxy)
tests/autopilot/unity8/shell/tests/helpers.pydeleted−161
@@ -1,161 +0,0 @@
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 testtools.matchers import Equals, NotEquals
9−from autopilot.matchers import Eventually
10−
11−import logging
12−
13−logger = logging.getLogger(__name__)
14−
15−class TestShellHelpers(object):
16− """Helpers for testing the Shell"""
17−
18− def select_greeter_user(self, username):
19− greeter = self.main_window.get_greeter()
20− self.assertThat(greeter.created, Eventually(Equals(True)))
21− self.assertThat(greeter.multiUser, Eventually(Equals(True)))
22−
23− login_loader = self.main_window.get_login_loader()
24− self.assertThat(login_loader.progress, Eventually(Equals(1)))
25−
26− login_list = self.main_window.get_login_list()
27− list_view = login_list.get_children_by_type("QQuickListView")[0]
28−
29− try_count = 0
30− max_tries = 50 # just in case we go off rails
31− while try_count < max_tries:
32− users = list_view.get_children_by_type("QQuickItem")[0].get_children_by_type("QQuickItem")
33− target_user = None
34− for user in users:
35− try:
36− user_label = user.get_children_by_type("Label")[0]
37− if user.opacity < 0.1:
38− continue # off-screen item
39− if user_label.text == username:
40− target_user = user
41− break
42− elif target_user is None or user.y > target_user.y:
43− target_user = user
44− except Exception:
45− pass
46− if target_user is None:
47− break
48− user_label = target_user.get_children_by_type("Label")[0]
49− self.touch.tap_object(user_label)
50− self.assertThat(list_view.movingInternally, Eventually(Equals(False)))
51− if user_label.text == username:
52− return login_list.get_children_by_type("TextField")[0]
53− try_count = try_count + 1
54− self.fail() # We didn't find it
55−
56− def unlock_greeter(self, retries=2):
57− greeter = self.main_window.get_greeter()
58− self.assertThat(greeter.created, Eventually(Equals(True)))
59−
60− if greeter.multiUser:
61− password_field = self.select_greeter_user("No Password")
62− self.assertThat(password_field.opacity, Eventually(Equals(1)))
63− self.touch.tap_object(password_field)
64−
65− else:
66− rect = greeter.globalRect
67− start_x = rect[0] + rect[2] - 3
68− start_y = int(rect[1] + rect[3] / 2)
69− stop_x = int(rect[0] + rect[2] * 0.2)
70− stop_y = start_y
71− self.touch.drag(start_x, start_y, stop_x, stop_y)
72−
73− # Because the shell loads up lots of stuff, unlocking the greeter can
74− # be a bit stuttery while scopes are still consuming all resources.
75− # Give it another (max retries) chance
76− try:
77− self.assertThat(greeter.created, Eventually(Equals(False)))
78− except:
79− if retries > 0:
80− logger.warning("Failed to unlock greeter. Retrying...")
81− self.unlock_greeter(retries-1)
82− else:
83− logger.warning("Failed to unlock greeter. Giving up. Tests may fail...")
84−
85−
86− def open_first_dash_home_app(self, retries=2):
87− self.assertThat(lambda: self.main_window.get_dash_home_applications_grid(), Eventually(NotEquals(None)))
88− app_grid = self.main_window.get_dash_home_applications_grid()
89− # Wait for the grids to be expanded
90− self.assertThat(app_grid.get_children()[0].totalContentHeight, Eventually(NotEquals(0)))
91− self.assertThat(app_grid.get_children()[0].height, Eventually(Equals(app_grid.get_children()[0].totalContentHeight)))
92− first_app = app_grid.get_children()[0].get_children()[0].get_children()[0].get_children()[0]
93− self.touch.tap_object(first_app)
94− bottombar = self.main_window.get_bottombar()
95−
96− # if we have huge amounts of pixels (e.g. Nexus10), but slow video (e.g. VM) it might take a little
97− # until the dash is fully rendered after sliding away the greeter/lockscreen and the click might
98− # go to the void for the first time because there's no real way to know what the display has
99− # painted already. Give it another (max retries) chance.
100− try:
101− self.assertThat(lambda: getattr(bottombar, "applicationIsOnForeground"),
102− Eventually(Equals(True)))
103− except:
104− if retries > 0:
105− logger.warning("Failed to launch app. Retrying...")
106− self.open_first_dash_home_app(retries-1)
107− else:
108− logger.warning("Failed to launch app. Giving up. Tests may fail...")
109−
110−
111− def show_hud(self, retries=2):
112− self.open_first_dash_home_app()
113−
114− hud_show_button = self.main_window.get_hud_show_button()
115− hud = self.main_window.get_hud()
116− window = self.main_window.get_qml_view()
117− start_x = int(window.x + window.width / 2)
118− start_y = window.y + window.height - 3
119− self.assertThat(hud_show_button.opacity, Eventually(Equals(0)))
120− self.touch.press(start_x, start_y)
121− self.touch._finger_move(start_x, start_y - self.grid_size)
122− self.assertThat(hud_show_button.opacity, Eventually(Equals(0)))
123− self.touch._finger_move(start_x, start_y - self.grid_size * 2)
124− self.touch._finger_move(start_x, start_y - self.grid_size * 3)
125− self.touch._finger_move(start_x, start_y - self.grid_size * 4)
126− try:
127− self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
128− except:
129− if retries > 0:
130− logger.warning("Failed to get hud button to show. Retrying...")
131− self.touch.release()
132− self.show_hud(retries-1)
133− return
134− else:
135− logger.warning("Failed to get hud button to show. Giving up. Tests may fail...")
136− self.assertThat(hud_show_button.mouseOver, Eventually(Equals(False)))
137− self.touch._finger_move(start_x, start_y - self.grid_size * 34)
138− self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
139− self.assertThat(hud_show_button.mouseOver, Eventually(Equals(True)))
140− self.touch.release()
141− self.assertThat(hud_show_button.opacity, Eventually(Equals(0)))
142− self.assertThat(hud.shown, Eventually(Equals(True)))
143−
144− def close_hud_click(self):
145− hud = self.main_window.get_hud()
146− self.assertThat(hud.shown, Eventually(Equals(True)))
147− rect = hud.globalRect
148− x = int(rect[0] + rect[2] / 2)
149− y = rect[1] + self.grid_size
150− self.touch.tap(x, y)
151− self.assertThat(hud.shown, Eventually(Equals(False)))
152−
153− def show_launcher(self):
154− launcher = self.main_window.get_launcher()
155− view = self.main_window.get_qml_view()
156− start_x = view.x + 1
157− start_y = view.y + view.height / 2
158− stop_x = start_x + launcher.panelWidth + 1
159− stop_y = start_y
160− self.touch.drag(start_x, start_y, stop_x, stop_y)
161− self.assertThat(launcher.shown, Eventually(Equals(True)))
tests/autopilot/unity8/shell/tests/test_hud.pynew file+151
@@ -0,0 +1,151 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 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+from __future__ import absolute_import
21+
22+from unity8.shell import with_lightdm_mock
23+from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
24+
25+from testtools.matchers import Equals
26+from autopilot.matchers import Eventually
27+
28+
29+class TestHud(UnityTestCase):
30+
31+ """Tests the Shell HUD."""
32+
33+ scenarios = _get_device_emulation_scenarios()
34+
35+ def test_show_hud_button_appears(self):
36+ """Swiping up while an app is active must show the 'show hud' button.
37+
38+ """
39+ self.launch_unity()
40+ self.main_window.get_greeter().unlock()
41+ window = self.main_window.get_qml_view()
42+ hud_show_button = self.main_window.get_hud_show_button()
43+ hud = self.main_window.get_hud()
44+
45+ self._launch_test_app_from_app_screen()
46+
47+ swipe_coords = hud.get_button_swipe_coords(
48+ window,
49+ hud_show_button
50+ )
51+ self.touch.press(swipe_coords.start_x, swipe_coords.start_y)
52+ self.addCleanup(self.touch.release)
53+ self.touch._finger_move(swipe_coords.end_x, swipe_coords.end_y)
54+ self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
55+
56+ def test_show_hud_appears(self):
57+ """Releasing the touch on the 'show hud' button must display the hud.
58+
59+ """
60+ self.launch_unity()
61+ self.main_window.get_greeter().unlock()
62+ window = self.main_window.get_qml_view()
63+ hud_show_button = self.main_window.get_hud_show_button()
64+ hud = self.main_window.get_hud()
65+
66+ self._launch_test_app_from_app_screen()
67+
68+ swipe_coords = hud.get_button_swipe_coords(
69+ window,
70+ hud_show_button
71+ )
72+ self.touch.press(swipe_coords.start_x, swipe_coords.start_y)
73+ self.addCleanup(self._maybe_release_finger)
74+ self.touch._finger_move(swipe_coords.end_x, swipe_coords.end_y)
75+
76+ self.assertThat(hud.shown, Eventually(Equals(False)))
77+ self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
78+ self.touch.release()
79+ self.assertThat(hud.shown, Eventually(Equals(True)))
80+
81+ def test_hide_hud_click(self):
82+ """Tapping the close button of the Hud must dismiss it."""
83+ self.launch_unity()
84+ self.main_window.get_greeter().unlock()
85+ hud = self.main_window.get_hud()
86+
87+ self._launch_test_app_from_app_screen()
88+ hud.show()
89+
90+ x, y = hud.get_close_button_coords()
91+ self.touch.tap(x, y)
92+ self.assertThat(hud.shown, Eventually(Equals(False)))
93+
94+ def test_hide_hud_dragging(self):
95+ """Once open the Hud must close if the upper bar is dragged and
96+ released downward.
97+
98+ """
99+ self.launch_unity()
100+ self.main_window.get_greeter().unlock()
101+ hud = self.main_window.get_hud()
102+ window = self.main_window.get_qml_view()
103+
104+ self._launch_test_app_from_app_screen()
105+ hud.show()
106+
107+ start_x, start_y = hud.get_close_button_coords()
108+ end_x = start_x
109+ end_y = int(window.height / 2)
110+
111+ self.touch.drag(start_x, start_y, end_x, end_y)
112+ self.assertThat(hud.shown, Eventually(Equals(False)))
113+
114+ def test_launcher_hides_hud(self):
115+ """Opening the Launcher while the Hud is active must close the Hud."""
116+ self.launch_unity()
117+ self.main_window.get_greeter().unlock()
118+ hud = self.main_window.get_hud()
119+ launcher = self.main_window.get_launcher()
120+
121+ self._launch_test_app_from_app_screen()
122+
123+ hud.show()
124+ launcher.show()
125+
126+ self.assertThat(hud.shown, Eventually(Equals(False)))
127+
128+ def _launch_test_app_from_app_screen(self):
129+ """Launches the camera app using the Dash UI.
130+
131+ Because when testing on the desktop running
132+ self.launch_application() will launch the application on the desktop
133+ itself and not within the Unity UI.
134+
135+ """
136+ dash = self.main_window.get_dash()
137+ icon = dash.get_application_icon('Camera')
138+ self.touch.tap_object(icon)
139+
140+ # Ensure application is open
141+ bottombar = self.main_window.get_bottombar()
142+ self.assertThat(bottombar.applicationIsOnForeground,
143+ Eventually(Equals(True)))
144+
145+ # Because some tests are manually manipulating the finger, we want to
146+ # cleanup if the test fails, but we don't want to fail with an exception if
147+ # we don't.
148+ def _maybe_release_finger(self):
149+ """Only release the finger if it is in fact down."""
150+ if self.touch._touch_finger is not None:
151+ self.touch.release()
tests/autopilot/unity8/shell/tests/test_lock_screen.pynew file+131
@@ -0,0 +1,131 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2012-2013 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+
21+from __future__ import absolute_import
22+
23+from unity8.shell import with_lightdm_mock
24+from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
25+
26+from autopilot.matchers import Eventually
27+from autopilot.platform import model
28+from testtools import skipUnless
29+from testtools.matchers import Equals
30+
31+
32+class TestLockscreen(UnityTestCase):
33+
34+ """Tests for the lock screen."""
35+
36+ scenarios = _get_device_emulation_scenarios()
37+
38+ @with_lightdm_mock("single-pin")
39+ def test_can_unlock_pin_screen(self):
40+ """Must be able to unlock the PIN entry lock screen."""
41+ self.launch_unity()
42+ greeter = self.main_window.get_greeter()
43+ greeter.unlock()
44+
45+ lockscreen = self._wait_for_lockscreen()
46+ self._enter_pincode("1234")
47+
48+ self.assertThat(lockscreen.shown, Eventually(Equals(False)))
49+
50+ @with_lightdm_mock("single-passphrase")
51+ def test_can_unlock_passphrase_screen(self):
52+ """Must be able to unlock the passphrase entry screen."""
53+ self.launch_unity()
54+ greeter = self.main_window.get_greeter()
55+ greeter.unlock()
56+
57+ lockscreen = self._wait_for_lockscreen()
58+ self._enter_passphrase("password")
59+
60+ self.assertThat(lockscreen.shown, Eventually(Equals(False)))
61+
62+ @with_lightdm_mock("single-pin")
63+ def test_pin_screen_wrong_code(self):
64+ """Entering the wrong pin code must not dismiss the lock screen."""
65+ self.launch_unity()
66+ greeter = self.main_window.get_greeter()
67+ greeter.unlock()
68+
69+ lockscreen = self._wait_for_lockscreen()
70+ self._enter_pincode("4321")
71+
72+ pinentryField = self.main_window.get_pinentryField()
73+ self.assertThat(pinentryField.text, Eventually(Equals("")))
74+ self.assertThat(lockscreen.shown, Eventually(Equals(True)))
75+
76+ @with_lightdm_mock("single-passphrase")
77+ def test_passphrase_screen_wrong_password(self):
78+ """Entering the wrong password must not dismiss the lock screen."""
79+ self.launch_unity()
80+ greeter = self.main_window.get_greeter()
81+ greeter.unlock()
82+
83+ lockscreen = self._wait_for_lockscreen()
84+ self._enter_passphrase("foobar")
85+
86+ pinentryField = self.main_window.get_pinentryField()
87+ self.assertThat(pinentryField.text, Eventually(Equals("")))
88+ self.assertThat(lockscreen.shown, Eventually(Equals(True)))
89+
90+ def _wait_for_lockscreen(self):
91+ """Wait for the lock screen to load, and return it."""
92+ pinPadLoader = self.main_window.get_pinPadLoader()
93+ self.assertThat(pinPadLoader.progress, Eventually(Equals(1)))
94+ lockscreen = self.main_window.get_lockscreen()
95+ self.assertThat(lockscreen.shown, Eventually(Equals(True)))
96+ return lockscreen
97+
98+ def _enter_pincode(self, code):
99+ """Enter code 'code' into the single-pin lightdm pincode entry
100+ screen.
101+
102+ :param code: must be a string of numeric characters.
103+ :raises: TypeError if code is not a string.
104+ :raises: ValueError if code contains non-numeric characters.
105+
106+ """
107+
108+ if not isinstance(code, basestring):
109+ raise TypeError("'code' parameter must be a string.")
110+ for num in code:
111+ if not num.isdigit():
112+ raise ValueError(
113+ "'code' parameter contains non-numeric characters."
114+ )
115+ self.touch.tap_object(self.main_window.get_pinPadButton(int(num)))
116+
117+ def _enter_passphrase(self, passphrase):
118+ """Enter the password specified in 'passphrase' into the password entry
119+ field.
120+
121+ :param passphrase: The string you want to enter.
122+ :raises: TypeError if passphrase is not a string.
123+
124+ """
125+ if not isinstance(passphrase, basestring):
126+ raise TypeError("'passphrase' parameter must be a string.")
127+
128+ pinentryField = self.main_window.get_pinentryField()
129+ self.touch.tap_object(pinentryField)
130+ self.keyboard.type(passphrase)
131+ self.keyboard.type("\n")
tests/autopilot/unity8/shell/tests/testbigscreen.pydeleted−25
@@ -1,25 +0,0 @@
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 everything is aligned correctly on huge screens. Because this test does not fit on most screens, you should not use input devices here or your tests are likely to fail"""
9−
10−from testtools.matchers import Equals
11−from autopilot.matchers import Eventually
12−
13−from unity8.shell.tests import ShellTestCase
14−
15−class TestBig(ShellTestCase):
16− def setUp(self):
17− super(TestBig, self).setUp("2560x1600", "20")
18− self.assertThat(self.main_window.get_qml_view().visible, Eventually(Equals(True)))
19−
20− def tearDown(self):
21− super(TestBig, self).tearDown()
22−
23− def test_hud_not_shown_greeter(self):
24− hud_showable = self.main_window.get_hud_showable()
25− self.assertThat(hud_showable.y, Eventually(Equals(1600)))
tests/autopilot/unity8/shell/tests/testhud.pydeleted−145
@@ -1,145 +0,0 @@
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−
9−# This file contains general purpose test cases for Unity.
10−# Each test written in this file will be executed for a variety of
11−# configurations, such as Phone, Tablet or Desktop form factors.
12−#
13−# Sometimes there is the need to disable a certain test for a particular
14−# configuration. To do so, add this in a new line directly below your test:
15−#
16−# test_testname.blacklist = (FormFactors.Tablet, FormFactors.Desktop,)
17−#
18−# Available form factors are:
19−# FormFactors.Phone
20−# FormFactors.Tablet
21−# FormFactors.Desktop
22−
23−
24−"""Tests for the Shell"""
25−
26−from __future__ import absolute_import
27−
28−from unity8.shell.tests import ShellTestCase, FormFactors
29−from unity8.shell.tests.helpers import TestShellHelpers
30−
31−from autopilot.input import Mouse, Touch, Pointer
32−from testtools.matchers import Equals, NotEquals, GreaterThan, MismatchError
33−from autopilot.matchers import Eventually
34−from autopilot.display import Display
35−from autopilot.platform import model
36−
37−import unittest
38−import time
39−import os
40−from os import path
41−
42−
43−class TestHud(ShellTestCase, TestShellHelpers):
44−
45− """Tests the Shell"""
46−
47− # Scenarios:
48− # Fill in the scenarios to run the whole test suite with multiple configurations.
49− # Use app_width, app_height and grid_unit_px to set the apps geometry.
50− # Set app_width and app_height to 0 to use fullscreen.
51− # Set grid_unit_px to 0 to use the current system environment.
52−
53− if model() == 'Desktop':
54− scenarios = [
55− ('Nexus 4', dict(app_width=768, app_height=1280, grid_unit_px=18, lightdm_mock="single")),
56− ('Nexus 10', dict(app_width=2560, app_height=1600, grid_unit_px=20, lightdm_mock="full")),
57−# TODO: don't run fullscreen tests just yet as the VM is performing too badly for that. Enable this once
58−# Autopilot tests are running on bear metal.
59−# ('Fullscreen', dict(app_width=0, app_height=0, grid_unit_px=10, lightdm_mock="full")),
60− ]
61− else:
62− scenarios = [
63− ('Fullscreen', dict(app_width=0, app_height=0, grid_unit_px=0, lightdm_mock="single")),
64− ]
65−
66− def setUp(self):
67− self.touch = Touch.create()
68−
69− sg = Display().create()
70− divisor = 1
71− while (sg.get_screen_width() < self.app_width / divisor or sg.get_screen_height() < self.app_height / divisor):
72− divisor = divisor * 2
73− super(TestHud, self).setUp("%sx%s" % (self.app_width / divisor, self.app_height / divisor), "%s" % (self.grid_unit_px / divisor))
74−
75− dash = self.main_window.get_dash()
76− self.assertThat(dash.showScopeOnLoaded, Eventually(Equals(""), timeout=30))
77−
78− def test_show_hud(self):
79− hud = self.main_window.get_hud()
80− self.unlock_greeter()
81− self.show_hud()
82− self.assertThat(hud.shown, Eventually(Equals(True)))
83−
84− def test_show_hud_button_dont_open(self):
85− self.unlock_greeter()
86− self.open_first_dash_home_app()
87− hud_show_button = self.main_window.get_hud_show_button()
88− hud = self.main_window.get_hud()
89− window = self.main_window.get_qml_view()
90− start_x = int(window.x + window.width / 2)
91− start_y = window.y + window.height - 2
92− self.assertThat(hud_show_button.opacity, Eventually(Equals(0)))
93− self.touch.press(start_x, start_y)
94− self.touch._finger_move(start_x, start_y - self.grid_size)
95− self.assertThat(hud_show_button.opacity, Eventually(Equals(0)))
96− self.touch._finger_move(start_x, start_y - self.grid_size * 2)
97− self.touch._finger_move(start_x, start_y - self.grid_size * 3)
98− self.touch._finger_move(start_x, start_y - self.grid_size * 4)
99− self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
100− self.assertThat(hud_show_button.mouseOver, Eventually(Equals(False)))
101− self.touch._finger_move(start_x, start_y - self.grid_size * 34)
102− self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
103− self.assertThat(hud_show_button.mouseOver, Eventually(Equals(True)))
104− self.touch._finger_move(start_x, start_y - self.grid_size)
105− self.assertThat(hud_show_button.opacity, Eventually(Equals(1.0)))
106− self.assertThat(hud_show_button.mouseOver, Eventually(Equals(False)))
107− self.touch.release()
108− self.assertThat(hud_show_button.opacity, Eventually(Equals(0)))
109− self.assertThat(hud.shown, Eventually(Equals(False)))
110−
111− def test_hide_hud_click(self):
112− hud = self.main_window.get_hud()
113− self.unlock_greeter()
114− self.show_hud()
115− self.close_hud_click()
116− self.assertThat(hud.shown, Eventually(Equals(False)))
117−
118− def test_hide_hud_click_outside_handle(self):
119− hud = self.main_window.get_hud()
120− self.unlock_greeter()
121− self.show_hud()
122− rect = hud.globalRect
123− x = int(rect[0] + rect[2] / 2)
124− y = rect[1] + hud.handleHeight + 1
125− self.touch.tap(x, y)
126− self.assertRaises(MismatchError, lambda: self.assertThat(hud.shown, Eventually(Equals(False), timeout=3)))
127−
128− def test_hide_hud_dragging(self):
129− hud = self.main_window.get_hud()
130− self.unlock_greeter()
131− self.show_hud()
132− rect = hud.globalRect
133− start_x = rect[0] + (rect[2] - rect[0]) / 2
134− start_y = rect[1] + 1
135− stop_x = start_x
136− stop_y = start_y + (rect[3] - rect[1]) / 2
137− self.touch.drag(start_x, start_y, stop_x, stop_y)
138− self.assertThat(hud.shown, Eventually(Equals(False)))
139−
140− def test_hide_hud_launcher(self):
141− hud = self.main_window.get_hud()
142− self.unlock_greeter()
143− self.show_hud()
144− self.show_launcher()
145− self.assertThat(hud.shown, Eventually(Equals(False)))
tests/autopilot/unity8/shell/tests/testlockscreen.pydeleted−118
@@ -1,118 +0,0 @@
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−
9−# This file contains general purpose test cases for Unity.
10−# Each test written in this file will be executed for a variety of
11−# configurations, such as Phone, Tablet or Desktop form factors.
12−#
13−# Sometimes there is the need to disable a certain test for a particular
14−# configuration. To do so, add this in a new line directly below your test:
15−#
16−# test_testname.blacklist = (FormFactors.Tablet, FormFactors.Desktop,)
17−#
18−# Available form factors are:
19−# FormFactors.Phone
20−# FormFactors.Tablet
21−# FormFactors.Desktop
22−
23−
24−"""Tests for the Shell"""
25−
26−from __future__ import absolute_import
27−
28−from unity8.shell.tests import ShellTestCase, FormFactors
29−from unity8.shell.tests.helpers import TestShellHelpers
30−
31−from autopilot.input import Mouse, Touch, Pointer
32−from testtools.matchers import Equals, NotEquals, GreaterThan, MismatchError
33−from autopilot.matchers import Eventually
34−from autopilot.display import Display
35−from autopilot.platform import model
36−
37−import unittest
38−import time
39−import os
40−from os import path
41−
42−
43−class TestLockscreens(ShellTestCase, TestShellHelpers):
44−
45− """Tests the Lockscreens"""
46−
47− # Scenarios:
48− # Fill in the scenarios to run the whole test suite with multiple configurations.
49− # Use app_width, app_height and grid_unit_px to set the apps geometry.
50− # Set app_width and app_height to 0 to use fullscreen.
51− # Set grid_unit_px to 0 to use the current system environment.
52−
53− if model() == 'Desktop':
54− scenarios = [
55− ('Pinlock', dict(app_width=768, app_height=1280, grid_unit_px=18, lightdm_mock="single-pin")),
56− ('Keylock', dict(app_width=768, app_height=1280, grid_unit_px=18, lightdm_mock="single-passphrase")),
57− ]
58− else:
59− scenarios = [
60− ('Pinlock', dict(app_width=0, app_height=0, grid_unit_px=0, lightdm_mock="single-pin")),
61− ('Keylock', dict(app_width=0, app_height=0, grid_unit_px=0, lightdm_mock="single-key")),
62− ]
63−
64− def setUp(self):
65− self.touch = Touch.create()
66−
67− sg = Display().create()
68− divisor = 1
69− while (sg.get_screen_width() < self.app_width / divisor or sg.get_screen_height() < self.app_height / divisor):
70− divisor = divisor * 2
71− super(TestLockscreens, self).setUp("%sx%s" % (self.app_width / divisor, self.app_height / divisor), "%s" % (self.grid_unit_px / divisor))
72−
73− dash = self.main_window.get_dash()
74− self.assertThat(dash.showScopeOnLoaded, Eventually(Equals(""), timeout=30))
75−
76− def test_unlock(self):
77− self.unlock_greeter()
78−
79− pinPadLoader = self.main_window.get_pinPadLoader();
80− self.assertThat(pinPadLoader.progress, Eventually(Equals(1)))
81− lockscreen = self.main_window.get_lockscreen();
82− self.assertThat(lockscreen.shown, Eventually(Equals(True)))
83−
84− if self.lightdm_mock == "single-pin":
85− self.touch.tap_object(self.main_window.get_pinPadButton(1))
86− self.touch.tap_object(self.main_window.get_pinPadButton(2))
87− self.touch.tap_object(self.main_window.get_pinPadButton(3))
88− self.touch.tap_object(self.main_window.get_pinPadButton(4))
89− self.assertThat(lockscreen.shown, Eventually(Equals(False)))
90− else:
91− pinentryField = self.main_window.get_pinentryField()
92− self.touch.tap_object(pinentryField)
93− self.keyboard.type("password\n")
94− self.assertThat(lockscreen.shown, Eventually(Equals(False)))
95−
96− def test_unlock_wrong(self):
97− self.unlock_greeter()
98−
99− pinPadLoader = self.main_window.get_pinPadLoader();
100− self.assertThat(pinPadLoader.progress, Eventually(Equals(1)))
101− lockscreen = self.main_window.get_lockscreen();
102− self.assertThat(lockscreen.shown, Eventually(Equals(True)))
103− pinentryField = self.main_window.get_pinentryField()
104−
105− if self.lightdm_mock == "single-pin":
106− self.touch.tap_object(self.main_window.get_pinPadButton(4))
107− self.touch.tap_object(self.main_window.get_pinPadButton(3))
108− self.touch.tap_object(self.main_window.get_pinPadButton(2))
109− self.assertThat(pinentryField.text, Eventually(Equals("432")))
110− self.touch.tap_object(self.main_window.get_pinPadButton(1))
111−
112− self.assertThat(pinentryField.text, Eventually(Equals("")))
113− self.assertThat(lockscreen.shown, Eventually(Equals(True)))
114− else:
115− self.touch.tap_object(pinentryField)
116− self.keyboard.type("foobar\n")
117− self.assertThat(pinentryField.text, Eventually(Equals("")))
118− self.assertThat(lockscreen.shown, Eventually(Equals(True)))
tests/mocks/CMakeLists.txt+1
@@ -1,5 +1,6 @@
1add_subdirectory(libusermetrics)
1add_subdirectory(libusermetrics)
2add_subdirectory(LightDM)
2add_subdirectory(LightDM)
3+add_subdirectory(QMenuModel)
3add_subdirectory(Ubuntu)
4add_subdirectory(Ubuntu)
4add_subdirectory(Unity)
5add_subdirectory(Unity)
5add_subdirectory(HudClient)
6add_subdirectory(HudClient)
tests/mocks/QMenuModel/CMakeLists.txtnew file+11
@@ -0,0 +1,11 @@
1+file(GLOB QMLFILES
2+ *.qml
3+ *.js
4+ qmldir
5+)
6+
7+# copy files into build directory for shadow builds
8+add_custom_target(QMenuModelQmlFiles ALL
9+ COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
10+ DEPENDS ${QMLFILES}
11+)
tests/mocks/QMenuModel/QDBusActionGroup.qmlnew file+27
@@ -0,0 +1,27 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Daniel d'Andrada <daniel.dandrada@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
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+import QtQuick 2.0
21+
22+QtObject {
23+ property int busType
24+ property string busName
25+ property string objectPath
26+ function start() {}
27+}
tests/mocks/QMenuModel/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module QMenuModel
2+QDBusActionGroup 0.1 QDBusActionGroup.qml
tests/mocks/Ubuntu/Application/ApplicationManager.cpp+8−4
@@ -37,8 +37,6 @@ ApplicationManager::ApplicationManager(QObject *parent)
37 , m_sideStage(0)
37 , m_sideStage(0)
38{
38{
39 buildListOfAvailableApplications();
39 buildListOfAvailableApplications();
40− createMainStageComponent();
41− createSideStageComponent();
42}
40}
43
41
44ApplicationManager::~ApplicationManager()
42ApplicationManager::~ApplicationManager()
@@ -321,10 +319,10 @@ void ApplicationManager::buildListOfAvailableApplications()
321 m_availableApplications.append(application);
319 m_availableApplications.append(application);
322
320
323 application = new ApplicationInfo(this);
321 application = new ApplicationInfo(this);
324− application->setDesktopFile("/usr/share/applications/ubuntu-calendar-app.desktop");
322+ application->setDesktopFile("/usr/share/applications/calendar-app.desktop");
325 application->setName("Calendar");
323 application->setName("Calendar");
326 application->setIcon("calendar");
324 application->setIcon("calendar");
327− application->setExec("/usr/bin/qmlscene /usr/share/ubuntu-calendar-app/calendar.qml");
325+ application->setExec("/usr/bin/qmlscene /usr/share/calendar-app/calendar.qml");
328 application->setStage(ApplicationInfo::SideStage);
326 application->setStage(ApplicationInfo::SideStage);
329 application->setHandle(nextHandle++);
327 application->setHandle(nextHandle++);
330 m_availableApplications.append(application);
328 m_availableApplications.append(application);
@@ -403,6 +401,9 @@ void ApplicationManager::createMainStageComponent()
403
401
404void ApplicationManager::createMainStage()
402void ApplicationManager::createMainStage()
405{
403{
404+ if (!m_mainStageComponent)
405+ createMainStageComponent();
406+
406 // The assumptions I make here really should hold.
407 // The assumptions I make here really should hold.
407 QQuickView *quickView =
408 QQuickView *quickView =
408 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
409 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
@@ -437,6 +438,9 @@ void ApplicationManager::createSideStageComponent()
437
438
438void ApplicationManager::createSideStage()
439void ApplicationManager::createSideStage()
439{
440{
441+ if (!m_sideStageComponent)
442+ createSideStageComponent();
443+
440 // The assumptions I make here really should hold.
444 // The assumptions I make here really should hold.
441 QQuickView *quickView =
445 QQuickView *quickView =
442 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
446 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
tests/mocks/Unity/CMakeLists.txt+1
@@ -44,3 +44,4 @@ file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
44 )
44 )
45
45
46add_subdirectory(Launcher)
46add_subdirectory(Launcher)
47+add_subdirectory(Notifications)
tests/mocks/Unity/Indicators/CMakeLists.txt+2−5
@@ -12,6 +12,7 @@ include_directories(
12set(IndicatorsFakeQml_SOURCES
12set(IndicatorsFakeQml_SOURCES
13 fakeplugin.cpp
13 fakeplugin.cpp
14 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/indicators.h
14 ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/indicators.h
15+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Indicators/menucontentactivator.cpp
15)
16)
16
17
17set(IndicatorsFakeQml_RESOURCES
18set(IndicatorsFakeQml_RESOURCES
@@ -26,11 +27,7 @@ add_library(IndicatorsFakeQml SHARED
26 ${IndicatorsFakeQml_RESOURCES_RCC}
27 ${IndicatorsFakeQml_RESOURCES_RCC}
27 ${IndicatorsFakeQml_SOURCES}
28 ${IndicatorsFakeQml_SOURCES}
28)
29)
29−# Because this is an internal support library, we want
30+add_definitions(-DUNITYINDICATORS_LIBRARY)
30−# to expose all symbols in it. Consider changing this
31−# either to a static library or just using the
32−# files directly in targets.
33−set_target_properties(IndicatorsFakeQml PROPERTIES COMPILE_FLAGS -fvisibility=default)
34
31
35target_link_libraries(IndicatorsFakeQml)
32target_link_libraries(IndicatorsFakeQml)
36
33
tests/mocks/Unity/Indicators/fakeplugin.cpp+4
@@ -24,11 +24,15 @@
24
24
25// local
25// local
26#include "indicators.h"
26#include "indicators.h"
27+#include "menucontentactivator.h"
27
28
28void IndicatorsFakePlugin::registerTypes(const char * uri)
29void IndicatorsFakePlugin::registerTypes(const char * uri)
29{
30{
30 Q_INIT_RESOURCE(indicators_fake);
31 Q_INIT_RESOURCE(indicators_fake);
31
32
33+ qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
34+
35+ qmlRegisterUncreatableType<MenuContentState>(uri, 0, 1, "MenuContentState", "Can't create MenuContentState class");
32 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
36 qmlRegisterUncreatableType<ActionState>(uri, 0, 1, "ActionState", "Can't create ActionState class");
33 qmlRegisterUncreatableType<NetworkActionState>(uri, 0, 1, "NetworkActionState", "Can't create NetworkActionState class");
37 qmlRegisterUncreatableType<NetworkActionState>(uri, 0, 1, "NetworkActionState", "Can't create NetworkActionState class");
34 qmlRegisterUncreatableType<NetworkConnection>(uri, 0, 1, "NetworkConnection", "Can't create NetworkConnection class");
38 qmlRegisterUncreatableType<NetworkConnection>(uri, 0, 1, "NetworkConnection", "Can't create NetworkConnection class");
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1
@@ -40,7 +40,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
40 m_list.append(item);
40 m_list.append(item);
41 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad");
41 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad");
42 m_list.append(item);
42 m_list.append(item);
43− item = new MockLauncherItem("ubuntu-calendar-app", "/usr/share/applications/ubuntu-calendar-app.desktop","Calendar", "calendar");
43+ item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar");
44 m_list.append(item);
44 m_list.append(item);
45}
45}
46
46
tests/mocks/Unity/Notifications/CMakeLists.txtnew file+11
@@ -0,0 +1,11 @@
1+file(GLOB QMLFILES
2+ *.qml
3+ *.js
4+ qmldir
5+)
6+
7+# copy files into build directory for shadow builds
8+add_custom_target(NotificationsQmlFiles ALL
9+ COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
10+ DEPENDS ${QMLFILES}
11+)
tests/mocks/Unity/fake_categories.cpp+5−2
@@ -32,10 +32,11 @@ Categories::Categories(QObject* parent)
32 m_roles[Categories::RoleName] = "name";
32 m_roles[Categories::RoleName] = "name";
33 m_roles[Categories::RoleIcon] = "icon";
33 m_roles[Categories::RoleIcon] = "icon";
34 m_roles[Categories::RoleRenderer] = "renderer";
34 m_roles[Categories::RoleRenderer] = "renderer";
35− m_roles[Categories::RoleContentType] = "content_type";
35+ m_roles[Categories::RoleContentType] = "contentType";
36 m_roles[Categories::RoleHints] = "hints";
36 m_roles[Categories::RoleHints] = "hints";
37 m_roles[Categories::RoleResults] = "results";
37 m_roles[Categories::RoleResults] = "results";
38 m_roles[Categories::RoleCount] = "count";
38 m_roles[Categories::RoleCount] = "count";
39+ m_roles[Categories::RoleCategoryIndex] = "categoryIndex";
39
40
40 // TODO This should not be needed but accumulatting the count changes
41 // TODO This should not be needed but accumulatting the count changes
41 // makes the visualization more stable and also makes crashes on fast
42 // makes the visualization more stable and also makes crashes on fast
@@ -154,7 +155,7 @@ Categories::data(const QModelIndex& index, int role) const
154
155
155 switch (role) {
156 switch (role) {
156 case RoleId:
157 case RoleId:
157− return QVariant::fromValue(index.row());
158+ return DeeListModel::data(index, 0); //ID
158 case RoleName:
159 case RoleName:
159 return DeeListModel::data(index, 1); //DISPLAY_NAME
160 return DeeListModel::data(index, 1); //DISPLAY_NAME
160 case RoleIcon:
161 case RoleIcon:
@@ -172,6 +173,8 @@ Categories::data(const QModelIndex& index, int role) const
172 return QVariant::fromValue(getFilter(index.row()));
173 return QVariant::fromValue(getFilter(index.row()));
173 case RoleCount:
174 case RoleCount:
174 return QVariant::fromValue(getFilter(index.row())->rowCount());
175 return QVariant::fromValue(getFilter(index.row())->rowCount());
176+ case RoleCategoryIndex:
177+ return QVariant::fromValue(index.row());
175 default:
178 default:
176 return QVariant();
179 return QVariant();
177 }
180 }
tests/mocks/Unity/fake_categories.h+2−1
@@ -41,7 +41,8 @@ public:
41 RoleContentType,
41 RoleContentType,
42 RoleHints,
42 RoleHints,
43 RoleResults,
43 RoleResults,
44− RoleCount
44+ RoleCount,
45+ RoleCategoryIndex
45 };
46 };
46
47
47 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
48 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
tests/mocks/Unity/fake_scopes.cpp+2−2
@@ -52,8 +52,8 @@ void Scopes::updateScopes()
52 clear();
52 clear();
53 addScope(new Scope("MockScope1", "People", true, this));
53 addScope(new Scope("MockScope1", "People", true, this));
54 addScope(new Scope("MockScope2", "Music", false, this));
54 addScope(new Scope("MockScope2", "Music", false, this));
55− addScope(new Scope("MockScope3", "Home", true, this));
55+ addScope(new Scope("home.scope", "Home", true, this));
56− addScope(new Scope("MockScope4", "Applications", true, this));
56+ addScope(new Scope("applications.scope", "Applications", true, this));
57 addScope(new Scope("MockScope5", "Videos", true, this));
57 addScope(new Scope("MockScope5", "Videos", true, this));
58
58
59 if (!m_loaded) {
59 if (!m_loaded) {
tests/plugins/ListViewWithPageHeader/CMakeLists.txt+6−1
@@ -1,7 +1,12 @@
1# There's no cmake var for v8 include path :-/
1# There's no cmake var for v8 include path :-/
2# so create one
2# so create one
3LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
3LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
4+if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
4−SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
5+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
6+else()
7+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
8+endif()
9+
5
10
6include_directories(
11include_directories(
7 ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
12 ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+31
@@ -22,7 +22,11 @@
22#include <QtTestGui>
22#include <QtTestGui>
23#pragma GCC diagnostic push
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-pedantic"
24#pragma GCC diagnostic ignored "-pedantic"
25+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
25#include <private/qquicklistmodel_p.h>
26#include <private/qquicklistmodel_p.h>
27+#else
28+#include <private/qqmllistmodel_p.h>
29+#endif
26#include <private/qquickanimation_p.h>
30#include <private/qquickanimation_p.h>
27#include <private/qquickitem_p.h>
31#include <private/qquickitem_p.h>
28#pragma GCC diagnostic pop
32#pragma GCC diagnostic pop
@@ -115,7 +119,11 @@ private Q_SLOTS:
115 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
119 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
116 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test.qml"));
120 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test.qml"));
117 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
121 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
122+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
118 model = view->rootObject()->findChild<QQuickListModel*>();
123 model = view->rootObject()->findChild<QQuickListModel*>();
124+#else
125+ model = view->rootObject()->findChild<QQmlListModel*>();
126+#endif
119 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
127 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
120 QVERIFY(lvwph);
128 QVERIFY(lvwph);
121 QVERIFY(model);
129 QVERIFY(model);
@@ -991,6 +999,25 @@ private Q_SLOTS:
991 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
999 QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
992 }
1000 }
993
1001
1002+ void testInsertToEmpty()
1003+ {
1004+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 6));
1005+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 0);
1006+ QCOMPARE(lvwph->m_minYExtent, 0.);
1007+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1008+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1009+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1010+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1011+ QCOMPARE(lvwph->contentY(), 0.);
1012+
1013+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 100));
1014+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 125));
1015+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1016+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1017+ verifyItem(0, 50., 125., false);
1018+ verifyItem(1, 175., 100., false);
1019+ }
1020+
994 void testRemoveItemsAtTop()
1021 void testRemoveItemsAtTop()
995 {
1022 {
996 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
1023 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
@@ -1366,7 +1393,11 @@ private Q_SLOTS:
1366private:
1393private:
1367 QQuickView *view;
1394 QQuickView *view;
1368 ListViewWithPageHeader *lvwph;
1395 ListViewWithPageHeader *lvwph;
1396+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1369 QQuickListModel *model;
1397 QQuickListModel *model;
1398+#else
1399+ QQmlListModel *model;
1400+#endif
1370 QQmlComponent *otherDelegate;
1401 QQmlComponent *otherDelegate;
1371};
1402};
1372
1403
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+31
@@ -22,7 +22,11 @@
22#include <QtTestGui>
22#include <QtTestGui>
23#pragma GCC diagnostic push
23#pragma GCC diagnostic push
24#pragma GCC diagnostic ignored "-pedantic"
24#pragma GCC diagnostic ignored "-pedantic"
25+#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
25#include <private/qquicklistmodel_p.h>
26#include <private/qquicklistmodel_p.h>
27+#else
28+#include <private/qqmllistmodel_p.h>
29+#endif
26#include <private/qquickanimation_p.h>
30#include <private/qquickanimation_p.h>
27#include <private/qquickitem_p.h>
31#include <private/qquickitem_p.h>
28#pragma GCC diagnostic pop
32#pragma GCC diagnostic pop
@@ -124,7 +128,11 @@ private Q_SLOTS:
124 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
128 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
125 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_section.qml"));
129 view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_section.qml"));
126 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
130 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
131+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
127 model = view->rootObject()->findChild<QQuickListModel*>();
132 model = view->rootObject()->findChild<QQuickListModel*>();
133+#else
134+ model = view->rootObject()->findChild<QQmlListModel*>();
135+#endif
128 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
136 otherDelegate = view->rootObject()->findChild<QQmlComponent*>();
129 QVERIFY(lvwph);
137 QVERIFY(lvwph);
130 QVERIFY(model);
138 QVERIFY(model);
@@ -1121,6 +1129,25 @@ private Q_SLOTS:
1121 QCOMPARE(lvwph->m_topSectionItem->y(), -23.);
1129 QCOMPARE(lvwph->m_topSectionItem->y(), -23.);
1122 }
1130 }
1123
1131
1132+ void testInsertToEmpty()
1133+ {
1134+ QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 6));
1135+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 0);
1136+ QCOMPARE(lvwph->m_minYExtent, 0.);
1137+ QCOMPARE(lvwph->m_clipItem->y(), 0.);
1138+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1139+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1140+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1141+ QCOMPARE(lvwph->contentY(), 0.);
1142+
1143+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 0), Q_ARG(QVariant, 100), Q_ARG(QVariant, "Agressive"));
1144+ QMetaObject::invokeMethod(model, "insertItem", Q_ARG(QVariant, 1), Q_ARG(QVariant, 125), Q_ARG(QVariant, "Regular"));
1145+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 2);
1146+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1147+ verifyItem(0, 50., 140., false, "Agressive", false);
1148+ verifyItem(1, 190., 165., false, "Regular", false);
1149+ }
1150+
1124 void testRemoveItemsAtTop()
1151 void testRemoveItemsAtTop()
1125 {
1152 {
1126 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
1153 QMetaObject::invokeMethod(model, "removeItems", Q_ARG(QVariant, 0), Q_ARG(QVariant, 2));
@@ -1618,7 +1645,11 @@ private Q_SLOTS:
1618private:
1645private:
1619 QQuickView *view;
1646 QQuickView *view;
1620 ListViewWithPageHeader *lvwph;
1647 ListViewWithPageHeader *lvwph;
1648+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1621 QQuickListModel *model;
1649 QQuickListModel *model;
1650+#else
1651+ QQmlListModel *model;
1652+#endif
1622 QQmlComponent *otherDelegate;
1653 QQmlComponent *otherDelegate;
1623};
1654};
1624
1655
tests/plugins/Unity/Indicators/CMakeLists.txt+1
@@ -24,4 +24,5 @@ endmacro(run_tests)
24run_tests(
24run_tests(
25 indicatorsmanagertest
25 indicatorsmanagertest
26 indicatorsmodeltest
26 indicatorsmodeltest
27+ menucontentactivatortest
27 )
28 )
tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp+1−1
@@ -134,5 +134,5 @@ private Q_SLOTS:
134 }
134 }
135};
135};
136
136
137−QTEST_MAIN(IndicatorsManagerTest)
137+QTEST_GUILESS_MAIN(IndicatorsManagerTest)
138#include "indicatorsmanagertest.moc"
138#include "indicatorsmanagertest.moc"
tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp+1−1
@@ -97,6 +97,6 @@ private Q_SLOTS:
97 }
97 }
98};
98};
99
99
100−QTEST_MAIN(IndicatorsModelTest)
100+QTEST_GUILESS_MAIN(IndicatorsModelTest)
101
101
102#include "indicatorsmodeltest.moc"
102#include "indicatorsmodeltest.moc"
tests/plugins/Unity/Indicators/menucontentactivatortest.cppnew file+303
@@ -0,0 +1,303 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#include "menucontentactivator.h"
21+#include "paths.h"
22+
23+#include <QtTest>
24+#include <QDebug>
25+
26+class FakeTimer : public UnityIndicators::AbstractTimer
27+{
28+ Q_OBJECT
29+public:
30+ FakeTimer(QObject *parent = 0)
31+ : UnityIndicators::AbstractTimer(parent)
32+ {}
33+
34+ virtual int interval() const { return m_duration; }
35+ virtual void setInterval(int msecs) { m_duration = msecs; }
36+
37+ void emitTimeout() {
38+ if (isRunning()) {
39+ Q_EMIT timeout();
40+ }
41+ }
42+private:
43+ int m_duration;
44+};
45+
46+
47+class MenuConentActivatorTest : public QObject
48+{
49+ Q_OBJECT
50+private Q_SLOTS:
51+ void init() // called right before each and every test function is executed
52+ {
53+ m_fakeTimeSource = new FakeTimer(this);
54+ m_deltas.clear();
55+ }
56+ void cleanup() // called right after each and every test function is executed
57+ {
58+ delete m_fakeTimeSource;
59+ m_fakeTimeSource = 0;
60+ }
61+
62+ /*
63+ * Tests the ordering of activation
64+ */
65+ void testContentActiveChange()
66+ {
67+ MenuContentActivator activator;
68+ activator.setContentTimer(m_fakeTimeSource);
69+ activator.setCount(10);
70+ activator.setBaseIndex(5);
71+ activator.restart();
72+
73+ QCOMPARE(activator.isMenuContentActive(4), false);
74+ QCOMPARE(activator.isMenuContentActive(5), true); // always active at base index.
75+ QCOMPARE(activator.isMenuContentActive(6), false);
76+
77+ m_fakeTimeSource->emitTimeout();
78+ QCOMPARE(activator.isMenuContentActive(4), false);
79+ QCOMPARE(activator.isMenuContentActive(5), true);
80+ QCOMPARE(activator.isMenuContentActive(6), true);
81+ QCOMPARE(activator.isMenuContentActive(7), false);
82+
83+ m_fakeTimeSource->emitTimeout();
84+ QCOMPARE(activator.isMenuContentActive(3), false);
85+ QCOMPARE(activator.isMenuContentActive(4), true);
86+ QCOMPARE(activator.isMenuContentActive(5), true);
87+ QCOMPARE(activator.isMenuContentActive(6), true);
88+ QCOMPARE(activator.isMenuContentActive(7), false);
89+
90+ m_fakeTimeSource->emitTimeout();
91+ QCOMPARE(activator.isMenuContentActive(3), false);
92+ QCOMPARE(activator.isMenuContentActive(4), true);
93+ QCOMPARE(activator.isMenuContentActive(5), true);
94+ QCOMPARE(activator.isMenuContentActive(6), true);
95+ QCOMPARE(activator.isMenuContentActive(7), true);
96+ QCOMPARE(activator.isMenuContentActive(8), false);
97+
98+ m_fakeTimeSource->emitTimeout();
99+ QCOMPARE(activator.isMenuContentActive(2), false);
100+ QCOMPARE(activator.isMenuContentActive(3), true);
101+ QCOMPARE(activator.isMenuContentActive(4), true);
102+ QCOMPARE(activator.isMenuContentActive(5), true);
103+ QCOMPARE(activator.isMenuContentActive(6), true);
104+ QCOMPARE(activator.isMenuContentActive(7), true);
105+ QCOMPARE(activator.isMenuContentActive(8), false);
106+
107+ m_fakeTimeSource->emitTimeout();
108+ QCOMPARE(activator.isMenuContentActive(2), false);
109+ QCOMPARE(activator.isMenuContentActive(3), true);
110+ QCOMPARE(activator.isMenuContentActive(4), true);
111+ QCOMPARE(activator.isMenuContentActive(5), true);
112+ QCOMPARE(activator.isMenuContentActive(6), true);
113+ QCOMPARE(activator.isMenuContentActive(7), true);
114+ QCOMPARE(activator.isMenuContentActive(8), true);
115+ QCOMPARE(activator.isMenuContentActive(9), false);
116+
117+ m_fakeTimeSource->emitTimeout();
118+ QCOMPARE(activator.isMenuContentActive(1), false);
119+ QCOMPARE(activator.isMenuContentActive(2), true);
120+ QCOMPARE(activator.isMenuContentActive(3), true);
121+ QCOMPARE(activator.isMenuContentActive(4), true);
122+ QCOMPARE(activator.isMenuContentActive(5), true);
123+ QCOMPARE(activator.isMenuContentActive(6), true);
124+ QCOMPARE(activator.isMenuContentActive(7), true);
125+ QCOMPARE(activator.isMenuContentActive(8), true);
126+ QCOMPARE(activator.isMenuContentActive(9), false);
127+
128+ m_fakeTimeSource->emitTimeout();
129+ QCOMPARE(activator.isMenuContentActive(1), false);
130+ QCOMPARE(activator.isMenuContentActive(2), true);
131+ QCOMPARE(activator.isMenuContentActive(3), true);
132+ QCOMPARE(activator.isMenuContentActive(4), true);
133+ QCOMPARE(activator.isMenuContentActive(5), true);
134+ QCOMPARE(activator.isMenuContentActive(6), true);
135+ QCOMPARE(activator.isMenuContentActive(7), true);
136+ QCOMPARE(activator.isMenuContentActive(8), true);
137+ QCOMPARE(activator.isMenuContentActive(9), true);
138+ QCOMPARE(activator.isMenuContentActive(10), false);
139+
140+ m_fakeTimeSource->emitTimeout();
141+ QCOMPARE(activator.isMenuContentActive(0), false);
142+ QCOMPARE(activator.isMenuContentActive(1), true);
143+ QCOMPARE(activator.isMenuContentActive(2), true);
144+ QCOMPARE(activator.isMenuContentActive(3), true);
145+ QCOMPARE(activator.isMenuContentActive(4), true);
146+ QCOMPARE(activator.isMenuContentActive(5), true);
147+ QCOMPARE(activator.isMenuContentActive(6), true);
148+ QCOMPARE(activator.isMenuContentActive(7), true);
149+ QCOMPARE(activator.isMenuContentActive(8), true);
150+ QCOMPARE(activator.isMenuContentActive(9), true);
151+ QCOMPARE(activator.isMenuContentActive(10), false);
152+
153+ m_fakeTimeSource->emitTimeout();
154+ QCOMPARE(activator.isMenuContentActive(-1), false);
155+ QCOMPARE(activator.isMenuContentActive(0), true);
156+ QCOMPARE(activator.isMenuContentActive(1), true);
157+ QCOMPARE(activator.isMenuContentActive(2), true);
158+ QCOMPARE(activator.isMenuContentActive(3), true);
159+ QCOMPARE(activator.isMenuContentActive(4), true);
160+ QCOMPARE(activator.isMenuContentActive(5), true);
161+ QCOMPARE(activator.isMenuContentActive(6), true);
162+ QCOMPARE(activator.isMenuContentActive(7), true);
163+ QCOMPARE(activator.isMenuContentActive(8), true);
164+ QCOMPARE(activator.isMenuContentActive(9), true);
165+ QCOMPARE(activator.isMenuContentActive(10), false);
166+ }
167+
168+ /*
169+ * Tests the delta calculation for each timeout.
170+ */
171+ void testDelta()
172+ {
173+ MenuContentActivator activator;
174+ activator.setContentTimer(m_fakeTimeSource);
175+ activator.setCount(9);
176+ activator.setBaseIndex(3);
177+
178+ connect(&activator, &MenuContentActivator::deltaChanged,
179+ this, &MenuConentActivatorTest::onDeltaChange);
180+ activator.restart();
181+
182+ QCOMPARE(m_deltas, QList<int>()); // empty
183+ QCOMPARE(getIndexList(&activator), QList<int>()); // empty
184+
185+ m_fakeTimeSource->emitTimeout();
186+ QCOMPARE(m_deltas, QList<int>() << 1);
187+ QCOMPARE(getIndexList(&activator), QList<int>() << 4);
188+
189+ m_fakeTimeSource->emitTimeout();
190+ QCOMPARE(m_deltas, QList<int>() << 1 << -1);
191+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2);
192+
193+ m_fakeTimeSource->emitTimeout();
194+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2);
195+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5);
196+
197+ m_fakeTimeSource->emitTimeout();
198+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2);
199+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1);
200+
201+ m_fakeTimeSource->emitTimeout();
202+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3);
203+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6);
204+
205+ m_fakeTimeSource->emitTimeout();
206+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3);
207+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0);
208+
209+ m_fakeTimeSource->emitTimeout();
210+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3 << 4);
211+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0 << 7);
212+
213+ m_fakeTimeSource->emitTimeout();
214+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3 << 4 << 5);
215+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0 << 7 << 8);
216+
217+ m_fakeTimeSource->emitTimeout();
218+ QCOMPARE(m_deltas, QList<int>() << 1 << -1 << 2 << -2 << 3 << -3 << 4 << 5);
219+ QCOMPARE(getIndexList(&activator), QList<int>() << 4 << 2 << 5 << 1 << 6 << 0 << 7 << 8);
220+ }
221+
222+ /*
223+ * Tests that changing the base index re-prioritizes the activation
224+ * around the base index.
225+ */
226+ void testBaseIndexChange()
227+ {
228+ MenuContentActivator activator;
229+ activator.setContentTimer(m_fakeTimeSource);
230+ activator.setCount(12);
231+ activator.setBaseIndex(5);
232+ activator.restart();
233+
234+ m_fakeTimeSource->emitTimeout();
235+ m_fakeTimeSource->emitTimeout();
236+ QCOMPARE(activator.isMenuContentActive(3), false);
237+ QCOMPARE(activator.isMenuContentActive(4), true);
238+ QCOMPARE(activator.isMenuContentActive(5), true); // always active at base index.
239+ QCOMPARE(activator.isMenuContentActive(6), true);
240+ QCOMPARE(activator.isMenuContentActive(7), false);
241+
242+ activator.setBaseIndex(8);
243+ QCOMPARE(activator.isMenuContentActive(3), false);
244+ QCOMPARE(activator.isMenuContentActive(4), true);
245+ QCOMPARE(activator.isMenuContentActive(5), true);
246+ QCOMPARE(activator.isMenuContentActive(6), true);
247+ QCOMPARE(activator.isMenuContentActive(7), false);
248+ QCOMPARE(activator.isMenuContentActive(8), true);
249+ QCOMPARE(activator.isMenuContentActive(9), false);
250+
251+ m_fakeTimeSource->emitTimeout();
252+ QCOMPARE(activator.isMenuContentActive(3), false);
253+ QCOMPARE(activator.isMenuContentActive(4), true);
254+ QCOMPARE(activator.isMenuContentActive(5), true);
255+ QCOMPARE(activator.isMenuContentActive(6), true);
256+ QCOMPARE(activator.isMenuContentActive(7), false);
257+ QCOMPARE(activator.isMenuContentActive(8), true);
258+ QCOMPARE(activator.isMenuContentActive(9), true);
259+ QCOMPARE(activator.isMenuContentActive(10), false);
260+
261+ m_fakeTimeSource->emitTimeout();
262+ QCOMPARE(activator.isMenuContentActive(3), false);
263+ QCOMPARE(activator.isMenuContentActive(4), true);
264+ QCOMPARE(activator.isMenuContentActive(5), true);
265+ QCOMPARE(activator.isMenuContentActive(6), true);
266+ QCOMPARE(activator.isMenuContentActive(7), true);
267+ QCOMPARE(activator.isMenuContentActive(8), true);
268+ QCOMPARE(activator.isMenuContentActive(9), true);
269+ QCOMPARE(activator.isMenuContentActive(10), false);
270+
271+ m_fakeTimeSource->emitTimeout();
272+ QCOMPARE(activator.isMenuContentActive(3), false);
273+ QCOMPARE(activator.isMenuContentActive(4), true);
274+ QCOMPARE(activator.isMenuContentActive(5), true);
275+ QCOMPARE(activator.isMenuContentActive(6), true);
276+ QCOMPARE(activator.isMenuContentActive(7), true);
277+ QCOMPARE(activator.isMenuContentActive(8), true);
278+ QCOMPARE(activator.isMenuContentActive(9), true);
279+ QCOMPARE(activator.isMenuContentActive(10), true);
280+ QCOMPARE(activator.isMenuContentActive(11), false);
281+ }
282+
283+ void onDeltaChange(int delta)
284+ {
285+ m_deltas << delta;
286+ }
287+
288+private:
289+ QList<int> getIndexList(MenuContentActivator* activator)
290+ {
291+ QList<int> list;
292+ Q_FOREACH(int delta, m_deltas) {
293+ list << (activator->baseIndex() + delta);
294+ }
295+ return list;
296+ }
297+
298+ FakeTimer* m_fakeTimeSource;
299+ QList<int> m_deltas;
300+};
301+
302+QTEST_GUILESS_MAIN(MenuConentActivatorTest)
303+#include "menucontentactivatortest.moc"
tests/plugins/Unity/previewbindingstest.cpp−2
@@ -165,5 +165,3 @@ void PreviewBindingsTest::testSocialPreview()
165}
165}
166
166
167QTEST_MAIN(PreviewBindingsTest)
167QTEST_MAIN(PreviewBindingsTest)
168−
169−#include "previewbindingstest.moc"
tests/plugins/Utils/qlimitproxymodeltest.cpp+1−1
@@ -481,6 +481,6 @@ private Q_SLOTS:
481 }
481 }
482};
482};
483
483
484−QTEST_MAIN(QLimitProxyModelTest)
484+QTEST_GUILESS_MAIN(QLimitProxyModelTest)
485
485
486#include "qlimitproxymodeltest.moc"
486#include "qlimitproxymodeltest.moc"
tests/plugins/Utils/qsortfilterproxymodeltest.cpp+1−1
@@ -285,6 +285,6 @@ private Q_SLOTS:
285 }
285 }
286};
286};
287
287
288−QTEST_MAIN(QSortFilterProxyModelTest)
288+QTEST_GUILESS_MAIN(QSortFilterProxyModelTest)
289
289
290#include "qsortfilterproxymodeltest.moc"
290#include "qsortfilterproxymodeltest.moc"
tests/qmltests/CMakeLists.txt+3−2
@@ -25,6 +25,9 @@ add_qml_test(utils/Unity/Test UnityTest)
25set(qmltest_DEFAULT_TARGETS qmluitests)
25set(qmltest_DEFAULT_TARGETS qmluitests)
26set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
26set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
27set(qmltest_DEFAULT_PROPERTIES "")
27set(qmltest_DEFAULT_PROPERTIES "")
28+
29+add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
30+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
28add_qml_test(Components DemoOverlay)
31add_qml_test(Components DemoOverlay)
29add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
32add_manual_qml_test(Components DragHandle IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
30add_qml_test(Components DraggingArea)
33add_qml_test(Components DraggingArea)
@@ -62,10 +65,8 @@ add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_P
62add_qml_test(Panel IndicatorRow)
65add_qml_test(Panel IndicatorRow)
63add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
66add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
64add_qml_test(Panel MenuContent)
67add_qml_test(Panel MenuContent)
65−add_qml_test(Panel Overview)
66add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
68add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
67add_qml_test(Panel SearchIndicator)
69add_qml_test(Panel SearchIndicator)
68−add_qml_test(Panel/Menus IndicatorMenuWindow IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
69add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
70add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
70 ${CMAKE_BINARY_DIR}/tests/mocks
71 ${CMAKE_BINARY_DIR}/tests/mocks
71 ${CMAKE_BINARY_DIR}/plugins)
72 ${CMAKE_BINARY_DIR}/plugins)
tests/qmltests/Components/tst_Stage.qml+1
@@ -161,6 +161,7 @@ Rectangle {
161 applicationManager: fakeAppManager
161 applicationManager: fakeAppManager
162 rightEdgeDraggingAreaWidth: units.gu(2)
162 rightEdgeDraggingAreaWidth: units.gu(2)
163 fullyShown: true
163 fullyShown: true
164+ fullyHidden: false
164 newApplicationScreenshot: FakeApplicationScreenshot {
165 newApplicationScreenshot: FakeApplicationScreenshot {
165 id: newAppScreenshot
166 id: newAppScreenshot
166 parent: stage
167 parent: stage
tests/qmltests/Dash/tst_Dash.qml+4−4
@@ -38,8 +38,8 @@ Item {
38 scopeDelegateMapping: {
38 scopeDelegateMapping: {
39 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
39 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
40 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
40 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
41− "MockScope3": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
41+ "home.scope": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
42− "MockScope4": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
42+ "applications.scope": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
43 }
43 }
44 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
44 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
45 }
45 }
@@ -69,8 +69,8 @@ Item {
69 return [
69 return [
70 { tag: "MockScope1", visualIndex: 0, shouldBeVisible: true },
70 { tag: "MockScope1", visualIndex: 0, shouldBeVisible: true },
71 { tag: "MockScope2", visualIndex: -1, shouldBeVisible: false },
71 { tag: "MockScope2", visualIndex: -1, shouldBeVisible: false },
72− { tag: "MockScope3", visualIndex: 1, shouldBeVisible: true },
72+ { tag: "home.scope", visualIndex: 1, shouldBeVisible: true },
73− { tag: "MockScope4", visualIndex: 2, shouldBeVisible: true },
73+ { tag: "applications.scope", visualIndex: 2, shouldBeVisible: true },
74 { tag: "MockScope5", visualIndex: 3, shouldBeVisible: true },
74 { tag: "MockScope5", visualIndex: 3, shouldBeVisible: true },
75 ]
75 ]
76 }
76 }
tests/qmltests/Dash/tst_DashContent.qml+12−12
@@ -31,8 +31,8 @@ Item {
31 property var scopeStatus: {
31 property var scopeStatus: {
32 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
32 'MockScope1': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
33 'MockScope2': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
33 'MockScope2': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
34− 'MockScope3': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
34+ 'home.scope': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
35− 'MockScope4': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
35+ 'applications.scope': { 'movementStarted': 0, 'positionedAtBeginning': 0 },
36 'MockScope5': { 'movementStarted': 0, 'positionedAtBeginning': 0 }
36 'MockScope5': { 'movementStarted': 0, 'positionedAtBeginning': 0 }
37 }
37 }
38
38
@@ -55,8 +55,8 @@ Item {
55 scopeDelegateMapping: {
55 scopeDelegateMapping: {
56 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
56 "MockScope1": "../tests/qmltests/Dash/qml/fake_scopeView1.qml",
57 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
57 "MockScope2": "../tests/qmltests/Dash/qml/fake_scopeView2.qml",
58− "MockScope3": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
58+ "home.scope": "../tests/qmltests/Dash/qml/fake_scopeView3.qml",
59− "MockScope4": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
59+ "applications.scope": "../tests/qmltests/Dash/qml/fake_scopeView4.qml"
60 }
60 }
61 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
61 genericScope: "../tests/qmltests/Dash/qml/fake_generic_scopeView.qml"
62 }
62 }
@@ -68,11 +68,11 @@ Item {
68 scopeStatus["MockScope2"].movementStarted = 0;
68 scopeStatus["MockScope2"].movementStarted = 0;
69 scopeStatus["MockScope2"].positionedAtBeginning = 0;
69 scopeStatus["MockScope2"].positionedAtBeginning = 0;
70
70
71− scopeStatus["MockScope3"].movementStarted = 0;
71+ scopeStatus["home.scope"].movementStarted = 0;
72− scopeStatus["MockScope3"].positionedAtBeginning = 0;
72+ scopeStatus["home.scope"].positionedAtBeginning = 0;
73
73
74− scopeStatus["MockScope4"].movementStarted = 0;
74+ scopeStatus["applications.scope"].movementStarted = 0;
75− scopeStatus["MockScope4"].positionedAtBeginning = 0;
75+ scopeStatus["applications.scope"].positionedAtBeginning = 0;
76
76
77 scopeStatus["MockScope5"].movementStarted = 0;
77 scopeStatus["MockScope5"].movementStarted = 0;
78 scopeStatus["MockScope5"].positionedAtBeginning = 0;
78 scopeStatus["MockScope5"].positionedAtBeginning = 0;
@@ -127,8 +127,8 @@ Item {
127 compare(movementStartedSpy.count, 1, "DashContent should have emitted movementStarted signal when content list did.");
127 compare(movementStartedSpy.count, 1, "DashContent should have emitted movementStarted signal when content list did.");
128 compare(scopeStatus["MockScope1"].movementStarted, 1, "MockScope1 should have emitted movementStarted signal when content list did.");
128 compare(scopeStatus["MockScope1"].movementStarted, 1, "MockScope1 should have emitted movementStarted signal when content list did.");
129 compare(scopeStatus["MockScope2"].movementStarted, 1, "MockScope2 should have emitted movementStarted signal when content list did.");
129 compare(scopeStatus["MockScope2"].movementStarted, 1, "MockScope2 should have emitted movementStarted signal when content list did.");
130− compare(scopeStatus["MockScope3"].movementStarted, 1, "MockScope3 should have emitted movementStarted signal when content list did.");
130+ compare(scopeStatus["home.scope"].movementStarted, 1, "home.scope should have emitted movementStarted signal when content list did.");
131− compare(scopeStatus["MockScope4"].movementStarted, 1, "MockScope4 should have emitted movementStarted signal when content list did.");
131+ compare(scopeStatus["applications.scope"].movementStarted, 1, "applications.scope should have emitted movementStarted signal when content list did.");
132 compare(scopeStatus["MockScope5"].movementStarted, 1, "MockScope5 should have emitted movementStarted signal when content list did.");
132 compare(scopeStatus["MockScope5"].movementStarted, 1, "MockScope5 should have emitted movementStarted signal when content list did.");
133 }
133 }
134
134
@@ -140,8 +140,8 @@ Item {
140 dashContent.positionedAtBeginning();
140 dashContent.positionedAtBeginning();
141 compare(scopeStatus["MockScope1"].positionedAtBeginning, 1, "MockScope1 should have emitted positionedAtBeginning signal when DashContent did.");
141 compare(scopeStatus["MockScope1"].positionedAtBeginning, 1, "MockScope1 should have emitted positionedAtBeginning signal when DashContent did.");
142 compare(scopeStatus["MockScope2"].positionedAtBeginning, 1, "MockScope2 should have emitted positionedAtBeginning signal when DashContent did.");
142 compare(scopeStatus["MockScope2"].positionedAtBeginning, 1, "MockScope2 should have emitted positionedAtBeginning signal when DashContent did.");
143− compare(scopeStatus["MockScope3"].positionedAtBeginning, 1, "MockScope3 should have emitted positionedAtBeginning signal when DashContent did.");
143+ compare(scopeStatus["home.scope"].positionedAtBeginning, 1, "home.scope should have emitted positionedAtBeginning signal when DashContent did.");
144− compare(scopeStatus["MockScope4"].positionedAtBeginning, 1, "MockScope4 should have emitted positionedAtBeginning signal when DashContent did.");
144+ compare(scopeStatus["applications.scope"].positionedAtBeginning, 1, "applications.scope should have emitted positionedAtBeginning signal when DashContent did.");
145 compare(scopeStatus["MockScope5"].positionedAtBeginning, 1, "MockScope5 should have emitted positionedAtBeginning signal when DashContent did.");
145 compare(scopeStatus["MockScope5"].positionedAtBeginning, 1, "MockScope5 should have emitted positionedAtBeginning signal when DashContent did.");
146 }
146 }
147
147
tests/qmltests/Notifications/tst_Notifications.qml+20−9
@@ -48,6 +48,7 @@ Row {
48 function addSnapDecisionNotification() {
48 function addSnapDecisionNotification() {
49 var n = {
49 var n = {
50 type: Notification.SnapDecision,
50 type: Notification.SnapDecision,
51+ hints: Notification.ButtonTint,
51 summary: "Tom Ato",
52 summary: "Tom Ato",
52 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
53 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
53 icon: "../graphics/avatars/funky.png",
54 icon: "../graphics/avatars/funky.png",
@@ -189,8 +190,9 @@ Row {
189 function test_NotificationRenderer_data() {
190 function test_NotificationRenderer_data() {
190 return [
191 return [
191 {
192 {
192− tag: "Snap Decision with secondary icon",
193+ tag: "Snap Decision with secondary icon and button-tint",
193 type: Notification.SnapDecision,
194 type: Notification.SnapDecision,
195+ hints: Notification.ButtonTint,
194 summary: "Tom Ato",
196 summary: "Tom Ato",
195 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
197 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
196 icon: "../graphics/avatars/funky.png",
198 icon: "../graphics/avatars/funky.png",
@@ -205,7 +207,8 @@ Row {
205 interactiveAreaEnabled: false,
207 interactiveAreaEnabled: false,
206 iconVisible: true,
208 iconVisible: true,
207 secondaryIconVisible: true,
209 secondaryIconVisible: true,
208− buttonRowVisible: true
210+ buttonRowVisible: true,
211+ buttonTinted: true
209 },
212 },
210 {
213 {
211 tag: "Ephemeral notification - icon-summary layout",
214 tag: "Ephemeral notification - icon-summary layout",
@@ -220,7 +223,8 @@ Row {
220 interactiveAreaEnabled: false,
223 interactiveAreaEnabled: false,
221 iconVisible: false,
224 iconVisible: false,
222 secondaryIconVisible: true,
225 secondaryIconVisible: true,
223− buttonRowVisible: false
226+ buttonRowVisible: false,
227+ buttonTinted: false
224 },
228 },
225 {
229 {
226 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
230 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
@@ -235,7 +239,8 @@ Row {
235 interactiveAreaEnabled: false,
239 interactiveAreaEnabled: false,
236 iconVisible: false,
240 iconVisible: false,
237 secondaryIconVisible: true,
241 secondaryIconVisible: true,
238− buttonRowVisible: false
242+ buttonRowVisible: false,
243+ buttonTinted: false
239 },
244 },
240 {
245 {
241 tag: "Interactive notification",
246 tag: "Interactive notification",
@@ -250,10 +255,11 @@ Row {
250 interactiveAreaEnabled: true,
255 interactiveAreaEnabled: true,
251 iconVisible: true,
256 iconVisible: true,
252 secondaryIconVisible: false,
257 secondaryIconVisible: false,
253− buttonRowVisible: false
258+ buttonRowVisible: false,
259+ buttonTinted: false
254 },
260 },
255 {
261 {
256− tag: "Snap Decision without secondary icon",
262+ tag: "Snap Decision without secondary icon and no button-tint",
257 type: Notification.SnapDecision,
263 type: Notification.SnapDecision,
258 summary: "Bro Coly",
264 summary: "Bro Coly",
259 body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
265 body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
@@ -266,7 +272,8 @@ Row {
266 interactiveAreaEnabled: false,
272 interactiveAreaEnabled: false,
267 iconVisible: true,
273 iconVisible: true,
268 secondaryIconVisible: false,
274 secondaryIconVisible: false,
269− buttonRowVisible: true
275+ buttonRowVisible: true,
276+ buttonTinted: false
270 },
277 },
271 {
278 {
272 tag: "Ephemeral notification",
279 tag: "Ephemeral notification",
@@ -281,7 +288,8 @@ Row {
281 interactiveAreaEnabled: false,
288 interactiveAreaEnabled: false,
282 iconVisible: true,
289 iconVisible: true,
283 secondaryIconVisible: true,
290 secondaryIconVisible: true,
284− buttonRowVisible: false
291+ buttonRowVisible: false,
292+ buttonTinted: false
285 }
293 }
286 ]
294 ]
287 }
295 }
@@ -356,6 +364,9 @@ Row {
356 actionSpy.clear()
364 actionSpy.clear()
357 }
365 }
358
366
367+ // check the tinting of the positive/right button
368+ verify(buttonAccept.gradient === data.buttonTinted ? UbuntuColors.orangeGradient : UbuntuColors.greyGradient, "button has the wrong color-tint")
369+
359 // click the positive/right button
370 // click the positive/right button
360 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
371 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
361 actionSpy.wait()
372 actionSpy.wait()
@@ -370,7 +381,7 @@ Row {
370 mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
381 mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
371 waitForRendering(notification)
382 waitForRendering(notification)
372 actionSpy.clear()
383 actionSpy.clear()
373− 
384+
374 // test the additional buttons
385 // test the additional buttons
375 for (var i = 2; i < data.actions.length; i++) {
386 for (var i = 2; i < data.actions.length; i++) {
376 waitForRendering(notification)
387 waitForRendering(notification)
tests/qmltests/Panel/Menus/tst_IndicatorMenuWindow.qmldeleted−68
@@ -1,68 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import "../.."
20−import "../../../../Panel/Menus"
21−import Ubuntu.Components 0.1
22−import Unity.Test 0.1 as UT
23−
24−Item {
25− id: testIndicatorMenuWindowItem
26− width: units.gu(9)
27− height: units.gu(3)
28−
29− MouseArea {
30− id: mouseArea
31− anchors.fill: parent
32− }
33−
34− IndicatorMenuWindow {
35− id: indicatorMenuWindow
36− name: "TestIndicatorMenuWindow"
37− anchors.fill: parent
38− }
39−
40− UT.UnityTestCase {
41− name: "IndicatorMenuWindow"
42− when: windowShown
43−
44− function test_mouseEvent_data() {
45− return [
46− {tag: "visible", shown: true, opacity: 1.0, mouseClicks: 0},
47− {tag: "invisible", shown: false, opacity: 0.0, mouseClicks: 1},
48− ]
49− }
50−
51− function test_mouseEvent(data) {
52− indicatorMenuWindow.shown = data.shown
53− tryCompare(indicatorMenuWindow, "opacity", data.opacity)
54−
55− clickedSpy.clear()
56− mouseClick(indicatorMenuWindow, indicatorMenuWindow.width / 2,
57− indicatorMenuWindow.height / 2)
58− compare(clickedSpy.count, data.mouseClicks,
59− "Check for Mouse event eating by indicatorMenuWindow failed")
60− }
61− }
62−
63− SignalSpy {
64− id: clickedSpy
65− target: mouseArea
66− signalName: "clicked"
67− }
68−}
tests/qmltests/Panel/tst_IndicatorItem.qml+10−16
@@ -34,34 +34,28 @@ Rectangle {
34 UT.UnityTestCase {
34 UT.UnityTestCase {
35 name: "IndicatorItem"
35 name: "IndicatorItem"
36
36
37− function init_test() {
38− }
39−
40 function test_dimmed() {
37 function test_dimmed() {
41− init_test()
42−
43− indicatorItem.dimmed = true
38+ indicatorItem.dimmed = false;
44− compare(indicatorItem.opacity > 0, true, "IndicatorItem opacity should not be 0")
39+ tryCompareFunction(function(){return indicatorItem.opacity}, 1.0);
40+ indicatorItem.dimmed = true;
45− compare(indicatorItem.opacity < 1, true, "IndicatorItem opacity should not be 1")
41+ tryCompareFunction(function(){return indicatorItem.opacity < 1.0}, true);
46 }
42 }
47
43
48 function test_highlight() {
44 function test_highlight() {
49− var itemHighlight = findChild(indicatorItem, "highlight")
45+ var itemHighlight = findChild(indicatorItem, "highlight");
50− verify(itemHighlight != undefined)
46+ verify(itemHighlight != undefined);
51
47
52 indicatorItem.highlighted = true;
48 indicatorItem.highlighted = true;
53− compare(itemHighlight.visible, true, "Indicator should be highlighted")
49+ compare(itemHighlight.visible, true, "Indicator should be highlighted");
54
50
55 indicatorItem.highlighted = false;
51 indicatorItem.highlighted = false;
56− compare(itemHighlight.visible, false, "Indicator should not be highlighted")
52+ compare(itemHighlight.visible, false, "Indicator should not be highlighted");
57 }
53 }
58
54
59 function test_empty() {
55 function test_empty() {
60− init_test()
61−
62− compare(indicatorItem.visible, false, "IndicatorItem should not be visible.")
56+ compare(indicatorItem.visible, false, "IndicatorItem should not be visible.");
63 indicatorItem.widgetSource = "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
57 indicatorItem.widgetSource = "qrc:/tests/indciators/qml/fake_menu_widget1.qml";
64− tryCompare(indicatorItem, "visible", true)
58+ tryCompare(indicatorItem, "visible", true);
65 }
59 }
66 }
60 }
67}
61}
tests/qmltests/Panel/tst_IndicatorRow.qml+21−35
@@ -32,7 +32,6 @@ Item {
32
32
33 function init_test()
33 function init_test()
34 {
34 {
35− indicatorRow.overviewActive = false;
36 indicatorRow.state = "initial";
35 indicatorRow.state = "initial";
37 indicatorRow.currentItem = null;
36 indicatorRow.currentItem = null;
38 }
37 }
@@ -62,13 +61,13 @@ Item {
62
61
63 function test_set_current_item() {
62 function test_set_current_item() {
64 init_test();
63 init_test();
65− indicatorRow.setItem(0);
64+ indicatorRow.setCurrentItem(0);
66 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu1", "Incorrect item at position 0");
65 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu1", "Incorrect item at position 0");
67
66
68− indicatorRow.setItem(1);
67+ indicatorRow.setCurrentItem(1);
69 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu2", "Incorrect item at position 1");
68 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu2", "Incorrect item at position 1");
70
69
71− indicatorRow.setItem(2);
70+ indicatorRow.setCurrentItem(2);
72 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu3", "Incorrect item at position 2");
71 compare(indicatorRow.indicatorsModel.get(indicatorRow.currentItemIndex).title, "Menu3", "Incorrect item at position 2");
73 }
72 }
74 }
73 }
@@ -84,13 +83,13 @@ Item {
84 function test_current_item_commit() {
83 function test_current_item_commit() {
85 init_test();
84 init_test();
86
85
87− indicatorRow.setItem(1);
86+ indicatorRow.setCurrentItem(1);
88 indicatorRow.state = "commit";
87 indicatorRow.state = "commit";
89− tryCompare(get_indicator_item_at(0), "y", -indicatorRow.height);
88+ tryCompare(get_indicator_item_at(0), "opacity", 0.0);
90− tryCompare(get_indicator_item_at(1), "y", 0);
89+ tryCompare(get_indicator_item_at(1), "opacity", 1.0);
91− tryCompare(get_indicator_item_at(2), "y", -indicatorRow.height);
90+ tryCompare(get_indicator_item_at(2), "opacity", 0.0);
92− tryCompare(get_indicator_item_at(3), "y", -indicatorRow.height);
91+ tryCompare(get_indicator_item_at(3), "opacity", 0.0);
93− tryCompare(get_indicator_item_at(4), "y", -indicatorRow.height);
92+ tryCompare(get_indicator_item_at(4), "opacity", 0.0);
94
93
95 }
94 }
96 }
95 }
@@ -107,7 +106,7 @@ Item {
107 init_test();
106 init_test();
108
107
109 indicatorRow.state = "initial";
108 indicatorRow.state = "initial";
110− indicatorRow.setItem(0);
109+ indicatorRow.setCurrentItem(0);
111
110
112 compare(indicatorRow.currentItem.highlighted, false, "Indicator should not highlight when in initial state");
111 compare(indicatorRow.currentItem.highlighted, false, "Indicator should not highlight when in initial state");
113 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in initial state");
112 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in initial state");
@@ -120,9 +119,9 @@ Item {
120 init_test();
119 init_test();
121
120
122 indicatorRow.state = "hint";
121 indicatorRow.state = "hint";
123− indicatorRow.setItem(0);
122+ indicatorRow.setCurrentItem(0);
124
123
125− compare(indicatorRow.currentItem.highlighted, false, "Indicator should not highlight when in hint state");
124+ compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in hint state");
126 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in hint state");
125 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in hint state");
127 compare(get_indicator_item_at(2).highlighted, false, "Other indicators should not highlight when in hint state");
126 compare(get_indicator_item_at(2).highlighted, false, "Other indicators should not highlight when in hint state");
128 compare(get_indicator_item_at(3).highlighted, false, "Other indicators should not highlight when in hint state");
127 compare(get_indicator_item_at(3).highlighted, false, "Other indicators should not highlight when in hint state");
@@ -133,7 +132,7 @@ Item {
133 init_test();
132 init_test();
134
133
135 indicatorRow.state = "reveal";
134 indicatorRow.state = "reveal";
136− indicatorRow.setItem(0);
135+ indicatorRow.setCurrentItem(0);
137
136
138 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in reveal state");
137 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in reveal state");
139 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
138 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
@@ -146,7 +145,7 @@ Item {
146 init_test();
145 init_test();
147
146
148 indicatorRow.state = "commit";
147 indicatorRow.state = "commit";
149− indicatorRow.setItem(0);
148+ indicatorRow.setCurrentItem(0);
150
149
151 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in commit state");
150 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in commit state");
152 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
151 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in commit state");
@@ -159,7 +158,7 @@ Item {
159 init_test();
158 init_test();
160
159
161 indicatorRow.state = "locked";
160 indicatorRow.state = "locked";
162− indicatorRow.setItem(0);
161+ indicatorRow.setCurrentItem(0);
163
162
164 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in locked state");
163 compare(indicatorRow.currentItem.highlighted, true, "Indicator should highlight when in locked state");
165 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in locked state");
164 compare(get_indicator_item_at(1).highlighted, false, "Other indicators should not highlight when in locked state");
@@ -181,7 +180,7 @@ Item {
181 init_test();
180 init_test();
182
181
183 indicatorRow.state = "initial";
182 indicatorRow.state = "initial";
184− indicatorRow.setItem(0);
183+ indicatorRow.setCurrentItem(0);
185
184
186 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in intiial state");
185 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in intiial state");
187 compare(get_indicator_item_at(1).dimmed, false, "Other indicators should not dim when in initial state");
186 compare(get_indicator_item_at(1).dimmed, false, "Other indicators should not dim when in initial state");
@@ -194,9 +193,9 @@ Item {
194 init_test();
193 init_test();
195
194
196 indicatorRow.state = "hint";
195 indicatorRow.state = "hint";
197− indicatorRow.setItem(0);
196+ indicatorRow.setCurrentItem(0);
198
197
199− compare(get_indicator_item_at(0).dimmed, true, "Current indicator should dim when in hint state");
198+ compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in hint state");
200 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in hint state");
199 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in hint state");
201 compare(get_indicator_item_at(2).dimmed, true, "Other indicators should dim when in hint state");
200 compare(get_indicator_item_at(2).dimmed, true, "Other indicators should dim when in hint state");
202 compare(get_indicator_item_at(3).dimmed, true, "Other indicators should dim when in hint state");
201 compare(get_indicator_item_at(3).dimmed, true, "Other indicators should dim when in hint state");
@@ -207,7 +206,7 @@ Item {
207 init_test();
206 init_test();
208
207
209 indicatorRow.state = "reveal";
208 indicatorRow.state = "reveal";
210− indicatorRow.setItem(0);
209+ indicatorRow.setCurrentItem(0);
211
210
212 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in reveal state");
211 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in reveal state");
213 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in reveal state");
212 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in reveal state");
@@ -220,7 +219,7 @@ Item {
220 init_test();
219 init_test();
221
220
222 indicatorRow.state = "commit";
221 indicatorRow.state = "commit";
223− indicatorRow.setItem(0);
222+ indicatorRow.setCurrentItem(0);
224
223
225 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in commit state");
224 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in commit state");
226 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in commit state");
225 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in commit state");
@@ -233,7 +232,7 @@ Item {
233 init_test();
232 init_test();
234
233
235 indicatorRow.state = "locked";
234 indicatorRow.state = "locked";
236− indicatorRow.setItem(0);
235+ indicatorRow.setCurrentItem(0);
237
236
238 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in locked state");
237 compare(get_indicator_item_at(0).dimmed, false, "Current indicator should not dim when in locked state");
239 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in locked state");
238 compare(get_indicator_item_at(1).dimmed, true, "Other indicators should dim when in locked state");
@@ -241,18 +240,5 @@ Item {
241 compare(get_indicator_item_at(3).dimmed, true, "Other indicators should dim when in locked state");
240 compare(get_indicator_item_at(3).dimmed, true, "Other indicators should dim when in locked state");
242 compare(get_indicator_item_at(4).dimmed, true, "Other indicators should dim when in locked state");
241 compare(get_indicator_item_at(4).dimmed, true, "Other indicators should dim when in locked state");
243 }
242 }
244−
245− function test_active_overview() {
246− init_test();
247−
248− indicatorRow.overviewActive = true;
249− indicatorRow.state = "commit";
250−
251− compare(get_indicator_item_at(0).dimmed, true, "Indicator should dim when in overview");
252− compare(get_indicator_item_at(1).dimmed, true, "Indicator should dim when in overview");
253− compare(get_indicator_item_at(2).dimmed, true, "Indicator should dim when in overview");
254− compare(get_indicator_item_at(3).dimmed, true, "Indicator should dim when in overview");
255− compare(get_indicator_item_at(4).dimmed, true, "Indicator should dim when in overview");
256− }
257 }
243 }
258}
244}
tests/qmltests/Panel/tst_Indicators.qml+1−39
@@ -69,7 +69,6 @@ Item {
69
69
70 onClicked: {
70 onClicked: {
71 if (!indicators.shown) {
71 if (!indicators.shown) {
72− indicators.openOverview();
73 indicators.show();
72 indicators.show();
74 } else {
73 } else {
75 indicators.hide();
74 indicators.hide();
@@ -89,47 +88,10 @@ Item {
89 tryCompare(indicators, "state", "initial");
88 tryCompare(indicators, "state", "initial");
90 }
89 }
91
90
92− // Showing the indicators should fully open the indicator panel with the overview menu visible.
91+ // Showing the indicators should fully open the indicator panel.
93 function test_show() {
92 function test_show() {
94 indicators.show()
93 indicators.show()
95 tryCompare(indicators, "fullyOpened", true);
94 tryCompare(indicators, "fullyOpened", true);
96−
97− // A show must open the indicators.
98− compare(findChild(indicators, "indicatorRow").overviewActive, true, "Overview indicator should be active when opened overview.")
99− }
100−
101− // Opening the overview menu will activate the overview panel.
102− function test_open_overview() {
103− indicators.openOverview();
104− compare(findChild(indicators, "indicatorRow").overviewActive, true, "Overview should be active when opened overview.")
105− }
106−
107− // Showing the indicators, then changing the progress (simulating drag) should keep the overview panel open until
108− // the reveal state is reached.
109− function test_slow_close_open_overview() {
110−
111− var indicator_row = findChild(indicators, "indicatorRow");
112− verify(indicator_row != undefined);
113−
114− indicators.show()
115− // wait for animation to end. (progress needs to be updated)
116− tryCompare(indicators.showAnimation, "running", false);
117− compare(indicator_row.overviewActive, true, "Overview should be active when opened overview.")
118−
119− // iteratively decrease the progress and ensure that it keeps the correct behaviour
120− var current_progress = indicators.progress - shell.height/20;
121− while (current_progress > 0) {
122− indicators.progress = current_progress;
123−
124− if (indicators.state == "commit" || indicators.state == "locked") {
125− compare(indicator_row.overviewActive, true, "Overview should be active when in locked or commit state after show.")
126− }
127− else if (indicators.state == "reveal" || indicators.state == "hint") {
128− compare(indicator_row.overviewActive, false, "Overview should be not active when not in commit or locked state.")
129− }
130−
131− current_progress = current_progress - shell.height/20;
132− }
133 }
95 }
134
96
135 // Test the change in the revealer lateral position changes the current panel menu to fit the position
97 // Test the change in the revealer lateral position changes the current panel menu to fit the position
tests/qmltests/Panel/tst_MenuContent.qml+14−84
@@ -52,8 +52,8 @@ Item {
52 height: parent.height - 50
52 height: parent.height - 50
53 }
53 }
54
54
55− Item {
55+ Rectangle {
56− id: click_me
56+ color: "#bbbbbb"
57
57
58 height: 50
58 height: 50
59 anchors {
59 anchors {
@@ -62,65 +62,30 @@ Item {
62 right: parent.right
62 right: parent.right
63 }
63 }
64
64
65− Rectangle {
65+ Text {
66− color: "#999999"
66+ text: "Next Indicator"
67−
68− anchors {
69− top: parent.top
70− left: parent.left
71− right: parent.horizontalCenter
72− bottom: parent.bottom
73− }
74−
75− Text {
76− text: "Devices"
77− anchors.fill: parent
67+ anchors.fill: parent
78− horizontalAlignment: Text.AlignHCenter
68+ horizontalAlignment: Text.AlignHCenter
79− verticalAlignment: Text.AlignVCenter
69+ verticalAlignment: Text.AlignVCenter
80− }
81−
82− MouseArea {
83− anchors.fill: parent
84− onClicked: menuContent.showOverview()
85− }
86 }
70 }
87
71
88− Rectangle {
89− color: "#bbbbbb"
90−
91− anchors {
92− top: parent.top
93− left: parent.horizontalCenter
94− right: parent.right
95− bottom: parent.bottom
96− }
97−
98− Text {
99− text: "Next Indicator"
100− anchors.fill: parent
101− horizontalAlignment: Text.AlignHCenter
102− verticalAlignment: Text.AlignVCenter
103− }
104−
105− MouseArea {
72+ MouseArea {
106− anchors.fill: parent
73+ anchors.fill: parent
107− onClicked: activate_next_content()
74+ onClicked: activate_next_content()
108− }
109 }
75 }
110 }
76 }
111
77
112 function activate_next_content()
78 function activate_next_content()
113 {
79 {
114− if (menuContent.currentIndex == -1)
80+ if (menuContent.currentMenuIndex == -1)
115 activate_content(0);
81 activate_content(0);
116 else
82 else
117− activate_content((menuContent.currentIndex + 1) % indicatorsModel.count)
83+ activate_content((menuContent.currentMenuIndex + 1) % indicatorsModel.count)
118 }
84 }
119
85
120 function activate_content(index)
86 function activate_content(index)
121 {
87 {
122− menuContent.currentIndex = index
88+ menuContent.currentMenuIndex = index
123− menuContent.showMenu();
124 }
89 }
125
90
126 function get_test_menu_objecName(index) {
91 function get_test_menu_objecName(index) {
@@ -151,7 +116,6 @@ Item {
151 when: windowShown
116 when: windowShown
152
117
153 function init() {
118 function init() {
154− menuContent.hideAll();
155 if (menuContent.__contentActive)
119 if (menuContent.__contentActive)
156 menuContent.releaseContent();
120 menuContent.releaseContent();
157 tryCompare(menuContent, "__contentActive", false);
121 tryCompare(menuContent, "__contentActive", false);
@@ -174,40 +138,6 @@ Item {
174 compare(menus.currentIndex, menu_index, "Current menu index does not match selected menu index");
138 compare(menus.currentIndex, menu_index, "Current menu index does not match selected menu index");
175 tryCompareFunction(current_menu_equals_test_menu, true);
139 tryCompareFunction(current_menu_equals_test_menu, true);
176 }
140 }
177− // overview should not be visible.
178− tryCompare(findChild(menuContent, "overview"), "visible", false);
179− }
180−
181− function test_show_overview() {
182− menuContent.showOverview();
183−
184− var overview = findChild(menuContent, "overview");
185− tryCompare(overview, "visible", true);
186− tryCompare(overview, "enabled", true);
187− tryCompare(overview, "opacity", 1.0);
188−
189− // menus should not be enabled.
190− tryCompare(findChild(menuContent, "menus"), "opacity", 0);
191− tryCompare(findChild(menuContent, "menus"), "enabled", false);
192− }
193−
194− function test_overview_menuSelected_signal() {
195− menuContent.showOverview();
196−
197− var overview = findChild(menuContent, "overview");
198− var menus = menu_content_test.findChild(menuContent, "menus")
199−
200− var menu_count = indicatorsModel.count;
201− verify(menu_count > 0, "Menu count should be greater than zero");
202− for (var i = 0; i < menu_count; i++) {
203− // manually emit signal from overview.
204− // we dont want to go with mouse events here, otherwise we're testing the overview and not the signal.
205− overview.menuSelected(i);
206−
207− test_menu_objectName = get_test_menu_objecName(i);
208− compare(menus.currentIndex, i, "Current menu index does not match selected menu index");
209− tryCompareFunction(current_menu_equals_test_menu, true);
210− }
211 }
141 }
212
142
213 // Calling activateContent should call start on all menus
143 // Calling activateContent should call start on all menus
@@ -267,7 +197,7 @@ Item {
267
197
268 for (var i = 0; i < 100; i++) {
198 for (var i = 0; i < 100; i++) {
269 activate_content(i % menu_count);
199 activate_content(i % menu_count);
270− compare(menuContent.currentIndex, i%menu_count);
200+ compare(menuContent.currentMenuIndex, i%menu_count);
271 }
201 }
272 wait(100);
202 wait(100);
273 }
203 }
tests/qmltests/Panel/tst_Overview.qmldeleted−142
@@ -1,142 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import ".."
20−import "../../../Panel/Menus"
21−import "../../../Components"
22−import Unity.Test 0.1 as UT
23−import Unity.Indicators 0.1 as Indicators
24−
25−Rectangle {
26− id: shell
27− width: units.gu(40)
28− height: units.gu(80)
29− color: "black"
30−
31− Overview {
32− id: overview
33− anchors.fill: parent
34− indicatorsModel: mockModel
35− shown: true
36− }
37−
38− Item {
39− id: volumeControl
40− property int volume
41− function volumeUp() {
42− volume = Math.min(100, volume + 10);
43− }
44− function volumeDown() {
45− volume = Math.max(0, volume - 10);
46− }
47− }
48−
49− ListModel {
50− id: mockModel
51− ListElement {title: "fake1"; widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget1.qml"; indicatorProperties: ""}
52− ListElement {title: "fake2"; widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget2.qml"; indicatorProperties: ""}
53− ListElement {title: "fake3"; widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget3.qml"; indicatorProperties: ""}
54− }
55−
56− ListModel {
57− id: mockModel2
58− }
59−
60− SignalSpy {
61− id: clickSpy
62− target: overview
63− signalName: "menuSelected"
64− }
65−
66− UT.UnityTestCase {
67− name: "Overview"
68− when: windowShown
69−
70− function initTestCase() {
71− // Spin the event loop once because the UI builds up delayed
72− wait(0);
73− }
74−
75− function test_menuSelected() {
76− overview.indicatorsModel = mockModel;
77−
78− for (var i = 0; i < mockModel.count; ++i) {
79− var button = findChild(overview, "overviewGridButton" + i);
80− clickSpy.clear();
81− mouseClick(button, button.width / 2, button.height / 2);
82− compare(clickSpy.count, 1, "Clicking on grid didn't work");
83− compare(clickSpy.signalArguments[0][0], i, "Clicking the grid returned a wrong index");
84− }
85− }
86−
87− function test_dynamic_addition() {
88− var overviewGrid = findChild(overview, "overviewGrid");
89−
90− for(var i = 0; i < mockModel.count; ++i) {
91− mockModel2.append(mockModel.get(i));
92− }
93− overview.indicatorsModel = mockModel2;
94− overviewGrid.forceLayout();
95− waitForRendering(overviewGrid);
96−
97− var button = findChild(overview, "overviewGridButton2");
98− verify(button !== undefined, "button2 wasn't found");
99− button = findChild(overview, "overviewGridButton3");
100− compare(button, undefined, "There should only be 3 buttons... found at least 4...");
101−
102− mockModel2.append({title: "humppa", widgetSource: "qrc:/tests/indciators/qml/fake_menu_widget4.qml", indicatorProperties: ""})
103− overviewGrid.forceLayout();
104− waitForRendering(overviewGrid);
105−
106− button = findChild(overview, "overviewGridButton3");
107− verify(button !== undefined, "button3 wasn't found");
108− }
109−
110− function test_volume_slider_data() {
111− return [
112− {tag: "0%", sliderPos:0},
113− {tag: "100%", sliderPos: 100},
114− {tag: "50%", sliderPos: 50}
115− ];
116− }
117−
118− function test_volume_slider(data) {
119− var volumeSlider = findChild(overview, "volumeSlider");
120− var startX = volumeSlider.width * volumeSlider.value / 100;
121− var startY = volumeSlider.y + volumeSlider.height / 2;
122− var stopX = (volumeSlider.width - units.gu(5)) * data.sliderPos / 100;
123− var stopY = volumeSlider.y + volumeSlider.height / 2;
124− mouseFlick(volumeSlider, startX, startY, stopX, stopY, true, true, 0.1);
125− }
126−
127− function test_volume_buttons(data) {
128− var volumeDownButton = findChild(overview, "minVolumeIcon");
129− var volumeUpButton = findChild(overview, "maxVolumeIcon");
130−
131− for (var i = 0; i < 10; ++i) {
132− mouseClick(volumeDownButton, volumeDownButton.width / 2, volumeDownButton.height / 2);
133− wait(0)
134− }
135− tryCompare(volumeControl, "volume", 0);
136− for (var i = 0; i < 10; ++i) {
137− mouseClick(volumeUpButton, 1, 1);
138− wait(0)
139− }
140− }
141− }
142−}
tests/qmltests/Panel/tst_Panel.qml+101−61
@@ -30,11 +30,11 @@ Item {
30 width: units.gu(40)
30 width: units.gu(40)
31 height: units.gu(80)
31 height: units.gu(80)
32
32
33− property bool search_clicked: false
33+ property bool searchClicked: false
34
34
35 Connections {
35 Connections {
36 target: panel
36 target: panel
37− onSearchClicked: search_clicked = true
37+ onSearchClicked: searchClicked = true
38 }
38 }
39
39
40 Panel {
40 Panel {
@@ -54,27 +54,26 @@ Item {
54
54
55
55
56 function init() {
56 function init() {
57− search_clicked = false;
57+ searchClicked = false;
58 panel.indicators.hide();
58 panel.indicators.hide();
59 tryCompare(panel.indicators.hideAnimation, "running", false);
59 tryCompare(panel.indicators.hideAnimation, "running", false);
60 tryCompare(panel.indicators, "state", "initial");
60 tryCompare(panel.indicators, "state", "initial");
61 }
61 }
62
62
63 function get_indicator_item(index) {
63 function get_indicator_item(index) {
64− var row_repeater = findChild(panel.indicators, "rowRepeater");
64+ var rowRepeater = findChild(panel.indicators, "rowRepeater");
65− verify(row_repeater != undefined)
65+ verify(rowRepeater != undefined);
66− return row_repeater.itemAt(index);
66+ return rowRepeater.itemAt(index);
67 }
67 }
68
68
69 function get_indicator_item_position(index) {
69 function get_indicator_item_position(index) {
70+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
71+ verify(indicatorRow != undefined);
70
72
71− var indicator_row = findChild(panel.indicators, "indicatorRow");
72− verify(indicator_row != undefined)
73−
74− var indicator_item = get_indicator_item(index);
73+ var indicatorItem = get_indicator_item(index);
75− verify(indicator_item != undefined);
74+ verify(indicatorItem != undefined);
76
75
77− return panel.mapFromItem(indicator_item, indicator_item.width/2, indicator_item.height/2);
76+ return panel.mapFromItem(indicatorItem, indicatorItem.width/2, indicatorItem.height/2);
78 }
77 }
79
78
80 // Pressing on the indicator panel should activate the indicator hints
79 // Pressing on the indicator panel should activate the indicator hints
@@ -83,11 +82,11 @@ Item {
83 panel.fullscreenMode = false;
82 panel.fullscreenMode = false;
84 // Wait for the indicators to get into position.
83 // Wait for the indicators to get into position.
85 // (switches between normal and fullscreen modes are animated)
84 // (switches between normal and fullscreen modes are animated)
86− tryCompare(panel.indicators, "y", 0)
85+ tryCompare(panel.indicators, "y", 0);
87
86
88− var indicator_item_coord = get_indicator_item_position(0);
87+ var indicatorItemCoord = get_indicator_item_position(0);
89
88
90− touchPress(panel, indicator_item_coord.x, panel.panelHeight / 2)
89+ touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
91
90
92 // hint animation should be run, meaning that indicators will move downwards
91 // hint animation should be run, meaning that indicators will move downwards
93 // by hintValue pixels without any drag taking place
92 // by hintValue pixels without any drag taking place
@@ -96,7 +95,7 @@ Item {
96 tryCompare(panel.indicators, "partiallyOpened", true);
95 tryCompare(panel.indicators, "partiallyOpened", true);
97 tryCompare(panel.indicators, "fullyOpened", false);
96 tryCompare(panel.indicators, "fullyOpened", false);
98
97
99− touchRelease(panel, indicator_item_coord.x, panel.panelHeight/2)
98+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
100 }
99 }
101
100
102 // Pressing on the top edge of the screen should have no effect if the panel
101 // Pressing on the top edge of the screen should have no effect if the panel
@@ -105,31 +104,31 @@ Item {
105 panel.fullscreenMode = true;
104 panel.fullscreenMode = true;
106 // Wait for the indicators to get into position.
105 // Wait for the indicators to get into position.
107 // (switches between normal and fullscreen modes are animated)
106 // (switches between normal and fullscreen modes are animated)
108− tryCompare(panel.indicators, "y", -panel.panelHeight)
107+ tryCompare(panel.indicators, "y", -panel.panelHeight);
109
108
110− var indicator_item_coord = get_indicator_item_position(0);
109+ var indicatorItemCoord = get_indicator_item_position(0);
111
110
112− touchPress(panel, indicator_item_coord.x, panel.panelHeight / 2)
111+ touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
113
112
114 // Give some time for a hint animation to change things, if any
113 // Give some time for a hint animation to change things, if any
115− wait(500)
114+ wait(500);
116
115
117 // no hint animation when fullscreen
116 // no hint animation when fullscreen
118− compare(panel.indicators.y, -panel.panelHeight)
117+ compare(panel.indicators.y, -panel.panelHeight);
119 var indicatorRow = findChild(panel.indicators, "indicatorRow");
118 var indicatorRow = findChild(panel.indicators, "indicatorRow");
120− verify(indicatorRow != undefined)
119+ verify(indicatorRow != undefined);
121− compare(indicatorRow.y, 0)
120+ compare(indicatorRow.y, 0);
122− compare(panel.indicators.height, panel.indicators.panelHeight)
121+ compare(panel.indicators.height, panel.indicators.panelHeight);
123 compare(panel.indicators.partiallyOpened, false,
122 compare(panel.indicators.partiallyOpened, false,
124 "Indicator should not be partially opened when panel is pressed in" +
123 "Indicator should not be partially opened when panel is pressed in" +
125− " fullscreenmode")
124+ " fullscreenmode");
126 compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
125 compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
127− " opened when panel is pressed in fullscreenmode")
126+ " opened when panel is pressed in fullscreenmode");
128
127
129− touchRelease(panel, indicator_item_coord.x, panel.panelHeight/2)
128+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
130 }
129 }
131
130
132− function test_drag_show_data() { return get_window_data() }
131+ function test_drag_show_data() { return get_window_data(); }
133
132
134 // Dragging from a indicator item in the panel will gradually expose the
133 // Dragging from a indicator item in the panel will gradually expose the
135 // indicators, first by running the hint animation, then after dragging down will
134 // indicators, first by running the hint animation, then after dragging down will
@@ -137,53 +136,53 @@ Item {
137 function test_drag_show(data) {
136 function test_drag_show(data) {
138 panel.fullscreenMode = data.fullscreenFlag;
137 panel.fullscreenMode = data.fullscreenFlag;
139
138
140− var indicator_row = findChild(panel.indicators, "indicatorRow");
139+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
141− verify(indicator_row != undefined)
140+ verify(indicatorRow != undefined);
142
141
143− var row_repeater = findChild(panel.indicators, "rowRepeater");
142+ var rowRepeater = findChild(panel.indicators, "rowRepeater");
144− verify(indicator_row != undefined)
143+ verify(indicatorRow != undefined);
145
144
146− var menu_content = findChild(panel.indicators, "menuContent");
145+ var menuContent = findChild(panel.indicators, "menuContent");
147− verify(indicator_row != undefined)
146+ verify(indicatorRow != undefined);
148
147
149 // Wait for the indicators to get into position.
148 // Wait for the indicators to get into position.
150 // (switches between normal and fullscreen modes are animated)
149 // (switches between normal and fullscreen modes are animated)
151 if (data.fullscreenFlag) {
150 if (data.fullscreenFlag) {
152− tryCompare(panel.indicators, "y", -panel.panelHeight)
151+ tryCompare(panel.indicators, "y", -panel.panelHeight);
153 } else {
152 } else {
154− tryCompare(panel.indicators, "y", 0)
153+ tryCompare(panel.indicators, "y", 0);
155 }
154 }
156
155
157 // do this for each indicator item
156 // do this for each indicator item
158− for (var i = 0; i < row_repeater.count; i++) {
157+ for (var i = 0; i < rowRepeater.count; i++) {
159
158
160− var indicator_item = get_indicator_item(i);
159+ var indicatorItem = get_indicator_item(i);
161− verify(indicator_item != undefined)
160+ verify(indicatorItem != undefined);
162
161
163− var indicator_item_coord = get_indicator_item_position(i);
162+ var indicatorItemCoord = get_indicator_item_position(i);
164
163
165 touchPress(panel,
164 touchPress(panel,
166− indicator_item_coord.x, panel.panelHeight / 2)
165+ indicatorItemCoord.x, panel.panelHeight / 2);
167
166
168 // 1) Drag the mouse down
167 // 1) Drag the mouse down
169 touchFlick(panel,
168 touchFlick(panel,
170− indicator_item_coord.x, panel.panelHeight / 2,
169+ indicatorItemCoord.x, panel.panelHeight / 2,
171− indicator_item_coord.x, panel.height * 0.8,
170+ indicatorItemCoord.x, panel.height * 0.8,
172− false /* beginTouch */, false /* endTouch */)
171+ false /* beginTouch */, false /* endTouch */);
173
172
174 // Indicators height should follow the drag, and therefore increase accordingly.
173 // Indicators height should follow the drag, and therefore increase accordingly.
175 // They should be at least half-way through the screen
174 // They should be at least half-way through the screen
176 tryCompareFunction(
175 tryCompareFunction(
177 function() {return panel.indicators.height >= panel.height * 0.5},
176 function() {return panel.indicators.height >= panel.height * 0.5},
178− true)
177+ true);
179
178
180− touchRelease(panel, indicator_item_coord.x, panel.height * 0.8)
179+ touchRelease(panel, indicatorItemCoord.x, panel.height * 0.8);
181
180
182− compare(indicator_row.currentItem, indicator_item,
181+ compare(indicatorRow.currentItem, indicatorItem,
183− "Incorrect item activated at position " + i)
182+ "Incorrect item activated at position " + i);
184− compare(menu_content.__shown, true, "Menu conetent should be enabled for item at position " + i);
183+ compare(menuContent.currentMenuIndex, i, "Menu conetent should be enabled for item at position " + i);
185
184
186− // init for next indicator_item
185+ // init for next indicatorItem
187 init();
186 init();
188 }
187 }
189 }
188 }
@@ -192,26 +191,67 @@ Item {
192 panel.fullscreenMode = false;
191 panel.fullscreenMode = false;
193 panel.searchVisible = true;
192 panel.searchVisible = true;
194
193
195− var search_indicator = findChild(panel, "search");
194+ var searchIndicator = findChild(panel, "search");
196− verify(search_indicator != undefined);
195+ verify(searchIndicator != undefined);
197
196
198− tap(search_indicator, 1, 1)
197+ tap(searchIndicator, 1, 1);
199
198
200− compare(search_clicked, true,
199+ compare(searchClicked, true,
201− "Tapping search indicator while it was enabled did not emit searchClicked signal")
200+ "Tapping search indicator while it was enabled did not emit searchClicked signal");
202 }
201 }
203
202
204 function test_search_click_when_not_visible() {
203 function test_search_click_when_not_visible() {
205 panel.fullscreenMode = false;
204 panel.fullscreenMode = false;
206− panel.searchVisible = false
205+ panel.searchVisible = false;
206+
207+ var searchIndicator = findChild(panel, "search");
208+ verify(searchIndicator != undefined);
209+
210+ tap(searchIndicator, 1, 1);
211+
212+ compare(searchClicked, false,
213+ "Tapping search indicator while it was not visible emitted searchClicked signal");
214+ }
215+
216+ // Test the vertical velocity check when flicking the indicators open at an angle.
217+ // If the vertical velocity is above a specific point, we shouldnt change active indicators
218+ // if the x position changes
219+ function test_vertical_velocity_detector() {
220+ panel.fullscreenMode = false;
221+ panel.searchVisible = false;
222+
223+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
224+ verify(indicatorRow != undefined);
225+
226+ var rowRepeater = findChild(panel.indicators, "rowRepeater");
227+ verify(indicatorRow != undefined);
228+
229+ // Get the first indicator
230+ var indicatorItemFirst = get_indicator_item(0);
231+ verify(indicatorItemFirst != undefined);
232+
233+ var indicatorItemCoordFirst = get_indicator_item_position(0);
234+ var indicatorItemCoordNext = get_indicator_item_position(indicatorRow.count - 1);
235+
236+ touchPress(panel,
237+ indicatorItemCoordFirst.x, panel.panelHeight / 2);
238+
239+ // 1) Drag the mouse down to hint a bit
240+ touchFlick(panel,
241+ indicatorItemCoordFirst.x, panel.panelHeight / 2,
242+ indicatorItemCoordFirst.x, panel.panelHeight * 2,
243+ false /* beginTouch */, false /* endTouch */);
207
244
208− var search_indicator = findChild(panel, "search");
245+ tryCompare(indicatorRow, "currentItem", indicatorItemFirst)
209− verify(search_indicator != undefined);
210
246
211− tap(search_indicator, 1, 1)
247+ // 1) Flick mouse down to bottom
248+ touchFlick(panel,
249+ indicatorItemCoordFirst.x, panel.panelHeight * 2,
250+ indicatorItemCoordNext.x, panel.height,
251+ false /* beginTouch */, true /* endTouch */,
252+ units.gu(10) /* speed */, 30 /* iterations */); // more samples needed for accurate velocity
212
253
213− compare(search_clicked, false,
254+ compare(indicatorRow.currentItem, indicatorItemFirst, "First indicator should still be the current item");
214− "Tapping search indicator while it was not visible emitted searchClicked signal")
215 }
255 }
216 }
256 }
217}
257}
tests/qmltests/Panel/tst_SearchIndicator.qml+8−10
@@ -41,24 +41,22 @@ Item {
41 when: windowShown
41 when: windowShown
42
42
43 function test_clickedSignal() {
43 function test_clickedSignal() {
44− clickedSpy.clear()
44+ clickedSpy.clear();
45 mouseClick(searchIndicator,
45 mouseClick(searchIndicator,
46 searchIndicator.width / 2, searchIndicator.height / 2);
46 searchIndicator.width / 2, searchIndicator.height / 2);
47− compare(clickedSpy.count, 1)
47+ compare(clickedSpy.count, 1);
48 }
48 }
49
49
50 function test_hideUp() {
50 function test_hideUp() {
51− var container = findChild(searchIndicator, "container")
51+ var container = findChild(searchIndicator, "container");
52− searchIndicator.state = "hiddenUp"
52+ searchIndicator.state = "hidden";
53− tryCompare(container, "opacity", 0)
53+ tryCompare(container, "opacity", 0);
54− tryCompare(container, "y", -container.height)
55 }
54 }
56
55
57 function test_show() {
56 function test_show() {
58− var container = findChild(searchIndicator, "container")
57+ var container = findChild(searchIndicator, "container");
59− searchIndicator.state = "visible"
58+ searchIndicator.state = "visible";
60− tryCompare(container, "opacity", 1)
59+ tryCompare(container, "opacity", 1);
61− tryCompare(container, "y", 0)
62 }
60 }
63 }
61 }
64}
62}
tests/qmltests/tst_Shell.qmlnew file+281
@@ -0,0 +1,281 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Daniel d'Andrada <daniel.dandrada@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
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+import QtQuick 2.0
21+import QtTest 1.0
22+import Ubuntu.Application 0.1
23+import Unity.Test 0.1 as UT
24+
25+import "../.."
26+
27+Item {
28+ width: shell.width
29+ height: shell.height
30+
31+ QtObject {
32+ id: applicationArguments
33+
34+ function hasGeometry() {
35+ return false;
36+ }
37+
38+ function width() {
39+ return 0;
40+ }
41+
42+ function height() {
43+ return 0;
44+ }
45+ }
46+
47+ Shell {
48+ id: shell
49+ }
50+
51+ UT.UnityTestCase {
52+ name: "Shell"
53+ when: windowShown
54+
55+ function initTestCase() {
56+ // swipe away the greeter/lockscreen
57+ var touchX = shell.width - (shell.edgeSize / 2);
58+ var touchY = shell.height / 2;
59+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY);
60+
61+ var dash = findChild(shell, "dash");
62+ // wait until the animation has finished
63+ tryCompare(dash, "contentScale", 1.0);
64+ tryCompare(dash, "opacity", 1.0);
65+ }
66+
67+ function cleanup() {
68+ // kill all (fake) running apps
69+ ApplicationManager.mainStageApplications.clear();
70+ ApplicationManager.sideStageApplications.clear();
71+
72+ var dashHome = findChild(shell, "DashHome");
73+ swipeUntilScopeViewIsReached(dashHome);
74+ }
75+
76+ /*
77+ Test the effect of a right-edge drag on the dash in 3 situations:
78+ 1 - when no application has been launched yet
79+ 2 - when there's a minimized application
80+ 3 - after the last running application has been closed/stopped
81+
82+ The behavior of Dash on 3 should be the same as on 1.
83+ */
84+ function test_rightEdgeDrag() {
85+ checkRightEdgeDragWithNoRunningApps();
86+
87+ dragLauncherIntoView();
88+
89+ // Launch an app from the launcher
90+ tapOnAppIconInLauncher();
91+ waitUntilApplicationWindowIsFullyVisible();
92+
93+ // Minimize the application we just launched
94+ swipeFromLeftEdge();
95+
96+ waitForUIToSettle();
97+
98+ checkRightEdgeDragWithMinimizedApp();
99+
100+ // Minimize that application once again
101+ swipeFromLeftEdge();
102+
103+ // kill it
104+ ApplicationManager.mainStageApplications.clear();
105+
106+ waitForUIToSettle();
107+
108+ // Right edge behavior should now be the same as before that app was launched
109+ checkRightEdgeDragWithNoRunningApps();
110+ }
111+
112+ /*
113+ Perform a right-edge drag when the Dash is being show and there are
114+ no running/minimized apps to be restored.
115+
116+ The expected behavior is that an animation should be played to hint the
117+ user that his right-edge drag gesture has been successfully recognized
118+ but there is no application to be brought to foreground.
119+ */
120+ function checkRightEdgeDragWithNoRunningApps() {
121+ var touchX = shell.width - (shell.edgeSize / 2);
122+ var touchY = shell.height / 2;
123+
124+ var dash = findChild(shell, "dash");
125+ // check that dash has normal scale and opacity
126+ compare(dash.contentScale, 1.0);
127+ compare(dash.opacity, 1.0);
128+
129+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
130+ true /* beginTouch */, false /* endTouch */);
131+
132+ // check that Dash has been scaled down and had its opacity reduced
133+ tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
134+ tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
135+
136+ touchRelease(shell, shell.width * 0.1, touchY);
137+
138+ // and now everything should have gone back to normal
139+ tryCompare(dash, "contentScale", 1.0);
140+ tryCompare(dash, "opacity", 1.0);
141+ }
142+
143+ /*
144+ Perform a right-edge drag when the Dash is being show and there is
145+ a running/minimized app to be restored.
146+
147+ The expected behavior is that the dash should fade away and ultimately be
148+ made invisible once the gesture is finished as the restored app will now
149+ be on foreground.
150+ */
151+ function checkRightEdgeDragWithMinimizedApp() {
152+ var touchX = shell.width - (shell.edgeSize / 2);
153+ var touchY = shell.height / 2;
154+
155+ var dash = findChild(shell, "dash");
156+ // check that dash has normal scale and opacity
157+ tryCompare(dash, "contentScale", 1.0);
158+ tryCompare(dash, "opacity", 1.0);
159+
160+ touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
161+ true /* beginTouch */, false /* endTouch */);
162+
163+ // check that Dash has been scaled down and had its opacity reduced
164+ tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
165+ tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
166+
167+ touchRelease(shell, shell.width * 0.1, touchY);
168+
169+ // dash should have gone away, now that the app is on foreground
170+ tryCompare(dash, "visible", false);
171+ }
172+
173+ // Wait for the whole UI to settle down
174+ function waitForUIToSettle() {
175+ waitUntilApplicationWindowIsFullyHidden();
176+ var dashContentList = findChild(shell, "dashContentList");
177+ tryCompare(dashContentList, "moving", false);
178+ }
179+
180+ function dragLauncherIntoView() {
181+ var launcherPanel = findChild(shell, "launcherPanel");
182+ verify(launcherPanel.x = - launcherPanel.width);
183+ swipeFromLeftEdge();
184+ tryCompare(launcherPanel, "x", 0);
185+ }
186+
187+ function tapOnAppIconInLauncher() {
188+ var launcherPanel = findChild(shell, "launcherPanel");
189+
190+ // pick the first icon, the one at the bottom.
191+ var appIcon = findChild(launcherPanel, "launcherDelegate0")
192+
193+ // Swipe upwards over the launcher to ensure that this icon
194+ // at the bottom is not folded and faded away.
195+ var touchStartX = launcherPanel.width / 2;
196+ var touchStartY = launcherPanel.height / 2;
197+ touchFlick(launcherPanel, touchStartX, touchStartY, touchStartX, 0);
198+ tryCompare(launcherPanel, "moving", false);
199+
200+ // NB tapping (i.e., using touch events) doesn't activate the icon... go figure...
201+ mouseClick(appIcon, appIcon.width / 2, appIcon.height / 2);
202+ }
203+
204+ function waitUntilApplicationWindowIsFullyVisible() {
205+ var underlay = findChild(shell, "underlay");
206+ tryCompare(underlay, "visible", false);
207+ }
208+
209+ function waitUntilApplicationWindowIsFullyHidden() {
210+ var stages = findChild(shell, "stages");
211+ tryCompare(stages, "fullyHidden", true);
212+ }
213+
214+ function swipeUntilScopeViewIsReached(scopeView) {
215+ while (!itemIsOnScreen(scopeView)) {
216+ if (itemIsToLeftOfScreen(scopeView)) {
217+ swipeRightFromCenter();
218+ } else {
219+ swipeLeftFromCenter();
220+ }
221+ waitUntilItemStopsMoving(scopeView);
222+ }
223+ }
224+
225+ function swipeFromLeftEdge() {
226+ var touchStartX = 2;
227+ var touchStartY = shell.height / 2;
228+ touchFlick(shell, touchStartX, touchStartY, shell.width * 0.75, touchStartY);
229+ }
230+
231+ function swipeLeftFromCenter() {
232+ var touchStartX = shell.width / 2;
233+ var touchStartY = shell.height / 2;
234+ touchFlick(shell, touchStartX, touchStartY, 0, touchStartY);
235+ }
236+
237+ function swipeRightFromCenter() {
238+ var touchStartX = shell.width / 2;
239+ var touchStartY = shell.height / 2;
240+ touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY);
241+ }
242+
243+ function swipeUpFromCenter() {
244+ var touchStartX = shell.width / 2;
245+ var touchStartY = shell.height / 2;
246+ touchFlick(shell, touchStartX, touchStartY, touchStartX, 0);
247+ }
248+
249+ function itemIsOnScreen(item) {
250+ var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
251+
252+ return itemRectInShell.x >= 0
253+ && itemRectInShell.y >= 0
254+ && itemRectInShell.x + itemRectInShell.width <= shell.width
255+ && itemRectInShell.y + itemRectInShell.height <= shell.height;
256+ }
257+
258+ function itemIsToLeftOfScreen(item) {
259+ var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
260+ return itemRectInShell.x < 0;
261+ }
262+
263+ function waitUntilItemStopsMoving(item) {
264+ var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
265+ var previousX = itemRectInShell.x;
266+ var previousY = itemRectInShell.y;
267+ var isStill = false;
268+
269+ do {
270+ wait(100);
271+ itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
272+ if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) {
273+ isStill = true;
274+ } else {
275+ previousX = itemRectInShell.x;
276+ previousY = itemRectInShell.y;
277+ }
278+ } while (!isStill);
279+ }
280+ }
281+}
tests/utils/modules/Unity/Test/UnityTestCase.qml+22−18
@@ -32,32 +32,34 @@ TestCase {
32 // Qt uses in QQuickViewTestUtil::flick
32 // Qt uses in QQuickViewTestUtil::flick
33 // speed is in pixels/second
33 // speed is in pixels/second
34 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
34 function mouseFlick(item, x, y, toX, toY, pressMouse, releaseMouse,
35− speed) {
35+ speed, iterations) {
36 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
36 pressMouse = ((pressMouse != null) ? pressMouse : true); // Default to true for pressMouse if not present
37 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
37 releaseMouse = ((releaseMouse != null) ? releaseMouse : true); // Default to true for releaseMouse if not present
38
38
39 // set a default speed if not specified
39 // set a default speed if not specified
40 speed = (speed != null) ? speed : units.gu(10);
40 speed = (speed != null) ? speed : units.gu(10);
41
41
42+ // set a default iterations if not specified
43+ iterations = (iterations !== undefined) ? iterations : 5
44+
42 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
45 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
43 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
46 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
44
47
45− var nIterations = 5
46− var timeStep = totalTime / nIterations
48+ var timeStep = totalTime / iterations
47− var diffX = (toX - x) / nIterations
49+ var diffX = (toX - x) / iterations
48− var diffY = (toY - y) / nIterations
50+ var diffY = (toY - y) / iterations
49 if (pressMouse) {
51 if (pressMouse) {
50 fakeDateTime.currentTimeMs += timeStep
52 fakeDateTime.currentTimeMs += timeStep
51 mousePress(item, x, y)
53 mousePress(item, x, y)
52 }
54 }
53− for (var i = 0; i < nIterations; ++i) {
55+ for (var i = 0; i < iterations; ++i) {
54 fakeDateTime.currentTimeMs += timeStep
56 fakeDateTime.currentTimeMs += timeStep
55− if (i === nIterations - 1) {
57+ if (i === iterations - 1) {
56 // Avoid any rounding errors by making the last move be at precisely
58 // Avoid any rounding errors by making the last move be at precisely
57 // the point specified
59 // the point specified
58− mouseMove(item, toX, toY, nIterations / speed)
60+ mouseMove(item, toX, toY, iterations / speed)
59 } else {
61 } else {
60− mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, nIterations / speed)
62+ mouseMove(item, x + (i + 1) * diffX, y + (i + 1) * diffY, iterations / speed)
61 }
63 }
62 }
64 }
63 if (releaseMouse) {
65 if (releaseMouse) {
@@ -186,7 +188,7 @@ TestCase {
186 }
188 }
187
189
188 // speed is in pixels/second
190 // speed is in pixels/second
189− function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed) {
191+ function touchFlick(item, x, y, toX, toY, beginTouch, endTouch, speed, iterations) {
190
192
191 // Default to true for beginTouch if not present
193 // Default to true for beginTouch if not present
192 beginTouch = (beginTouch !== undefined) ? beginTouch : true
194 beginTouch = (beginTouch !== undefined) ? beginTouch : true
@@ -197,13 +199,15 @@ TestCase {
197 // Set a default speed if not specified
199 // Set a default speed if not specified
198 speed = (speed !== undefined) ? speed : units.gu(10)
200 speed = (speed !== undefined) ? speed : units.gu(10)
199
201
202+ // Set a default iterations if not specified
203+ var iterations = (iterations !== undefined) ? iterations : 5
204+
200 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
205 var distance = Math.sqrt(Math.pow(toX - x, 2) + Math.pow(toY - y, 2))
201 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
206 var totalTime = (distance / speed) * 1000 /* converting speed to pixels/ms */
202
207
203− var nIterations = 5
204− var timeStep = totalTime / nIterations
208+ var timeStep = totalTime / iterations
205− var diffX = (toX - x) / nIterations
209+ var diffX = (toX - x) / iterations
206− var diffY = (toY - y) / nIterations
210+ var diffY = (toY - y) / iterations
207 if (beginTouch) {
211 if (beginTouch) {
208 fakeDateTime.currentTimeMs += timeStep
212 fakeDateTime.currentTimeMs += timeStep
209
213
@@ -211,17 +215,17 @@ TestCase {
211 event.press(0 /* touchId */, x, y)
215 event.press(0 /* touchId */, x, y)
212 event.commit()
216 event.commit()
213 }
217 }
214− for (var i = 0; i < nIterations; ++i) {
218+ for (var i = 0; i < iterations; ++i) {
215 fakeDateTime.currentTimeMs += timeStep
219 fakeDateTime.currentTimeMs += timeStep
216− if (i === nIterations - 1) {
220+ if (i === iterations - 1) {
217 // Avoid any rounding errors by making the last move be at precisely
221 // Avoid any rounding errors by making the last move be at precisely
218 // the point specified
222 // the point specified
219− wait(nIterations / speed)
223+ wait(iterations / speed)
220 var event = touchEvent()
224 var event = touchEvent()
221 event.move(0 /* touchId */, toX, toY)
225 event.move(0 /* touchId */, toX, toY)
222 event.commit()
226 event.commit()
223 } else {
227 } else {
224− wait(nIterations / speed)
228+ wait(iterations / speed)
225 var event = touchEvent()
229 var event = touchEvent()
226 event.move(0 /* touchId */, x + (i + 1) * diffX, y + (i + 1) * diffY)
230 event.move(0 /* touchId */, x + (i + 1) * diffX, y + (i + 1) * diffY)
227 event.commit()
231 event.commit()