on xenial help sign in
merged with trunk
commit031898fa21dc05b1161b88c0b40aad92c46ca555 authorNick Dedekind <nicholas.dedekind@gmail.com> dateTue 16 Jul 2013, 22:04 (13 years ago) parent99aa1a8a841ebd
117 files changed+3421−1138
CMakeLists.txt+3−4 CODING+5−6 Components/OpenEffect.qml+9−1 Components/Showable.qml+5−14 Dash/Apps/ApplicationsFilterGrid.qml+3−3 Dash/DashApps.qml+10−8 Dash/DashHome.qml+20−31 Dash/DashVideos.qml+2−2 Dash/Generic/GenericPreview.qml+84 Dash/GenericScopeView.qml+121−2 Dash/Music/CarouselDelegateMusic.qml+1−1 Dash/Music/MusicFilterGrid.qml+3−3 Launcher/ShortcutsContainer.qml → Dash/PreviewDelegateMapper.qml+13−18 Dash/Video/CarouselDelegateVideo.qml+1−1 Dash/Video/VideosFilterGrid.qml+4−4 Launcher/Launcher.qml+2−5 Launcher/LauncherPanel.qml+4−2 Panel/Indicators/NetworkIndicatorPage.qml+1−2 Shell.qml−3 build+2−6 cmake/modules/Plugins.cmake+48 cmake/modules/autopilot.cmake+7−4 debian/changelog+103 debian/control+42−37 debian/unity8-autopilot.install−1 plugins/HudClient/CMakeLists.txt+5−12 plugins/HudClient/qmldir+1 plugins/LightDM/CMakeLists.txt+5−12 plugins/LightDM/qmldir+1 plugins/ListViewWithPageHeader/CMakeLists.txt+5−12 plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+16 plugins/ListViewWithPageHeader/listviewwithpageheader.h+3 plugins/ListViewWithPageHeader/qmldir+1 plugins/Ubuntu/Gestures/CMakeLists.txt+5−13 plugins/Ubuntu/Gestures/qmldir+1 plugins/Unity/CMakeLists.txt+9−14 plugins/Unity/Indicators/Network/qml/PasswordPage.qml+1−1 plugins/Unity/Indicators/qml/SliderMenuItem.qml+7−1 plugins/Unity/Launcher/CMakeLists.txt+27 plugins/Unity/Launcher/backend/launcherbackend.cpp+145 plugins/Unity/Launcher/backend/launcherbackend.h+132 plugins/Unity/categoryfilter.cpp → plugins/Unity/Launcher/common/quicklistentry.cpp+28−19 plugins/Unity/Launcher/common/quicklistentry.h+44 plugins/Unity/Launcher/launcheritem.cpp+127 plugins/Unity/Launcher/launcheritem.h+76 plugins/Unity/Launcher/launchermodel.cpp+170 plugins/Unity/Launcher/launchermodel.h+61 plugins/Unity/Launcher/plugin.cpp+47 plugins/Unity/categoryfilter.h → plugins/Unity/Launcher/plugin.h+10−24 plugins/Unity/Launcher/qmldir+2 plugins/Unity/Launcher/quicklistmodel.cpp+60 plugins/Unity/Launcher/quicklistmodel.h+48 plugins/Unity/categories.cpp+56−42 plugins/Unity/categories.h+13−16 plugins/Unity/categoryresults.cpp+96 plugins/Unity/categoryresults.h+67 plugins/Unity/genericpreview.cpp+5 plugins/Unity/genericpreview.h+6 plugins/Unity/launchermodel.cpp−153 plugins/Unity/launchermodel.h−86 plugins/Unity/plugin.cpp+4−5 plugins/Unity/preview.cpp+4 plugins/Unity/previewaction.h+1−1 plugins/Unity/qmldir+1 plugins/Unity/scope.cpp+19−57 plugins/Unity/scope.h+8−12 plugins/Unity/socialpreview.cpp+83 plugins/Unity/socialpreview.h+63 plugins/Unity/socialpreviewcomment.cpp+63 plugins/Unity/socialpreviewcomment.h+57 plugins/Utils/CMakeLists.txt+2−12 plugins/Utils/qmldir+1 po/es.po+7−31 run_on_device+1−3 src/Panel/Indicators/client/indicatorsclient.cpp+20−10 tests/autopilot/unity8/indicators_client/__init__.py+8 tests/autopilot/indicators_client/emulators/__init__.py → tests/autopilot/unity8/indicators_client/emulators/__init__.py tests/autopilot/indicators_client/emulators/common.py → tests/autopilot/unity8/indicators_client/emulators/common.py tests/autopilot/indicators_client/emulators/main_window.py → tests/autopilot/unity8/indicators_client/emulators/main_window.py−2 tests/autopilot/indicators_client/tests/__init__.py → tests/autopilot/unity8/indicators_client/tests/__init__.py+22−8 tests/autopilot/indicators_client/tests/test_battery.py → tests/autopilot/unity8/indicators_client/tests/test_battery.py+14−11 tests/autopilot/indicators_client/__init__.py → tests/autopilot/unity8/shell/__init__.py+1−1 tests/autopilot/unity8/emulators/__init__.py → tests/autopilot/unity8/shell/emulators/__init__.py tests/autopilot/unity8/emulators/main_window.py → tests/autopilot/unity8/shell/emulators/main_window.py tests/autopilot/unity8/tests/__init__.py → tests/autopilot/unity8/shell/tests/__init__.py+1−1 tests/autopilot/unity8/tests/helpers.py → tests/autopilot/unity8/shell/tests/helpers.py tests/autopilot/unity8/tests/testbigscreen.py → tests/autopilot/unity8/shell/tests/testbigscreen.py+1−1 tests/autopilot/unity8/tests/testhud.py → tests/autopilot/unity8/shell/tests/testhud.py+2−2 tests/autopilot/unity8/tests/testlockscreen.py → tests/autopilot/unity8/shell/tests/testlockscreen.py+2−2 tests/mocks/LightDM/demo/InfographicModelPrivate.cpp+3−3 tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1 tests/mocks/Unity/CMakeLists.txt+4−4 tests/mocks/Unity/Launcher/CMakeLists.txt+26 tests/mocks/Unity/Launcher/MockLauncherItem.cpp+134 tests/mocks/Unity/Launcher/MockLauncherItem.h+70 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+152 tests/mocks/Unity/Launcher/MockLauncherModel.h+54 tests/mocks/Unity/Launcher/MockQuickListModel.cpp+46 tests/mocks/Unity/Launcher/MockQuickListModel.h+38 tests/mocks/Unity/Launcher/plugin.cpp+45 tests/mocks/Unity/Launcher/plugin.h+35 tests/mocks/Unity/Launcher/qmldir+2 tests/mocks/Unity/fake_categories.cpp+178 tests/mocks/Unity/fake_categories.h+69 tests/mocks/Unity/fake_launchermodel.cpp−150 tests/mocks/Unity/fake_launchermodel.h−86 tests/mocks/Unity/fake_scope.cpp+104−73 tests/mocks/Unity/fake_scope.h+43−11 tests/mocks/Unity/fake_unity_plugin.cpp+3−6 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+58 tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+60 tests/plugins/Unity/CMakeLists.txt+1−1 tests/plugins/Unity/previewbindingstest.cpp+113−58 tests/plugins/Unity/previewbindingstest.h+1 tests/qmltests/Components/tst_OpenEffect.qml+1−1 tests/qmltests/Dash/qml/FakeScopeView.qml+2−2 tests/qmltests/Dash/tst_FilterGrids.qml+20−20
CMakeLists.txt+3−4
@@ -91,10 +91,8 @@ enable_testing()
9191
9292# Autopilot tests
9393include(autopilot)
94−declare_autopilot_test(unity8 ${CMAKE_SOURCE_DIR}/tests/autopilot/)
95−declare_autopilot_test(indicators_client ${CMAKE_SOURCE_DIR}/tests/autopilot/)
96−
97−add_subdirectory(tests)
94+declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
95+declare_autopilot_test(indicators_client unity8.indicators_client ${CMAKE_SOURCE_DIR}/tests/autopilot/)
9896
9997set(SHELL_APP unity8)
10098
@@ -133,6 +131,7 @@ install(FILES ${QML_JS_FILES}
133131 )
134132
135133# add subdirectories to build
134+add_subdirectory(tests)
136135add_subdirectory(plugins)
137136add_subdirectory(src)
138137
CODING+5−6
@@ -23,15 +23,12 @@ $ cd ~/unity8/trunk
2323$ ./build --setup
2424
2525 this will:
26− - add the following PPA's
27− - ppa:phablet-team/desktop-deps
28− - ppa:canonical-qt5-edgers/qt5-proper
29− - ppa:ubuntu-sdk-team
26+ - add ppa:ubuntu-unity/next
3027 - install the required dependencies to build, as well as run on the desktop
3128 - it should also install unity-scope-home and unity-lens-application which
3229 are technically "recommends", not strict dependencies
3330
34−Note, once the PPA's are added, the script runs apt-get update, if you have
31+Note, once the PPA is added, the script runs apt-get update, if you have
3532any failures associated with it, the build script will bail out of the setup
3633and fail to install all the required dependencies.
3734
@@ -45,6 +42,7 @@ $ ./build
4542You may also rebuild with the -c for clean, which just deletes the build
4643directory.
4744
45+
4846Running Unity 8 on your desktop
4947===============================
5048
@@ -73,6 +71,7 @@ Notes
7371 - Create an EDS address book
7472 - Populate the address book with sample data
7573
74+
7675Running Unity 8 on devices
7776==========================
7877- Ubuntu Touch builds are currently only available in 13.10 flavour
@@ -91,7 +90,6 @@ $ cd ~/unity/trunk
9190$ ./run_on_device --setup
9291 this will:
9392 - install your public SSH key on the device
94− - add ppa:canonical-qt5-edgers/qt5-proper and ppa:phablet-team
9593 - install the needed dependencies
9694
9795$ ./run_on_device
@@ -109,6 +107,7 @@ $ ./run_on_device -p OR -k
109107Notes
110108-----
111109- using adb over TCP has some advantages, Google will be of help here
110+ - NOTE: this is not yet available for flipped images
112111 - TL;DR: `adb tcpip 5555; adb connect $your_device_ip`
113112 - you can persist the above via `adb shell setprop persist.adb.tcp.port 5555`
114113 - it's unsafe - anyone can connect to your device
Components/OpenEffect.qml+9−1
@@ -19,11 +19,13 @@ import QtQuick 2.0
1919Item {
2020 id: effect
2121 property bool enabled: topGapPx != positionPx || bottomGapPx != positionPx
22+ property alias live: effectSource.live
2223 property Item sourceItem
2324 property ShaderEffectSource source: ShaderEffectSource {
25+ id: effectSource
2426 sourceItem: effect.enabled ? effect.sourceItem : null
2527 hideSource: effect.enabled
26− live: effect.enabled
28+ live: false
2729 sourceRect: {
2830 if (effect.enabled) {
2931 Qt.rect(0, -effect.topOverflow, sourceItem.width, sourceItem.height + effect.topOverflow + effect.bottomOverflow)
@@ -33,6 +35,8 @@ Item {
3335 }
3436 }
3537
38+ onEnabledChanged: if (!live && enabled) scheduleUpdate()
39+
3640 /*!
3741 \qmlproperty real positionPx
3842 The y coordinate of where to perform the split.
@@ -60,6 +64,10 @@ Item {
6064
6165 property real __roundedPositionPx: Math.round(positionPx)
6266
67+ function scheduleUpdate() {
68+ source.scheduleUpdate();
69+ }
70+
6371 ShaderEffect {
6472 id: top
6573 visible: effect.enabled
Components/Showable.qml+5−14
@@ -52,7 +52,7 @@ Item {
5252 function show() {
5353 required = true;
5454 if (created) {
55− __reallyShow(true);
55+ __reallyShow();
5656 } else {
5757 __shouldShow = true;
5858 }
@@ -60,16 +60,12 @@ Item {
6060
6161 onCreatedChanged: {
6262 if (created && __shouldShow) {
63− __reallyShow(true);
63+ __reallyShow();
6464 __shouldShow = false;
6565 }
6666 }
6767
68− function showWithoutAnimation() {
69− __reallyShow(false);
70− }
71−
72− function __reallyShow(animated) {
68+ function __reallyShow() {
7369 if (!available) {
7470 return false;
7571 }
@@ -81,13 +77,8 @@ Item {
8177 }
8278
8379 if (showAnimation != undefined) {
84− if (animated) {
85− if (!showAnimation.running) {
86− showAnimation.restart()
87− }
88− } else {
89− showAnimation.start();
90− showAnimation.complete();
80+ if (!showAnimation.running) {
81+ showAnimation.restart()
9182 }
9283 } else {
9384 visible = true;
Dash/Apps/ApplicationsFilterGrid.qml+3−3
@@ -36,7 +36,7 @@ FilterGrid {
3636 objectName: "delegate" + index
3737 Application {
3838 id: application
39− desktopFile: model.column_7 ? stripProtocol(model.column_7) : model.desktopFile // FIXME: this is temporary
39+ desktopFile: model.dndUri ? stripProtocol(model.dndUri) : model.desktopFile // FIXME: this is temporary
4040
4141 function stripProtocol(uri) {
4242 var chunks = uri.split('file://')
@@ -44,11 +44,11 @@ FilterGrid {
4444 }
4545 }
4646
47− property string icon: model.column_1 ? model.column_1 : "../../graphics/applicationIcons/" + application.icon + ".png" // FIXME: this is temporary
47+ property string icon: model.icon ? model.icon : "../../graphics/applicationIcons/" + application.icon + ".png" // FIXME: this is temporary
4848
4949 width: filterGrid.cellWidth
5050 height: filterGrid.cellHeight
51− text: model.column_5 ? model.column_5 : application.name // FIXME: this is temporary
51+ text: model.title ? model.title : application.name // FIXME: this is temporary
5252 imageWidth: units.gu(8)
5353 imageHeight: units.gu(7.5)
5454 source: IconUtil.from_gicon(icon)
Dash/DashApps.qml+10−8
@@ -81,17 +81,19 @@ ScopeView {
8181 AppsAvailableForDownloadModel { id: appsAvailableForDownloadModel }
8282
8383 // FIXME this should not be needed, the backend should handle all that itself
84− SortFilterProxyModel {
85− id: installedFilter
86− dynamicSortFilter: true
87− filterRole: 2 // this is the category id for each result
88− filterRegExp: /^3$/ // only proxy items that are category 3 - Installed
89− model: dashContent.scopes.get("applications.scope").results
84+ property var installedModel: null
85+
86+ Repeater {
87+ model: scopeView.scope.categories
88+
89+ delegate: Item {
90+ Component.onCompleted: if (index == 3) scopeView.installedModel = Qt.binding(function() { return model.results; });
91+ }
9092 }
9193
9294 property var categoryModels: {
9395 "FrequentlyUsedAppsModel": frequentlyUsedAppsModel,
94− "InstalledApplicationsModel": installedFilter,
96+ "InstalledApplicationsModel": installedModel,
9597 "AppsAvailableForDownloadModel": appsAvailableForDownloadModel,
9698 }
9799
@@ -134,7 +136,7 @@ ScopeView {
134136 shell.activateApplication(data);
135137 }
136138
137− item.model = categoryModels[modelName]
139+ item.model = Qt.binding(function() { return categoryModels[modelName]; });
138140 item.clicked.connect(activateApplication);
139141
140142 }
Dash/DashHome.qml+20−31
@@ -52,42 +52,33 @@ ScopeView {
5252 FrequentlyUsedAppsModel { id: appsModel }
5353
5454 // FIXME this should be handled by the backends by populating the global search model
55− SortFilterProxyModel {
56− id: favouritesFilter
57− dynamicSortFilter: true
58− filterRole: 2
59− filterRegExp: /^0$/
60− }
55+ property var musicModel: null
56+ property var videosModel: null
6157
62− SortFilterProxyModel {
63− id: recentFilter
64− dynamicSortFilter: true
65− filterRole: 2
66− filterRegExp: /^2$/
67− }
58+ Repeater {
59+ id: musicRepeater
6860
69− SortFilterProxyModel {
70− id: musicFilter
71− dynamicSortFilter: true
72− filterRole: 2
73− filterRegExp: /^1$/
61+ delegate: Item {
62+ Component.onCompleted: if (index == 1) musicModel = Qt.binding(function() { return model.results; });
63+ }
7464 }
7565
76− SortFilterProxyModel {
77− id: videosFilter
78− dynamicSortFilter: true
79− filterRole: 2
80− filterRegExp: /^3$/
66+ Repeater {
67+ id: videosRepeater
68+
69+ delegate: Item {
70+ Component.onCompleted: if (index == 3) videosModel = Qt.binding(function() { return model.results; });
71+ }
8172 }
8273
8374 Component.onCompleted: {
8475 var scope = dashContent.scopes.get("mockmusicmaster.scope")
8576 if (scope) {
86− musicFilter.model = dashContent.scopes.get("mockmusicmaster.scope").results
77+ musicRepeater.model = dashContent.scopes.get("mockmusicmaster.scope").categories
8778 }
8879 scope = dashContent.scopes.get("mockvideosmaster.scope")
8980 if (scope) {
90− videosFilter.model = dashContent.scopes.get("mockvideosmaster.scope").results
81+ videosRepeater.model = dashContent.scopes.get("mockvideosmaster.scope").categories
9182 }
9283 }
9384
@@ -95,19 +86,17 @@ ScopeView {
9586 target: dashContent
9687 onScopeLoaded: switch (scopeId) {
9788 case "mockmusicmaster.scope":
98− musicFilter.model = dashContent.scopes.get("mockmusicmaster.scope").results
89+ musicRepeater.model = dashContent.scopes.get("mockmusicmaster.scope").categories
9990 break;
10091 case "mockvideosmaster.scope":
101− videosFilter.model = dashContent.scopes.get("mockvideosmaster.scope").results
92+ videosRepeater.model = dashContent.scopes.get("mockvideosmaster.scope").categories
10293 break;
10394 }
10495 }
10596
10697 property var categoryModels: {"AppsModel": appsModel,
107− "FavouriteModel": favouritesFilter,
108− "RecentModel": recentFilter,
109− "MusicModel": musicFilter,
110− "VideosModel": videosFilter,
98+ "MusicModel": musicModel,
99+ "VideosModel": videosModel,
111100 }
112101
113102 ScopeListView {
@@ -127,7 +116,7 @@ ScopeView {
127116 anchors { top: parent.top; left: parent.left; right: parent.right }
128117 source: component
129118 onLoaded: {
130− item.model = categoryModels[modelName]
119+ item.model = Qt.binding(function() { return categoryModels[modelName]; });
131120
132121 //FIXME: workaround for lack of previews for videos in Home scope.
133122 //Need to connect to the clicked() signal here and act upon it here instead.
Dash/DashVideos.qml+2−2
@@ -120,8 +120,8 @@ ScopeView {
120120 // VideosCarousel and VideosFilterGrid have different
121121 // clicked signals, accomodate for that
122122 if (categoryId == 1) {
123− var fileUri = delegateItem.model.column_0.replace(/^[^:]+:/, "")
124− dataItem = {fileUri: fileUri, nfoUri: delegateItem.model.column_6}
123+ var fileUri = delegateItem.model.uri.replace(/^[^:]+:/, "")
124+ dataItem = {fileUri: fileUri, nfoUri: delegateItem.model.comment}
125125 } else {
126126 dataItem = data;
127127 }
Dash/Generic/GenericPreview.qmlnew file+84
@@ -0,0 +1,84 @@
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 "../../Components/IconUtil.js" as IconUtil
22+import ".."
23+
24+DashPreview {
25+ id: genericPreview
26+ property var previewData
27+
28+ title: previewData.title
29+ url: IconUtil.from_gicon(previewData.image)
30+ previewWidthRatio: 0.6
31+
32+ buttons: GridView {
33+ id: buttons
34+ model: genericPreview.previewData.actions
35+
36+ property int numOfRows: (count + 1) / 2
37+ property int spacing: units.gu(1)
38+ height: Math.max(units.gu(4), units.gu(4)*numOfRows + spacing*(numOfRows - 1))
39+
40+ cellWidth: Math.max(units.gu(9), width / 2)
41+ cellHeight: buttonHeight + spacing
42+ property int buttonWidth: Math.max(0, width / 2 - spacing)
43+ property int buttonHeight: units.gu(4)
44+
45+ delegate: Button {
46+ width: Math.max(units.gu(4), buttons.buttonWidth)
47+ height: buttons.buttonHeight
48+ color: "#dd4814"
49+ text: modelData.displayName
50+ iconSource: modelData.iconHint
51+ iconPosition: "right"
52+ visible: true
53+ onClicked: {
54+ genericPreview.previewData.execute(modelData.id, { })
55+ }
56+ }
57+ focus: false
58+ }
59+ description: Column {
60+ spacing: units.gu(2)
61+
62+ Label {
63+ visible: text != ""
64+ fontSize: "medium"
65+ opacity: 0.6
66+ color: "white"
67+ text: previewData.subtitle
68+ style: Text.Raised
69+ styleColor: "black"
70+ wrapMode: Text.WordWrap
71+ }
72+
73+ Label {
74+ visible: text != ""
75+ fontSize: "small"
76+ opacity: 0.6
77+ color: "white"
78+ text: previewData.description
79+ style: Text.Raised
80+ styleColor: "black"
81+ wrapMode: Text.WordWrap
82+ }
83+ }
84+}
Dash/GenericScopeView.qml+121−2
@@ -22,6 +22,7 @@ import "../Components/IconUtil.js" as IconUtil
2222
2323ScopeView {
2424 id: scopeView
25+ property alias previewShown: previewLoader.onScreen
2526
2627 onIsCurrentChanged: {
2728 pageHeader.resetSearch();
@@ -47,6 +48,8 @@ ScopeView {
4748 id: categoryView
4849 anchors.fill: parent
4950 model: scopeView.categories
51+ forceNoClip: previewLoader.onScreen
52+
5053 onAtYEndChanged: if (atYEnd) endReached()
5154 onMovingChanged: if (moving && atYEnd) endReached()
5255
@@ -72,10 +75,35 @@ ScopeView {
7275 delegate: Tile {
7376 width: filtergrid.cellWidth
7477 height: filtergrid.cellHeight
75− text: column_5 ? column_5 : "" // FIXME: this shouldn't be necessary
78+ text: title
7679 imageWidth: units.gu(11)
7780 imageHeight: units.gu(16)
78− source: column_1 ? IconUtil.from_gicon(column_1) : "" // FIXME: ditto
81+
82+ source: IconUtil.from_gicon(icon)
83+
84+ MouseArea {
85+ anchors {
86+ fill: parent
87+ }
88+ onClicked: {
89+ mouse.accepted = true
90+ effect.positionPx = mapToItem(categoryView, 0, 0).y
91+ scopeView.scope.activate(uri, icon,
92+ category, 0,
93+ mimetype, title,
94+ comment, dndUri,
95+ metadata)
96+ }
97+ onPressAndHold: {
98+ mouse.accepted = true
99+ effect.positionPx = mapToItem(categoryView, 0, 0).y
100+ scopeView.scope.preview(uri, icon,
101+ category, 0,
102+ mimetype, title,
103+ comment, dndUri,
104+ metadata)
105+ }
106+ }
79107 }
80108 }
81109 }
@@ -93,4 +121,95 @@ ScopeView {
93121 searchEntryEnabled: true
94122 }
95123 }
124+
125+ OpenEffect {
126+ id: effect
127+ anchors {
128+ fill: parent
129+ bottomMargin: -bottomOverflow
130+ }
131+ sourceItem: categoryView
132+
133+ enabled: gap > 0.0
134+
135+ topGapPx: (1 - gap) * positionPx
136+ topOpacity: (1 - gap * 1.2)
137+ bottomGapPx: positionPx + gap * (targetBottomGapPx - positionPx)
138+ bottomOverflow: units.gu(20)
139+ bottomOpacity: 1 - (gap * 0.8)
140+
141+ property int targetBottomGapPx: height - units.gu(8) - bottomOverflow
142+ property real gap: previewLoader.open ? 1.0 : 0.0
143+
144+ Behavior on gap {
145+ NumberAnimation {
146+ duration: 200
147+ easing.type: Easing.InOutQuad
148+ onRunningChanged: {
149+ if (!previewLoader.open && !running) {
150+ previewLoader.onScreen = false
151+ }
152+ }
153+ }
154+ }
155+ }
156+
157+ Connections {
158+ target: scopeView.scope
159+ onPreviewReady: {
160+ previewLoader.previewData = preview
161+ previewLoader.open = true
162+ }
163+ }
164+
165+ PreviewDelegateMapper {
166+ id: previewDelegateMapper
167+ }
168+
169+ Connections {
170+ ignoreUnknownSignals: true
171+ target: previewLoader.valid ? previewLoader.item : null
172+ onClose: {
173+ previewLoader.open = false
174+ }
175+ }
176+
177+ Loader {
178+ id: previewLoader
179+ property var previewData
180+ height: effect.bottomGapPx - effect.topGapPx
181+ anchors {
182+ top: parent.top
183+ topMargin: effect.topGapPx
184+ left: parent.left
185+ right: parent.right
186+ }
187+ source: onScreen ? previewDelegateMapper.map(previewLoader.previewData.rendererName) : ""
188+
189+ property bool open: false
190+ property bool onScreen: false
191+ property bool valid: item !== null
192+
193+ onOpenChanged: {
194+ if (open) {
195+ onScreen = true
196+ }
197+ }
198+
199+ onLoaded: {
200+ item.previewData = previewLoader.previewData
201+ }
202+ }
203+
204+ // TODO: Move as InverseMouseArea to DashPreview
205+ MouseArea {
206+ enabled: previewLoader.onScreen
207+ anchors {
208+ fill: parent
209+ topMargin: effect.bottomGapPx
210+ }
211+ onClicked: {
212+ previewLoader.open = false;
213+ }
214+ }
96215}
Dash/Music/CarouselDelegateMusic.qml+1−1
@@ -28,7 +28,7 @@ BaseCarouselDelegate {
2828 image: Image {
2929 asynchronous: true
3030 sourceSize { width: item.width; height: item.height }
31− source: model ? model.column_1 : ""
31+ source: model ? model.icon : ""
3232 }
3333 }
3434
Dash/Music/MusicFilterGrid.qml+3−3
@@ -38,9 +38,9 @@ FilterGrid {
3838 height: filterGrid.cellHeight
3939 iconWidth: filterGrid.iconWidth
4040 iconHeight: filterGrid.iconHeight
41− artist: model.column_5
42− album: model.column_6
43− source: model.column_1
41+ artist: model.title
42+ album: model.comment
43+ source: model.icon
4444 onClicked: {
4545 filterGrid.clicked(index);
4646 }
Launcher/ShortcutsContainer.qml → Dash/PreviewDelegateMapper.qmlrenamed+13−18
@@ -16,24 +16,19 @@
1616
1717import QtQuick 2.0
1818
19−Column {
20− id: shortcutsContainer
21−
22− property int foldedAngle: 0
23− property int initialFoldedOffset: 0
24− property int foldedOffset: 0
25− property int initialIndex: 0
26−
27− property bool animating: angleAnimation.running || offsetAnimation.running
28−
29− property ListModel model
30− property var delegate
31−
32− Behavior on foldedAngle { NumberAnimation { id: angleAnimation; duration: 200; } }
33− Behavior on foldedOffset { NumberAnimation { id: offsetAnimation; duration: 200; } }
19+QtObject {
20+ property var d: QtObject {
21+ readonly property string genericPreview: "Generic/GenericPreview.qml"
22+ property var previewDelegateMapping: {"preview-generic": genericPreview,
23+ }
24+ }
3425
35− Repeater {
36− model: shortcutsContainer.model
37− delegate: shortcutsContainer.delegate
26+ function map(rendererName) {
27+ var customPreview = d.previewDelegateMapping[rendererName]
28+ if (customPreview != undefined) {
29+ return customPreview
30+ }
31+ console.debug("Renderer "+rendererName+" not found, using preview-generic")
32+ return d.genericPreview
3833 }
3934}
Dash/Video/CarouselDelegateVideo.qml+1−1
@@ -28,7 +28,7 @@ BaseCarouselDelegate {
2828 image: Image {
2929 asynchronous: true
3030 sourceSize { width: item.width; height: item.height }
31− source: model ? model.column_1 : ""
31+ source: model ? model.icon : ""
3232 }
3333 }
3434
Dash/Video/VideosFilterGrid.qml+4−4
@@ -37,14 +37,14 @@ FilterGrid {
3737 objectName: "delegate" + index
3838 width: filtergrid.cellWidth
3939 height: filtergrid.cellHeight
40− text: model.column_5
40+ text: model.title
4141 imageWidth: filtergrid.iconWidth
4242 imageHeight: filtergrid.iconHeight
43− source: model.column_1
43+ source: model.icon
4444 fillMode: Image.PreserveAspectCrop
4545 onClicked: {
46− var fileUri = model.column_0.replace(/^[^:]+:/, "")
47− var data = {fileUri: fileUri, nfoUri: model.column_6}
46+ var fileUri = model.uri.replace(/^[^:]+:/, "")
47+ var data = {fileUri: fileUri, nfoUri: model.comment}
4848 filtergrid.clicked(index, data, tile.y);
4949 }
5050 }
Launcher/Launcher.qml+2−5
@@ -19,6 +19,7 @@ import "../Components"
1919import Ubuntu.Components 0.1
2020import Ubuntu.Gestures 0.1
2121import Unity 0.1
22+import Unity.Launcher 0.1
2223
2324Item {
2425 id: root
@@ -96,10 +97,6 @@ Item {
9697 }
9798 }
9899
99− LauncherModel {
100− id: launcherModel
101− }
102−
103100 MouseArea {
104101 id: launcherDragArea
105102 enabled: root.state == "visible"
@@ -152,7 +149,7 @@ Item {
152149 bottom: parent.bottom
153150 }
154151 x: -width
155− model: launcherModel
152+ model: LauncherModel
156153
157154 property bool animate: true
158155
Launcher/LauncherPanel.qml+4−2
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Unity 0.1
20+import Unity.Launcher 0.1
2021import "../Components/ListItems"
2122
2223Item {
@@ -83,6 +84,7 @@ Item {
8384 height: width
8485 anchors.centerIn: parent
8586 source: "graphics/home.png"
87+ rotation: root.rotation
8688 }
8789 }
8890 ThinDivider {
@@ -139,7 +141,7 @@ Item {
139141 } else if (angle < -12) {
140142 launcherListView.flick(0, launcherListView.clickFlickSpeed);
141143 } else {
142− root.applicationSelected(launcherModel.get(index).desktopFile);
144+ root.applicationSelected(LauncherModel.get(index).desktopFile);
143145 }
144146 return;
145147 }
@@ -150,7 +152,7 @@ Item {
150152 } else if (angle < -30) {
151153 launcherListView.flick(0, launcherListView.clickFlickSpeed);
152154 } else {
153− root.applicationSelected(launcherModel.get(index).desktopFile);
155+ root.applicationSelected(LauncherModel.get(index).desktopFile);
154156 }
155157 }
156158 }
Panel/Indicators/NetworkIndicatorPage.qml+1−2
@@ -49,7 +49,6 @@ PageStack {
4949
5050 ICNetwork.PasswordPage {
5151 agent: networkAgent
52− token: token
5352 }
5453 }
5554
@@ -57,7 +56,7 @@ PageStack {
5756 id: networkAgent
5857
5958 onSecretRequested: {
60− _network.push(passwordPageComponent);
59+ _network.push(passwordPageComponent, {"token": token});
6160 }
6261 }
6362
Shell.qml−3
@@ -263,9 +263,6 @@ FocusScope {
263263 function show() {
264264 stages.show();
265265 }
266− function showWithoutAnimation() {
267− stages.showWithoutAnimation();
268− }
269266 function hide() {
270267 }
271268
build+2−6
@@ -36,16 +36,12 @@ BUILD_TYPE="debug"
3636[ $# -eq 1 ] && BUILD_TYPE="$1"
3737
3838install_dependencies() {
39− [ -f /etc/apt/sources.list.d/phablet-team-desktop-deps-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:phablet-team/desktop-deps || exit 1
40− [ -f /etc/apt/sources.list.d/canonical-qt5-edgers-qt5-proper-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:canonical-qt5-edgers/qt5-proper || exit 2;
41− [ -f /etc/apt/sources.list.d/ubuntu-sdk-team-ppa-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:ubuntu-sdk-team/ppa || exit 3
39+ [ -f /etc/apt/sources.list.d/ubuntu-unity-next-${DISTRIB_CODENAME}.list ] || sudo add-apt-repository ppa:ubuntu-unity/next || exit 1
4240 sudo apt-get update || exit 4
4341 echo "Installing Unity 8 dependencies.."
4442 sudo apt-get install devscripts \
4543 equivs \
46− libnm-glib-dev \
47− libnm-util-dev \
48− libqmenumodel-dev \
44+ qmenumodel-qml \
4945 qtdeclarative5-ubuntu-ui-toolkit-plugin \
5046 qtdeclarative5-dee-plugin \
5147 ubuntu-mobile-icons \
cmake/modules/Plugins.cmakenew file+48
@@ -0,0 +1,48 @@
1+# Creates targets for copying and installing qmlfiles and generating the qmltypes file for a plugin
2+#
3+# export_qmlplugin(plugin version sub_path [TARGETS target1 [target2 ...]])
4+#
5+# TARGETS additional install targets (eg the plugin shared object)
6+#
7+# Two targets will be created:
8+# - 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+
12+macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
13+ set(multi_value_keywords TARGETS)
14+ cmake_parse_arguments(qmlplugin "" "" "${multi_value_keywords}" ${ARGN})
15+
16+ file(GLOB QMLFILES
17+ *.qml
18+ *.js
19+ qmldir
20+ )
21+
22+ # copy the qmldir file
23+ add_custom_target(${PLUGIN}-qmlfiles ALL
24+ COMMAND cp ${QMLFILES} ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}
25+ DEPENDS ${QMLFILES}
26+ )
27+
28+ # create the plugin.qmltypes file
29+ add_custom_target(${PLUGIN}-qmltypes ALL
30+ COMMAND qmlplugindump -notrelocatable ${PLUGIN} ${VERSION} ${CMAKE_BINARY_DIR}/plugins > ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
31+ )
32+ add_dependencies(${PLUGIN}-qmltypes ${PLUGIN}-qmlfiles ${qmlplugin_TARGETS})
33+
34+ # install the qmldir file.
35+ install(FILES ${QMLFILES}
36+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
37+ )
38+
39+ # install the qmltypes file.
40+ install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
41+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
42+ )
43+
44+ # install the additional targets
45+ install(TARGETS ${qmlplugin_TARGETS}
46+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
47+ )
48+endmacro(export_qmlplugin)
cmake/modules/autopilot.cmake+7−4
@@ -1,7 +1,10 @@
11add_custom_target(autopilot)
22
3−function(declare_autopilot_test TEST_NAME WORKING_DIR)
4− add_custom_command(TARGET autopilot
5− COMMAND autopilot run ${TEST_NAME}
6− WORKING_DIRECTORY ${WORKING_DIR})
3+function(declare_autopilot_test TEST_NAME TEST_SUITE WORKING_DIR)
4+ add_custom_target(autopilot-${TEST_NAME}
5+ COMMAND autopilot run ${TEST_SUITE}
6+ WORKING_DIRECTORY ${WORKING_DIR}
7+ )
8+
9+ add_dependencies(autopilot autopilot-${TEST_NAME})
710endfunction()
debian/changelog+103
@@ -1,3 +1,106 @@
1+unity8 (7.81.3+13.10.20130716ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2+
3+ [ Pete Woods ]
4+ * Rename the demo user "single" to "phablet" Fix the infographics on
5+ the device At the moment the mock lightdm backend we are using says
6+ the current user is called "single", while in reality the processes
7+ all run as the "phablet" user.
8+
9+ [ Michał Sawicz ]
10+ * Only use ppa:ubuntu-unity/next and clean build scripts and CODING,
11+ accordingly.
12+ * Do not recommend indicator-power and indicator-sound. On device
13+ they're provided by lp:indicator-server for the time being.
14+ * Fix the Network page to provide the correct token. (LP: #1201529)
15+
16+ [ Ubuntu daily release ]
17+ * Automatic snapshot from revision 109 (ubuntu-unity/next)
18+
19+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 16 Jul 2013 02:32:03 +0000
20+
21+unity8 (7.81.3+13.10.20130714ubuntu.unity.next-0ubuntu1) saucy; urgency=low
22+
23+ [ Michael Terry ]
24+ * Change Ok to OK. (LP: #1131842)
25+
26+ [ Ubuntu daily release ]
27+ * Automatic snapshot from revision 104 (ubuntu-unity/next)
28+
29+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Sun, 14 Jul 2013 02:31:57 +0000
30+
31+unity8 (7.81.3+13.10.20130712ubuntu.unity.next-0ubuntu1) saucy; urgency=low
32+
33+ [ Michael Zanetti ]
34+ * Make use of the launcher API defined in unity-api and separate the
35+ model from the backend.
36+
37+ [ Michał Sawicz ]
38+ * Issue wrap-and-sort -abt on debian/.
39+
40+ [ Nick Dedekind ]
41+ * Moved indicators-client code into unity8. (LP: #1191132, #1191822)
42+
43+ [ Ubuntu daily release ]
44+ * Automatic snapshot from revision 102 (ubuntu-unity/next)
45+
46+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 12 Jul 2013 02:31:59 +0000
47+
48+unity8 (7.81.3+13.10.20130711ubuntu.unity.next-0ubuntu1) saucy; urgency=low
49+
50+ [ Michael Zanetti ]
51+ * invert the home button too in case the whole panel is inverted. (LP:
52+ #1199622)
53+
54+ [ Michał Sawicz ]
55+ * Make the OpenEffect non-live by default to improve performance. (LP:
56+ #1124584)
57+
58+ [ Ying-Chun Liu ]
59+ * Add Generic Preview. Modify GenericScopeView to support activate and
60+ preview.
61+
62+ [ Ubuntu daily release ]
63+ * Automatic snapshot from revision 98 (ubuntu-unity/next)
64+
65+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 11 Jul 2013 03:00:53 +0000
66+
67+unity8 (7.81.3+13.10.20130710ubuntu.unity.next-0ubuntu1) saucy; urgency=low
68+
69+ [ Michael Zanetti ]
70+ * removed unused old file ShortcutsContainer.qml.
71+
72+ [ Michał Sawicz ]
73+ * Fix fetching data from scopes in the custom scope pages. (LP:
74+ #1199322)
75+
76+ [ Ying-Chun Liu ]
77+ * Fix references to scope data. (LP: #1199322)
78+
79+ [ Albert Astals ]
80+ * Fix showHeader animation when the header is half shown at top .
81+ * Disable -pedantic on the private Qt headers .
82+
83+ [ Pawel Stolowski ]
84+ * Bindings for SocialPreview.
85+
86+ [ Ubuntu daily release ]
87+ * Automatic snapshot from revision 94 (ubuntu-unity/next)
88+
89+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 10 Jul 2013 02:32:00 +0000
90+
91+unity8 (7.81.3+13.10.20130709ubuntu.unity.next-0ubuntu1) saucy; urgency=low
92+
93+ [ Michal Hruby ]
94+ * Implement CategoryResults based on DeeFilterModel.
95+
96+ [ Nick Dedekind ]
97+ * Added plugin cmake procedure for qmltypes files.
98+
99+ [ Ubuntu daily release ]
100+ * Automatic snapshot from revision 86 (ubuntu-unity/next)
101+
102+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 09 Jul 2013 02:58:58 +0000
103+
1104unity8 (7.81.3+13.10.20130708ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2105
3106 [ Michael Terry ]
debian/control+42−37
@@ -15,6 +15,7 @@ Build-Depends: cmake,
1515 libpulse-dev,
1616 libqmenumodel-dev,
1717 libqt5v8-5-private-dev,
18+ libunity-api-dev (>= 7.80.3),
1819 libunity-core-6.0-dev (<< 7.80),
1920 libunity-dev (>= 7.0.3),
2021 libunity-scopes-json-def-phone,
@@ -34,7 +35,7 @@ Build-Depends: cmake,
3435 qtdeclarative5-test-plugin,
3536 qtdeclarative5-ubuntu-ui-toolkit-plugin,
3637 qtdeclarative5-xmllistmodel-plugin,
37− ttf-ubuntu-font-family
38+ ttf-ubuntu-font-family,
3839Standards-Version: 3.9.4
3940Homepage: http://launchpad.net/unity
4041# If you aren't a member of ~unity-team but need to upload
@@ -43,6 +44,16 @@ Homepage: http://launchpad.net/unity
4344Vcs-Bzr: https://code.launchpad.net/unity8
4445Vcs-Browser: https://bazaar.launchpad.net/~unity-team/unity8/trunk
4546
47+Package: indicators-client
48+Architecture: amd64 armhf i386
49+Depends: qmenumodel-qml,
50+ qtdeclarative5-ubuntu-ui-toolkit-plugin | qt-components-ubuntu,
51+ unity8 (= ${binary:Version}),
52+ ${misc:Depends},
53+ ${shlibs:Depends},
54+Description: Indicators client test application
55+ This package contains the client application for indicators used by autopilot
56+
4657Package: unity8
4758Architecture: any
4859Depends: qmenumodel-qml,
@@ -50,51 +61,20 @@ Depends: qmenumodel-qml,
5061 qtdeclarative5-ubuntu-ui-toolkit-plugin,
5162 qtdeclarative5-unity-notifications-plugin | unity-notifications-impl,
5263 qtdeclarative5-xmllistmodel-plugin,
64+ unity-launcher-impl-2,
5365 unity-notifications-impl-1,
5466 unity8-fake-env | qtubuntu-shell,
5567 unity8-private (= ${binary:Version}),
68+ unity8-private | unity-launcher-impl,
5669 ${misc:Depends},
57− ${shlibs:Depends}
70+ ${shlibs:Depends},
5871Recommends: indicator-battery,
5972 indicator-messages,
60− indicator-network,
61− indicator-sound,
6273 indicator-time,
63− ${unity-default-masterscopes}
74+ ${unity-default-masterscopes},
6475Description: Unity 8 shell
6576 The Unity 8 shell is the primary user interface for Ubuntu devices.
6677
67−Package: unity8-private
68−Architecture: any
69−Multi-Arch: same
70−Pre-Depends: ${misc:Pre-Depends}
71−Depends: ${misc:Depends}, ${shlibs:Depends}
72−Description: Unity 8 private libs
73− The Unity 8 shell is the primary user interface for Ubuntu devices.
74− .
75− This package contains the private libraries for QML and other components
76− only used by the shell.
77−
78−Package: unity8-fake-env
79−Architecture: any
80−Multi-Arch: same
81−Pre-Depends: ${misc:Pre-Depends}
82−Depends: ${misc:Depends}, ${shlibs:Depends}
83−Provides: qtubuntu-shell
84−Description: Fake environment for running Unity 8 shell
85− Provides fake implementations of some QML modules used by Unity 8 shell
86− (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
87−
88−Package: indicators-client
89−Architecture: amd64 armhf i386
90−Depends: qmenumodel-qml,
91− qtdeclarative5-ubuntu-ui-toolkit-plugin | qt-components-ubuntu,
92− unity8 (= ${binary:Version}),
93− ${misc:Depends},
94− ${shlibs:Depends}
95−Description: Indicators client test application
96− This package contains the client application for indicators used by autopilot
97−
9878Package: unity8-autopilot
9979Architecture: all
10080Depends: indicators-client (>= ${source:Version}),
@@ -106,6 +86,31 @@ Depends: indicators-client (>= ${source:Version}),
10686 unity8-fake-env (>= ${source:Version}),
10787 ${misc:Depends},
10888 ${python:Depends},
109− ${shlibs:Depends}
89+ ${shlibs:Depends},
11090Description: Test package for Unity 8 shell
11191 Autopilot tests for the unity8 package
92+
93+Package: unity8-fake-env
94+Architecture: any
95+Multi-Arch: same
96+Pre-Depends: ${misc:Pre-Depends},
97+Depends: ${misc:Depends},
98+ ${shlibs:Depends},
99+Provides: qtubuntu-shell,
100+Description: Fake environment for running Unity 8 shell
101+ Provides fake implementations of some QML modules used by Unity 8 shell
102+ (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
103+
104+Package: unity8-private
105+Architecture: any
106+Multi-Arch: same
107+Pre-Depends: ${misc:Pre-Depends},
108+Depends: ${misc:Depends},
109+ ${shlibs:Depends},
110+Provides: unity-launcher-impl,
111+ unity-launcher-impl-2,
112+Description: Unity 8 private libs
113+ The Unity 8 shell is the primary user interface for Ubuntu devices.
114+ .
115+ This package contains the private libraries for QML and other components
116+ only used by the shell.
debian/unity8-autopilot.install−1
@@ -1,2 +1 @@
1−usr/lib/python*/*/indicators_client
21usr/lib/python*/*/unity*
plugins/HudClient/CMakeLists.txt+5−12
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14find_package(Qt5Core REQUIRED)
25find_package(Qt5Quick REQUIRED)
36pkg_search_module(DEE dee-1.0 REQUIRED)
@@ -35,15 +38,5 @@ target_link_libraries(HudClientQml
3538
3639qt5_use_modules(HudClientQml Qml)
3740
38−# copy qmldir file into build directory for shadow builds
39−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
40− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
41− )
42−
43−install(TARGETS HudClientQml
44− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/HudClient
45− )
46−
47−install(FILES qmldir
48− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/HudClient
49− )
41+# export the qmldir and qmltypes files
42+export_qmlplugin(HudClient 0.1 HudClient TARGETS HudClientQml)
plugins/HudClient/qmldir+1
@@ -1 +1,2 @@
11plugin HudClientQml
2+typeinfo plugin.qmltypes
plugins/LightDM/CMakeLists.txt+5−12
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14# Dependencies
25include(FindPkgConfig)
36pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
@@ -32,15 +35,5 @@ target_link_libraries(LightDM-qml
3235
3336qt5_use_modules(LightDM-qml Gui Qml)
3437
35−# copy qmldir file into build directory for shadow builds
36−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
37− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
38− )
39−
40−install(TARGETS LightDM-qml
41− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/LightDM
42− )
43−
44−install(FILES qmldir
45− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/LightDM
46− )
38+# export the qmldir and qmltypes files
39+export_qmlplugin(LightDM 0.1 LightDM TARGETS LightDM-qml)
plugins/LightDM/qmldir+1
@@ -1,2 +1,3 @@
11module LightDM
22plugin LightDM-qml
3+typeinfo plugin.qmltypes
plugins/ListViewWithPageHeader/CMakeLists.txt+5−12
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14# There's no cmake var for v8 include path :-/
25# so create one
36LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
@@ -30,15 +33,5 @@ target_link_libraries(ListViewWithPageHeader-qml
3033
3134qt5_use_modules(ListViewWithPageHeader-qml Qml Quick)
3235
33−# copy qmldir file into build directory for shadow builds
34−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
35− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
36− )
37−
38−install(TARGETS ListViewWithPageHeader-qml
39− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/ListViewWithPageHeader
40− )
41−
42−install(FILES qmldir
43− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/ListViewWithPageHeader
44− )
36+# export the qmldir and qmltypes files
37+export_qmlplugin(ListViewWithPageHeader 0.1 ListViewWithPageHeader TARGETS ListViewWithPageHeader-qml)
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+16
@@ -94,10 +94,13 @@
9494#include <QDebug>
9595#include <qqmlinfo.h>
9696#include <qqmlengine.h>
97+#pragma GCC diagnostic push
98+#pragma GCC diagnostic ignored "-pedantic"
9799#include <private/qquickvisualdatamodel_p.h>
98100#include <private/qqmlglobal_p.h>
99101#include <private/qquickitem_p.h>
100102#include <private/qquickanimation_p.h>
103+#pragma GCC diagnostic pop
101104// #include <private/qquickrectangle_p.h>
102105
103106static const qreal bufferRatio = 0.5;
@@ -347,6 +350,19 @@ void ListViewWithPageHeader::showHeader()
347350
348351 auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
349352 if (to != contentY()) {
353+ const bool headerShownByItsOwn = contentY() < m_headerItem->y() + m_headerItem->height();
354+ if (headerShownByItsOwn && m_headerItemShownHeight == 0) {
355+ // We are not clipping since we are just at the top of the viewport
356+ // but because of the showHeader animation we will need to, so
357+ // enable the clipping without logically moving the items
358+ m_headerItemShownHeight = m_headerItem->y() + m_headerItem->height() - contentY();
359+ if (!m_visibleItems.isEmpty()) {
360+ updateClipItem();
361+ ListItem *firstItem = m_visibleItems.first();
362+ firstItem->setY(firstItem->y() - m_headerItemShownHeight);
363+ layout();
364+ }
365+ }
350366 m_headerShowAnimation->setTo(to);
351367 m_headerShowAnimation->start();
352368 }
plugins/ListViewWithPageHeader/listviewwithpageheader.h+3
@@ -17,8 +17,11 @@
1717#ifndef LISTVIEWWITHPAGEHEADER_H
1818#define LISTVIEWWITHPAGEHEADER_H
1919
20+#pragma GCC diagnostic push
21+#pragma GCC diagnostic ignored "-pedantic"
2022#include <private/qquickitemchangelistener_p.h>
2123#include <private/qquickflickable_p.h>
24+#pragma GCC diagnostic pop
2225
2326class QAbstractItemModel;
2427class QQuickChangeSet;
plugins/ListViewWithPageHeader/qmldir+1
@@ -1,2 +1,3 @@
11module ListViewWithPageHeader
22plugin ListViewWithPageHeader-qml
3+typeinfo plugin.qmltypes
plugins/Ubuntu/Gestures/CMakeLists.txt+5−13
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14set(CMAKE_AUTOMOC ON)
25
36include(FindPkgConfig)
@@ -20,16 +23,5 @@ qt5_use_modules(UbuntuGestureQml Core Quick)
2023# So that Foo.cpp can #include "Foo.moc"
2124include_directories(${CMAKE_CURRENT_BINARY_DIR})
2225
23−# copy files into build directory for shadow builds
24−add_custom_target(UbuntuGestureQmlDirFile ALL
25− COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
26− DEPENDS qmldir
27−)
28−
29−install(TARGETS UbuntuGestureQml
30− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Ubuntu/Gestures
31− )
32−
33−install(FILES qmldir
34− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Ubuntu/Gestures
35− )
26+# export the qmldir and qmltypes files
27+export_qmlplugin(Ubuntu.Gestures 0.1 Ubuntu/Gestures TARGETS UbuntuGestureQml)
plugins/Ubuntu/Gestures/qmldir+1
@@ -1,2 +1,3 @@
11module Ubuntu.Gestures
22plugin UbuntuGestureQml
3+typeinfo plugin.qmltypes
plugins/Unity/CMakeLists.txt+9−14
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14add_subdirectory(Indicators)
25
36# Dependencies
@@ -14,14 +17,12 @@ include_directories(
1417)
1518
1619set(QMLPLUGIN_SRC
17− ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
1820 scope.cpp
1921 scopes.cpp
2022 categories.cpp
21− categoryfilter.cpp
23+ categoryresults.cpp
2224 plugin.cpp
2325 bottombarvisibilitycommunicatorshell.cpp
24− launchermodel.cpp
2526 applicationpreview.cpp
2627 genericpreview.cpp
2728 moviepreview.cpp
@@ -29,6 +30,8 @@ set(QMLPLUGIN_SRC
2930 preview.cpp
3031 previewaction.cpp
3132 previewinfohint.cpp
33+ socialpreview.cpp
34+ socialpreviewcomment.cpp
3235 variantutils.cpp
3336 )
3437
@@ -45,15 +48,7 @@ target_link_libraries(Unity-qml
4548
4649qt5_use_modules(Unity-qml Qml)
4750
48−# copy qmldir file into build directory for shadow builds
49−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
50− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
51− )
51+# export the qmldir and qmltypes files
52+export_qmlplugin(Unity 0.1 Unity TARGETS Unity-qml)
5253
53−install(TARGETS Unity-qml
54− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity
55− )
56−
57−install(FILES qmldir
58− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity
59− )
54+add_subdirectory(Launcher)
plugins/Unity/Indicators/Network/qml/PasswordPage.qml+1−1
@@ -75,7 +75,7 @@ Page {
7575 }
7676
7777 Button {
78− text: "Ok"
78+ text: "OK"
7979 width: units.gu(10)
8080 onClicked: {
8181 agent.authenticate(token, password.text);
plugins/Unity/Indicators/qml/SliderMenuItem.qml+7−1
@@ -39,7 +39,13 @@ MenuItem {
3939 // passed to QStateAction::updateState(…). The server chokes on
4040 // those values, complaining that they’re not of the right type…
4141 minimumValue: menu.extra.canonical_min ? menu.extra.canonical_min * 1.000001 : 0.0000001
42− maximumValue: menu.extra.canonical_max ? menu.extra.canonical_max * 1.000001 : 0.9999999
42+ maximumValue: {
43+ var maximum = menu.extra.canonical_max ? menu.extra.canonical_max * 1.000001 : 0.9999999
44+ if (maximum <= minimumValue) {
45+ return minimumValue + 1;
46+ }
47+ return maximum;
48+ }
4349
4450 // FIXME - to be deprecated in Ubuntu.Components.
4551 // Use this to disable the label, since there is not way to do it on the component.
plugins/Unity/Launcher/CMakeLists.txtnew file+27
@@ -0,0 +1,27 @@
1+include(FindPkgConfig)
2+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
3+
4+include_directories(
5+ ${CMAKE_CURRENT_SOURCE_DIR}
6+)
7+
8+set(QMLLAUNCHERPLUGIN_SRC
9+ plugin.cpp
10+ launchermodel.cpp
11+ launcheritem.cpp
12+ quicklistmodel.cpp
13+ common/quicklistentry.cpp
14+ backend/launcherbackend.cpp
15+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
16+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
17+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
18+ )
19+
20+add_library(UnityLauncher-qml MODULE
21+ ${QMLLAUNCHERPLUGIN_SRC}
22+ )
23+
24+qt5_use_modules(UnityLauncher-qml Qml)
25+
26+# export the qmldir and qmltypes files
27+export_qmlplugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
plugins/Unity/Launcher/backend/launcherbackend.cppnew file+145
@@ -0,0 +1,145 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michael Zanetti <michael.zanetti@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+#include "launcherbackend.h"
21+
22+#include <QHash>
23+
24+LauncherBackend::LauncherBackend(QObject *parent):
25+ QObject(parent)
26+{
27+
28+ // TODO: load default pinned ones from default config, instead of hardcoding here...
29+
30+ m_storedApps <<
31+ QLatin1String("phone-app.desktop") <<
32+ QLatin1String("camera-app.desktop") <<
33+ QLatin1String("gallery-app.desktop") <<
34+ QLatin1String("facebook-webapp.desktop") <<
35+ QLatin1String("webbrowser-app.desktop") <<
36+ QLatin1String("twitter-webapp.desktop") <<
37+ QLatin1String("gmail-webapp.desktop") <<
38+ QLatin1String("ubuntu-weather-app.desktop") <<
39+ QLatin1String("notes-app.desktop") <<
40+ QLatin1String("ubuntu-calendar-app.desktop");
41+
42+ // TODO: get stuff from desktop files instead this hardcoded map
43+ m_displayNameMap.insert("phone-app.desktop", "Phone");
44+ m_displayNameMap.insert("camera-app.desktop", "Camera");
45+ m_displayNameMap.insert("gallery-app.desktop", "Gallery");
46+ m_displayNameMap.insert("facebook-webapp.desktop", "Facebook");
47+ m_displayNameMap.insert("webbrowser-app.desktop", "Browser");
48+ m_displayNameMap.insert("twitter-webapp.desktop", "Twitter");
49+ m_displayNameMap.insert("gmail-webapp.desktop", "GMail");
50+ m_displayNameMap.insert("ubuntu-weather-app.desktop", "Weather");
51+ m_displayNameMap.insert("notes-app.desktop", "Notes");
52+ m_displayNameMap.insert("ubuntu-calendar-app.desktop", "Calendar");
53+
54+ // TODO: get stuff from desktop files instead this hardcoded map
55+ m_iconMap.insert("phone-app.desktop", "phone-app");
56+ m_iconMap.insert("camera-app.desktop", "camera");
57+ m_iconMap.insert("gallery-app.desktop", "gallery");
58+ m_iconMap.insert("facebook-webapp.desktop", "facebook");
59+ m_iconMap.insert("webbrowser-app.desktop", "browser");
60+ m_iconMap.insert("twitter-webapp.desktop", "twitter");
61+ m_iconMap.insert("gmail-webapp.desktop", "gmail");
62+ m_iconMap.insert("ubuntu-weather-app.desktop", "weather");
63+ m_iconMap.insert("notes-app.desktop", "notepad");
64+ m_iconMap.insert("ubuntu-calendar-app.desktop", "calendar");
65+
66+}
67+
68+LauncherBackend::~LauncherBackend()
69+{
70+
71+}
72+
73+QStringList LauncherBackend::storedApplications() const
74+{
75+ return m_storedApps;
76+}
77+
78+void LauncherBackend::setStoredApplications(const QStringList &appIds)
79+{
80+ m_storedApps = appIds;
81+ // TODO: Cleanup pinned state from settings for apps not in list any more.
82+}
83+
84+QString LauncherBackend::desktopFile(const QString &appId) const
85+{
86+ // TODO: return real path instead of this hardcoded one
87+ return QLatin1String("/usr/share/applications/") + appId;
88+}
89+
90+QString LauncherBackend::displayName(const QString &appId) const
91+{
92+ return m_displayNameMap.value(appId);
93+}
94+
95+QString LauncherBackend::icon(const QString &appId) const
96+{
97+ return m_iconMap.value(appId);
98+}
99+
100+bool LauncherBackend::isPinned(const QString &appId) const
101+{
102+ // TODO: return app's pinned state from settings
103+ Q_UNUSED(appId)
104+ return true;
105+}
106+
107+void LauncherBackend::setPinned(const QString &appId, bool pinned)
108+{
109+ // TODO: Store pinned state in settings.
110+ Q_UNUSED(appId)
111+ Q_UNUSED(pinned)
112+}
113+
114+QList<QuickListEntry> LauncherBackend::quickList(const QString &appId) const
115+{
116+ // TODO: Get static (from .desktop file) and dynamic (from the app itself)
117+ // entries and return them here. Frontend related entries (like "Pin to launcher")
118+ // don't matter here. This is just the backend part.
119+ // TODO: emit quickListChanged() when the dynamic part changes
120+ Q_UNUSED(appId)
121+ return QList<QuickListEntry>();
122+}
123+
124+int LauncherBackend::progress(const QString &appId) const
125+{
126+ // TODO: Return value for progress emblem.
127+ // TODO: emit progressChanged() when this value changes.
128+ Q_UNUSED(appId)
129+ return -1;
130+}
131+
132+int LauncherBackend::count(const QString &appId) const
133+{
134+ // TODO: Return value for count emblem.
135+ // TODO: emit countChanged() when this value changes.
136+ Q_UNUSED(appId)
137+ return 0;
138+}
139+
140+void LauncherBackend::triggerQuickListAction(const QString &appId, const QString &quickListId)
141+{
142+ // TODO: execute the given quicklist action
143+ Q_UNUSED(appId)
144+ Q_UNUSED(quickListId)
145+}
plugins/Unity/Launcher/backend/launcherbackend.hnew file+132
@@ -0,0 +1,132 @@
1+/* Copyright (C) 2013 Canonical, Ltd.
2+ *
3+ * Authors:
4+ * Michael Zanetti <michael.zanetti@canonical.com>
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; version 3.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+#ifndef LAUNCHERBACKEND_H
20+#define LAUNCHERBACKEND_H
21+
22+#include "common/quicklistentry.h"
23+
24+#include <QObject>
25+#include <QStringList>
26+#include <QHash>
27+
28+/**
29+ * @brief An interface that provides all the data needed by the launcher.
30+ */
31+
32+class LauncherBackend : public QObject
33+{
34+ Q_OBJECT
35+
36+
37+public:
38+ LauncherBackend(QObject *parent = 0);
39+ virtual ~LauncherBackend();
40+
41+ /**
42+ * @brief Returns a list of stored applications.
43+ * @returns A list of application IDs.
44+ */
45+ QStringList storedApplications() const;
46+
47+ /**
48+ * @brief Set the list of stored applications.
49+ *
50+ * Any previously stored information for apps not contained
51+ * in the list any more, e.g. the pinned state, will be
52+ * discarded.
53+ *
54+ * @param appIds The new list of stored applications.
55+ */
56+ void setStoredApplications(const QStringList &appIds);
57+
58+ /**
59+ * @brief Get the full path to the .desktop file.
60+ * @returns The full path to the .dekstop file.
61+ */
62+ QString desktopFile(const QString &appId) const;
63+
64+ /**
65+ * @brief Get the user friendly name of an application.
66+ * @param appId The ID of the application.
67+ * @returns The user friendly name of the application.
68+ */
69+ QString displayName(const QString &appId) const;
70+
71+ /**
72+ * @brief Get the icon of an application.
73+ * @param appId The ID of the application.
74+ * @returns The full path to the icon for the application.
75+ */
76+ QString icon(const QString &appId) const;
77+
78+ /**
79+ * @brief Is the app manually pinned?
80+ * @returns true if pinned, otherwise false.
81+ */
82+ bool isPinned(const QString &appId) const;
83+
84+ /**
85+ * @brief Change the pinned state of an application.
86+ * @param appId The application where the pinned flag should be set.
87+ * @param pinned true if pinned, otherwise false.
88+ */
89+ void setPinned(const QString &appId, bool pinned);
90+
91+ //TODO: Fill in getters for all the other things needed from the .desktop file.
92+
93+ /**
94+ * @brief Get the QuickList for an application.
95+ * @param appId The ID of the application.
96+ * @returns A QuickListModelInterface containing the QuickList.
97+ */
98+ QList<QuickListEntry> quickList(const QString &appId) const;
99+
100+ /**
101+ * @brief Execute an action from the quickList
102+ * @param appId The app ID for which the action was triggered
103+ * @param the quicklist ID of the action that was triggered
104+ */
105+ void triggerQuickListAction(const QString &appId, const QString &entryId);
106+
107+ /**
108+ * @brief Get the progress for the progress overlay of an application.
109+ * @param appId The ID of the application.
110+ * @returns The percentage of the overlay progress bar. -1 if no progress bar available.
111+ */
112+ int progress(const QString &appId) const;
113+
114+ /**
115+ * @brief Get the count of the count overlay of an application.
116+ * @param appId The ID of the application.
117+ * @returns The number to be displayed in the overlay. -1 if no count overlay is available.
118+ */
119+ int count(const QString &appId) const;
120+
121+Q_SIGNALS:
122+ void quickListChanged(const QString &appId, const QList<QuickListEntry> &quickList);
123+ void progressChanged(const QString &appId, int progress);
124+ void countChanged(const QString &appId, int count);
125+
126+private:
127+ QStringList m_storedApps;
128+ QHash<QString, QString> m_displayNameMap;
129+ QHash<QString, QString> m_iconMap;
130+};
131+
132+#endif // LAUNCHERBACKEND_H
plugins/Unity/categoryfilter.cpp → plugins/Unity/Launcher/common/quicklistentry.cpprenamed+28−19
@@ -1,8 +1,7 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
1+/* Copyright (C) 2013 Canonical, Ltd.
32 *
43 * Authors:
5− * Michał Sawicz <michal.sawicz@canonical.com>
4+ * Michael Zanetti <michael.zanetti@canonical.com>
65 *
76 * This program is free software; you can redistribute it and/or modify
87 * it under the terms of the GNU General Public License as published by
@@ -17,29 +16,39 @@
1716 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1817 */
1918
20−#include "categoryfilter.h"
19+#include "quicklistentry.h"
2120
22−int const CATEGORY_COLUMN = 2;
21+QuickListEntry::QuickListEntry()
22+{
23+
24+}
25+
26+QString QuickListEntry::actionId() const
27+{
28+ return m_actionId;
29+}
30+
31+void QuickListEntry::setActionId(const QString &actionId)
32+{
33+ m_actionId = actionId;
34+}
35+
36+QString QuickListEntry::text() const
37+{
38+ return m_text;
39+}
2340
24−CategoryFilter::CategoryFilter(QObject* parent)
25− : QSortFilterProxyModelQML(parent)
26− , m_index(-1)
41+void QuickListEntry::setText(const QString &text)
2742{
28− setDynamicSortFilter(true);
29− setFilterRole(CATEGORY_COLUMN);
30− setFilterRegExp(QString("^%1$").arg(m_index));
43+ m_text = text;
3144}
3245
33−int CategoryFilter::index() const
46+QString QuickListEntry::icon() const
3447{
35− return m_index;
48+ return m_icon;
3649}
3750
38−void CategoryFilter::setIndex(int index)
51+void QuickListEntry::setIcon(const QString &icon)
3952{
40− if (index != m_index) {
41− m_index = index;
42− setFilterRegExp(QString("^%1$").arg(m_index));
43− Q_EMIT indexChanged(m_index);
44− }
53+ m_icon = icon;
4554}
plugins/Unity/Launcher/common/quicklistentry.hnew file+44
@@ -0,0 +1,44 @@
1+/* Copyright (C) 2013 Canonical, Ltd.
2+ *
3+ * Authors:
4+ * Michael Zanetti <michael.zanetti@canonical.com>
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; version 3.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+#ifndef QUICKLISTENTRY_H
20+#define QUICKLISTENTRY_H
21+
22+#include <QString>
23+
24+class QuickListEntry
25+{
26+public:
27+ QuickListEntry();
28+
29+ QString actionId() const;
30+ void setActionId(const QString &actionId);
31+
32+ QString text() const;
33+ void setText(const QString &text);
34+
35+ QString icon() const;
36+ void setIcon(const QString &icon);
37+
38+private:
39+ QString m_actionId;
40+ QString m_text;
41+ QString m_icon;
42+};
43+
44+#endif // QUICKLISTENTRY
plugins/Unity/Launcher/launcheritem.cppnew file+127
@@ -0,0 +1,127 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "launcheritem.h"
21+#include "quicklistmodel.h"
22+
23+LauncherItem::LauncherItem(const QString &appId, const QString &desktopFile, const QString &name, const QString &icon, QObject *parent) :
24+ LauncherItemInterface(parent),
25+ m_appId(appId),
26+ m_desktopFile(desktopFile),
27+ m_name(name),
28+ m_icon(icon),
29+ m_pinned(false),
30+ m_running(false),
31+ m_recent(false),
32+ m_progress(-1),
33+ m_count(0),
34+ m_quickList(new QuickListModel(this))
35+{
36+
37+}
38+
39+QString LauncherItem::appId() const
40+{
41+ return m_appId;
42+}
43+
44+QString LauncherItem::desktopFile() const
45+{
46+ return m_desktopFile;
47+}
48+
49+QString LauncherItem::name() const
50+{
51+ return m_name;
52+}
53+
54+QString LauncherItem::icon() const
55+{
56+ return m_icon;
57+}
58+
59+bool LauncherItem::pinned() const
60+{
61+ return m_pinned;
62+}
63+
64+void LauncherItem::setPinned(bool pinned)
65+{
66+ if (m_pinned != pinned) {
67+ m_pinned = pinned;
68+ Q_EMIT pinnedChanged(pinned);
69+ }
70+}
71+
72+bool LauncherItem::running() const
73+{
74+ return m_running;
75+}
76+
77+void LauncherItem::setRunning(bool running)
78+{
79+ if (m_running != running) {
80+ m_running = running;
81+ Q_EMIT runningChanged(running);
82+ }
83+}
84+
85+bool LauncherItem::recent() const
86+{
87+ return m_recent;
88+}
89+
90+void LauncherItem::setRecent(bool recent)
91+{
92+ if (m_recent != recent) {
93+ m_recent = recent;
94+ Q_EMIT recentChanged(recent);
95+ }
96+}
97+
98+int LauncherItem::progress() const
99+{
100+ return m_progress;
101+}
102+
103+void LauncherItem::setProgress(int progress)
104+{
105+ if (m_progress != progress) {
106+ m_progress = progress;
107+ Q_EMIT progressChanged(progress);
108+ }
109+}
110+
111+int LauncherItem::count() const
112+{
113+ return m_count;
114+}
115+
116+void LauncherItem::setCount(int count)
117+{
118+ if (m_count != count) {
119+ m_count = count;
120+ Q_EMIT countChanged(count);
121+ }
122+}
123+
124+unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
125+{
126+ return m_quickList;
127+}
plugins/Unity/Launcher/launcheritem.hnew file+76
@@ -0,0 +1,76 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef LAUNCHERITEM_H
21+#define LAUNCHERITEM_H
22+
23+#include "quicklistmodel.h"
24+
25+#include <unity/shell/launcher/LauncherItemInterface.h>
26+
27+class QuickListModel;
28+
29+using namespace unity::shell::launcher;
30+
31+class LauncherItem: public LauncherItemInterface
32+{
33+ Q_OBJECT
34+public:
35+ LauncherItem(const QString &appId, const QString &desktopFile, const QString &name, const QString &icon, QObject *parent = 0);
36+
37+ QString appId() const;
38+ QString desktopFile() const;
39+ QString name() const;
40+ QString icon() const;
41+
42+ bool pinned() const;
43+ void setPinned(bool pinned);
44+
45+ bool running() const;
46+ void setRunning(bool running);
47+
48+ bool recent() const;
49+ void setRecent(bool recent);
50+
51+ int progress() const;
52+ void setProgress(int progress);
53+
54+ int count() const;
55+ void setCount(int count);
56+
57+ unity::shell::launcher::QuickListModelInterface *quickList() const;
58+
59+Q_SIGNALS:
60+ void favoriteChanged(bool favorite);
61+ void runningChanged(bool running);
62+
63+private:
64+ QString m_appId;
65+ QString m_desktopFile;
66+ QString m_name;
67+ QString m_icon;
68+ bool m_pinned;
69+ bool m_running;
70+ bool m_recent;
71+ int m_progress;
72+ int m_count;
73+ QuickListModel *m_quickList;
74+};
75+
76+#endif // LAUNCHERITEM_H
plugins/Unity/Launcher/launchermodel.cppnew file+170
@@ -0,0 +1,170 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "launchermodel.h"
21+#include "launcheritem.h"
22+#include "backend/launcherbackend.h"
23+
24+LauncherModel::LauncherModel(QObject *parent):
25+ LauncherModelInterface(parent),
26+ m_backend(new LauncherBackend(this))
27+{
28+ Q_FOREACH (const QString &entry, m_backend->storedApplications()) {
29+ LauncherItem *item = new LauncherItem(entry,
30+ m_backend->desktopFile(entry),
31+ m_backend->displayName(entry),
32+ m_backend->icon(entry),
33+ this);
34+ if (m_backend->isPinned(entry)) {
35+ item->setPinned(true);
36+ } else {
37+ item->setRecent(true);
38+ }
39+ m_list.append(item);
40+ }
41+}
42+
43+LauncherModel::~LauncherModel()
44+{
45+ while (!m_list.empty()) {
46+ m_list.takeFirst()->deleteLater();
47+ }
48+}
49+
50+int LauncherModel::rowCount(const QModelIndex &parent) const
51+{
52+ Q_UNUSED(parent)
53+ return m_list.count();
54+}
55+
56+QVariant LauncherModel::data(const QModelIndex &index, int role) const
57+{
58+ LauncherItem *item = m_list.at(index.row());
59+ switch(role) {
60+ case RoleAppId:
61+ return item->desktopFile();
62+ case RoleDesktopFile:
63+ return item->desktopFile();
64+ case RoleName:
65+ return item->name();
66+ case RoleIcon:
67+ return item->icon();
68+ case RolePinned:
69+ return item->pinned();
70+ }
71+
72+ return QVariant();
73+}
74+
75+unity::shell::launcher::LauncherItemInterface *LauncherModel::get(int index) const
76+{
77+ if (index < 0 || index >= m_list.count()) {
78+ return 0;
79+ }
80+ return m_list.at(index);
81+}
82+
83+void LauncherModel::move(int oldIndex, int newIndex)
84+{
85+ // Perform the move in our list
86+ beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
87+ m_list.move(oldIndex, newIndex);
88+ endMoveRows();
89+
90+ storeAppList();
91+
92+ pin(m_list.at(newIndex)->appId());
93+}
94+
95+void LauncherModel::pin(const QString &appId, int index)
96+{
97+ int currentIndex = findApplication(appId);
98+
99+ if (currentIndex >= 0) {
100+ if (index == -1 || index == currentIndex) {
101+ m_list.at(currentIndex)->setPinned(true);
102+ QModelIndex modelIndex = this->index(currentIndex);
103+ Q_EMIT dataChanged(modelIndex, modelIndex);
104+ } else {
105+ move(currentIndex, index);
106+ }
107+ } else {
108+ if (index == -1) {
109+ index = m_list.count();
110+ }
111+ beginInsertRows(QModelIndex(), index, index);
112+ LauncherItem *item = new LauncherItem(appId,
113+ m_backend->desktopFile(appId),
114+ m_backend->displayName(appId),
115+ m_backend->icon(appId));
116+ item->setPinned(true);
117+ m_list.insert(index, item);
118+ endInsertRows();
119+ }
120+}
121+
122+void LauncherModel::requestRemove(const QString &appId)
123+{
124+ int index = findApplication(appId);
125+ if (index < 0) {
126+ return;
127+ }
128+
129+ beginRemoveRows(QModelIndex(), index, index);
130+ m_list.takeAt(index)->deleteLater();
131+ endRemoveRows();
132+
133+ storeAppList();
134+}
135+
136+void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex)
137+{
138+ int index = findApplication(appId);
139+ if (index < 0) {
140+ return;
141+ }
142+
143+ QuickListModel *model = qobject_cast<QuickListModel*>(m_list.at(index)->quickList());
144+ if (model) {
145+ QString actionId = model->get(actionIndex).actionId();
146+ m_backend->triggerQuickListAction(appId, actionId);
147+ }
148+}
149+
150+void LauncherModel::storeAppList()
151+{
152+ QStringList appIds;
153+ Q_FOREACH(LauncherItem *item, m_list) {
154+ if (item->pinned() || item->recent()) {
155+ appIds << item->appId();
156+ }
157+ }
158+ m_backend->setStoredApplications(appIds);
159+}
160+
161+int LauncherModel::findApplication(const QString &appId)
162+{
163+ for (int i = 0; i < m_list.count(); ++i) {
164+ LauncherItem *item = m_list.at(i);
165+ if (item->appId() == appId) {
166+ return i;
167+ }
168+ }
169+ return -1;
170+}
plugins/Unity/Launcher/launchermodel.hnew file+61
@@ -0,0 +1,61 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef LAUNCHERMODELH
21+#define LAUNCHERMODEL_H
22+
23+// unity-api
24+#include <unity/shell/launcher/LauncherModelInterface.h>
25+
26+// Qt
27+#include <QAbstractListModel>
28+
29+class LauncherItem;
30+class LauncherBackend;
31+
32+using namespace unity::shell::launcher;
33+
34+class LauncherModel: public LauncherModelInterface
35+{
36+ Q_OBJECT
37+
38+public:
39+ LauncherModel(QObject *parent = 0);
40+ ~LauncherModel();
41+
42+ int rowCount(const QModelIndex &parent) const;
43+
44+ QVariant data(const QModelIndex &index, int role) const;
45+
46+ Q_INVOKABLE unity::shell::launcher::LauncherItemInterface* get(int index) const;
47+ Q_INVOKABLE void move(int oldIndex, int newIndex);
48+ Q_INVOKABLE void pin(const QString &appId, int index = -1);
49+ Q_INVOKABLE void requestRemove(const QString &appId);
50+ Q_INVOKABLE void quickListActionInvoked(const QString &appId, int actionIndex);
51+
52+private:
53+ void storeAppList();
54+ int findApplication(const QString &appId);
55+
56+private:
57+ QList<LauncherItem*> m_list;
58+ LauncherBackend *m_backend;
59+};
60+
61+#endif // LAUNCHERMODEL_H
plugins/Unity/Launcher/plugin.cppnew file+47
@@ -0,0 +1,47 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+// Qt
21+#include <QtQml>
22+
23+// self
24+#include "plugin.h"
25+
26+// local
27+#include "launchermodel.h"
28+#include "launcheritem.h"
29+
30+
31+using namespace unity::shell::launcher;
32+
33+static QObject* modelProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
34+{
35+ return new LauncherModel();
36+}
37+
38+void UnityLauncherPlugin::registerTypes(const char *uri)
39+{
40+ Q_ASSERT(uri == QLatin1String("Unity.Launcher"));
41+
42+ qmlRegisterUncreatableType<LauncherModelInterface>(uri, 0, 1, "LauncherModelInterface", "Abstract Interface. Cannot be instantiated.");
43+ qmlRegisterUncreatableType<LauncherItemInterface>(uri, 0, 1, "LauncherItemInterface", "Abstract Interface. Cannot be instantiated.");
44+
45+ qmlRegisterSingletonType<LauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
46+ qmlRegisterUncreatableType<LauncherItem>(uri, 0, 1, "LauncherItem", "Can't create new Launcher Items in QML. Get them from the LauncherModel.");
47+}
plugins/Unity/categoryfilter.h → plugins/Unity/Launcher/plugin.hrenamed+10−24
@@ -1,9 +1,6 @@
11/*
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
4− * Authors:
5− * Michał Sawicz <michal.sawicz@canonical.com>
6− *
74 * This program is free software; you can redistribute it and/or modify
85 * it under the terms of the GNU General Public License as published by
96 * the Free Software Foundation; version 3.
@@ -15,34 +12,23 @@
1512 *
1613 * You should have received a copy of the GNU General Public License
1714 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Zanetti <michael.zanetti@canonical.com>
1817 */
1918
20−#ifndef CATEGORY_FILTER_H
21−#define CATEGORY_FILTER_H
19+#ifndef UNITY_LAUNCHER_PLUGIN_H
20+#define UNITY_LAUNCHER_PLUGIN_H
2221
23−// Utils
24−#include "plugins/Utils/qsortfilterproxymodelqml.h"
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
2524
26−class CategoryFilter : public QSortFilterProxyModelQML
25+class UnityLauncherPlugin : public QQmlExtensionPlugin
2726{
2827 Q_OBJECT
29−
30− Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged)
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
3129
3230public:
33− explicit CategoryFilter(QObject* parent = 0);
34−
35− /* getters */
36− int index() const;
37−
38− /* setters */
39− void setIndex(int index);
40−
41−Q_SIGNALS:
42− void indexChanged(int index);
43−
44−private:
45− int m_index;
31+ void registerTypes(const char *uri);
4632};
4733
48−#endif // CATEGORY_FILTER_H
34+#endif
plugins/Unity/Launcher/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Unity.Launcher
2+plugin UnityLauncher-qml
plugins/Unity/Launcher/quicklistmodel.cppnew file+60
@@ -0,0 +1,60 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "quicklistmodel.h"
21+
22+QuickListModel::QuickListModel(QObject *parent) :
23+ QuickListModelInterface(parent)
24+{
25+
26+}
27+
28+QuickListModel::~QuickListModel()
29+{
30+
31+}
32+
33+void QuickListModel::appendAction(const QuickListEntry &entry)
34+{
35+ beginInsertRows(QModelIndex(), m_list.count() - 1, m_list.count() -1);
36+ m_list.append(entry);
37+ endInsertRows();
38+}
39+
40+QuickListEntry QuickListModel::get(int index) const
41+{
42+ return m_list.at(index);
43+}
44+
45+int QuickListModel::rowCount(const QModelIndex &index) const
46+{
47+ Q_UNUSED(index)
48+ return m_list.count();
49+}
50+
51+QVariant QuickListModel::data(const QModelIndex &index, int role) const
52+{
53+ switch (role) {
54+ case RoleLabel:
55+ return m_list.at(index.row()).text();
56+ case RoleIcon:
57+ return m_list.at(index.row()).icon();
58+ }
59+ return QVariant();
60+}
plugins/Unity/Launcher/quicklistmodel.hnew file+48
@@ -0,0 +1,48 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef QUICKLISTMODEL_H
21+#define QUICKLISTMODEL_H
22+
23+#include "common/quicklistentry.h"
24+
25+#include <unity/shell/launcher/QuickListModelInterface.h>
26+
27+using namespace unity::shell::launcher;
28+
29+class QuickListModel: public QuickListModelInterface
30+{
31+ Q_OBJECT
32+
33+public:
34+ explicit QuickListModel(QObject *parent = 0);
35+
36+ ~QuickListModel();
37+
38+ void appendAction(const QuickListEntry &entry);
39+ QuickListEntry get(int index) const;
40+
41+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
42+ QVariant data(const QModelIndex &index, int role) const;
43+
44+private:
45+ QList<QuickListEntry> m_list;
46+};
47+
48+#endif // QUICKLISTMODEL_H
plugins/Unity/categories.cpp+56−42
@@ -3,6 +3,7 @@
33 *
44 * Authors:
55 * Michał Sawicz <michal.sawicz@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
@@ -19,18 +20,25 @@
1920
2021// self
2122#include "categories.h"
22−#include "categoryfilter.h"
23+#include "categoryresults.h"
24+
25+// TODO: use something from libunity once it's public
26+enum CategoryColumn {
27+ ID,
28+ DISPLAY_NAME,
29+ ICON_HINT,
30+ RENDERER_NAME,
31+ HINTS
32+};
2333
2434Categories::Categories(QObject* parent)
2535 : DeeListModel(parent)
26− , m_resultModel(0)
2736{
28− // FIXME: need to clean up unused filters on countChanged
2937 m_roles[Categories::RoleId] = "id";
3038 m_roles[Categories::RoleName] = "name";
3139 m_roles[Categories::RoleIcon] = "icon";
3240 m_roles[Categories::RoleRenderer] = "renderer";
33− m_roles[Categories::RoleContentType] = "content_type";
41+ m_roles[Categories::RoleContentType] = "contentType";
3442 m_roles[Categories::RoleHints] = "hints";
3543 m_roles[Categories::RoleResults] = "results";
3644 m_roles[Categories::RoleCount] = "count";
@@ -40,49 +48,57 @@ Categories::Categories(QObject* parent)
4048 // change of the search term harder to reproduce
4149 m_timer.setSingleShot(true);
4250 m_timer.setInterval(50);
43− connect(&m_timer, SIGNAL(timeout()), this, SLOT(onEmitCountChanged()));
51+ connect(&m_timer, &QTimer::timeout, this, &Categories::onEmitCountChanged);
4452}
4553
46−Categories::~Categories()
54+DeeListModel*
55+Categories::getResults(int index) const
4756{
48− qDeleteAll(m_filters);
49−}
57+ if (!m_results.contains(index)) {
58+ CategoryResults* results = new CategoryResults(const_cast<Categories*>(this));
59+ results->setCategoryIndex(index);
60+ connect(results, &DeeListModel::countChanged, this, &Categories::onCountChanged);
5061
51−CategoryFilter*
52−Categories::getFilter(int index) const
53−{
54− if (!m_filters.contains(index)) {
55− CategoryFilter* filter = new CategoryFilter();
56− connect(filter, SIGNAL(countChanged()), this, SLOT(onCountChanged()));
57− filter->setModel(m_resultModel);
58− filter->setIndex(index);
62+ unsigned categoryIndex = static_cast<unsigned>(index);
63+ auto unity_results = m_unityScope->GetResultsForCategory(categoryIndex);
64+ results->setModel(unity_results->model());
5965
60− m_filters.insert(index, filter);
66+ m_results.insert(index, results);
6167 }
6268
63− return m_filters[index];
69+ return m_results[index];
70+}
71+
72+void Categories::onCategoriesModelChanged(unity::glib::Object<DeeModel> model)
73+{
74+ m_updatedCategories.clear();
75+ // FIXME: this might destroy the renderer view and re-create it, optimize?
76+ Q_FOREACH(DeeListModel* model, m_results) {
77+ delete model;
78+ }
79+ m_results.clear();
80+ setModel(model);
6481}
6582
6683void
67−Categories::setResultModel(DeeListModel* model)
84+Categories::setUnityScope(const unity::dash::Scope::Ptr& scope)
6885{
69− if (model != m_resultModel) {
70− m_resultModel = model;
86+ m_unityScope = scope;
7187
72− Q_FOREACH(CategoryFilter* filter, m_filters) {
73− filter->setModel(m_resultModel);
74− }
88+ // no need to call this, we'll get notified
89+ //setModel(m_unityScope->categories()->model());
7590
76− Q_EMIT resultModelChanged(m_resultModel);
77− }
91+ m_categoriesChangedConnection.disconnect();
92+ m_categoriesChangedConnection =
93+ m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Categories::onCategoriesModelChanged));
7894}
7995
8096void
8197Categories::onCountChanged()
8298{
83− CategoryFilter* filter = qobject_cast<CategoryFilter*>(sender());
84− if (filter) {
85− m_timerFilters << filter;
99+ CategoryResults* results = qobject_cast<CategoryResults*>(sender());
100+ if (results) {
101+ m_updatedCategories << results->categoryIndex();
86102 m_timer.start();
87103 }
88104}
@@ -92,11 +108,12 @@ Categories::onEmitCountChanged()
92108{
93109 QVector<int> roles;
94110 roles.append(Categories::RoleCount);
95− Q_FOREACH(CategoryFilter* filter, m_timerFilters) {
96− QModelIndex changedIndex = index(filter->index());
111+ Q_FOREACH(int categoryIndex, m_updatedCategories) {
112+ if (!m_results.contains(categoryIndex)) continue;
113+ QModelIndex changedIndex = index(categoryIndex);
97114 Q_EMIT dataChanged(changedIndex, changedIndex, roles);
98115 }
99− m_timerFilters.clear();
116+ m_updatedCategories.clear();
100117}
101118
102119QHash<int, QByteArray>
@@ -116,25 +133,22 @@ Categories::data(const QModelIndex& index, int role) const
116133 case RoleId:
117134 return QVariant::fromValue(index.row());
118135 case RoleName:
119− return QVariant::fromValue(DeeListModel::data(index, 1)); //DISPLAY_NAME
136+ return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
120137 case RoleIcon:
121− return QVariant::fromValue(DeeListModel::data(index, 2)); //ICON_HINT
138+ return DeeListModel::data(index, CategoryColumn::ICON_HINT);
122139 case RoleRenderer:
123− return QVariant::fromValue(DeeListModel::data(index, 3)); //RENDERER_NAME
140+ return DeeListModel::data(index, CategoryColumn::RENDERER_NAME);
124141 case RoleContentType:
125142 {
126− auto hints = QVariant::fromValue(DeeListModel::data(index, 4)).toHash();
143+ auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
127144 return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
128145 }
129146 case RoleHints:
130− return QVariant::fromValue(DeeListModel::data(index, 4)); //HINTS
147+ return DeeListModel::data(index, CategoryColumn::HINTS);
131148 case RoleResults:
132− return QVariant::fromValue(getFilter(index.row()));
149+ return QVariant::fromValue(getResults(index.row()));
133150 case RoleCount:
134− {
135− CategoryFilter* filter = getFilter(index.row());
136− return QVariant::fromValue(filter->rowCount());
137− }
151+ return QVariant::fromValue(getResults(index.row())->rowCount());
138152 default:
139153 return QVariant();
140154 }
plugins/Unity/categories.h+13−16
@@ -3,6 +3,7 @@
33 *
44 * Authors:
55 * Michał Sawicz <michal.sawicz@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
@@ -21,25 +22,24 @@
2122#ifndef CATEGORIES_H
2223#define CATEGORIES_H
2324
25+// unity-core
26+#include <UnityCore/Scope.h>
27+
2428// dee-qt
2529#include "deelistmodel.h"
2630
31+#include <QPointer>
2732#include <QSet>
2833#include <QTimer>
2934
30−class CategoryFilter;
31−
3235class Categories : public DeeListModel
3336{
3437 Q_OBJECT
3538
3639 Q_ENUMS(Roles)
3740
38− Q_PROPERTY(DeeListModel* resultModel READ resultModel WRITE setResultModel NOTIFY resultModelChanged)
39−
4041public:
4142 explicit Categories(QObject* parent = 0);
42− ~Categories();
4343
4444 enum Roles {
4545 RoleId,
@@ -56,27 +56,24 @@ public:
5656
5757 QHash<int, QByteArray> roleNames() const;
5858
59− /* getters */
60− DeeListModel* resultModel() { return m_resultModel; }
61−
6259 /* setters */
63− void setResultModel(DeeListModel*);
64−
65−Q_SIGNALS:
66− void resultModelChanged(DeeListModel*);
60+ void setUnityScope(const unity::dash::Scope::Ptr& scope);
6761
6862private Q_SLOTS:
6963 void onCountChanged();
7064 void onEmitCountChanged();
7165
7266private:
73− CategoryFilter* getFilter(int index) const;
67+ void onCategoriesModelChanged(unity::glib::Object<DeeModel> model);
68+
69+ DeeListModel* getResults(int index) const;
7470
71+ unity::dash::Scope::Ptr m_unityScope;
7572 QTimer m_timer;
76− QSet<CategoryFilter*> m_timerFilters;
73+ QSet<int> m_updatedCategories;
7774 QHash<int, QByteArray> m_roles;
78− DeeListModel* m_resultModel;
79− mutable QMap<int, CategoryFilter*> m_filters;
75+ mutable QMap<int, DeeListModel*> m_results;
76+ sigc::connection m_categoriesChangedConnection;
8077};
8178
8279#endif // CATEGORIES_H
plugins/Unity/categoryresults.cppnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michal Hruby <michal.hruby@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+// self
21+#include "categoryresults.h"
22+
23+// TODO: use something from libunity once it's public
24+enum ResultsColumn {
25+ URI,
26+ ICON_HINT,
27+ CATEGORY,
28+ RESULT_TYPE,
29+ MIMETYPE,
30+ TITLE,
31+ COMMENT,
32+ DND_URI,
33+ METADATA
34+};
35+
36+CategoryResults::CategoryResults(QObject* parent)
37+ : DeeListModel(parent)
38+ , m_categoryIndex(-1)
39+{
40+ m_roles[CategoryResults::RoleUri] = "uri";
41+ m_roles[CategoryResults::RoleIconHint] = "icon";
42+ m_roles[CategoryResults::RoleCategory] = "category";
43+ m_roles[CategoryResults::RoleMimetype] = "mimetype";
44+ m_roles[CategoryResults::RoleTitle] = "title";
45+ m_roles[CategoryResults::RoleComment] = "comment";
46+ m_roles[CategoryResults::RoleDndUri] = "dndUri";
47+ m_roles[CategoryResults::RoleMetadata] = "metadata";
48+}
49+
50+int CategoryResults::categoryIndex() const
51+{
52+ return m_categoryIndex;
53+}
54+
55+void CategoryResults::setCategoryIndex(int index)
56+{
57+ if (m_categoryIndex != index) {
58+ m_categoryIndex = index;
59+ Q_EMIT categoryIndexChanged(m_categoryIndex);
60+ }
61+}
62+
63+QHash<int, QByteArray>
64+CategoryResults::roleNames() const
65+{
66+ return m_roles;
67+}
68+
69+QVariant
70+CategoryResults::data(const QModelIndex& index, int role) const
71+{
72+ if (!index.isValid()) {
73+ return QVariant();
74+ }
75+
76+ switch (role) {
77+ case RoleUri:
78+ return DeeListModel::data(index, ResultsColumn::URI);
79+ case RoleIconHint:
80+ return DeeListModel::data(index, ResultsColumn::ICON_HINT);
81+ case RoleCategory:
82+ return DeeListModel::data(index, ResultsColumn::CATEGORY);
83+ case RoleMimetype:
84+ return DeeListModel::data(index, ResultsColumn::MIMETYPE);
85+ case RoleTitle:
86+ return DeeListModel::data(index, ResultsColumn::TITLE);
87+ case RoleComment:
88+ return DeeListModel::data(index, ResultsColumn::COMMENT);
89+ case RoleDndUri:
90+ return DeeListModel::data(index, ResultsColumn::DND_URI);
91+ case RoleMetadata:
92+ return DeeListModel::data(index, ResultsColumn::METADATA);
93+ default:
94+ return QVariant();
95+ }
96+}
plugins/Unity/categoryresults.hnew file+67
@@ -0,0 +1,67 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michal Hruby <michal.hruby@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+
21+#ifndef CATEGORY_RESULTS_H
22+#define CATEGORY_RESULTS_H
23+
24+// dee-qt
25+#include "deelistmodel.h"
26+
27+class CategoryResults : public DeeListModel
28+{
29+ Q_OBJECT
30+
31+ Q_ENUMS(Roles)
32+
33+ Q_PROPERTY(int categoryIndex READ categoryIndex WRITE setCategoryIndex NOTIFY categoryIndexChanged)
34+
35+public:
36+ explicit CategoryResults(QObject* parent = 0);
37+
38+ enum Roles {
39+ RoleUri,
40+ RoleIconHint,
41+ RoleCategory,
42+ RoleMimetype,
43+ RoleTitle,
44+ RoleComment,
45+ RoleDndUri,
46+ RoleMetadata
47+ };
48+
49+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
50+
51+ QHash<int, QByteArray> roleNames() const;
52+
53+ /* getters */
54+ int categoryIndex() const;
55+
56+ /* setters */
57+ void setCategoryIndex(int index);
58+
59+Q_SIGNALS:
60+ void categoryIndexChanged(int index);
61+
62+private:
63+ QHash<int, QByteArray> m_roles;
64+ int m_categoryIndex;
65+};
66+
67+#endif // CATEGORY_RESULTS_H
plugins/Unity/genericpreview.cpp+5
@@ -24,3 +24,8 @@ GenericPreview::GenericPreview(QObject *parent):
2424 Preview(parent)
2525{
2626}
27+
28+void GenericPreview::setUnityPreview(unity::dash::Preview::Ptr /* unityPreview */)
29+{
30+ Q_EMIT previewChanged();
31+}
plugins/Unity/genericpreview.h+6
@@ -33,6 +33,12 @@ class GenericPreview : public Preview
3333
3434public:
3535 explicit GenericPreview(QObject *parent = 0);
36+
37+Q_SIGNALS:
38+ void previewChanged();
39+
40+protected:
41+ void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
3642};
3743
3844Q_DECLARE_METATYPE(GenericPreview *)
plugins/Unity/launchermodel.cppdeleted−153
@@ -1,153 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Michael Zanetti <michael.zanetti@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−#include "launchermodel.h"
21−
22−LauncherModel::LauncherModel(QObject *parent): QAbstractListModel(parent)
23−{
24− // FIXME: Dummy data... Aggregate real data from backends
25−
26− // Fake favorites
27− LauncherItem *item = new LauncherItem("/usr/share/applications/phone-app.desktop", "Phone", "phone-app");
28− m_list.append(item);
29− item = new LauncherItem("/usr/share/applications/camera-app.desktop", "Camera", "camera");
30− m_list.append(item);
31− item = new LauncherItem("/usr/share/applications/gallery-app.desktop", "Gallery", "gallery");
32− m_list.append(item);
33− item = new LauncherItem("/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook");
34− m_list.append(item);
35− item = new LauncherItem("/usr/share/applications/webbrowser-app.desktop", "Browser", "browser");
36− m_list.append(item);
37− item = new LauncherItem("/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter");
38− m_list.append(item);
39− item = new LauncherItem("/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail");
40− m_list.append(item);
41− item = new LauncherItem("/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather");
42− m_list.append(item);
43− item = new LauncherItem("/usr/share/applications/notes-app.desktop", "Notepad", "notepad");
44− m_list.append(item);
45− item = new LauncherItem("/usr/share/applications/ubuntu-calendar-app.desktop","Calendar", "calendar");
46− m_list.append(item);
47−}
48−
49−LauncherModel::~LauncherModel()
50−{
51− while (!m_list.empty()) {
52− m_list.takeFirst()->deleteLater();
53− }
54−}
55−
56−int LauncherModel::rowCount(const QModelIndex &parent) const
57−{
58− Q_UNUSED(parent)
59− return m_list.count();
60−}
61−
62−QVariant LauncherModel::data(const QModelIndex &index, int role) const
63−{
64− LauncherItem *item = m_list.at(index.row());
65− switch(role) {
66− case RoleName:
67− return item->name();
68− case RoleIcon:
69− return item->icon();
70− case RoleFavorite:
71− return item->favorite();
72− }
73−
74− return QVariant();
75−}
76−
77−LauncherItem *LauncherModel::get(int index) const
78−{
79− if (index < 0 || index >= m_list.count()) {
80− return 0;
81− }
82− return m_list.at(index);
83−}
84−
85−void LauncherModel::move(int oldIndex, int newIndex)
86−{
87− beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
88− m_list.move(oldIndex, newIndex);
89− endMoveRows();
90−}
91−
92−QHash<int, QByteArray> LauncherModel::roleNames() const
93−{
94− QHash<int, QByteArray> roles;
95− roles.insert(RoleDesktopFile, "desktopFile");
96− roles.insert(RoleName, "name");
97− roles.insert(RoleIcon, "icon");
98− roles.insert(RoleFavorite, "favorite");
99− roles.insert(RoleRunning, "runnng");
100− return roles;
101−}
102−
103−
104−LauncherItem::LauncherItem(const QString &desktopFile, const QString &name, const QString &icon, QObject *parent):
105− QObject(parent),
106− m_desktopFile(desktopFile),
107− m_name(name),
108− m_icon(icon),
109− m_favorite(false)
110−{
111−
112−}
113−
114−QString LauncherItem::desktopFile() const
115−{
116− return m_desktopFile;
117−}
118−
119−QString LauncherItem::name() const
120−{
121− return m_name;
122−}
123−
124−QString LauncherItem::icon() const
125−{
126− return m_icon;
127−}
128−
129−bool LauncherItem::favorite() const
130−{
131− return m_favorite;
132−}
133−
134−void LauncherItem::setFavorite(bool favorite)
135−{
136− if (m_favorite != favorite) {
137− m_favorite = favorite;
138− Q_EMIT favoriteChanged(m_favorite);
139− }
140−}
141−
142−bool LauncherItem::running() const
143−{
144− return m_running;
145−}
146−
147−void LauncherItem::setRunning(bool running)
148−{
149− if (m_running != running) {
150− m_running = running;
151− Q_EMIT runningChanged(running);
152− }
153−}
plugins/Unity/launchermodel.hdeleted−86
@@ -1,86 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Michael Zanetti <michael.zanetti@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−#include <QAbstractListModel>
21−
22−class LauncherItem;
23−
24−class LauncherModel: public QAbstractListModel
25−{
26− Q_OBJECT
27−
28−public:
29− enum Roles {
30− RoleDesktopFile = Qt::UserRole,
31− RoleName,
32− RoleIcon,
33− RoleFavorite,
34− RoleRunning
35− };
36−
37− LauncherModel(QObject *parent = 0);
38− ~LauncherModel();
39−
40− int rowCount(const QModelIndex &parent) const;
41−
42− QVariant data(const QModelIndex &index, int role) const;
43−
44− Q_INVOKABLE LauncherItem* get(int index) const;
45− Q_INVOKABLE void move(int oldIndex, int newIndex);
46−
47− QHash<int, QByteArray> roleNames() const;
48−
49−private:
50− QList<LauncherItem*> m_list;
51−};
52−
53−class LauncherItem: public QObject
54−{
55− Q_OBJECT
56− Q_PROPERTY(QString desktopFile READ desktopFile CONSTANT)
57− Q_PROPERTY(QString name READ name CONSTANT)
58− Q_PROPERTY(QString icon READ icon CONSTANT)
59− Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged)
60− Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
61−
62−public:
63− LauncherItem(const QString &desktopFile, const QString &name, const QString &icon, QObject *parent = 0);
64−
65− QString desktopFile() const;
66−
67− QString name() const;
68− QString icon() const;
69−
70− bool favorite() const;
71− void setFavorite(bool favorite);
72−
73− bool running() const;
74− void setRunning(bool running);
75−
76−Q_SIGNALS:
77− void favoriteChanged(bool favorite);
78− void runningChanged(bool running);
79−
80−private:
81− QString m_desktopFile;
82− QString m_name;
83− QString m_icon;
84− bool m_favorite;
85− bool m_running;
86−};
plugins/Unity/plugin.cpp+4−5
@@ -27,12 +27,12 @@
2727#include "preview.h"
2828#include "previewaction.h"
2929#include "previewinfohint.h"
30+#include "socialpreviewcomment.h"
3031#include "scope.h"
3132#include "scopes.h"
3233#include "categories.h"
33−#include "categoryfilter.h"
34+#include "categoryresults.h"
3435#include "bottombarvisibilitycommunicatorshell.h"
35−#include "launchermodel.h"
3636
3737// libqtdee
3838#include "deelistmodel.h"
@@ -46,13 +46,12 @@ void UnityPlugin::registerTypes(const char *uri)
4646 qmlRegisterUncreatableType<Preview>(uri, 0, 1, "Preview", "Can't create Preview object in QML.");
4747 qmlRegisterUncreatableType<PreviewAction>(uri, 0, 1, "PreviewAction", "Can't create PreviewAction object in QML.");
4848 qmlRegisterUncreatableType<PreviewInfoHint>(uri, 0, 1, "PreviewInfoHint", "Can't create PreviewInfoHint object in QML.");
49+ qmlRegisterUncreatableType<SocialPreviewComment>(uri, 0, 1, "SocialPreviewComment", "Can't create SocialPreviewComment object in QML.");
4950 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
5051 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
5152 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
52− qmlRegisterType<CategoryFilter>(uri, 0, 1, "CategoryFilter");
53+ qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create new Category Results in QML. Get them from Categories instance.");
5354 qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
54− qmlRegisterType<LauncherModel>(uri, 0, 1, "LauncherModel");
55− qmlRegisterUncreatableType<LauncherItem>(uri, 0, 1, "LauncherItem", "Can't create new Launcher Items in QML. Get them from the LauncherModel.");
5655 qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
5756}
5857
plugins/Unity/preview.cpp+4
@@ -25,6 +25,7 @@
2525#include "applicationpreview.h"
2626#include "moviepreview.h"
2727#include "musicpreview.h"
28+#include "socialpreview.h"
2829#include "variantutils.h"
2930
3031// Qt
@@ -35,6 +36,7 @@
3536#include <UnityCore/ApplicationPreview.h>
3637#include <UnityCore/MoviePreview.h>
3738#include <UnityCore/MusicPreview.h>
39+#include <UnityCore/SocialPreview.h>
3840
3941Preview::Preview(QObject *parent):
4042 QObject(parent),
@@ -124,6 +126,8 @@ Preview* Preview::newFromUnityPreview(unity::dash::Preview::Ptr unityPreview)
124126 preview = new MoviePreview();
125127 } else if (dynamic_cast<unity::dash::ApplicationPreview *>(unityPreview.get()) != nullptr) {
126128 preview = new ApplicationPreview();
129+ } else if (dynamic_cast<unity::dash::SocialPreview *>(unityPreview.get()) != nullptr) {
130+ preview = new SocialPreview();
127131 } else {
128132 qWarning() << "Unknown preview type: " << typeid(*unityPreview).name();
129133 preview = new GenericPreview();
plugins/Unity/previewaction.h+1−1
@@ -36,7 +36,7 @@ enum LayoutHint // keep in sync with unty::dash::LayoutHint
3636 Bottom
3737};
3838
39−class PreviewAction : public QObject
39+class Q_DECL_EXPORT PreviewAction : public QObject
4040{
4141 Q_OBJECT
4242
plugins/Unity/qmldir+1
@@ -1,2 +1,3 @@
11module Unity
22plugin Unity-qml
3+typeinfo plugin.qmltypes
plugins/Unity/scope.cpp+19−57
@@ -3,6 +3,7 @@
33 *
44 * Authors:
55 * Florian Boucault <florian.boucault@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
@@ -38,10 +39,7 @@
3839Scope::Scope(QObject *parent) :
3940 QObject(parent)
4041{
41− m_results = new DeeListModel(this);
42− m_categories = new Categories(this);
43−
44− m_categories->setResultModel(m_results);
42+ m_categories.reset(new Categories(this));
4543}
4644
4745QString Scope::id() const
@@ -84,14 +82,9 @@ bool Scope::connected() const
8482 return m_unityScope->connected();
8583}
8684
87−DeeListModel* Scope::results() const
88−{
89− return m_results;
90−}
91−
9285Categories* Scope::categories() const
9386{
94− return m_categories;
87+ return m_categories.get();
9588}
9689
9790QString Scope::searchQuery() const
@@ -104,6 +97,11 @@ QString Scope::noResultsHint() const
10497 return m_noResultsHint;
10598}
10699
100+QString Scope::formFactor() const
101+{
102+ return m_formFactor;
103+}
104+
107105void Scope::setSearchQuery(const QString& search_query)
108106{
109107 /* Checking for m_searchQuery.isNull() which returns true only when the string
@@ -125,6 +123,15 @@ void Scope::setNoResultsHint(const QString& hint) {
125123 }
126124}
127125
126+void Scope::setFormFactor(const QString& form_factor) {
127+ if (form_factor != m_formFactor) {
128+ m_formFactor = form_factor;
129+ if (m_unityScope) {
130+ m_unityScope->form_factor = m_formFactor.toStdString();
131+ }
132+ Q_EMIT formFactorChanged();
133+ }
134+}
128135
129136unity::dash::LocalResult Scope::createLocalResult(const QVariant &uri, const QVariant &icon_hint,
130137 const QVariant &category, const QVariant &result_type,
@@ -237,18 +244,9 @@ void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
237244{
238245 m_unityScope = scope;
239246
240− if (QString::fromStdString(m_unityScope->results()->swarm_name) == QString(":local")) {
241− m_results->setModel(m_unityScope->results()->model());
242− } else {
243− m_results->setName(QString::fromStdString(m_unityScope->results()->swarm_name));
244− }
245−
246− if (QString::fromStdString(m_unityScope->categories()->swarm_name) == QString(":local")) {
247− m_categories->setModel(m_unityScope->categories()->model());
248− } else {
249− m_categories->setName(QString::fromStdString(m_unityScope->categories()->swarm_name));
250− }
247+ m_categories->setUnityScope(m_unityScope);
251248
249+ m_unityScope->form_factor = m_formFactor.toStdString();
252250 /* Property change signals */
253251 m_unityScope->id.changed.connect(sigc::mem_fun(this, &Scope::idChanged));
254252 m_unityScope->name.changed.connect(sigc::mem_fun(this, &Scope::nameChanged));
@@ -258,12 +256,6 @@ void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
258256 m_unityScope->visible.changed.connect(sigc::mem_fun(this, &Scope::visibleChanged));
259257 m_unityScope->shortcut.changed.connect(sigc::mem_fun(this, &Scope::shortcutChanged));
260258 m_unityScope->connected.changed.connect(sigc::mem_fun(this, &Scope::connectedChanged));
261− m_unityScope->results.changed.connect(sigc::mem_fun(this, &Scope::onResultsChanged));
262− m_unityScope->results()->swarm_name.changed.connect(sigc::mem_fun(this, &Scope::onResultsSwarmNameChanged));
263− m_unityScope->results()->model.changed.connect(sigc::mem_fun(this, &Scope::onResultsModelChanged));
264− m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Scope::onCategoriesModelChanged));
265− m_unityScope->categories.changed.connect(sigc::mem_fun(this, &Scope::onCategoriesChanged));
266− m_unityScope->categories()->swarm_name.changed.connect(sigc::mem_fun(this, &Scope::onCategoriesSwarmNameChanged));
267259 /* Signals forwarding */
268260 connect(this, SIGNAL(searchFinished(const std::string &, unity::glib::HintsMap const &, unity::glib::Error const &)), SLOT(onSearchFinished(const std::string &, unity::glib::HintsMap const &)));
269261
@@ -294,36 +286,6 @@ void Scope::synchronizeStates()
294286 }
295287}
296288
297−void Scope::onResultsSwarmNameChanged(const std::string& /* swarm_name */)
298−{
299− m_results->setName(QString::fromStdString(m_unityScope->results()->swarm_name));
300−}
301−
302−void Scope::onResultsChanged(const unity::dash::Results::Ptr& /* results */)
303−{
304− m_results->setName(QString::fromStdString(m_unityScope->results()->swarm_name));
305−}
306−
307−void Scope::onResultsModelChanged(unity::glib::Object<DeeModel> /* model */)
308−{
309− m_results->setModel(m_unityScope->results()->model());
310−}
311−
312−void Scope::onCategoriesSwarmNameChanged(const std::string& /* swarm_name */)
313−{
314− m_categories->setName(QString::fromStdString(m_unityScope->categories()->swarm_name));
315−}
316−
317−void Scope::onCategoriesChanged(const unity::dash::Categories::Ptr& /* categories */)
318−{
319− m_categories->setName(QString::fromStdString(m_unityScope->categories()->swarm_name));
320−}
321−
322−void Scope::onCategoriesModelChanged(unity::glib::Object<DeeModel> model)
323−{
324− m_categories->setModel(model);
325−}
326−
327289void Scope::onSearchFinished(const std::string& /* query */, unity::glib::HintsMap const &hints)
328290{
329291 QString hint;
plugins/Unity/scope.h+8−12
@@ -32,7 +32,8 @@
3232// dee-qt
3333#include "deelistmodel.h"
3434
35−class Categories;
35+#include "categories.h"
36+
3637class Preview;
3738
3839class Scope : public QObject
@@ -47,11 +48,11 @@ class Scope : public QObject
4748 Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
4849 Q_PROPERTY(QString shortcut READ shortcut NOTIFY shortcutChanged)
4950 Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
50− Q_PROPERTY(DeeListModel* results READ results NOTIFY resultsChanged)
5151 Q_PROPERTY(Categories* categories READ categories NOTIFY categoriesChanged)
5252
5353 Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
5454 Q_PROPERTY(QString noResultsHint READ noResultsHint WRITE setNoResultsHint NOTIFY noResultsHintChanged)
55+ Q_PROPERTY(QString formFactor READ formFactor WRITE setFormFactor NOTIFY formFactorChanged)
5556
5657public:
5758 explicit Scope(QObject *parent = 0);
@@ -65,14 +66,15 @@ public:
6566 bool visible() const;
6667 QString shortcut() const;
6768 bool connected() const;
68− DeeListModel* results() const;
6969 Categories* categories() const;
7070 QString searchQuery() const;
7171 QString noResultsHint() const;
72+ QString formFactor() const;
7273
7374 /* setters */
7475 void setSearchQuery(const QString& search_query);
7576 void setNoResultsHint(const QString& hint);
77+ void setFormFactor(const QString& form_factor);
7678
7779 Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
7880 const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
@@ -94,11 +96,11 @@ Q_SIGNALS:
9496 void visibleChanged(bool);
9597 void shortcutChanged(const std::string&);
9698 void connectedChanged(bool);
97− void resultsChanged();
9899 void categoriesChanged();
99100 void searchFinished(const std::string&, unity::glib::HintsMap const&, unity::glib::Error const&);
100101 void searchQueryChanged();
101102 void noResultsHintChanged();
103+ void formFactorChanged();
102104
103105 // signals triggered by activate(..) or preview(..) requests.
104106 void previewReady(Preview *preview);
@@ -111,12 +113,6 @@ private Q_SLOTS:
111113 void onSearchFinished(const std::string &, unity::glib::HintsMap const &);
112114
113115private:
114− void onResultsSwarmNameChanged(const std::string&);
115− void onResultsChanged(const unity::dash::Results::Ptr&);
116− void onResultsModelChanged(unity::glib::Object<DeeModel>);
117− void onCategoriesSwarmNameChanged(const std::string&);
118− void onCategoriesModelChanged(unity::glib::Object<DeeModel>);
119− void onCategoriesChanged(const unity::dash::Categories::Ptr&);
120116 unity::dash::LocalResult createLocalResult(const QVariant &uri, const QVariant &icon_hint,
121117 const QVariant &category, const QVariant &result_type,
122118 const QVariant &mimetype, const QVariant &title,
@@ -127,10 +123,10 @@ private:
127123 void fallbackActivate(const QString& uri);
128124
129125 unity::dash::Scope::Ptr m_unityScope;
130− DeeListModel* m_results;
131− Categories* m_categories;
126+ std::unique_ptr<Categories> m_categories;
132127 QString m_searchQuery;
133128 QString m_noResultsHint;
129+ QString m_formFactor;
134130};
135131
136132Q_DECLARE_METATYPE(Scope*)
plugins/Unity/socialpreview.cppnew file+83
@@ -0,0 +1,83 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@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+#include "socialpreview.h"
21+#include "socialpreviewcomment.h"
22+
23+#include <QDebug>
24+
25+SocialPreview::SocialPreview(QObject *parent):
26+ Preview(parent),
27+ m_unitySocialPreview(nullptr)
28+{
29+}
30+
31+QString SocialPreview::sender() const
32+{
33+ if (m_unitySocialPreview) {
34+ return QString::fromStdString(m_unitySocialPreview->sender());
35+ } else {
36+ qWarning() << "Preview not set";
37+ }
38+ return QString();
39+}
40+
41+QString SocialPreview::content() const
42+{
43+ if (m_unitySocialPreview) {
44+ return QString::fromStdString(m_unitySocialPreview->content());
45+ } else {
46+ qWarning() << "Preview not set";
47+ }
48+ return QString();
49+}
50+
51+QString SocialPreview::avatar() const
52+{
53+ if (m_unitySocialPreview) {
54+ return QString::fromUtf8(g_icon_to_string(m_unitySocialPreview->avatar()));
55+ } else {
56+ qWarning() << "Preview not set";
57+ }
58+ return QString();
59+}
60+
61+QVariant SocialPreview::comments()
62+{
63+ return QVariant::fromValue(m_comments);
64+}
65+
66+void SocialPreview::setUnityPreview(unity::dash::Preview::Ptr unityPreview)
67+{
68+ m_unitySocialPreview = std::dynamic_pointer_cast<unity::dash::SocialPreview>(unityPreview);
69+ qDeleteAll(m_comments);
70+ m_comments.clear();
71+
72+ if (m_unitySocialPreview) {
73+ for (auto unityComment: m_unitySocialPreview->GetComments()) {
74+ auto comment = new SocialPreviewComment(this);
75+ comment->setUnityComment(unityComment);
76+ m_comments.append(comment);
77+
78+ Q_EMIT previewChanged();
79+ }
80+ } else {
81+ qWarning() << "Incorrect preview type";
82+ }
83+}
plugins/Unity/socialpreview.hnew file+63
@@ -0,0 +1,63 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@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+#ifndef SOCIALPREVIEW_H
21+#define SOCIALPREVIEW_H
22+
23+// local
24+#include "preview.h"
25+
26+// Qt
27+#include <QObject>
28+#include <QList>
29+#include <QMetaType>
30+
31+// libunity-core
32+#include <UnityCore/SocialPreview.h>
33+
34+class Q_DECL_EXPORT SocialPreview: public Preview
35+{
36+ Q_OBJECT
37+
38+ Q_PROPERTY(QString sender READ sender NOTIFY previewChanged)
39+ Q_PROPERTY(QString content READ content NOTIFY previewChanged)
40+ Q_PROPERTY(QString avatar READ avatar NOTIFY previewChanged)
41+
42+public:
43+ explicit SocialPreview(QObject *parent = 0);
44+
45+ QString sender() const;
46+ QString content() const;
47+ QString avatar() const;
48+ QVariant comments();
49+
50+Q_SIGNALS:
51+ void previewChanged();
52+
53+protected:
54+ void setUnityPreview(unity::dash::Preview::Ptr unityPreview) override;
55+
56+private:
57+ unity::dash::SocialPreview::Ptr m_unitySocialPreview;
58+ QList<QObject *> m_comments;
59+};
60+
61+Q_DECLARE_METATYPE(SocialPreview *)
62+
63+#endif
plugins/Unity/socialpreviewcomment.cppnew file+63
@@ -0,0 +1,63 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@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+// local
21+#include "socialpreviewcomment.h"
22+
23+SocialPreviewComment::SocialPreviewComment(QObject *parent) :
24+ QObject(parent)
25+{
26+}
27+
28+void SocialPreviewComment::setUnityComment(unity::dash::SocialPreview::CommentPtr unityComment)
29+{
30+ m_unityComment = unityComment;
31+}
32+
33+QString SocialPreviewComment::id() const
34+{
35+ if (m_unityComment) {
36+ return QString::fromStdString(m_unityComment->id);
37+ }
38+ return QString();
39+}
40+
41+QString SocialPreviewComment::displayName() const
42+{
43+ if (m_unityComment) {
44+ return QString::fromStdString(m_unityComment->display_name);
45+ }
46+ return QString();
47+}
48+
49+QString SocialPreviewComment::content() const
50+{
51+ if (m_unityComment) {
52+ return QString::fromStdString(m_unityComment->content);
53+ }
54+ return QString();
55+}
56+
57+QString SocialPreviewComment::time() const
58+{
59+ if (m_unityComment) {
60+ return QString::fromStdString(m_unityComment->time);
61+ }
62+ return QString();
63+}
plugins/Unity/socialpreviewcomment.hnew file+57
@@ -0,0 +1,57 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@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+#ifndef SOCIALPREVIEWCOMMENT_H
21+#define SOCIALPREVIEWCOMMENT_H
22+
23+// Qt
24+#include <QObject>
25+#include <QMetaType>
26+
27+// libunity-core
28+#include <UnityCore/SocialPreview.h>
29+
30+class Q_DECL_EXPORT SocialPreviewComment : public QObject
31+{
32+ Q_OBJECT
33+
34+ Q_PROPERTY(QString id READ id NOTIFY socialPreviewCommentChanged)
35+ Q_PROPERTY(QString displayName READ displayName NOTIFY socialPreviewCommentChanged)
36+ Q_PROPERTY(QString content READ content NOTIFY socialPreviewCommentChanged)
37+ Q_PROPERTY(QString time READ time NOTIFY socialPreviewCommentChanged)
38+
39+public:
40+ explicit SocialPreviewComment(QObject *parent = 0);
41+ void setUnityComment(unity::dash::SocialPreview::CommentPtr unityComment);
42+
43+ QString id() const;
44+ QString displayName() const;
45+ QString content() const;
46+ QString time() const;
47+
48+Q_SIGNALS:
49+ void socialPreviewCommentChanged();
50+
51+private:
52+ unity::dash::SocialPreview::CommentPtr m_unityComment;
53+};
54+
55+Q_DECLARE_METATYPE(SocialPreviewComment *)
56+
57+#endif
plugins/Utils/CMakeLists.txt+2−12
@@ -23,15 +23,5 @@ set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
2323
2424qt5_use_modules(Utils-qml Qml Quick)
2525
26−# copy qmldir file into build directory for shadow builds
27−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
28− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
29− )
30−
31−install(TARGETS Utils-qml
32− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Utils
33− )
34−
35−install(FILES qmldir
36− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Utils
37− )
26+# export the qmldir and qmltypes files
27+export_qmlplugin(Utils 0.1 Utils TARGETS Utils-qml)
plugins/Utils/qmldir+1
@@ -1,2 +1,3 @@
11module Utils
22plugin Utils-qml
3+typeinfo plugin.qmltypes
po/es.po+7−31
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-16 23:44+0000\n"
11+"PO-Revision-Date: 2013-07-08 07:25+0000\n"
1212"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
1313"Language-Team: Spanish <es@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-27 16:16+0000\n"
18−"X-Generator: Launchpad (build 16681)\n"
17+"X-Launchpad-Export-Date: 2013-07-09 06:13+0000\n"
18+"X-Generator: Launchpad (build 16696)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -167,16 +167,16 @@ msgstr "Autor:"
167167
168168#: Greeter/Lockscreen.qml:133
169169msgid "Emergency call"
170−msgstr ""
170+msgstr "Llamada de emergencia"
171171
172172#: Greeter/PassphraseLockscreen.qml:59
173173#, qt-format
174174msgid "Hello %1"
175−msgstr ""
175+msgstr "Hola %1"
176176
177177#: Greeter/PassphraseLockscreen.qml:59
178178msgid "Hello"
179−msgstr ""
179+msgstr "Hola"
180180
181181#: Hud/HudParametrizedActionsPage.qml:132
182182msgid "Confirm"
@@ -217,28 +217,4 @@ msgstr "No hay nada que coincida con su búsqueda."
217217#: Shell.qml:383
218218#, qt-format
219219msgid "Please enter %1"
220−msgstr ""
221−
222−#~ msgid "People"
223−#~ msgstr "Gente"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Pantalla de inicio"
227−
228−#~ msgid "Favourite People"
229−#~ msgstr "Gente favorita"
230−
231−#~ msgid "People Recently in Touch"
232−#~ msgstr "Gente contactada recientemente"
233−
234−#~ msgid "Recently in touch"
235−#~ msgstr "Contactados recientemente"
236−
237−#~ msgid "Favourites"
238−#~ msgstr "Favoritos"
239−
240−#~ msgid "A-Z"
241−#~ msgstr "A-Z"
242−
243−#~ msgid "New Contacts"
244−#~ msgstr "Contactos nuevos"
220+msgstr "Introduzca %1"
run_on_device+1−3
@@ -65,11 +65,9 @@ setup_adb_forwarding() {
6565}
6666
6767install_dependencies() {
68+ exec_with_adb apt-get update
6869 exec_with_adb apt-get -y install openssh-server
6970 exec_with_ssh $SUDO apt-get -y install build-essential rsync bzr ccache gdb ninja-build devscripts equivs
70− exec_with_ssh $SUDO add-apt-repository -y ppa:canonical-qt5-edgers/qt5-proper
71− exec_with_ssh $SUDO add-apt-repository -s -y ppa:phablet-team/ppa
72− exec_with_ssh $SUDO apt-get update
7371}
7472
7573sync_code() {
src/Panel/Indicators/client/indicatorsclient.cpp+20−10
@@ -56,6 +56,26 @@ IndicatorsClient::IndicatorsClient(int &argc, char **argv)
5656 m_view(0)
5757{
5858 m_application = new QApplication(argc, argv);
59+ QStringList args = m_application->arguments();
60+
61+ m_view = new QQuickView;
62+ m_view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()+"Panel/Indicators/client/"));
63+ prependImportPaths(m_view->engine(), ::overrideImportPaths());
64+ appendImportPaths(m_view->engine(), ::fallbackImportPaths());
65+
66+ m_view->setSource(QUrl("IndicatorsClient.qml"));
67+ m_view->setResizeMode(QQuickView::SizeRootObjectToView);
68+
69+ if (args.contains(QLatin1String("-geometry")) && args.size() > args.indexOf(QLatin1String("-geometry")) + 1) {
70+ QStringList geometryArg = args.at(args.indexOf(QLatin1String("-geometry")) + 1).split('x');
71+ if (geometryArg.size() == 2) {
72+ m_view->resize(geometryArg.at(0).toInt(), geometryArg.at(1).toInt());
73+ }
74+ }
75+ else {
76+ //Usable size on desktop
77+ m_view->setMinimumSize(QSize(480, 720));
78+ }
5979}
6080
6181IndicatorsClient::~IndicatorsClient()
@@ -69,21 +89,11 @@ IndicatorsClient::~IndicatorsClient()
6989
7090void IndicatorsClient::setupUI()
7191{
72− m_view = new QQuickView;
73− m_view->engine()->setBaseUrl(QUrl::fromLocalFile(::shellAppDirectory()+"Panel/Indicators/client/"));
74− prependImportPaths(m_view->engine(), ::overrideImportPaths());
75− appendImportPaths(m_view->engine(), ::fallbackImportPaths());
76−
77− m_view->setSource(QUrl("IndicatorsClient.qml"));
78− m_view->setResizeMode(QQuickView::SizeRootObjectToView);
7992
80− //Usable size on desktop
81− m_view->setMinimumSize(QSize(480, 720));
8293}
8394
8495int IndicatorsClient::run()
8596{
86− setupUI();
8797 m_view->show();
8898 return m_application->exec();
8999}
tests/autopilot/unity8/indicators_client/__init__.pynew file+8
@@ -0,0 +1,8 @@
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+"""unity8 indicators-client autopilot tests and emulators - sub level package."""
tests/autopilot/indicators_client/emulators/__init__.py → tests/autopilot/unity8/indicators_client/emulators/__init__.pyrenamed

The content is the same.

tests/autopilot/indicators_client/emulators/common.py → tests/autopilot/unity8/indicators_client/emulators/common.pyrenamed

The content is the same.

tests/autopilot/indicators_client/emulators/main_window.py → tests/autopilot/unity8/indicators_client/emulators/main_window.pyrenamed−2
@@ -5,8 +5,6 @@
55# under the terms of the GNU General Public License version 3, as published
66# by the Free Software Foundation.
77
8−from indicators_client.emulators import IndicatorsIntrospectionObject
9−
108class MainWindow(object):
119 """An emulator class that makes it easy to interact with the shell"""
1210
tests/autopilot/indicators_client/tests/__init__.py → tests/autopilot/unity8/indicators_client/tests/__init__.pyrenamed+22−8
@@ -15,7 +15,7 @@ from autopilot.matchers import Eventually
1515from autopilot.platform import model
1616from testtools.matchers import Equals
1717
18−from indicators_client.emulators.main_window import MainWindow
18+from unity8.indicators_client.emulators.main_window import MainWindow
1919from logging import getLogger
2020import sys
2121from time import sleep
@@ -38,19 +38,33 @@ class IndicatorsTestCase(AutopilotTestCase):
3838 ('with touch', dict(input_device_class=Touch)),
3939 ]
4040
41− def setUp(self):
41+ def setUp(self, geometry, grid_size):
4242 self.pointing_device = Pointer(self.input_device_class.create())
4343 super(IndicatorsTestCase, self).setUp()
44+ if grid_size != "0":
45+ os.environ['GRID_UNIT_PX'] = grid_size
46+ self.grid_size = int(grid_size)
47+ else:
48+ self.grid_size = int(os.environ['GRID_UNIT_PX'])
49+
4450 if os.path.realpath(__file__).startswith("/usr/"):
45− self.launch_test_installed()
51+ self.launch_test_installed(geometry)
4652 else:
47− self.launch_test_local()
53+ self.launch_test_local(geometry)
4854
49− def launch_test_local(self):
50− self.app = self.launch_test_application("../../builddir/src/Panel/Indicators/client/indicators-client", app_type='qt')
55+ def launch_test_local(self, geometry):
56+ if geometry != "0x0":
57+ self.app = self.launch_test_application("../../builddir/src/Panel/Indicators/client/indicators-client",
58+ "-geometry", geometry, app_type='qt')
59+ else:
60+ self.app = self.launch_test_application("../../builddir/src/Panel/Indicators/client/indicators-client",
61+ app_type='qt')
5162
52− def launch_test_installed(self):
53− self.app = self.launch_test_application("indicators-client", app_type='qt')
63+ def launch_test_installed(self, geometry):
64+ if geometry != "0x0":
65+ self.app = self.launch_test_application("indicators-client", "-geometry", geometry, app_type='qt')
66+ else:
67+ self.app = self.launch_test_application("indicators-client", app_type='qt')
5468
5569 def skipWrapper(*args, **kwargs):
5670 pass
tests/autopilot/indicators_client/tests/test_battery.py → tests/autopilot/unity8/indicators_client/tests/test_battery.pyrenamed+14−11
@@ -10,30 +10,30 @@
1010from testtools.matchers import Equals, NotEquals
1111from autopilot.matchers import Eventually
1212
13−from indicators_client.tests import IndicatorsTestCase
13+from unity8.indicators_client.tests import IndicatorsTestCase
1414from time import sleep
1515import random
1616import math
1717
1818class TestDisplayMenus(IndicatorsTestCase):
1919 def setUp(self):
20− super(TestDisplayMenus, self).setUp()
20+ super(TestDisplayMenus, self).setUp("400x800", "12")
2121
2222 # This opens the messaging menu so you don't have to do that in
2323 # every test case
24− battery_menu = self.main_window.get_battery_menu()
25− self.pointing_device.move_to_object(battery_menu)
24+ self.assertThat(lambda: self.main_window.get_battery_menu(), Eventually(NotEquals(None)));
25+ self.pointing_device.move_to_object(self.main_window.get_battery_menu())
2626 self.pointing_device.click()
2727
28− self.page = self.app.select_single("IndicatorsPage");
29− page_loader = self.app.select_single("IndicatorsPage/QQuickLoader", objectName="page_loader");
28+ fn_loader = lambda: self.app.select_single("IndicatorsPage/QQuickLoader", objectName="page_loader");
29+ self.assertThat(fn_loader, Eventually(NotEquals(None)));
30+ page_loader = fn_loader();
3031 self.assertThat(page_loader.progress, Eventually(Equals(1.0)))
3132
3233 def tearDown(self):
3334 # self.main_window.get_indicators_client().reset()
3435 super(TestDisplayMenus, self).tearDown()
3536
36−
3737 # START SECTION
3838 # We need to move these to emulators once autopilot supports emulators for
3939 # applications started with AutopilotTestCase.launch_test_application
@@ -67,8 +67,10 @@ class TestDisplayMenus(IndicatorsTestCase):
6767 def test_auto_bright_switch(self):
6868 """Test the auto-bright switch"""
6969
70− auto_brightness = self.app.select_single("SwitchMenuItem", objectName="auto-brightness")
71− self.assertThat(auto_brightness, NotEquals(None))
70+ # wait for the switch menu item
71+ fn_auto_brightness = lambda: self.app.select_single("SwitchMenuItem", objectName="auto-brightness");
72+ self.assertThat(fn_auto_brightness, Eventually(NotEquals(None)));
73+ auto_brightness = fn_auto_brightness();
7274
7375 old_ab_value = auto_brightness.checked
7476
@@ -80,8 +82,9 @@ class TestDisplayMenus(IndicatorsTestCase):
8082 def test_brightness_slider(self):
8183 """Test the auto-bright switch"""
8284
83− brightness_menu = self.app.select_single("SliderMenuItem", objectName="brightness")
84− self.assertThat(brightness_menu, NotEquals(None))
85+ fn_brightness_menu = lambda: self.app.select_single("SliderMenuItem", objectName="brightness");
86+ self.assertThat(fn_brightness_menu, Eventually(NotEquals(None)));
87+ brightness_menu = fn_brightness_menu();
8588
8689 old_ab_value = brightness_menu.value
8790 # find a new value to do to. At least 1/4 distance away from current value
tests/autopilot/indicators_client/__init__.py → tests/autopilot/unity8/shell/__init__.pyrenamed+1−1
@@ -5,4 +5,4 @@
55# under the terms of the GNU General Public License version 3, as published
66# by the Free Software Foundation.
77
8−"""indicators-client autopilot tests and emulators - top level package."""
8+"""unity8 shell autopilot tests and emulators - sub level package."""
tests/autopilot/unity8/emulators/__init__.py → tests/autopilot/unity8/shell/emulators/__init__.pyrenamed

The content is the same.

tests/autopilot/unity8/emulators/main_window.py → tests/autopilot/unity8/shell/emulators/main_window.pyrenamed

The content is the same.

tests/autopilot/unity8/tests/__init__.py → tests/autopilot/unity8/shell/tests/__init__.pyrenamed+1−1
@@ -15,7 +15,7 @@ from autopilot.matchers import Eventually
1515from autopilot.platform import model
1616from testtools.matchers import Equals
1717
18−from unity8.emulators.main_window import MainWindow
18+from unity8.shell.emulators.main_window import MainWindow
1919
2020class FormFactors(object):
2121 Phone, Tablet, Desktop = range(3)
tests/autopilot/unity8/tests/helpers.py → tests/autopilot/unity8/shell/tests/helpers.pyrenamed

The content is the same.

tests/autopilot/unity8/tests/testbigscreen.py → tests/autopilot/unity8/shell/tests/testbigscreen.pyrenamed+1−1
@@ -10,7 +10,7 @@
1010from testtools.matchers import Equals
1111from autopilot.matchers import Eventually
1212
13−from unity8.tests import ShellTestCase
13+from unity8.shell.tests import ShellTestCase
1414
1515class TestBig(ShellTestCase):
1616 def setUp(self):
tests/autopilot/unity8/tests/testhud.py → tests/autopilot/unity8/shell/tests/testhud.pyrenamed+2−2
@@ -25,8 +25,8 @@
2525
2626from __future__ import absolute_import
2727
28−from unity8.tests import ShellTestCase, FormFactors
29−from unity8.tests.helpers import TestShellHelpers
28+from unity8.shell.tests import ShellTestCase, FormFactors
29+from unity8.shell.tests.helpers import TestShellHelpers
3030
3131from autopilot.input import Mouse, Touch, Pointer
3232from testtools.matchers import Equals, NotEquals, GreaterThan, MismatchError
tests/autopilot/unity8/tests/testlockscreen.py → tests/autopilot/unity8/shell/tests/testlockscreen.pyrenamed+2−2
@@ -25,8 +25,8 @@
2525
2626from __future__ import absolute_import
2727
28−from unity8.tests import ShellTestCase, FormFactors
29−from unity8.tests.helpers import TestShellHelpers
28+from unity8.shell.tests import ShellTestCase, FormFactors
29+from unity8.shell.tests.helpers import TestShellHelpers
3030
3131from autopilot.input import Mouse, Touch, Pointer
3232from testtools.matchers import Equals, NotEquals, GreaterThan, MismatchError
tests/mocks/LightDM/demo/InfographicModelPrivate.cpp+3−3
@@ -54,7 +54,7 @@ void InfographicModelPrivate::generateFakeData()
5454 QSharedPointer<InfographicData> data(
5555 new InfographicData("<b>52km</b> travelled", yellowTheme, firstMonth,
5656 orangeTheme, secondMonth, this));
57− m_fakeData.insert("guest", data);
57+ m_fakeData.insert("phablet", data);
5858 }
5959
6060 {
@@ -69,7 +69,7 @@ void InfographicModelPrivate::generateFakeData()
6969 QSharedPointer<InfographicData> data(
7070 new InfographicData("<b>33</b> messages today", pinkTheme,
7171 firstMonth, orangeTheme, secondMonth, this));
72− m_fakeData.insert("guest", data);
72+ m_fakeData.insert("phablet", data);
7373 }
7474
7575 {
@@ -84,7 +84,7 @@ void InfographicModelPrivate::generateFakeData()
8484 QSharedPointer<InfographicData> data(
8585 new InfographicData("<b>69</b> minutes talk time", darkPurpleTheme,
8686 firstMonth, redTheme, secondMonth, this));
87− m_fakeData.insert("guest", data);
87+ m_fakeData.insert("phablet", data);
8888 }
8989}
9090
tests/mocks/LightDM/demo/UsersModelPrivate.cpp+1−1
@@ -26,7 +26,7 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
2626{
2727 entries =
2828 {
29− { "single", "Guest", 0, 0, false, false, 0, 0 },
29+ { "phablet", "Guest", 0, 0, false, false, 0, 0 },
3030 };
3131}
3232
tests/mocks/Unity/CMakeLists.txt+4−4
@@ -21,13 +21,11 @@ include_directories(
2121add_definitions(-DQT_NO_KEYWORDS)
2222
2323set(UnityQML_SOURCES
24− ${CMAKE_SOURCE_DIR}/plugins/Unity/categories.cpp
25− ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryfilter.cpp
26− ${CMAKE_SOURCE_DIR}/plugins/Utils/qsortfilterproxymodelqml.cpp
24+ ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
2725 fake_scope.cpp
2826 fake_scopes.cpp
27+ fake_categories.cpp
2928 fake_unity_plugin.cpp
30− fake_launchermodel.cpp
3129)
3230
3331add_library(FakeUnityQml MODULE ${UnityQML_SOURCES})
@@ -44,3 +42,5 @@ qt5_use_modules(FakeUnityQml Qml)
4442file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
4543 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
4644 )
45+
46+add_subdirectory(Launcher)
tests/mocks/Unity/Launcher/CMakeLists.txtnew file+26
@@ -0,0 +1,26 @@
1+include(FindPkgConfig)
2+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
3+
4+include_directories(
5+ ${CMAKE_CURRENT_SOURCE_DIR}
6+)
7+
8+set(MockLauncherModel_SOURCES
9+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
10+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
11+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
12+ plugin.cpp
13+ MockLauncherModel.cpp
14+ MockLauncherItem.cpp
15+ MockQuickListModel.cpp
16+)
17+
18+add_library(MockLauncherPlugin MODULE ${MockLauncherModel_SOURCES})
19+
20+qt5_use_modules(MockLauncherPlugin Core Quick)
21+
22+# copy files into build directory for shadow builds
23+add_custom_target(LauncherPluginQmlDirFile ALL
24+ COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
25+ DEPENDS qmldir
26+)
tests/mocks/Unity/Launcher/MockLauncherItem.cppnew file+134
@@ -0,0 +1,134 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "MockLauncherItem.h"
21+#include "MockQuickListModel.h"
22+
23+using namespace unity::shell::launcher;
24+
25+MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopFile, const QString& name, const QString& icon, QObject* parent):
26+ LauncherItemInterface(parent),
27+ m_appId(appId),
28+ m_desktopFile(desktopFile),
29+ m_name(name),
30+ m_icon(icon),
31+ m_pinned(false),
32+ m_running(false),
33+ m_recent(false),
34+ m_progress(8),
35+ m_count(8),
36+ m_quickList(new MockQuickListModel(this))
37+{
38+
39+}
40+
41+QString MockLauncherItem::appId() const
42+{
43+ return m_appId;
44+}
45+
46+QString MockLauncherItem::desktopFile() const
47+{
48+ return m_desktopFile;
49+}
50+
51+QString MockLauncherItem::name() const
52+{
53+ return m_name;
54+}
55+
56+QString MockLauncherItem::icon() const
57+{
58+ return m_icon;
59+}
60+
61+bool MockLauncherItem::pinned() const
62+{
63+ return m_pinned;
64+}
65+
66+void MockLauncherItem::setPinned(bool pinned)
67+{
68+ if (m_pinned != pinned)
69+ {
70+ m_pinned = pinned;
71+ Q_EMIT pinnedChanged(m_pinned);
72+ }
73+}
74+
75+bool MockLauncherItem::running() const
76+{
77+ return m_running;
78+}
79+
80+void MockLauncherItem::setRunning(bool running)
81+{
82+ if (m_running != running)
83+ {
84+ m_running = running;
85+ Q_EMIT runningChanged(running);
86+ }
87+}
88+
89+bool MockLauncherItem::recent() const
90+{
91+ return m_recent;
92+}
93+
94+void MockLauncherItem::setRecent(bool recent)
95+{
96+ if (m_recent != recent)
97+ {
98+ m_recent = recent;
99+ Q_EMIT recentChanged(recent);
100+ }
101+}
102+
103+int MockLauncherItem::progress() const
104+{
105+ return m_progress;
106+}
107+
108+void MockLauncherItem::setProgress(int progress)
109+{
110+ if (m_progress != progress)
111+ {
112+ m_progress = progress;
113+ Q_EMIT progressChanged(progress);
114+ }
115+}
116+
117+int MockLauncherItem::count() const
118+{
119+ return m_count;
120+}
121+
122+void MockLauncherItem::setCount(int count)
123+{
124+ if (m_count != count)
125+ {
126+ m_count = count;
127+ Q_EMIT countChanged(count);
128+ }
129+}
130+
131+unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
132+{
133+ return m_quickList;
134+}
tests/mocks/Unity/Launcher/MockLauncherItem.hnew file+70
@@ -0,0 +1,70 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef MOCKLAUNCHERITEM_H
21+#define MOCKLAUNCHERITEM_H
22+
23+#include <unity/shell/launcher/LauncherItemInterface.h>
24+
25+class MockQuickListModel;
26+
27+using namespace unity::shell::launcher;
28+
29+class MockLauncherItem: public LauncherItemInterface
30+{
31+ Q_OBJECT
32+public:
33+ MockLauncherItem(const QString &appId, const QString& desktopFile, const QString& name, const QString& icon, QObject* parent = 0);
34+
35+ QString appId() const;
36+ QString desktopFile() const;
37+ QString name() const;
38+ QString icon() const;
39+
40+ bool pinned() const;
41+ void setPinned(bool pinned);
42+
43+ bool running() const;
44+ void setRunning(bool running);
45+
46+ bool recent() const;
47+ void setRecent(bool recent);
48+
49+ int progress() const;
50+ void setProgress(int progress);
51+
52+ int count() const;
53+ void setCount(int count);
54+
55+ unity::shell::launcher::QuickListModelInterface *quickList() const;
56+
57+private:
58+ QString m_appId;
59+ QString m_desktopFile;
60+ QString m_name;
61+ QString m_icon;
62+ bool m_pinned;
63+ bool m_running;
64+ bool m_recent;
65+ int m_progress;
66+ int m_count;
67+ MockQuickListModel *m_quickList;
68+};
69+
70+#endif // MOCKLAUNCHERITEM_H
tests/mocks/Unity/Launcher/MockLauncherModel.cppnew file+152
@@ -0,0 +1,152 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "MockLauncherModel.h"
21+#include "MockLauncherItem.h"
22+
23+MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
24+{
25+ MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app");
26+ m_list.append(item);
27+ item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera");
28+ m_list.append(item);
29+ item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery");
30+ m_list.append(item);
31+ item = new MockLauncherItem("facebook-webapp", "/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook");
32+ m_list.append(item);
33+ item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser");
34+ m_list.append(item);
35+ item = new MockLauncherItem("twitter-webapp", "/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter");
36+ m_list.append(item);
37+ item = new MockLauncherItem("gmail-webapp", "/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail");
38+ m_list.append(item);
39+ item = new MockLauncherItem("ubuntu-weather-app", "/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather");
40+ m_list.append(item);
41+ item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad");
42+ m_list.append(item);
43+ item = new MockLauncherItem("ubuntu-calendar-app", "/usr/share/applications/ubuntu-calendar-app.desktop","Calendar", "calendar");
44+ m_list.append(item);
45+}
46+
47+MockLauncherModel::~MockLauncherModel()
48+{
49+ while (!m_list.empty())
50+ {
51+ m_list.takeFirst()->deleteLater();
52+ }
53+}
54+
55+int MockLauncherModel::rowCount(const QModelIndex& parent) const
56+{
57+ Q_UNUSED(parent)
58+ return m_list.count();
59+}
60+
61+QVariant MockLauncherModel::data(const QModelIndex& index, int role) const
62+{
63+ LauncherItemInterface *item = m_list.at(index.row());
64+ switch(role)
65+ {
66+ case RoleDesktopFile:
67+ return item->desktopFile();
68+ case RoleName:
69+ return item->name();
70+ case RoleIcon:
71+ return item->icon();
72+ case RolePinned:
73+ return item->pinned();
74+ case RoleRunning:
75+ return item->running();
76+ case RoleRecent:
77+ return item->recent();
78+ case RoleProgress:
79+ return item->progress();
80+ case RoleCount:
81+ return item->count();
82+ }
83+
84+ return QVariant();
85+}
86+
87+unity::shell::launcher::LauncherItemInterface *MockLauncherModel::get(int index) const
88+{
89+ if (index < 0 || index >= m_list.count())
90+ {
91+ return 0;
92+ }
93+ return m_list.at(index);
94+}
95+
96+void MockLauncherModel::move(int oldIndex, int newIndex)
97+{
98+ beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
99+ m_list.move(oldIndex, newIndex);
100+ endMoveRows();
101+}
102+
103+void MockLauncherModel::pin(const QString &appId, int index)
104+{
105+ int currentIndex = findApp(appId);
106+
107+ if (currentIndex >= 0) {
108+ if (index == -1 || index == currentIndex) {
109+ m_list.at(currentIndex)->setPinned(true);
110+ QModelIndex modelIndex = this->index(currentIndex);
111+ Q_EMIT dataChanged(modelIndex, modelIndex);
112+ } else {
113+ move(currentIndex, index);
114+ }
115+ } else {
116+ beginInsertRows(QModelIndex(), index, index);
117+ m_list.insert(index, new MockLauncherItem(appId,
118+ appId + ".desktop",
119+ appId,
120+ appId + ".png"));
121+ m_list.at(index)->setPinned(true);
122+ endInsertRows();
123+ }
124+}
125+
126+void MockLauncherModel::requestRemove(const QString &appId)
127+{
128+ int index = findApp(appId);
129+ if (index >= 0) {
130+ beginRemoveRows(QModelIndex(), index, 0);
131+ m_list.takeAt(index)->deleteLater();
132+ endRemoveRows();
133+ }
134+}
135+
136+void MockLauncherModel::quickListActionInvoked(const QString &appId, int actionIndex)
137+{
138+ Q_UNUSED(appId)
139+ Q_UNUSED(actionIndex)
140+ // Nothing to mock yet...
141+}
142+
143+int MockLauncherModel::findApp(const QString &appId)
144+{
145+ for (int i = 0; i < m_list.count(); ++i) {
146+ MockLauncherItem *item = m_list.at(i);
147+ if (item->appId() == appId) {
148+ return i;
149+ }
150+ }
151+ return -1;
152+}
tests/mocks/Unity/Launcher/MockLauncherModel.hnew file+54
@@ -0,0 +1,54 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef MOCKLAUNCHERMODEL_H
21+#define MOCKLAUNCHERMODEL_H
22+
23+#include <unity/shell/launcher/LauncherModelInterface.h>
24+
25+class MockLauncherItem;
26+
27+using namespace unity::shell::launcher;
28+
29+class MockLauncherModel: public LauncherModelInterface
30+{
31+ Q_OBJECT
32+
33+public:
34+ MockLauncherModel(QObject* parent = 0);
35+ ~MockLauncherModel();
36+
37+ int rowCount(const QModelIndex& parent) const;
38+
39+ QVariant data(const QModelIndex& index, int role) const;
40+
41+ Q_INVOKABLE unity::shell::launcher::LauncherItemInterface *get(int index) const;
42+ Q_INVOKABLE void move(int oldIndex, int newIndex);
43+ Q_INVOKABLE void pin(const QString &appId, int index = -1);
44+ Q_INVOKABLE void requestRemove(const QString &appId);
45+ Q_INVOKABLE void quickListActionInvoked(const QString &appId, int actionIndex);
46+
47+private:
48+ int findApp(const QString &appId);
49+
50+private:
51+ QList<MockLauncherItem*> m_list;
52+};
53+
54+#endif // MOCKLAUNCHERMODEL_H
tests/mocks/Unity/Launcher/MockQuickListModel.cppnew file+46
@@ -0,0 +1,46 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include <MockQuickListModel.h>
21+
22+using namespace unity::shell::launcher;
23+
24+MockQuickListModel::MockQuickListModel(QObject *parent) :
25+ QuickListModelInterface(parent)
26+{
27+
28+}
29+
30+QVariant MockQuickListModel::data(const QModelIndex &index, int role) const
31+{
32+ switch (role)
33+ {
34+ case RoleLabel:
35+ return QLatin1String("test menu entry ") + QString::number(index.row());
36+ case RoleIcon:
37+ return QLatin1String("copy.png");
38+ }
39+ return QVariant();
40+}
41+
42+int MockQuickListModel::rowCount(const QModelIndex &parent) const
43+{
44+ Q_UNUSED(parent)
45+ return 4;
46+}
tests/mocks/Unity/Launcher/MockQuickListModel.hnew file+38
@@ -0,0 +1,38 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef MOCKQUICKLISTMODEL_H
21+#define MOCKQUICKLISTMODEL_H
22+
23+#include <unity/shell/launcher/QuickListModelInterface.h>
24+
25+using namespace unity::shell::launcher;
26+
27+class MockQuickListModel: public QuickListModelInterface
28+{
29+ Q_OBJECT
30+public:
31+ MockQuickListModel(QObject *parent = 0);
32+
33+ QVariant data(const QModelIndex &index, int role) const;
34+
35+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
36+};
37+
38+#endif // MOCKQUICKLISTMODEL_H
tests/mocks/Unity/Launcher/plugin.cppnew file+45
@@ -0,0 +1,45 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "plugin.h"
21+#include "MockLauncherModel.h"
22+#include "MockLauncherItem.h"
23+
24+#include <unity/shell/launcher/LauncherModelInterface.h>
25+#include <unity/shell/launcher/LauncherItemInterface.h>
26+
27+#include <QtQml/qqml.h>
28+
29+using namespace unity::shell::launcher;
30+
31+static QObject* modelProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
32+{
33+ return new MockLauncherModel();
34+}
35+
36+// cppcheck-suppress unusedFunction
37+void TestLauncherPlugin::registerTypes(const char* uri)
38+{
39+ // @uri Unity.Launcher
40+ qmlRegisterUncreatableType<LauncherModelInterface>(uri, 0, 1, "LauncherModelInterface", "Abstract Interface. Cannot be instantiated.");
41+ qmlRegisterUncreatableType<LauncherItemInterface>(uri, 0, 1, "LauncherItemInterface", "Abstract Interface. Cannot be instantiated.");
42+
43+ qmlRegisterSingletonType<MockLauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
44+ qmlRegisterUncreatableType<MockLauncherItem>(uri, 0, 1, "LauncherItem", "Can't create LauncherItems in QML. Get them from the LauncherModel");
45+}
tests/mocks/Unity/Launcher/plugin.hnew file+35
@@ -0,0 +1,35 @@
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+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+
21+#ifndef TESTLAUNCHER_PLUGIN_H
22+#define TESTLAUNCHER_PLUGIN_H
23+
24+#include <QtQml/QQmlExtensionPlugin>
25+
26+class TestLauncherPlugin : public QQmlExtensionPlugin
27+{
28+ Q_OBJECT
29+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
30+
31+public:
32+ void registerTypes(const char* uri);
33+};
34+
35+#endif // TESTLAUNCHER_PLUGIN_H
tests/mocks/Unity/Launcher/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Unity.Launcher
2+plugin MockLauncherPlugin
tests/mocks/Unity/fake_categories.cppnew file+178
@@ -0,0 +1,178 @@
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+// self
20+#include "fake_categories.h"
21+
22+// local
23+#include "categoryresults.h"
24+
25+#define CATEGORY_COLUMN 2
26+
27+Categories::Categories(QObject* parent)
28+ : DeeListModel(parent)
29+{
30+ // FIXME: need to clean up unused filters on countChanged
31+ m_roles[Categories::RoleId] = "id";
32+ m_roles[Categories::RoleName] = "name";
33+ m_roles[Categories::RoleIcon] = "icon";
34+ m_roles[Categories::RoleRenderer] = "renderer";
35+ m_roles[Categories::RoleContentType] = "content_type";
36+ m_roles[Categories::RoleHints] = "hints";
37+ m_roles[Categories::RoleResults] = "results";
38+ m_roles[Categories::RoleCount] = "count";
39+
40+ // TODO This should not be needed but accumulatting the count changes
41+ // makes the visualization more stable and also makes crashes on fast
42+ // change of the search term harder to reproduce
43+ m_timer.setSingleShot(true);
44+ m_timer.setInterval(50);
45+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(onEmitCountChanged()));
46+}
47+
48+DeeListModel*
49+Categories::getFilter(int index) const
50+{
51+ if (!m_filters.contains(index)) {
52+ auto results = new CategoryResults ();
53+ results->setCategoryIndex(index);
54+ connect(results, SIGNAL(countChanged()), this, SLOT(onCountChanged()));
55+
56+ unsigned cat_index = static_cast<unsigned>(index);
57+ auto model = getResultsForCategory(cat_index);
58+ results->setModel(model);
59+
60+ m_filters.insert(index, results);
61+ }
62+
63+ return m_filters[index];
64+}
65+
66+void
67+Categories::onCountChanged()
68+{
69+ DeeListModel* filter = qobject_cast<DeeListModel*>(sender());
70+ if (filter) {
71+ m_timerFilters << filter;
72+ m_timer.start();
73+ }
74+}
75+
76+void
77+Categories::onEmitCountChanged()
78+{
79+ QVector<int> roles;
80+ roles.append(Categories::RoleCount);
81+ Q_FOREACH(DeeListModel* results, m_timerFilters) {
82+ auto cat_results = qobject_cast<CategoryResults*>(results);
83+ QModelIndex changedIndex = index(cat_results->categoryIndex());
84+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
85+ }
86+ m_timerFilters.clear();
87+}
88+
89+QHash<int, QByteArray>
90+Categories::roleNames() const
91+{
92+ return m_roles;
93+}
94+
95+void Categories::setResultModel(DeeModel* model)
96+{
97+ // FIXME: should ref it
98+ m_dee_results = model;
99+}
100+
101+
102+static void category_filter_map_func (DeeModel* orig_model,
103+ DeeFilterModel* filter_model,
104+ gpointer user_data)
105+{
106+ DeeModelIter* iter;
107+ DeeModelIter* end;
108+ unsigned index = GPOINTER_TO_UINT(user_data);
109+
110+ iter = dee_model_get_first_iter(orig_model);
111+ end = dee_model_get_last_iter(orig_model);
112+ while (iter != end) {
113+ unsigned category_index = dee_model_get_uint32(orig_model, iter, CATEGORY_COLUMN);
114+ if (index == category_index) {
115+ dee_filter_model_append_iter(filter_model, iter);
116+ }
117+ iter = dee_model_next(orig_model, iter);
118+ }
119+}
120+
121+static gboolean category_filter_notify_func (DeeModel* orig_model,
122+ DeeModelIter* orig_iter,
123+ DeeFilterModel* filter_model,
124+ gpointer user_data)
125+{
126+ unsigned index = GPOINTER_TO_UINT(user_data);
127+ unsigned category_index = dee_model_get_uint32(orig_model, orig_iter, CATEGORY_COLUMN);
128+
129+ if (index != category_index)
130+ return FALSE;
131+
132+ dee_filter_model_insert_iter_with_original_order(filter_model, orig_iter);
133+ return TRUE;
134+}
135+
136+DeeModel* Categories::getResultsForCategory(unsigned cat_index) const
137+{
138+ DeeFilter filter;
139+ filter.map_func = category_filter_map_func;
140+ filter.map_notify = category_filter_notify_func;
141+ filter.destroy = nullptr;
142+ filter.userdata = GUINT_TO_POINTER(cat_index);
143+
144+ DeeModel* filtered_model = dee_filter_model_new(m_dee_results, &filter);
145+ return filtered_model;
146+}
147+
148+QVariant
149+Categories::data(const QModelIndex& index, int role) const
150+{
151+ if (!index.isValid()) {
152+ return QVariant();
153+ }
154+
155+ switch (role) {
156+ case RoleId:
157+ return QVariant::fromValue(index.row());
158+ case RoleName:
159+ return DeeListModel::data(index, 1); //DISPLAY_NAME
160+ case RoleIcon:
161+ return DeeListModel::data(index, 2); //ICON_HINT
162+ case RoleRenderer:
163+ return DeeListModel::data(index, 3); //RENDERER_NAME
164+ case RoleContentType:
165+ {
166+ auto hints = DeeListModel::data(index, 4).toHash();
167+ return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
168+ }
169+ case RoleHints:
170+ return DeeListModel::data(index, 4); //HINTS
171+ case RoleResults:
172+ return QVariant::fromValue(getFilter(index.row()));
173+ case RoleCount:
174+ return QVariant::fromValue(getFilter(index.row())->rowCount());
175+ default:
176+ return QVariant();
177+ }
178+}
tests/mocks/Unity/fake_categories.hnew file+69
@@ -0,0 +1,69 @@
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+#ifndef FAKE_CATEGORIES_H
18+#define FAKE_CATEGORIES_H
19+
20+// Qt
21+#include <QObject>
22+#include <QSet>
23+#include <QTimer>
24+
25+#include <dee.h>
26+#include <deelistmodel.h>
27+
28+class Categories : public DeeListModel
29+{
30+ Q_OBJECT
31+
32+ Q_ENUMS(Roles)
33+
34+public:
35+ Categories(QObject* parent = 0);
36+ enum Roles {
37+ RoleId,
38+ RoleName,
39+ RoleIcon,
40+ RoleRenderer,
41+ RoleContentType,
42+ RoleHints,
43+ RoleResults,
44+ RoleCount
45+ };
46+
47+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
48+
49+ QHash<int, QByteArray> roleNames() const;
50+
51+ /* setters */
52+ void setResultModel(DeeModel* model);
53+
54+private Q_SLOTS:
55+ void onCountChanged();
56+ void onEmitCountChanged();
57+
58+private:
59+ DeeModel* getResultsForCategory(unsigned index) const;
60+ DeeListModel* getFilter(int index) const;
61+
62+ DeeModel* m_dee_results;
63+ QTimer m_timer;
64+ QSet<DeeListModel*> m_timerFilters;
65+ QHash<int, QByteArray> m_roles;
66+ mutable QMap<int, DeeListModel*> m_filters;
67+};
68+
69+#endif // FAKE_CATEGORIES_H
tests/mocks/Unity/fake_launchermodel.cppdeleted−150
@@ -1,150 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Michael Zanetti <michael.zanetti@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−#include "launchermodel.h"
21−
22−LauncherModel::LauncherModel(QObject *parent): QAbstractListModel(parent)
23−{
24− LauncherItem *item = new LauncherItem("/usr/share/applications/phone-app.desktop", "Phone", "phone-app");
25− m_list.append(item);
26− item = new LauncherItem("/usr/share/applications/camera-app.desktop", "Camera", "camera");
27− m_list.append(item);
28− item = new LauncherItem("/usr/share/applications/gallery-app.desktop", "Gallery", "gallery");
29− m_list.append(item);
30− item = new LauncherItem("/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook");
31− m_list.append(item);
32− item = new LauncherItem("/usr/share/applications/webbrowser-app.desktop", "Browser", "browser");
33− m_list.append(item);
34− item = new LauncherItem("/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter");
35− m_list.append(item);
36− item = new LauncherItem("/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail");
37− m_list.append(item);
38− item = new LauncherItem("/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather");
39− m_list.append(item);
40− item = new LauncherItem("/usr/share/applications/notes-app.desktop", "Notepad", "notepad");
41− m_list.append(item);
42− item = new LauncherItem("/usr/share/applications/ubuntu-calendar-app.desktop","Calendar", "calendar");
43− m_list.append(item);
44−}
45−
46−LauncherModel::~LauncherModel()
47−{
48− while (!m_list.empty()) {
49− m_list.takeFirst()->deleteLater();
50− }
51−}
52−
53−int LauncherModel::rowCount(const QModelIndex &parent) const
54−{
55− Q_UNUSED(parent)
56− return m_list.count();
57−}
58−
59−QVariant LauncherModel::data(const QModelIndex &index, int role) const
60−{
61− LauncherItem *item = m_list.at(index.row());
62− switch(role) {
63− case RoleName:
64− return item->name();
65− case RoleIcon:
66− return item->icon();
67− case RoleFavorite:
68− return item->favorite();
69− }
70−
71− return QVariant();
72−}
73−
74−LauncherItem *LauncherModel::get(int index) const
75−{
76− if (index < 0 || index >= m_list.count()) {
77− return 0;
78− }
79− return m_list.at(index);
80−}
81−
82−void LauncherModel::move(int oldIndex, int newIndex)
83−{
84− beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
85− m_list.move(oldIndex, newIndex);
86− endMoveRows();
87−}
88−
89−QHash<int, QByteArray> LauncherModel::roleNames() const
90−{
91− QHash<int, QByteArray> roles;
92− roles.insert(RoleDesktopFile, "desktopFile");
93− roles.insert(RoleName, "name");
94− roles.insert(RoleIcon, "icon");
95− roles.insert(RoleFavorite, "favorite");
96− roles.insert(RoleRunning, "runnng");
97− return roles;
98−}
99−
100−
101−LauncherItem::LauncherItem(const QString &desktopFile, const QString &name, const QString &icon, QObject *parent):
102− QObject(parent),
103− m_desktopFile(desktopFile),
104− m_name(name),
105− m_icon(icon),
106− m_favorite(false)
107−{
108−
109−}
110−
111−QString LauncherItem::desktopFile() const
112−{
113− return m_desktopFile;
114−}
115−
116−QString LauncherItem::name() const
117−{
118− return m_name;
119−}
120−
121−QString LauncherItem::icon() const
122−{
123− return m_icon;
124−}
125−
126−bool LauncherItem::favorite() const
127−{
128− return m_favorite;
129−}
130−
131−void LauncherItem::setFavorite(bool favorite)
132−{
133− if (m_favorite != favorite) {
134− m_favorite = favorite;
135− Q_EMIT favoriteChanged(m_favorite);
136− }
137−}
138−
139−bool LauncherItem::running() const
140−{
141− return m_running;
142−}
143−
144−void LauncherItem::setRunning(bool running)
145−{
146− if (m_running != running) {
147− m_running = running;
148− Q_EMIT runningChanged(running);
149− }
150−}
tests/mocks/Unity/fake_launchermodel.hdeleted−86
@@ -1,86 +0,0 @@
1−/*
2− * Copyright (C) 2011 Canonical, Ltd.
3− *
4− * Authors:
5− * Michael Zanetti <michael.zanetti@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−#include <QAbstractListModel>
21−
22−class LauncherItem;
23−
24−class LauncherModel: public QAbstractListModel
25−{
26− Q_OBJECT
27−
28−public:
29− enum Roles {
30− RoleDesktopFile = Qt::UserRole,
31− RoleName,
32− RoleIcon,
33− RoleFavorite,
34− RoleRunning
35− };
36−
37− LauncherModel(QObject *parent = 0);
38− ~LauncherModel();
39−
40− int rowCount(const QModelIndex &parent) const;
41−
42− QVariant data(const QModelIndex &index, int role) const;
43−
44− Q_INVOKABLE LauncherItem* get(int index) const;
45− Q_INVOKABLE void move(int oldIndex, int newIndex);
46−
47− QHash<int, QByteArray> roleNames() const;
48−
49−private:
50− QList<LauncherItem*> m_list;
51−};
52−
53−class LauncherItem: public QObject
54−{
55− Q_OBJECT
56− Q_PROPERTY(QString desktopFile READ desktopFile CONSTANT)
57− Q_PROPERTY(QString name READ name CONSTANT)
58− Q_PROPERTY(QString icon READ icon CONSTANT)
59− Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged)
60− Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
61−
62−public:
63− LauncherItem(const QString &desktopFile, const QString &name, const QString &icon, QObject *parent = 0);
64−
65− QString desktopFile() const;
66−
67− QString name() const;
68− QString icon() const;
69−
70− bool favorite() const;
71− void setFavorite(bool favorite);
72−
73− bool running() const;
74− void setRunning(bool running);
75−
76−Q_SIGNALS:
77− void favoriteChanged(bool favorite);
78− void runningChanged(bool running);
79−
80−private:
81− QString m_desktopFile;
82− QString m_name;
83− QString m_icon;
84− bool m_favorite;
85− bool m_running;
86−};
tests/mocks/Unity/fake_scope.cpp+104−73
@@ -26,32 +26,29 @@ static DeeModel* create_results_model(unsigned category_count, unsigned result_c
2626// TODO: Implement remaining pieces
2727
2828Scope::Scope(QObject* parent)
29−: QObject(parent),
30− m_visible(false),
31− m_categories(new Categories(this)),
32− m_results(new DeeListModel(this))
29+ : QObject(parent)
30+ , m_visible(false)
31+ , m_categories(new Categories(this))
32+ , m_results(new DeeListModel(this))
3333{
34+ DeeModel* results_model = create_results_model(4, 30);
35+ m_categories->setResultModel(results_model);
3436 m_categories->setModel(create_categories_model(4));
35− m_results->setModel(create_results_model(4, 30));
36−
37− m_categories->setResultModel(m_results);
37+ m_results->setModel(results_model);
3838}
3939
40−Scope::Scope(QString const& id,
41− QString const& name,
42− bool visible,
43− QObject* parent)
44−: QObject(parent),
45− m_id(id),
46− m_name(name),
47− m_visible(visible),
48− m_categories(new Categories(this)),
49− m_results(new DeeListModel(this))
40+Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
41+ : QObject(parent)
42+ , m_id(id)
43+ , m_name(name)
44+ , m_visible(visible)
45+ , m_categories(new Categories(this))
46+ , m_results(new DeeListModel(this))
5047{
48+ DeeModel* results_model = create_results_model(4, 30);
49+ m_categories->setResultModel(results_model);
5150 m_categories->setModel(create_categories_model(4));
52− m_results->setModel(create_results_model(4, 30));
53−
54− m_categories->setResultModel(m_results);
51+ m_results->setModel(results_model);
5552}
5653
5754QString Scope::id() const {
@@ -66,6 +63,42 @@ QString Scope::searchQuery() const {
6663 return m_searchQuery;
6764}
6865
66+QString Scope::iconHint() const {
67+ return m_iconHint;
68+}
69+
70+QString Scope::description() const {
71+ return m_description;
72+}
73+
74+QString Scope::searchHint() const {
75+ return QString("");
76+}
77+
78+QString Scope::shortcut() const {
79+ return QString("");
80+}
81+
82+bool Scope::connected() const {
83+ return true;
84+}
85+
86+Categories* Scope::categories() const {
87+ return m_categories;
88+}
89+
90+QString Scope::noResultsHint() const {
91+ return m_noResultsHint;
92+}
93+
94+QString Scope::formFactor() const {
95+ return m_formFactor;
96+}
97+
98+bool Scope::visible() const {
99+ return m_visible;
100+}
101+
69102void Scope::setName(const QString &str) {
70103 if (str != m_name) {
71104 m_name = str;
@@ -76,45 +109,47 @@ void Scope::setName(const QString &str) {
76109void Scope::setSearchQuery(const QString &str) {
77110 if (str != m_searchQuery) {
78111 m_searchQuery = str;
79− Q_EMIT searchQueryChanged(m_searchQuery);
112+ Q_EMIT searchQueryChanged();
80113 }
81114}
82115
83−bool Scope::visible() const {
84− return m_visible;
116+void Scope::setFormFactor(const QString &str) {
117+ if (str != m_formFactor) {
118+ m_formFactor = str;
119+ Q_EMIT formFactorChanged();
120+ }
85121}
86122
87−Categories* Scope::categories() const {
88− return m_categories;
123+void Scope::setNoResultsHint(const QString& str) {
124+ if (str != m_noResultsHint) {
125+ m_noResultsHint = str;
126+ Q_EMIT noResultsHintChanged();
127+ }
89128}
90129
91130static const gchar * categories_model_schema[] = {
92− "s", //ID
93− "s", // DISPLAY_NAME
94− "s", // ICON_HINT
95− "s", // RENDERER_NAME
96− "a{sv}" // HINTS
131+ "s", //ID
132+ "s", // DISPLAY_NAME
133+ "s", // ICON_HINT
134+ "s", // RENDERER_NAME
135+ "a{sv}" // HINTS
97136};
98137
99138
100139DeeModel* create_categories_model(unsigned category_count) {
101140 DeeModel* category_model = dee_sequence_model_new();
102141 dee_model_set_schema_full(category_model, categories_model_schema, G_N_ELEMENTS(categories_model_schema));
103−
104− GVariantBuilder b;
105− g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
106− GVariant *hints = g_variant_builder_end(&b);
142+ GVariant* hints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0);
107143
108144 for(unsigned i = 0; i < category_count; ++i)
109145 {
110− dee_model_append(category_model,
111− std::to_string(i).c_str(),
112− ("Category "+std::to_string(i)).c_str(),
113− "gtk-apply",
114− "grid",
115− hints);
146+ dee_model_append(category_model,
147+ std::to_string(i).c_str(),
148+ ("Category "+std::to_string(i)).c_str(),
149+ "gtk-apply",
150+ "grid",
151+ hints);
116152 }
117− g_variant_unref(hints);
118153 return category_model;
119154}
120155
@@ -122,48 +157,44 @@ DeeModel* create_categories_model(unsigned category_count) {
122157/* Schema that is used in the DeeModel representing
123158 the results */
124159static const gchar * results_model_schema[] = {
125− "s", // URI
126− "s", // ICON_HINT
127− "u", // CATEGORY
128− "u", // RESULT_TYPE
129− "s", // MIMETYPE
130− "s", // TITLE
131− "s", // COMMENT
132− "s", // DND_URI
133− "a{sv}" // METADATA
160+ "s", // URI
161+ "s", // ICON_HINT
162+ "u", // CATEGORY
163+ "u", // RESULT_TYPE
164+ "s", // MIMETYPE
165+ "s", // TITLE
166+ "s", // COMMENT
167+ "s", // DND_URI
168+ "a{sv}" // METADATA
134169};
135170
136171static const gchar * icons[] = {
137− "Applications.png",
138− "Home.png",
139− "Music.png",
140− "People.png",
141− "Videos.png",
172+ "Applications.png",
173+ "Home.png",
174+ "Music.png",
175+ "People.png",
176+ "Videos.png",
142177};
143178
144179DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
145180 DeeModel* results_model = dee_sequence_model_new();
146181 dee_model_set_schema_full(results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
147−
148− GVariantBuilder b;
149− g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
150− GVariant *hints = g_variant_builder_end(&b);
182+ GVariant* hints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0);
151183
152184 for(unsigned i = 0; i < result_count; ++i)
153185 {
154− unsigned category = i % category_count;
155−
156− dee_model_append(results_model,
157− ("uri://result."+std::to_string(i)).c_str(),
158− (shellAppDirectory() + "Dash/graphics/scopeIcons/" + (icons[i%G_N_ELEMENTS(icons)])).toLatin1().data(),
159− category,
160− 0,
161− "application/x-desktop",
162− ("Title."+std::to_string(i)).c_str(),
163− ("Comment."+std::to_string(i)).c_str(),
164− ("uri://result."+std::to_string(i)).c_str(),
165− hints);
186+ unsigned category = i % category_count;
187+
188+ dee_model_append(results_model,
189+ ("uri://result."+std::to_string(i)).c_str(),
190+ (shellAppDirectory() + "Dash/graphics/scopeIcons/" + (icons[i%G_N_ELEMENTS(icons)])).toLatin1().data(),
191+ category,
192+ 0,
193+ "application/x-desktop",
194+ ("Title."+std::to_string(i)).c_str(),
195+ ("Comment."+std::to_string(i)).c_str(),
196+ ("uri://result."+std::to_string(i)).c_str(),
197+ hints);
166198 }
167− g_variant_unref(hints);
168199 return results_model;
169− }
200+}
tests/mocks/Unity/fake_scope.h+43−11
@@ -19,43 +19,75 @@
1919
2020// Qt
2121#include <QObject>
22−#include "categories.h"
22+#include "fake_categories.h"
2323
2424class Scope : public QObject
2525{
2626 Q_OBJECT
27+
2728 Q_PROPERTY(QString id READ id NOTIFY idChanged)
28− Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
29− Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
29+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
30+ Q_PROPERTY(QString iconHint READ iconHint NOTIFY iconHintChanged)
31+ Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
32+ Q_PROPERTY(QString searchHint READ searchHint NOTIFY searchHintChanged)
3033 Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
34+ Q_PROPERTY(QString shortcut READ shortcut NOTIFY shortcutChanged)
35+ Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
3136 Q_PROPERTY(Categories* categories READ categories NOTIFY categoriesChanged)
3237
38+ Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
39+ Q_PROPERTY(QString noResultsHint READ noResultsHint WRITE setNoResultsHint NOTIFY noResultsHintChanged)
40+ Q_PROPERTY(QString formFactor READ formFactor WRITE setFormFactor NOTIFY formFactorChanged)
41+
3342public:
3443 Scope(QObject* parent = 0);
3544 Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0);
3645
46+ /* getters */
3747 QString id() const;
3848 QString name() const;
39− QString searchQuery() const;
49+ QString iconHint() const;
50+ QString description() const;
51+ QString searchHint() const;
4052 bool visible() const;
41−
42− void setName(const QString &str);
43− void setSearchQuery(const QString &str);
44−
53+ QString shortcut() const;
54+ bool connected() const;
4555 Categories* categories() const;
56+ QString searchQuery() const;
57+ QString noResultsHint() const;
58+ QString formFactor() const;
59+
60+ /* setters */
61+ void setName(const QString& name);
62+ void setSearchQuery(const QString& search_query);
63+ void setNoResultsHint(const QString& hint);
64+ void setFormFactor(const QString& form_factor);
4665
4766Q_SIGNALS:
48− void idChanged(QString);
49− void nameChanged(QString);
50− void searchQueryChanged(QString);
67+ void idChanged(const QString&);
68+ void nameChanged(const QString&);
69+ void iconHintChanged(const QString&);
70+ void descriptionChanged(const QString&);
71+ void searchHintChanged(const QString&);
5172 void visibleChanged(bool);
73+ void shortcutChanged(const QString&);
74+ void connectedChanged(bool);
5275 void categoriesChanged();
76+ void searchFinished(const QString&);
77+ void searchQueryChanged();
78+ void noResultsHintChanged();
79+ void formFactorChanged();
5380
5481private:
5582 QString m_id;
83+ QString m_iconHint;
84+ QString m_description;
5685 QString m_name;
5786 QString m_searchQuery;
87+ QString m_noResultsHint;
88+ QString m_formFactor;
5889 bool m_visible;
90+
5991 Categories* m_categories;
6092 DeeListModel* m_results;
6193};
tests/mocks/Unity/fake_unity_plugin.cpp+3−6
@@ -21,9 +21,8 @@
2121
2222// local
2323#include "fake_scopes.h"
24−#include "categories.h"
25−#include "categoryfilter.h"
26−#include "fake_launchermodel.h"
24+#include "fake_categories.h"
25+#include "categoryresults.h"
2726
2827// External
2928#include <glib-object.h>
@@ -40,7 +39,5 @@ void FakeUnityPlugin::registerTypes(const char *uri)
4039 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
4140 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
4241 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
43− qmlRegisterType<CategoryFilter>(uri, 0, 1, "CategoryFilter");
44− qmlRegisterType<LauncherModel>(uri, 0, 1, "LauncherModel");
45− qmlRegisterUncreatableType<LauncherItem>(uri, 0, 1, "LauncherItem", "Can't create");
42+ qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create");
4643}
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+58
@@ -20,9 +20,12 @@
2020#include <QQmlEngine>
2121#include <QQuickView>
2222#include <QtTestGui>
23+#pragma GCC diagnostic push
24+#pragma GCC diagnostic ignored "-pedantic"
2325#include <private/qquicklistmodel_p.h>
2426#include <private/qquickanimation_p.h>
2527#include <private/qquickitem_p.h>
28+#pragma GCC diagnostic pop
2629
2730class ListViewWithPageHeaderTest : public QObject
2831{
@@ -1248,6 +1251,61 @@ private Q_SLOTS:
12481251 QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
12491252 }
12501253
1254+ void testShowHeaderHalfShown()
1255+ {
1256+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1257+ QSKIP("This test is extremely unstable in 5.0.x");
1258+#endif
1259+ changeContentY(20);
1260+
1261+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1262+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1263+ verifyItem(0, 30., 150., false);
1264+ verifyItem(1, 180, 200., false);
1265+ verifyItem(2, 380, 350., false);
1266+ verifyItem(3, 730, 350., true);
1267+ QCOMPARE(lvwph->m_minYExtent, 0.);
1268+ QCOMPARE(lvwph->m_clipItem->y(), 20.);
1269+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1270+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1271+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1272+ QCOMPARE(lvwph->contentY(), 20.);
1273+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);;
1274+
1275+ lvwph->showHeader();
1276+
1277+ QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1278+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1279+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1280+ verifyItem(0, -20., 150., false);
1281+ verifyItem(1, 130, 200., false);
1282+ verifyItem(2, 330, 350., false);
1283+ verifyItem(3, 680, 350., true);
1284+ QCOMPARE(lvwph->m_minYExtent, 20.);
1285+ QCOMPARE(lvwph->m_clipItem->y(), 50.);
1286+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1287+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1288+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1289+ QCOMPARE(lvwph->contentY(), 0.);
1290+ QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1291+
1292+ scrollToTop();
1293+
1294+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1295+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1296+ verifyItem(0, 50., 150., false);
1297+ verifyItem(1, 200., 200., false);
1298+ verifyItem(2, 400., 350., false);
1299+ verifyItem(3, 750, 350., true);
1300+ QCOMPARE(lvwph->m_minYExtent, 20.);
1301+ QCOMPARE(lvwph->m_clipItem->y(), -20.);
1302+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1303+ QCOMPARE(lvwph->m_headerItem->y(), -20.);
1304+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1305+ QCOMPARE(lvwph->contentY(), -20.);
1306+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1307+ }
1308+
12511309 void testShowHeaderAtBottom()
12521310 {
12531311 scrollToBottom();
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+60
@@ -20,9 +20,12 @@
2020#include <QQmlEngine>
2121#include <QQuickView>
2222#include <QtTestGui>
23+#pragma GCC diagnostic push
24+#pragma GCC diagnostic ignored "-pedantic"
2325#include <private/qquicklistmodel_p.h>
2426#include <private/qquickanimation_p.h>
2527#include <private/qquickitem_p.h>
28+#pragma GCC diagnostic pop
2629
2730class ListViewWithPageHeaderTestSection : public QObject
2831{
@@ -1407,6 +1410,63 @@ private Q_SLOTS:
14071410 QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
14081411 }
14091412
1413+ void testShowHeaderHalfShown()
1414+ {
1415+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1416+ QSKIP("This test is extremely unstable in 5.0.x");
1417+#endif
1418+ changeContentY(20);
1419+
1420+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1421+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1422+ verifyItem(0, 30., 190., false, "Agressive", false);
1423+ verifyItem(1, 220, 240., false, "Regular", false);
1424+ verifyItem(2, 460, 390., false, "Mild", false);
1425+ QCOMPARE(lvwph->m_minYExtent, 0.);
1426+ QCOMPARE(lvwph->m_clipItem->y(), 20.);
1427+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1428+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1429+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1430+ QCOMPARE(lvwph->contentY(), 20.);
1431+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);;
1432+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1433+
1434+ lvwph->showHeader();
1435+
1436+ QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1437+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1438+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1439+ verifyItem(0, -20., 190., false, "Agressive", true);
1440+ verifyItem(1, 170, 240., false, "Regular", false);
1441+ verifyItem(2, 410, 390., false, "Mild", false);
1442+ QCOMPARE(lvwph->m_minYExtent, 20.);
1443+ QCOMPARE(lvwph->m_clipItem->y(), 50.);
1444+ QCOMPARE(lvwph->m_clipItem->clip(), true);
1445+ QCOMPARE(lvwph->m_headerItem->y(), 0.);
1446+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1447+ QCOMPARE(lvwph->contentY(), 0.);
1448+ QCOMPARE(lvwph->m_headerItemShownHeight, 50.);
1449+ QVERIFY(!QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1450+ QCOMPARE(section(lvwph->m_topSectionItem), QString("Agressive"));
1451+ QCOMPARE(lvwph->m_topSectionItem->y(), 0.);
1452+
1453+ scrollToTop();
1454+
1455+ QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1456+ QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1457+ verifyItem(0, 50., 190., false, "Agressive", false);
1458+ verifyItem(1, 240., 240., false, "Regular", false);
1459+ verifyItem(2, 480., 390., false, "Mild", false);
1460+ QCOMPARE(lvwph->m_minYExtent, 20.);
1461+ QCOMPARE(lvwph->m_clipItem->y(), -20.);
1462+ QCOMPARE(lvwph->m_clipItem->clip(), false);
1463+ QCOMPARE(lvwph->m_headerItem->y(), -20.);
1464+ QCOMPARE(lvwph->m_headerItem->height(), 50.);
1465+ QCOMPARE(lvwph->contentY(), -20.);
1466+ QCOMPARE(lvwph->m_headerItemShownHeight, 0.);
1467+ QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
1468+ }
1469+
14101470 void testShowHeaderCloseToTheTop()
14111471 {
14121472 changeContentY(375);
tests/plugins/Unity/CMakeLists.txt+1−1
@@ -23,7 +23,7 @@ macro(run_tests)
2323 add_executable(${_test}Exec ${_test}.cpp previewbindingstest.cpp)
2424 qt5_use_modules(${_test}Exec Test Core Qml)
2525 set_tests_properties(test${CLASSNAME}${_test}
26− PROPERTIES ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS})
26+ PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS}")
2727
2828 target_link_libraries(${_test}Exec
2929 Unity-qml
tests/plugins/Unity/previewbindingstest.cpp+113−58
@@ -25,6 +25,12 @@
2525#include "applicationpreview.h"
2626#include "moviepreview.h"
2727#include "musicpreview.h"
28+#include "socialpreview.h"
29+#include "socialpreviewcomment.h"
30+#include "previewaction.h"
31+
32+#include <glib.h>
33+#include <glib-object.h>
2834
2935void PreviewBindingsTest::initTestCase()
3036{
@@ -32,81 +38,130 @@ void PreviewBindingsTest::initTestCase()
3238
3339void PreviewBindingsTest::testGenericPreview()
3440{
35− auto raw_preview = (GObject *)unity_protocol_generic_preview_new();
36− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Metallica");
37− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Ride The Lightning");
38− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
39− unity::glib::Object<GObject> gen_prv(raw_preview);
40−
41− auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
42− auto prv = Preview::newFromUnityPreview(core_prv);
41+ auto rawPreview = (GObject *)unity_protocol_generic_preview_new();
42+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Metallica");
43+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Ride The Lightning");
44+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
45+ GFile *iconFile = g_file_new_for_path("/foo.png");
46+ GIcon *icon = g_file_icon_new(iconFile);
47+ unity_protocol_preview_add_action(UNITY_PROTOCOL_PREVIEW(rawPreview), "1", "Action1", icon,
48+ UNITY_PROTOCOL_LAYOUT_HINT_LEFT);
49+ unity::glib::Object<GObject> genPrv(rawPreview);
50+
51+ auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
52+ auto prv = Preview::newFromUnityPreview(corePrv);
4353
4454 QCOMPARE(prv != nullptr, true);
4555 QCOMPARE(prv->title(), QString("Metallica"));
4656 QCOMPARE(prv->subtitle(), QString("Ride The Lightning"));
4757 QCOMPARE(prv->description(), QString("Lorem ipsum dolor sit amet"));
58+
59+ auto actions = prv->actions().value<QList<QObject *>>();
60+ QCOMPARE(actions.size(), 1);
61+ auto act = dynamic_cast<PreviewAction *>(actions[0]);
62+ QVERIFY(act != nullptr);
63+ QCOMPARE(act->id(), QString("1"));
64+ QCOMPARE(act->displayName(), QString("Action1"));
65+ QCOMPARE(act->iconHint(), QString("/foo.png"));
66+
67+ g_object_unref(icon);
68+ g_object_unref(iconFile);
4869}
4970
5071void PreviewBindingsTest::testApplicationPreview()
5172{
52− auto raw_preview = (GObject *)unity_protocol_application_preview_new();
53− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Firefox");
54− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Web Browser");
55− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
56− unity_protocol_application_preview_set_license(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), "GPL");
57− unity_protocol_application_preview_set_rating(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), 0.5f);
58− unity_protocol_application_preview_set_num_ratings(UNITY_PROTOCOL_APPLICATION_PREVIEW(raw_preview), 4);
59− unity::glib::Object<GObject> gen_prv(raw_preview);
60−
61− auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
62− auto prv = Preview::newFromUnityPreview(core_prv);
63− auto app_prv = dynamic_cast<ApplicationPreview*>(prv);
64−
65− QCOMPARE(app_prv != nullptr, true);
66− QCOMPARE(app_prv->title(), QString("Firefox"));
67− QCOMPARE(app_prv->subtitle(), QString("Web Browser"));
68− QCOMPARE(app_prv->description(), QString("Lorem ipsum dolor sit amet"));
69− QCOMPARE(app_prv->license(), QString("GPL"));
70− QCOMPARE(app_prv->rating(), 0.5f);
71− QCOMPARE(app_prv->numRatings(), unsigned (4));
73+ auto rawPreview = (GObject *)unity_protocol_application_preview_new();
74+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Firefox");
75+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Web Browser");
76+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
77+ unity_protocol_application_preview_set_license(UNITY_PROTOCOL_APPLICATION_PREVIEW(rawPreview), "GPL");
78+ unity_protocol_application_preview_set_rating(UNITY_PROTOCOL_APPLICATION_PREVIEW(rawPreview), 0.5f);
79+ unity_protocol_application_preview_set_num_ratings(UNITY_PROTOCOL_APPLICATION_PREVIEW(rawPreview), 4);
80+ unity::glib::Object<GObject> genPrv(rawPreview);
81+
82+ auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
83+ auto prv = Preview::newFromUnityPreview(corePrv);
84+ auto appPrv = dynamic_cast<ApplicationPreview*>(prv);
85+
86+ QCOMPARE(appPrv != nullptr, true);
87+ QCOMPARE(appPrv->title(), QString("Firefox"));
88+ QCOMPARE(appPrv->subtitle(), QString("Web Browser"));
89+ QCOMPARE(appPrv->description(), QString("Lorem ipsum dolor sit amet"));
90+ QCOMPARE(appPrv->license(), QString("GPL"));
91+ QCOMPARE(appPrv->rating(), 0.5f);
92+ QCOMPARE(appPrv->numRatings(), unsigned (4));
7293}
7394
7495void PreviewBindingsTest::testMoviePreview()
7596{
76− auto raw_preview = (GObject *)unity_protocol_movie_preview_new();
77− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Blade Runner");
78− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Ridley Scott");
79− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
80− unity_protocol_movie_preview_set_year(UNITY_PROTOCOL_MOVIE_PREVIEW(raw_preview), "1982");
81− unity::glib::Object<GObject> gen_prv(raw_preview);
82−
83− auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
84− auto prv = Preview::newFromUnityPreview(core_prv);
85− auto movie_prv = dynamic_cast<MoviePreview*>(prv);
86−
87− QCOMPARE(movie_prv != nullptr, true);
88− QCOMPARE(movie_prv->title(), QString("Blade Runner"));
89− QCOMPARE(movie_prv->subtitle(), QString("Ridley Scott"));
90− QCOMPARE(movie_prv->description(), QString("Lorem ipsum dolor sit amet"));
91− QCOMPARE(movie_prv->year(), QString("1982"));
97+ auto rawPreview = (GObject *)unity_protocol_movie_preview_new();
98+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Blade Runner");
99+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Ridley Scott");
100+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
101+ unity_protocol_movie_preview_set_year(UNITY_PROTOCOL_MOVIE_PREVIEW(rawPreview), "1982");
102+ unity::glib::Object<GObject> genPrv(rawPreview);
103+
104+ auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
105+ auto prv = Preview::newFromUnityPreview(corePrv);
106+ auto moviePrv = dynamic_cast<MoviePreview*>(prv);
107+
108+ QCOMPARE(moviePrv != nullptr, true);
109+ QCOMPARE(moviePrv->title(), QString("Blade Runner"));
110+ QCOMPARE(moviePrv->subtitle(), QString("Ridley Scott"));
111+ QCOMPARE(moviePrv->description(), QString("Lorem ipsum dolor sit amet"));
112+ QCOMPARE(moviePrv->year(), QString("1982"));
92113}
93114
94115void PreviewBindingsTest::testMusicPreview()
95116{
96− auto raw_preview = (GObject *)unity_protocol_music_preview_new();
97− unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(raw_preview), "Metallica");
98− unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(raw_preview), "Death Magnetic");
99− unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(raw_preview), "Lorem ipsum dolor sit amet");
100− unity::glib::Object<GObject> gen_prv(raw_preview);
101−
102− auto core_prv = unity::dash::Preview::PreviewForProtocolObject(gen_prv);
103− auto prv = Preview::newFromUnityPreview(core_prv);
104− auto music_prv = dynamic_cast<MusicPreview*>(prv);
105−
106− QCOMPARE(music_prv != nullptr, true);
107− QCOMPARE(music_prv->title(), QString("Metallica"));
108− QCOMPARE(music_prv->subtitle(), QString("Death Magnetic"));
109− QCOMPARE(music_prv->description(), QString("Lorem ipsum dolor sit amet"));
117+ auto rawPreview = (GObject *)unity_protocol_music_preview_new();
118+ unity_protocol_preview_set_title(UNITY_PROTOCOL_PREVIEW(rawPreview), "Metallica");
119+ unity_protocol_preview_set_subtitle(UNITY_PROTOCOL_PREVIEW(rawPreview), "Death Magnetic");
120+ unity_protocol_preview_set_description(UNITY_PROTOCOL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
121+ unity::glib::Object<GObject> genPrv(rawPreview);
122+
123+ auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
124+ auto prv = Preview::newFromUnityPreview(corePrv);
125+ auto musicPrv = dynamic_cast<MusicPreview*>(prv);
126+
127+ QCOMPARE(musicPrv != nullptr, true);
128+ QCOMPARE(musicPrv->title(), QString("Metallica"));
129+ QCOMPARE(musicPrv->subtitle(), QString("Death Magnetic"));
130+ QCOMPARE(musicPrv->description(), QString("Lorem ipsum dolor sit amet"));
131+}
132+
133+void PreviewBindingsTest::testSocialPreview()
134+{
135+ GFile *iconFile = g_file_new_for_path("/foo.png");
136+ GIcon *icon = g_file_icon_new(iconFile);
137+
138+ auto rawPreview = (GObject *)unity_protocol_social_preview_new();
139+ unity_protocol_social_preview_set_sender(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), "John");
140+ unity_protocol_social_preview_set_avatar(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), icon);
141+ unity_protocol_social_preview_set_content(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), "Lorem ipsum dolor sit amet");
142+ unity_protocol_social_preview_add_comment(UNITY_PROTOCOL_SOCIAL_PREVIEW(rawPreview), "1", "comment1", "Ubuntu", "2013-07-04 14:10");
143+ unity::glib::Object<GObject> genPrv(rawPreview);
144+
145+ auto corePrv = unity::dash::Preview::PreviewForProtocolObject(genPrv);
146+ auto prv = Preview::newFromUnityPreview(corePrv);
147+ auto socialPrv = dynamic_cast<SocialPreview*>(prv);
148+
149+ QCOMPARE(socialPrv != nullptr, true);
150+ QCOMPARE(socialPrv->sender(), QString("John"));
151+ QCOMPARE(socialPrv->content(), QString("Lorem ipsum dolor sit amet"));
152+ QCOMPARE(socialPrv->avatar(), QString("/foo.png"));
153+
154+ auto comments = socialPrv->comments().value<QList<QObject *>>();
155+ QCOMPARE(comments.size(), 1);
156+ auto cmt = dynamic_cast<SocialPreviewComment *>(comments[0]);
157+ QVERIFY(cmt != nullptr);
158+ QCOMPARE(cmt->id(), QString("1"));
159+ QCOMPARE(cmt->displayName(), QString("comment1"));
160+ QCOMPARE(cmt->content(), QString("Ubuntu"));
161+ QCOMPARE(cmt->time(), QString("2013-07-04 14:10"));
162+
163+ g_object_unref(icon);
164+ g_object_unref(iconFile);
110165}
111166
112167QTEST_MAIN(PreviewBindingsTest)
tests/plugins/Unity/previewbindingstest.h+1
@@ -29,6 +29,7 @@ class PreviewBindingsTest : public QObject
2929 void testApplicationPreview();
3030 void testMoviePreview();
3131 void testMusicPreview();
32+ void testSocialPreview();
3233};
3334
3435#endif
tests/qmltests/Components/tst_OpenEffect.qml+1−1
@@ -28,7 +28,7 @@ TestCase {
2828 function test_openeffect_shadereffectsource() {
2929 compare(openEffect1.source.hideSource, true, "OpenEffect ShaderEffectSource is incorrect")
3030 compare(openEffect1.source.sourceItem, rectangle2, "OpenEffect ShaderEffectSource is incorrect")
31− compare(openEffect1.source.live, true, "OpenEffect ShaderEffectSource is incorrect")
31+ compare(openEffect1.source.live, false, "OpenEffect ShaderEffectSource is incorrect")
3232 compare(openEffect1.source.sourceRect.x, 0, "OpenEffect ShaderEffectSource is incorrect")
3333 compare(openEffect1.source.sourceRect.y, 0, "OpenEffect ShaderEffectSource is incorrect")
3434 compare(openEffect1.source.sourceRect.width, 50, "OpenEffect ShaderEffectSource is incorrect")
tests/qmltests/Dash/qml/FakeScopeView.qml+2−2
@@ -107,10 +107,10 @@ FocusScope {
107107 Image {
108108 width: units.gu(5)
109109 height: units.gu(5)
110− source: column_1
110+ source: icon
111111 anchors.horizontalCenter: parent.horizontalCenter
112112 }
113− Text { text: column_4; anchors.horizontalCenter: parent.horizontalCenter }
113+ Text { text: title; anchors.horizontalCenter: parent.horizontalCenter }
114114 }
115115 }
116116 }
tests/qmltests/Dash/tst_FilterGrids.qml+20−20
@@ -53,26 +53,26 @@ Rectangle {
5353
5454 ListModel {
5555 id: fakeModel
56− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item0"; column_5: ""; column_6: "dummy.desktop" }
57− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item1"; column_5: ""; column_6: "dummy.desktop" }
58− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item2"; column_5: ""; column_6: "dummy.desktop" }
59− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item3"; column_5: ""; column_6: "dummy.desktop" }
60− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item4"; column_5: ""; column_6: "dummy.desktop" }
61− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item5"; column_5: ""; column_6: "dummy.desktop" }
62− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item6"; column_5: ""; column_6: "dummy.desktop" }
63− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item7"; column_5: ""; column_6: "dummy.desktop" }
64− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item8"; column_5: ""; column_6: "dummy.desktop" }
65− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item9"; column_5: ""; column_6: "dummy.desktop" }
66− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item10"; column_5: ""; column_6: "dummy.desktop" }
67− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item11"; column_5: ""; column_6: "dummy.desktop" }
68− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item12"; column_5: ""; column_6: "dummy.desktop" }
69− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item13"; column_5: ""; column_6: "dummy.desktop" }
70− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item14"; column_5: ""; column_6: "dummy.desktop" }
71− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item15"; column_5: ""; column_6: "dummy.desktop" }
72− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item16"; column_5: ""; column_6: "dummy.desktop" }
73− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item17"; column_5: ""; column_6: "dummy.desktop" }
74− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item18"; column_5: ""; column_6: "dummy.desktop" }
75− ListElement { column_0: "Column0"; column_1: "../../graphics/clock.png"; column_4: "Item19"; column_5: ""; column_6: "dummy.desktop" }
56+ ListElement { icon: "../../graphics/clock.png"; title: "Item0"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
57+ ListElement { icon: "../../graphics/clock.png"; title: "Item1"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
58+ ListElement { icon: "../../graphics/clock.png"; title: "Item2"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
59+ ListElement { icon: "../../graphics/clock.png"; title: "Item3"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
60+ ListElement { icon: "../../graphics/clock.png"; title: "Item4"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
61+ ListElement { icon: "../../graphics/clock.png"; title: "Item5"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
62+ ListElement { icon: "../../graphics/clock.png"; title: "Item6"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
63+ ListElement { icon: "../../graphics/clock.png"; title: "Item7"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
64+ ListElement { icon: "../../graphics/clock.png"; title: "Item8"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
65+ ListElement { icon: "../../graphics/clock.png"; title: "Item9"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
66+ ListElement { icon: "../../graphics/clock.png"; title: "Item10"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
67+ ListElement { icon: "../../graphics/clock.png"; title: "Item11"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
68+ ListElement { icon: "../../graphics/clock.png"; title: "Item12"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
69+ ListElement { icon: "../../graphics/clock.png"; title: "Item13"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
70+ ListElement { icon: "../../graphics/clock.png"; title: "Item14"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
71+ ListElement { icon: "../../graphics/clock.png"; title: "Item15"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
72+ ListElement { icon: "../../graphics/clock.png"; title: "Item16"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
73+ ListElement { icon: "../../graphics/clock.png"; title: "Item17"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
74+ ListElement { icon: "../../graphics/clock.png"; title: "Item18"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
75+ ListElement { icon: "../../graphics/clock.png"; title: "Item19"; comment: ""; uri: "dummy.desktop"; dndUri: "dummy.desktop" }
7676 }
7777
7878 Rectangle {