on xenial help sign in
merged with trunk
commit025c8a6bec061fb07ddebf631af278ca9315d579 authorNick Dedekind <nicholas.dedekind@gmail.com> dateFri 11 Oct 2013, 17:36 (13 years ago) parent7c68bd9d802be8
28 files changed+204−382
Components/ApplicationManagerWrapper.qml+13−1 Components/DragHandle.qml−1 Components/FilterGrid.qml+4−3 Components/ListItems/Header.qml+1−1 Components/ResponsiveGridView.qml+2 Components/Stage.qml+5 Dash/Apps/RunningApplicationTile.qml+2−2 Dash/DashContent.qml+5−5 Dash/DashMusic.qml−96 Dash/DashVideos.qml−201 Dash/GenericScopeView.qml+31 Dash/ScopeDelegateMapper.qml+2−4 Dash/ScopeListView.qml+5 Dash/ScopeView.qml+1 Greeter/Clock.qml+31−12 main.cpp+1 plugins/AccountsService/AccountsService.cpp+3−1 plugins/Unity/Indicators/rootactionstate.cpp+15−1 plugins/Unity/Indicators/rootactionstate.h+1 plugins/Unity/scope.cpp+1 po/unity8.pot+3−31 tests/autopilot/unity8/shell/tests/__init__.py+6 tests/mocks/Unity/Application/ApplicationInfo.h+1 tests/mocks/Unity/Application/ApplicationManager.h+1 tests/plugins/Unity/Indicators/CMakeLists.txt+3 tests/plugins/Unity/Indicators/rootactionstatetest.cpp+58 tests/qmltests/CMakeLists.txt+1−1 tests/qmltests/Greeter/tst_Clock.qml+8−22
Components/ApplicationManagerWrapper.qml+13−1
@@ -18,7 +18,7 @@ import QtQuick 2.0
1818import Unity.Application 0.1
1919
2020Item {
21− id: applicationManager
21+ id: root
2222
2323 property alias mainStageApplications: mainStageModel
2424 property alias sideStageApplications: sideStageModel
@@ -30,6 +30,8 @@ Item {
3030
3131 property bool fake: ApplicationManager.fake ? ApplicationManager.fake : false
3232
33+ signal focusRequested(string appId)
34+
3335 ApplicationsModelStageFiltered {
3436 id: mainStageModel
3537 stage: ApplicationInfo.MainStage
@@ -61,6 +63,16 @@ Item {
6163 }
6264 }
6365 }
66+
67+ onFocusRequested: {
68+ // if no side stage enabled, override application's stage parameter
69+ var app = ApplicationManager.findApplication(appId);
70+ if (app && app.stage === ApplicationInfo.SideStage && !sideStageEnabled) {
71+ app.stage = ApplicationInfo.MainStage;
72+ }
73+
74+ root.focusRequested(appId);
75+ }
6476 }
6577
6678 function activateApplication(desktopFile, argument) {
Components/DragHandle.qml−1
@@ -208,5 +208,4 @@ EdgeDragArea {
208208
209209 d.previousStatus = status;
210210 }
211−
212211}
Components/FilterGrid.qml+4−3
@@ -57,6 +57,8 @@ Item {
5757 property alias delegate: iconTileGrid.delegate
5858 property alias cellWidth: iconTileGrid.cellWidth
5959 property alias cellHeight: iconTileGrid.cellHeight
60+ property alias delegateCreationBegin: iconTileGrid.delegateCreationBegin
61+ property alias delegateCreationEnd: iconTileGrid.delegateCreationEnd
6062 readonly property alias flicking: iconTileGrid.flicking
6163 readonly property alias moving: iconTileGrid.moving
6264 readonly property alias pressDelay: iconTileGrid.pressDelay
@@ -64,7 +66,7 @@ Item {
6466 height: !filterAnimation.running ? childrenRect.height : height
6567 clip: filterAnimation.running
6668
67− NumberAnimation {
69+ SmoothedAnimation {
6870 property bool filterEndValue
6971 id: filterAnimation
7072 target: root
@@ -73,7 +75,7 @@ Item {
7375 // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
7476 // otherwise since both animations can run at the same time you'll get
7577 // some visual weirdness.
76− duration: 200
78+ velocity: units.gu(100)
7779 easing.type: Easing.InOutQuad
7880 onStopped: {
7981 root.filter = filterEndValue;
@@ -102,6 +104,5 @@ Item {
102104 model: root.model
103105 limit: (filter && !filterAnimation.running) ? collapsedRowCount * iconTileGrid.columns : -1
104106 }
105−
106107 }
107108}
Components/ListItems/Header.qml+1−1
@@ -28,7 +28,7 @@ Item {
2828
2929 signal clicked(variant mouse)
3030
31− height: units.gu(4.5)
31+ height: units.gu(5)
3232
3333 Item {
3434 anchors {
Components/ResponsiveGridView.qml+2
@@ -39,6 +39,8 @@ Item {
3939 readonly property alias flicking: gridView.flicking
4040 readonly property alias moving: gridView.moving
4141 readonly property alias pressDelay: gridView.pressDelay
42+ property alias delegateCreationBegin: gridView.delegateCreationBegin
43+ property alias delegateCreationEnd: gridView.delegateCreationEnd
4244
4345 function contentHeightForRows(rows) {
4446 return rows * cellHeight + verticalSpacing
Components/Stage.qml+5
@@ -84,6 +84,11 @@ Showable {
8484 }
8585 }
8686
87+ Connections {
88+ target: applicationManager
89+ onFocusRequested: activateApplication(appId)
90+ }
91+
8792 /* Keep a reference to the focused application so that we can safely
8893 unfocus it when the stage is not fully shown and refocus it when the stage
8994 is fully shown again.
Dash/Apps/RunningApplicationTile.qml+2−2
@@ -124,8 +124,8 @@ AbstractButton {
124124
125125 CloseIcon {
126126 anchors {
127− right: shapedApplicationImage.right
128− rightMargin: -units.gu(1)
127+ left: shapedApplicationImage.left
128+ leftMargin: -units.gu(1)
129129 top: parent.top
130130 topMargin: -units.gu(1)
131131 }
Dash/DashContent.qml+5−5
@@ -83,7 +83,7 @@ Item {
8383 id: dashContentList
8484 objectName: "dashContentList"
8585
86− interactive: dashContent.scopes.loaded
86+ interactive: dashContent.scopes.loaded && !currentItem.previewShown && !currentItem.moving
8787
8888 anchors.fill: parent
8989 model: dashContent.model
@@ -116,6 +116,9 @@ Item {
116116 source: scopeMapper.map(scope.id)
117117 objectName: scope.id + " loader"
118118
119+ readonly property bool previewShown: item.previewShown
120+ readonly property bool moving: item.moving
121+
119122 // these are needed for autopilot tests
120123 readonly property string scopeId: scope.id
121124 readonly property bool isCurrent: ListView.isCurrentItem
@@ -135,10 +138,7 @@ Item {
135138 onEndReached: contentEndReached()
136139 onPreviewShownChanged: {
137140 if (item.previewShown) {
138− previewShown()
139− dashContentList.interactive = false
140− } else {
141− dashContentList.interactive = true
141+ dashContent.previewShown()
142142 }
143143 }
144144 }
Dash/DashMusic.qmldeleted−96
@@ -1,96 +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−import "../Components/ListItems" as ListItems
21−import "Music"
22−
23−ScopeView {
24− id: scopeView
25−
26− property var categoryNames: [
27− i18n.tr("Featured"),
28− i18n.tr("Recent"),
29− i18n.tr("New Releases"),
30− i18n.tr("Top Charting")
31− ]
32−
33− onIsCurrentChanged: {
34− pageHeader.resetSearch();
35− }
36−
37− onMovementStarted: categoryView.showHeader()
38−
39− Binding {
40− target: scopeView.scope
41− property: "searchQuery"
42− value: pageHeader.searchQuery
43− }
44−
45− Connections {
46− target: panel
47− onSearchClicked: if (isCurrent) {
48− pageHeader.triggerSearch()
49− categoryView.showHeader()
50− }
51− }
52−
53− function getRenderer(categoryId) {
54− switch (categoryId) {
55− case "featured": return "Music/MusicCarousel.qml"
56− default: return "Music/MusicFilterGrid.qml"
57− }
58− }
59−
60− ScopeListView {
61− id: categoryView
62− anchors.fill: parent
63− model: scopeView.categories
64−
65− onAtYEndChanged: if (atYEnd) endReached()
66− onMovingChanged: if (moving && atYEnd) endReached()
67−
68− delegate: ListItems.Base {
69− id: base
70− highlightWhenPressed: false
71−
72− property string categoryId: model.categoryId
73−
74− Loader {
75− anchors { top: parent.top; left: parent.left; right: parent.right }
76− source: scopeView.getRenderer(base.categoryId)
77− onLoaded: {
78− item.model = results
79− }
80− }
81− }
82−
83− sectionProperty: "name"
84− sectionDelegate: ListItems.Header {
85− width: categoryView.width
86− text: i18n.tr(section)
87− }
88− pageHeader: PageHeader {
89− id: pageHeader
90− width: categoryView.width
91− text: i18n.tr("Music")
92− searchEntryEnabled: true
93− searchHistory: scopeView.searchHistory
94− }
95− }
96−}
Dash/DashVideos.qmldeleted−201
@@ -1,201 +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−import "../Components/ListItems" as ListItems
21−import "Video"
22−
23−ScopeView {
24− id: scopeView
25− property alias previewShown: previewLoader.onScreen
26−
27− property var categoryNames: [
28− i18n.tr("Featured"),
29− i18n.tr("Recent"),
30− i18n.tr("New Releases"),
31− i18n.tr("Popular Online")
32− ]
33−
34− onIsCurrentChanged: {
35− pageHeader.resetSearch();
36− }
37−
38− onMovementStarted: categoryView.showHeader()
39−
40− Binding {
41− target: scopeView.scope
42− property: "searchQuery"
43− value: pageHeader.searchQuery
44− }
45−
46− Connections {
47− target: panel
48− onSearchClicked: if (isCurrent) {
49− pageHeader.triggerSearch()
50− categoryView.showHeader()
51− }
52− }
53−
54− function getRenderer(categoryId) {
55− switch (categoryId) {
56− case "featured": return "Video/VideosCarousel.qml"
57− default: return "Video/VideosFilterGrid.qml"
58− }
59− }
60−
61− OpenEffect {
62− id: effect
63− anchors {
64− fill: parent
65− bottomMargin: -bottomOverflow
66− }
67− sourceItem: categoryView
68−
69− enabled: gap > 0.0
70−
71− topGapPx: (1 - gap) * positionPx
72− topOpacity: Math.max(0, (1 - gap * 1.2))
73− bottomGapPx: positionPx + gap * (targetBottomGapPx - positionPx)
74− bottomOverflow: units.gu(6)
75− bottomOpacity: 1 - (gap * 0.8)
76−
77− property int targetBottomGapPx: height - units.gu(8) - bottomOverflow
78− property real gap: previewLoader.open ? 1.0 : 0.0
79−
80− Behavior on gap {
81− NumberAnimation {
82− duration: 200
83− easing.type: Easing.InOutQuad
84− onRunningChanged: {
85− if (!previewLoader.open && !running) {
86− previewLoader.onScreen = false;
87− }
88− }
89− }
90− }
91− }
92−
93− ScopeListView {
94− id: categoryView
95− anchors.fill: parent
96− model: scopeView.categories
97− forceNoClip: previewLoader.onScreen
98−
99− onAtYEndChanged: if (atYEnd) endReached()
100− onMovingChanged: if (moving && atYEnd) endReached()
101−
102− delegate: ListItems.Base {
103− id: base
104− highlightWhenPressed: false
105− property string categoryId: model.categoryId
106−
107− Loader {
108− id: loader
109− anchors { top: parent.top; left: parent.left; right: parent.right }
110− source: scopeView.getRenderer(base.categoryId)
111− onLoaded: {
112− item.model = results
113− }
114−
115− Connections {
116− target: loader.item
117− onClicked: {
118− var dataItem;
119− // VideosCarousel and VideosFilterGrid have different
120− // clicked signals, accomodate for that
121− if (categoryId == "featured") {
122− var fileUri = delegateItem.model.uri.replace(/^[^:]+:/, "")
123− dataItem = {fileUri: fileUri, nfoUri: delegateItem.model.comment}
124− } else {
125− dataItem = data;
126− }
127− if (dataItem.nfoUri != "") {
128− previewLoader.videoData = dataItem;
129− previewLoader.open = true;
130− effect.positionPx = mapToItem(categoryView, 0, itemY).y;
131− }
132− }
133− }
134− }
135− }
136−
137− sectionProperty: "name"
138− sectionDelegate: ListItems.Header {
139− width: categoryView.width
140− text: i18n.tr(section)
141− }
142−
143− pageHeader: PageHeader {
144− id: pageHeader
145− width: categoryView.width
146− text: i18n.tr("Videos")
147− searchEntryEnabled: true
148− searchHistory: scopeView.searchHistory
149− }
150− }
151−
152− Loader {
153− id: previewLoader
154− height: effect.bottomGapPx - effect.topGapPx
155− anchors {
156− top: parent.top
157− topMargin: effect.topGapPx
158− left: parent.left
159− right: parent.right
160− }
161− sourceComponent: onScreen ? previewComponent : undefined
162−
163− property bool open: false
164− property bool onScreen: false
165− property var videoData
166−
167−
168− onOpenChanged: {
169− if (open) {
170− onScreen = true;
171− }
172− }
173−
174− onLoaded: {
175− item.item = videoData;
176− }
177− }
178−
179− Component {
180− id: previewComponent
181−
182− VideoPreview {
183− id: preview
184− anchors.fill: parent
185− onClose: open = false;
186− }
187− }
188−
189− // TODO: Move as InverseMouseArea to DashPreview
190− MouseArea {
191− enabled: previewLoader.onScreen
192− anchors {
193− fill: parent
194− topMargin: effect.bottomGapPx
195− }
196− onClicked: {
197− previewLoader.open = false;
198− }
199− }
200−
201−}
Dash/GenericScopeView.qml+31
@@ -24,6 +24,8 @@ ScopeView {
2424 readonly property alias previewShown: previewLoader.onScreen
2525 property bool enableHeightBehaviorOnNextCreation: false
2626
27+ moving: categoryView.moving
28+
2729 onIsCurrentChanged: {
2830 pageHeader.resetSearch();
2931 previewLoader.open = false;
@@ -72,6 +74,7 @@ ScopeView {
7274 property string expandedCategoryId: ""
7375
7476 delegate: ListItems.Base {
77+ id: baseItem
7578 highlightWhenPressed: false
7679
7780 readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
@@ -108,6 +111,7 @@ ScopeView {
108111 item.filter = shouldFilter;
109112 }
110113 }
114+ updateDelegateCreationRange();
111115 }
112116
113117 Component.onDestruction: {
@@ -164,6 +168,33 @@ ScopeView {
164168 }
165169 }
166170 }
171+ onContentYChanged: rendererLoader.updateDelegateCreationRange();
172+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
173+ }
174+
175+ function updateDelegateCreationRange() {
176+ // Do not update the range if we are overshooting up or down, since we'll come back
177+ // to the stable position and delete/create items without any reason
178+ if (categoryView.contentY < categoryView.originY) {
179+ return;
180+ } else if (categoryView.contentY + categoryView.height > categoryView.contentHeight) {
181+ return;
182+ }
183+
184+ if (item.hasOwnProperty("delegateCreationBegin")) {
185+ if (baseItem.y + baseItem.height <= 0) {
186+ // Not visible (item at top of the list)
187+ item.delegateCreationBegin = baseItem.height
188+ item.delegateCreationEnd = baseItem.height
189+ } else if (baseItem.y >= categoryView.height) {
190+ // Not visible (item at bottom of the list)
191+ item.delegateCreationBegin = 0
192+ item.delegateCreationEnd = 0
193+ } else {
194+ item.delegateCreationBegin = Math.max(-baseItem.y, 0)
195+ item.delegateCreationEnd = Math.min(categoryView.height + item.delegateCreationBegin, baseItem.height)
196+ }
197+ }
167198 }
168199 }
169200 }
Dash/ScopeDelegateMapper.qml+2−4
@@ -17,10 +17,8 @@
1717import QtQuick 2.0
1818
1919QtObject {
20− property var scopeDelegateMapping: {"mockmusicmaster.scope": "DashMusic.qml",
21− "applications.scope": "DashApps.qml",
22− "home.scope": "DashHome.qml",
23− "mockvideosmaster.scope": "DashVideos.qml"
20+ property var scopeDelegateMapping: {"applications.scope": "DashApps.qml",
21+ "home.scope": "DashHome.qml"
2422 }
2523 property string genericScope: "GenericScopeView.qml"
2624
Dash/ScopeListView.qml+5
@@ -20,4 +20,9 @@ import ListViewWithPageHeader 0.1
2020ListViewWithPageHeader {
2121 maximumFlickVelocity: height * 10
2222 flickDeceleration: height * 2
23+
24+ Connections {
25+ target: greeter
26+ onShownChanged: if (greeter.shown) showHeader()
27+ }
2328}
Dash/ScopeView.qml+1
@@ -23,6 +23,7 @@ FocusScope {
2323 property SortFilterProxyModel categories: categoryFilter
2424 property bool isCurrent
2525 property ListModel searchHistory
26+ property bool moving: false
2627
2728 signal endReached
2829 signal movementStarted
Greeter/Clock.qml+31−12
@@ -16,6 +16,7 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19+import Unity.Indicators 0.1 as Indicators
1920
2021Item {
2122 id: clock
@@ -23,17 +24,35 @@ Item {
2324 implicitWidth: childrenRect.width
2425 implicitHeight: childrenRect.height
2526
26− property date __date
27− property alias __timerInterval: timer.interval
28− readonly property bool __timerRunning: timer.running
27+ // Allows to set the current Date. Will be overwritten if active
28+ property date currentDate
2929
30− Timer {
31− id: timer
32− interval: 1000 * 60
33− running: clock.enabled && clock.visible && clock.opacity != 0
34− repeat: true
35− triggeredOnStart: true
36− onTriggered: __date = new Date
30+ // If active, time will be updated through the indicators service
31+ property bool active: clock.enabled && clock.visible
32+
33+ Component.onCompleted: {
34+ if (active) {
35+ currentDate = new Date()
36+ }
37+ }
38+
39+ Indicators.CachedUnityMenuModel {
40+ id: timeModel
41+ objectName: "timeModel"
42+
43+ busName: "com.canonical.indicator.datetime"
44+ actionsObjectPath: "/com/canonical/indicator/datetime"
45+ menuObjectPath: clock.active ? "/com/canonical/indicator/datetime/phone" : ""
46+
47+ Indicators.RootActionState {
48+ menu: timeModel.model
49+ onUpdated: {
50+ if (timeLabel.text != rightLabel) {
51+ timeLabel.text = rightLabel;
52+ clock.currentDate = new Date();
53+ }
54+ }
55+ }
3756 }
3857
3958 Column {
@@ -47,7 +66,7 @@ Item {
4766 font.pixelSize: units.gu(7.5)
4867 color: "white"
4968 opacity: 0.5
50− text: Qt.formatTime(__date)
69+ text: Qt.formatTime(clock.currentDate)
5170 font.weight: Font.Light
5271 }
5372
@@ -59,7 +78,7 @@ Item {
5978 fontSize: "medium"
6079 color: "white"
6180 opacity: 0.5
62− text: Qt.formatDate(__date, Qt.DefaultLocaleLongDate)
81+ text: Qt.formatDate(clock.currentDate, Qt.DefaultLocaleLongDate)
6382 font.weight: Font.Light
6483 }
6584 }
main.cpp+1
@@ -177,6 +177,7 @@ int startShell(int argc, const char** argv, void* server)
177177
178178 int result = application->exec();
179179
180+ delete view;
180181 delete mouseTouchAdaptor;
181182 delete application;
182183
plugins/AccountsService/AccountsService.cpp+3−1
@@ -24,7 +24,9 @@
2424AccountsService::AccountsService(QObject* parent)
2525 : QObject(parent),
2626 m_service(new AccountsServiceDBusAdaptor(this)),
27− m_user(qgetenv("USER"))
27+ m_user(qgetenv("USER")),
28+ m_demoEdges(false),
29+ m_statsWelcomeScreen(false)
2830{
2931 connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),
3032 this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));
plugins/Unity/Indicators/rootactionstate.cpp+15−1
@@ -57,7 +57,7 @@ void RootActionState::setMenu(UnityMenuModel* menu)
5757 connect(m_menu, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(onModelRowsRemoved(const QModelIndex&, int, int)));
5858 connect(m_menu, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(onModelDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
5959
60− m_menu->setActionStateParser(this);
60+ connect(m_menu, SIGNAL(destroyed()), SLOT(reset()));
6161 }
6262 updateActionState();
6363 Q_EMIT menuChanged();
@@ -92,10 +92,24 @@ void RootActionState::onModelDataChanged(const QModelIndex& topLeft, const QMode
9292 }
9393}
9494
95+void RootActionState::reset()
96+{
97+ m_cachedState.clear();
98+ m_menu = NULL;
99+
100+ Q_EMIT menuChanged();
101+ Q_EMIT updated();
102+}
103+
95104void RootActionState::updateActionState()
96105{
97106 if (m_menu && m_menu->rowCount() > 0) {
107+ ActionStateParser* oldParser = m_menu->actionStateParser();
108+ m_menu->setActionStateParser(this);
109+
98110 m_cachedState = m_menu->get(0, "actionState").toMap();
111+
112+ m_menu->setActionStateParser(oldParser);
99113 } else {
100114 m_cachedState.clear();
101115 }
plugins/Unity/Indicators/rootactionstate.h+1
@@ -77,6 +77,7 @@ private Q_SLOTS:
7777 void onModelRowsAdded(const QModelIndex& parent, int start, int end);
7878 void onModelRowsRemoved(const QModelIndex& parent, int start, int end);
7979 void onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>&);
80+ void reset();
8081
8182private:
8283 void updateActionState();
plugins/Unity/scope.cpp+1
@@ -40,6 +40,7 @@
4040
4141Scope::Scope(QObject *parent) : QObject(parent)
4242 , m_formFactor("phone")
43+ , m_isActive(false)
4344 , m_searchInProgress(false)
4445{
4546 m_categories.reset(new Categories(this));
po/unity8.pot+3−31
@@ -8,7 +8,7 @@ msgid ""
88msgstr ""
99"Project-Id-Version: unity8\n"
1010"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2013-10-07 10:49+0200\n"
11+"POT-Creation-Date: 2013-10-11 12:12+0200\n"
1212"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -156,34 +156,6 @@ msgstr[1] ""
156156msgid "Rate this"
157157msgstr ""
158158
159−#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
160−msgid "Featured"
161−msgstr ""
162−
163−#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
164−msgid "Recent"
165−msgstr ""
166−
167−#: Dash/DashMusic.qml:29 Dash/DashVideos.qml:30
168−msgid "New Releases"
169−msgstr ""
170−
171−#: Dash/DashMusic.qml:30
172−msgid "Top Charting"
173−msgstr ""
174−
175−#: Dash/DashMusic.qml:91
176−msgid "Music"
177−msgstr ""
178−
179−#: Dash/DashVideos.qml:31
180−msgid "Popular Online"
181−msgstr ""
182−
183−#: Dash/DashVideos.qml:146
184−msgid "Videos"
185−msgstr ""
186−
187159#: Dash/Previews/Reviews.qml:74
188160msgid "Add a review"
189161msgstr ""
@@ -237,7 +209,7 @@ msgstr ""
237209msgid "Search"
238210msgstr ""
239211
240−#: plugins/Unity/scope.cpp:361
212+#: plugins/Unity/scope.cpp:398
241213msgid "Sorry, there is nothing that matches your search."
242214msgstr ""
243215
@@ -245,7 +217,7 @@ msgstr ""
245217msgid "All"
246218msgstr ""
247219
248−#: Shell.qml:453
220+#: Shell.qml:438
249221#, qt-format
250222msgid "Please enter %1"
251223msgstr ""
tests/autopilot/unity8/shell/tests/__init__.py+6
@@ -87,6 +87,12 @@ class UnityTestCase(AutopilotTestCase):
8787 self._proxy = None
8888 self._lightdm_mock_type = None
8989 self._qml_mock_enabled = True
90+
91+ #### FIXME: This is a work around re: lp:1238417 ####
92+ from autopilot.input import _uinput
93+ _uinput._touch_device = _uinput.create_touch_device()
94+ ####
95+
9096 self.touch = Touch.create()
9197 self._setup_display_details()
9298
tests/mocks/Unity/Application/ApplicationInfo.h+1
@@ -35,6 +35,7 @@ class ApplicationInfo : public ApplicationInfoInterface {
3535 Q_OBJECT
3636
3737 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
38+ Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged)
3839
3940 // Only exists in this fake implementation
4041
tests/mocks/Unity/Application/ApplicationManager.h+1
@@ -99,6 +99,7 @@ class ApplicationManager : public ApplicationManagerInterface {
9999 void keyboardHeightChanged();
100100 void keyboardVisibleChanged();
101101 void focusRequested(FavoriteApplication favoriteApplication);
102+ void focusRequested(const QString &appId);
102103
103104 private:
104105 void add(ApplicationInfo *application);
tests/plugins/Unity/Indicators/CMakeLists.txt+3
@@ -1,5 +1,6 @@
11pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
22pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
3+pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
34
45set(INDICATORS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators)
56set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
@@ -30,6 +31,7 @@ macro(indicator_test TEST)
3031 ${test_ADDITIONAL_LIBS}
3132 ${GLIB_LIBRARIES}
3233 ${GIO_LIBRARIES}
34+ ${QMENUMODEL_LDFLAGS}
3335 )
3436endmacro(indicator_test)
3537
@@ -37,3 +39,4 @@ indicator_test(indicatorsmanagertest ADDITIONAL_LIBS IndicatorsQml)
3739indicator_test(indicatorsmodeltest ADDITIONAL_LIBS IndicatorsQml)
3840indicator_test(menucontentactivatortest ADDITIONAL_CPPS ${INDICATORS_DIR}/menucontentactivator.cpp)
3941indicator_test(unitymenumodelstacktest ADDITIONAL_CPPS ${TEST_DIR}/mocks/QMenuModel/unitymenumodel.cpp ${INDICATORS_DIR}/unitymenumodelstack.cpp)
42+indicator_test(rootactionstatetest ADDITIONAL_LIBS IndicatorsQml)
tests/plugins/Unity/Indicators/rootactionstatetest.cppnew file+58
@@ -0,0 +1,58 @@
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 "rootactionstate.h"
21+
22+#include <unitymenumodel.h>
23+#include <QtTest>
24+
25+class RootActionStateTest : public QObject
26+{
27+ Q_OBJECT
28+private Q_SLOTS:
29+
30+ void testDeleteRootActionState()
31+ {
32+ UnityMenuModel* menuModel = new UnityMenuModel();
33+ ActionStateParser* originalParser = menuModel->actionStateParser();
34+ RootActionState* rootState = new RootActionState();
35+
36+ rootState->setMenu(menuModel);
37+
38+ delete rootState;
39+ QCOMPARE(menuModel->actionStateParser(), originalParser);
40+ delete menuModel;
41+ }
42+
43+ void testDeleteUnityMenuModel()
44+ {
45+ UnityMenuModel* menuModel = new UnityMenuModel();
46+ RootActionState* rootState = new RootActionState();
47+
48+ rootState->setMenu(menuModel);
49+
50+ QCOMPARE(rootState->menu(), menuModel);
51+ delete menuModel;
52+ QVERIFY(rootState->menu() == NULL);
53+ delete rootState;
54+ }
55+};
56+
57+QTEST_GUILESS_MAIN(RootActionStateTest)
58+#include "rootactionstatetest.moc"
tests/qmltests/CMakeLists.txt+1−1
@@ -17,7 +17,7 @@ add_qml_test(Components MathLocal)
1717add_qml_test(Components OpenEffect)
1818add_qml_test(Components RatingStars)
1919add_qml_test(Components TimeLocal)
20−add_qml_test(Greeter Clock)
20+add_qml_test(Greeter Clock IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
2121add_qml_test(Panel IndicatorItem)
2222add_qml_test(utils/Unity/Test UnityTest)
2323
tests/qmltests/Greeter/tst_Clock.qml+8−22
@@ -43,8 +43,7 @@ Rectangle {
4343 var dateString = Qt.formatDate(dateObj, Qt.DefaultLocaleLongDate)
4444 var timeString = Qt.formatTime(dateObj)
4545
46− clock.__timerInterval = 60000
47− clock.__date = dateObj
46+ clock.currentDate = dateObj
4847 var dateLabel = findChild(clock, "dateLabel")
4948 compare(dateLabel.text, dateString, "Not the expected date")
5049 var timeLabel = findChild(clock, "timeLabel")
@@ -57,33 +56,20 @@ Rectangle {
5756 var timeString = Qt.formatTime(dateObj)
5857
5958 clock.enabled = false
60− compare(clock.__timerRunning, false, "Timer should not be running")
61− clock.__date = dateObj
62− clock.__timerInterval = 5
63− wait(5) // spin event loop (only that would trigger the timer and reveal eventual bugs)
59+ var timeModel = findInvisibleChild(clock, "timeModel")
60+
61+ compare(timeModel.menuObjectPath, "", "Clock shouldn't be connected to Indicators when not active.")
62+
63+ clock.currentDate = dateObj
64+
6465 var dateLabel = findChild(clock, "dateLabel")
6566 compare(dateLabel.text, dateString, "Not the expected date")
6667 var timeLabel = findChild(clock, "timeLabel")
6768 compare(timeLabel.text, timeString, "Not the expected time")
6869
6970 clock.enabled = true
70− compare(clock.__timerRunning, true, "Timer should be running")
71− wait(0) // spin event loop to trigger the timer
72− verify(dateLabel.text !== dateString)
73− if (timeLabel.text.indexOf("11:13") != -1) wait(60000) // next test will fail at 11:13, wait 1 minute
74− verify(timeLabel.text !== timeString)
75− }
7671
77− function test_timerRunning() {
78− // tests for clock.enabled property are already in test_dateUpdate()
79− clock.opacity = 0.0
80− compare(clock.__timerRunning, false, "Timer should not be running")
81− clock.opacity = 1.0
82− compare(clock.__timerRunning, true, "Timer should be running")
83− clock.visible = false
84− compare(clock.__timerRunning, false, "Timer should not be running")
85− clock.visible = true
86− compare(clock.__timerRunning, true, "Timer should be running")
72+ verify(timeModel.menuObjectPath != "", "Should be connected to Indicators.")
8773 }
8874 }
8975}