Merge lp:~mzanetti/unity/phablet-autopilot into lp:unity

Proposed by Michael Zanetti on 2013-03-01
Status: Superseded
Proposed branch: lp:~mzanetti/unity/phablet-autopilot
Merge into: lp:unity
Diff against target: 22429 lines (+21010/-0) (has conflicts)
212 files modified
.bzrignore (+13/-0)
Applications/Application.qml (+53/-0)
Applications/applications.js (+166/-0)
Bottombar/Bottombar.qml (+138/-0)
Bottombar/HudButton.qml (+47/-0)
CMakeLists.txt (+102/-0)
COPYING (+674/-0)
Components/AnimationControllerWithSignals.qml (+69/-0)
Components/ApplicationImageFake.qml (+36/-0)
Components/ApplicationImageWrapper.qml (+5/-0)
Components/ApplicationManagerFake.qml (+141/-0)
Components/ApplicationManagerWrapper.qml (+145/-0)
Components/ApplicationScreenshot.qml (+68/-0)
Components/ApplicationWindowFake.qml (+53/-0)
Components/BaseCarouselDelegate.qml (+23/-0)
Components/Carousel.qml (+257/-0)
Components/CrossFadeImage.qml (+142/-0)
Components/DraggingArea.qml (+115/-0)
Components/FilterGrid.qml (+138/-0)
Components/InputFilterArea.qml (+29/-0)
Components/ListItems/Base.qml (+127/-0)
Components/ListItems/Header.qml (+73/-0)
Components/ListItems/Highlight.qml (+46/-0)
Components/ListItems/ThinDivider.qml (+31/-0)
Components/ListItems/VerticalThinDivider.qml (+26/-0)
Components/ListViewWithPageHeader.qml (+180/-0)
Components/Math.js (+26/-0)
Components/OpenEffect.qml (+124/-0)
Components/PageHeader.qml (+338/-0)
Components/QuitResetDialog.qml (+99/-0)
Components/RatingStars.qml (+42/-0)
Components/ResponsiveFlowView.qml (+62/-0)
Components/ResponsiveGridView.qml (+69/-0)
Components/Revealer.qml (+232/-0)
Components/RevealingRectangle.qml (+75/-0)
Components/Showable.qml (+124/-0)
Components/Stage.qml (+481/-0)
Components/StandardAnimation.qml (+22/-0)
Components/Tile.qml (+90/-0)
Components/Time.js (+47/-0)
Components/UbuntuShapeForItem.qml (+89/-0)
Components/carousel.js (+85/-0)
Components/graphics/PageHeaderBaseDivider@18.sci (+5/-0)
Components/graphics/non-selected@18.sci (+5/-0)
Dash/Apps/ApplicationsFilterGrid.qml (+45/-0)
Dash/Apps/AppsAvailableForDownloadModel.qml (+28/-0)
Dash/Apps/FrequentlyUsedAppsModel.qml (+26/-0)
Dash/Apps/InstalledApplicationsModel.qml (+32/-0)
Dash/Apps/RunningApplicationTile.qml (+107/-0)
Dash/Apps/RunningApplicationTileFake.qml (+41/-0)
Dash/Apps/RunningApplicationsGrid.qml (+72/-0)
Dash/Dash.qml (+107/-0)
Dash/DashApps.qml (+110/-0)
Dash/DashBar.qml (+148/-0)
Dash/DashContent.qml (+136/-0)
Dash/DashHome.qml (+176/-0)
Dash/DashMusic.qml (+96/-0)
Dash/DashPeople.qml (+229/-0)
Dash/DashPreview.qml (+211/-0)
Dash/DashVideos.qml (+194/-0)
Dash/GenericLensView.qml (+94/-0)
Dash/LensView.qml (+46/-0)
Dash/Music/AlbumTile.qml (+116/-0)
Dash/Music/CarouselDelegateMusic.qml (+42/-0)
Dash/Music/MusicCarousel.qml (+34/-0)
Dash/Music/MusicFilterGrid.qml (+42/-0)
Dash/People/CarouselDelegatePeople.qml (+139/-0)
Dash/People/Data.qml (+71/-0)
Dash/People/Delegate.qml (+167/-0)
Dash/People/PeopleCarousel.qml (+43/-0)
Dash/People/PeopleFilterGrid.qml (+70/-0)
Dash/People/PeoplePreview.qml (+118/-0)
Dash/People/Preview/Address.qml (+74/-0)
Dash/People/Preview/Base.qml (+22/-0)
Dash/People/Preview/Generic.qml (+80/-0)
Dash/People/Preview/Header.qml (+80/-0)
Dash/People/Preview/Phone.qml (+108/-0)
Dash/People/Preview/Status.qml (+97/-0)
Dash/People/graphics/bottomshape@18.sci (+5/-0)
Dash/Video/CarouselDelegateVideo.qml (+42/-0)
Dash/Video/VideoInfo.qml (+68/-0)
Dash/Video/VideoPreview.qml (+178/-0)
Dash/Video/VideosCarousel.qml (+34/-0)
Dash/Video/VideosFilterGrid.qml (+47/-0)
Greeter/Clock.qml (+61/-0)
Greeter/Greeter.qml (+77/-0)
Greeter/GreeterContent.qml (+105/-0)
Greeter/LoginList.qml (+270/-0)
Hud/AppStack.qml (+271/-0)
Hud/AppStackItem.qml (+48/-0)
Hud/Hud.qml (+509/-0)
Hud/HudParametrizedActionsPage.qml (+172/-0)
Hud/Result.qml (+52/-0)
Hud/ResultList.qml (+101/-0)
Hud/SearchBar.qml (+107/-0)
Hud/ShowingAnimation.qml (+54/-0)
Hud/SliderLabel.qml (+74/-0)
Hud/SoundAmplitudeDelegate.qml (+52/-0)
Hud/SoundAmplitudeVisual.qml (+145/-0)
Hud/ToolBar.qml (+40/-0)
Hud/ToolBarIcon.qml (+34/-0)
Hud/graphics/divider@20.sci (+5/-0)
Launcher/Launcher.qml (+481/-0)
Launcher/LauncherLabel.qml (+64/-0)
Launcher/LauncherShortcuts.qml (+374/-0)
Launcher/ShortcutsContainer.qml (+39/-0)
Launcher/graphics/launcher_bg@18.sci (+5/-0)
Launcher/graphics/non-selected@18.sci (+5/-0)
Launcher/graphics/selected@18.sci (+5/-0)
Notifications/Bubble/ActionButton.qml (+140/-0)
Notifications/Bubble/Background.qml (+88/-0)
Notifications/Bubble/Bubble.qml (+147/-0)
Notifications/Bubble/Content.qml (+180/-0)
Notifications/Bubble/ImageMaskEffect.qml (+41/-0)
Notifications/Bubble/RadialGradient.qml (+53/-0)
Notifications/Bubble/SplitButton.qml (+400/-0)
Notifications/Bubble/TextDropShadow.qml (+33/-0)
Notifications/Bubble/settings.js (+23/-0)
Notifications/Model.js (+50/-0)
Notifications/NotificationButtons.qml (+116/-0)
Notifications/Notifications.qml (+289/-0)
OnScreenKeyboard/OnScreenKeyboard.qml (+39/-0)
Panel/IndicatorItem.qml (+66/-0)
Panel/IndicatorRow.qml (+101/-0)
Panel/Indicators.qml (+304/-0)
Panel/MenuContent.qml (+180/-0)
Panel/Menus/IndicatorMenuWindow.qml (+35/-0)
Panel/Menus/Overview.qml (+69/-0)
Panel/Menus/Overview/FlightModeWidget.qml (+60/-0)
Panel/Menus/Overview/OverviewGrid.qml (+139/-0)
Panel/Menus/Overview/VolumeWidget.qml (+64/-0)
Panel/Panel.qml (+206/-0)
Panel/PanelBackground.qml (+21/-0)
Panel/PanelSeparatorLine.qml (+25/-0)
Panel/SearchIndicator.qml (+106/-0)
Panel/graphics/handle@12.sci (+5/-0)
Panel/graphics/rectangular_dropshadow@30.sci (+5/-0)
Shell.qml (+558/-0)
SideStage/SideStage.qml (+67/-0)
SideStage/SidestageHandle.qml (+22/-0)
SideStage/graphics/sidestage_handle@20.sci (+5/-0)
VolumeControl.qml (+26/-0)
build (+61/-0)
build_unity (+180/-0)
cmake/autopilot.cmake (+7/-0)
config.h.in (+45/-0)
debian/changelog (+457/-0)
debian/compat (+1/-0)
debian/control (+47/-0)
debian/copyright (+21/-0)
debian/qml-phone-shell-autopilot.install (+1/-0)
debian/qml-phone-shell.install (+3/-0)
debian/rules (+14/-0)
debian/source/format (+1/-0)
main.cpp (+97/-0)
plugins/ApplicationLauncher/CMakeLists.txt (+26/-0)
plugins/ApplicationLauncher/applicationlauncher.cpp (+54/-0)
plugins/ApplicationLauncher/applicationlauncher.h (+53/-0)
plugins/ApplicationLauncher/plugin.cpp (+35/-0)
plugins/ApplicationLauncher/plugin.h (+35/-0)
plugins/ApplicationLauncher/qmldir (+2/-0)
plugins/CMakeLists.txt (+4/-0)
plugins/HudClient/CMakeLists.txt (+59/-0)
plugins/HudClient/hudclient.cpp (+265/-0)
plugins/HudClient/hudclient.h (+78/-0)
plugins/HudClient/plugin.cpp (+34/-0)
plugins/HudClient/plugin.h (+31/-0)
plugins/HudClient/qmldir (+1/-0)
plugins/HudClient/volumepeakdetector.cpp (+187/-0)
plugins/HudClient/volumepeakdetector.h (+68/-0)
plugins/Unity/CMakeLists.txt (+56/-0)
plugins/Unity/bottombarvisibilitycommunicatorshell.cpp (+35/-0)
plugins/Unity/bottombarvisibilitycommunicatorshell.h (+53/-0)
plugins/Unity/categories.cpp (+225/-0)
plugins/Unity/categories.h (+94/-0)
plugins/Unity/lens.cpp (+340/-0)
plugins/Unity/lens.h (+149/-0)
plugins/Unity/lenses.cpp (+181/-0)
plugins/Unity/lenses.h (+90/-0)
plugins/Unity/peoplepreviewdata.cpp (+438/-0)
plugins/Unity/peoplepreviewdata.h (+249/-0)
plugins/Unity/plugin.cpp (+62/-0)
plugins/Unity/plugin.h (+35/-0)
plugins/Unity/qmldir (+2/-0)
plugins/Utils/CMakeLists.txt (+34/-0)
plugins/Utils/plugin.cpp (+35/-0)
plugins/Utils/plugin.h (+34/-0)
plugins/Utils/qmldir (+2/-0)
plugins/Utils/qsortfilterproxymodelqml.cpp (+185/-0)
plugins/Utils/qsortfilterproxymodelqml.h (+67/-0)
plugins/Utils/tests/CMakeLists.txt (+24/-0)
plugins/Utils/tests/qsortfilterproxymodeltest.cpp (+442/-0)
plugins/Utils/ubuntuwindow.cpp (+38/-0)
plugins/Utils/ubuntuwindow.h (+42/-0)
qml-phone-shell.desktop.in (+9/-0)
run (+4/-0)
run_on_device (+126/-0)
tests/CMakeLists.txt (+2/-0)
tests/autopilot/CMakeLists.txt (+8/-0)
tests/autopilot/qml_phone_shell/__init__.py (+8/-0)
tests/autopilot/qml_phone_shell/emulators/__init__.py (+6/-0)
tests/autopilot/qml_phone_shell/emulators/main_window.py (+25/-0)
tests/autopilot/qml_phone_shell/tests/__init__.py (+71/-0)
tests/autopilot/qml_phone_shell/tests/helpers.py (+44/-0)
tests/autopilot/qml_phone_shell/tests/testcases.py (+44/-0)
tests/autopilot/qml_phone_shell/tests/testconfigurations.py (+55/-0)
tests/unittests/testListViewWithPageHeader.qml (+142/-0)
tests/unittests/testPeopleView.qml (+83/-0)
tests/unittests/testResponsiveGridView.qml (+94/-0)
tests/unittests/testRevealer.qml (+48/-0)
tests/unittests/testUnityLens.qml (+142/-0)
unity.qmlproject (+20/-0)
Conflict adding file .bzrignore.  Moved existing file to .bzrignore.moved.
Conflict adding file CMakeLists.txt.  Moved existing file to CMakeLists.txt.moved.
Conflict adding file COPYING.  Moved existing file to COPYING.moved.
Conflict adding file cmake.  Moved existing file to cmake.moved.
Conflict adding file debian.  Moved existing file to debian.moved.
Conflict adding file plugins.  Moved existing file to plugins.moved.
Conflict adding file tests.  Moved existing file to tests.moved.
To merge this branch: bzr merge lp:~mzanetti/unity/phablet-autopilot
Reviewer Review Type Date Requested Status
Unity Team 2013-03-01 Pending
Review via email: mp+151161@code.launchpad.net

This proposal has been superseded by a proposal from 2013-03-01.

Commit message

added missing helpers.py file

Description of the change

added missing helpers.py file

To post a comment you must log in.

Unmerged revisions

442. By Michael Zanetti on 2013-03-01

added missing file

441. By Michael Zanetti on 2013-02-27

move helper functions to a separate class

440. By Michael Zanetti on 2013-02-27

remove unused comment

439. By Michael Zanetti on 2013-02-27

added possibility to blacklist tests for certain form factors

438. By Michael Zanetti on 2013-02-26

cleanup

437. By Michael Zanetti on 2013-02-26

added autopilot infrastructure
- autopilot tests skeleton
- autopilot package
- autopilot make target

436. By Florian Boucault on 2013-02-25

Reduced sizes of the following image assets:
- HUD handle
- HUD divider
- launcher background
- panel handle. Fixes: https://bugs.launchpad.net/bugs/1132610.

Approved by Michael Zanetti.

435. By Florian Boucault on 2013-02-25

ApplicationScreenshot: set size to 0x0 when not in use. Saves a large amount of memory, 4 bytes per pixel.

Approved by Michael Zanetti.

434. By Florian Boucault on 2013-02-25

Window management: update screenshots manually and only when an application in focus goes out out focus.
Dash apps lens: use screenshot of applications from cache when going back to dash. Fixes: https://bugs.launchpad.net/bugs/1090756, https://bugs.launchpad.net/bugs/1127573, https://bugs.launchpad.net/bugs/1132169.

Approved by Ricardo Mendoza, Ricardo Salveti.

433. By Florian Boucault on 2013-02-23

Sidestage: make the handle bigger to make it easier to grab. Fixes: https://bugs.launchpad.net/bugs/1131969.

Approved by Ricardo Salveti, PS Jenkins bot, Michał Sawicz.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2013-03-01 09:12:23 +0000
4@@ -0,0 +1,13 @@
5+*.moc
6+*automoc*
7+moc_*
8+*.cmake
9+CMakeCache.txt
10+CMakeFiles
11+Makefile
12+plugins/Utils/tests/CMakeFiles/qsortfilterproxymodeltest.dir
13+plugins/Utils/tests/CMakeFiles/progress.marks
14+plugins/Utils/tests/qsortfilterproxymodeltest
15+config.h
16+qml-phone-shell
17+qml-phone-shell.desktop
18
19=== renamed file '.bzrignore' => '.bzrignore.moved'
20=== added directory 'Applications'
21=== added file 'Applications/Application.qml'
22--- Applications/Application.qml 1970-01-01 00:00:00 +0000
23+++ Applications/Application.qml 2013-03-01 09:12:23 +0000
24@@ -0,0 +1,53 @@
25+/*
26+ * Copyright (C) 2013 Canonical, Ltd.
27+ *
28+ * This program is free software; you can redistribute it and/or modify
29+ * it under the terms of the GNU General Public License as published by
30+ * the Free Software Foundation; version 3.
31+ *
32+ * This program is distributed in the hope that it will be useful,
33+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35+ * GNU General Public License for more details.
36+ *
37+ * You should have received a copy of the GNU General Public License
38+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
39+ */
40+
41+import QtQuick 2.0
42+import "applications.js" as ApplicationsModel
43+
44+/* This class is temporary. It is meant to be API compatible with qthybris' Application
45+ class.
46+ This class can be removed as soon as qthybris' Application is instantiable from QML
47+ and its 'desktopFile' property becomes writable.
48+ This also requires qthybris to be easily compilable on the desktop.
49+*/
50+QtObject {
51+ id: application
52+
53+ property string desktopFile
54+ property string name
55+ property string comment
56+ property string icon
57+ property string exec
58+ property string stage
59+ property bool fullscreen
60+
61+ onDesktopFileChanged: {
62+ var applicationData = ApplicationsModel.__availableApplications[desktopFile];
63+ if (applicationData) {
64+ application.name = applicationData.name;
65+ application.icon = applicationData.icon;
66+ application.exec = applicationData.exec;
67+ application.stage = applicationData.stage ? applicationData.stage : ApplicationsModel.MainStage;
68+ application.fullscreen = applicationData.fullscreen ? applicationData.fullscreen : false;
69+ } else {
70+ application.name = "";
71+ application.icon = "";
72+ application.exec = "";
73+ application.stage = "";
74+ application.fullscreen = false;
75+ }
76+ }
77+}
78
79=== added file 'Applications/applications.js'
80--- Applications/applications.js 1970-01-01 00:00:00 +0000
81+++ Applications/applications.js 2013-03-01 09:12:23 +0000
82@@ -0,0 +1,166 @@
83+/*
84+ * Copyright (C) 2013 Canonical, Ltd.
85+ *
86+ * 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
88+ * the Free Software Foundation; version 3.
89+ *
90+ * This program is distributed in the hope that it will be useful,
91+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
92+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93+ * GNU General Public License for more details.
94+ *
95+ * You should have received a copy of the GNU General Public License
96+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
97+ */
98+
99+function createApplicationForDesktopFile(desktopFile) {
100+ var applicationData = __availableApplications[desktopFile];
101+ if (applicationData) {
102+ var component = Qt.createComponent("Application.qml");
103+ return component.createObject(null, {"desktopFile": desktopFile});
104+ } else {
105+ return null;
106+ }
107+}
108+
109+// FIXME: mimic qtubuntu's Application.Stage enum
110+var MainStage = 0;
111+var SideStage = 1;
112+
113+var __availableApplications = {
114+ 'telephony-app.desktop': {
115+ 'name': 'Phone',
116+ 'icon': 'telephony',
117+ 'exec': '/usr/bin/telephony-app',
118+ 'stage': SideStage
119+ },
120+ 'camera-app.desktop': {
121+ 'name': 'Camera',
122+ 'icon': 'camera',
123+ 'fullscreen': true,
124+ 'exec': '/usr/bin/camera-app --fullscreen'
125+ },
126+ 'ubuntu-gallery.desktop': {
127+ 'name': 'Gallery',
128+ 'icon': 'gallery',
129+ 'exec': '/usr/bin/ubuntu-gallery'
130+ },
131+ 'facebook-webapp.desktop': {
132+ 'name': 'Facebook',
133+ 'icon': 'facebook',
134+ 'exec': '/usr/bin/ubuntu-browser --chromeless http://m.facebook.com',
135+ 'stage': SideStage
136+ },
137+ 'ubuntu-browser.desktop': {
138+ 'name': 'Browser',
139+ 'icon': 'browser',
140+ 'exec': '/usr/bin/ubuntu-browser'
141+ },
142+ 'twitter-webapp.desktop': {
143+ 'name': 'Twitter',
144+ 'icon': 'twitter',
145+ 'exec': '/usr/bin/ubuntu-browser --chromeless http://www.twitter.com',
146+ 'stage': SideStage
147+ },
148+ 'gmail-webapp.desktop': {
149+ 'name': 'GMail',
150+ 'icon': 'gmail',
151+ 'exec': '/usr/bin/ubuntu-browser --chromeless http://m.gmail.com'
152+ },
153+ 'music-player-mockapp.desktop': {
154+ 'name': 'Music',
155+ 'icon': 'music',
156+ 'exec': '/usr/bin/qmlscene /usr/share/demo-mock-apps/music.qml'
157+ },
158+ 'notepad.desktop': {
159+ 'name': 'Notepad',
160+ 'icon': 'notepad',
161+ 'exec': '/usr/bin/qmlscene /usr/share/notepad-qml/Notepad.qml',
162+ 'stage': SideStage
163+ },
164+ 'ski-safari-mockapp.desktop': {
165+ 'name': 'Ski Safari',
166+ 'icon': 'ski_safari',
167+ 'exec': '/usr/bin/qmlscene /usr/share/demo-mock-apps/ski-safari.qml'
168+ },
169+ 'share-app.desktop': {
170+ 'name': 'Sharing',
171+ 'icon': 'share',
172+ 'exec': '/usr/bin/share-app',
173+ 'stage': SideStage
174+ },
175+ 'media-player.desktop': {
176+ 'name': 'Media Player',
177+ 'icon': 'media-player',
178+ 'fullscreen': true,
179+ 'exec': '/usr/bin/media-player'
180+ },
181+ 'ebay-webapp.desktop': {
182+ 'name': 'eBay',
183+ 'icon': 'ebay',
184+ 'exec': '/usr/bin/ubuntu-browser --chromeless http://ebay.com'
185+ },
186+ 'amazon-webapp.desktop': {
187+ 'name': 'Amazon',
188+ 'icon': 'amazon',
189+ 'exec': '/usr/bin/ubuntu-browser --chromeless http://m.amazon.com'
190+ },
191+ 'ubuntuone-webapp.desktop': {
192+ 'name': 'Ubuntu One',
193+ 'icon': 'ubuntuone',
194+ 'exec': '/usr/bin/ubuntu-browser --chromeless http://one.ubuntu.com'
195+ },
196+ 'calculator-mockapp.desktop': {
197+ 'name': 'Calculator',
198+ 'icon': 'calculator',
199+ 'exec': '/usr/bin/qmlscene /usr/share/demo-mock-apps/calculator.qml',
200+ 'stage': SideStage
201+ },
202+ 'weather-mockapp.desktop': {
203+ 'name': 'Weather',
204+ 'icon': 'weather',
205+ 'exec': '/usr/bin/qmlscene /usr/share/demo-mock-apps/weather.qml',
206+ 'stage': SideStage
207+ },
208+ 'calendar.desktop': {
209+ 'name': 'Calendar',
210+ 'icon': 'calendar',
211+ 'exec': ''
212+ },
213+ 'clock.desktop': {
214+ 'name': 'Clock',
215+ 'icon': 'clock',
216+ 'exec': ''
217+ },
218+ 'evernote.desktop': {
219+ 'name': 'Evernote',
220+ 'icon': 'evernote',
221+ 'exec': ''
222+ },
223+ 'map.desktop': {
224+ 'name': 'Map',
225+ 'icon': 'map',
226+ 'exec': ''
227+ },
228+ 'pinterest.desktop': {
229+ 'name': 'Pinterest',
230+ 'icon': 'pinterest',
231+ 'exec': ''
232+ },
233+ 'soundcloud.desktop': {
234+ 'name': 'SoundCloud',
235+ 'icon': 'soundcloud',
236+ 'exec': ''
237+ },
238+ 'wikipedia.desktop': {
239+ 'name': 'Wikipedia',
240+ 'icon': 'wikipedia',
241+ 'exec': ''
242+ },
243+ 'youtube.desktop': {
244+ 'name': 'YouTube',
245+ 'icon': 'youtube',
246+ 'exec': ''
247+ },
248+}
249
250=== added directory 'Bottombar'
251=== added file 'Bottombar/Bottombar.qml'
252--- Bottombar/Bottombar.qml 1970-01-01 00:00:00 +0000
253+++ Bottombar/Bottombar.qml 2013-03-01 09:12:23 +0000
254@@ -0,0 +1,138 @@
255+import QtQuick 2.0
256+import "../Components"
257+import "../Components/Math.js" as MathLocal
258+import Unity 0.1
259+
260+Item {
261+ id: bottombar
262+ width: shell.width
263+ height: shell.height
264+
265+ property variant theHud
266+ property bool enabled: false
267+ property real sideStageWidth: -1
268+ readonly property real bottomEdgeButtonCenterDistance: units.gu(34)
269+ readonly property real bottomEdgeShowButtonDistance: units.gu(5)
270+
271+ property bool __applicationInFocus: false
272+
273+ state: "hidden"
274+
275+ HudButton {
276+ id: hudButton
277+
278+ x: MathLocal.clamp(hudButtonRevealer.pressedX - width / 2, 0, bottombar.width - width)
279+ y: bottombar.height - bottomEdgeButtonCenterDistance - height / 2 - bottomMargin
280+ Behavior on bottomMargin {
281+ NumberAnimation{duration: hudButton.opacity < 0.01 ? 200 : 70; easing.type: Easing.OutQuart}
282+ }
283+ mouse: {
284+ if (hudButtonRevealer.draggingArea.pressed) {
285+ var mapped = mapFromItem(hudButtonRevealer.draggingArea, hudButtonRevealer.draggingArea.mouseX, hudButtonRevealer.draggingArea.mouseY)
286+ return Qt.point(mapped.x, mapped.y)
287+ } else {
288+ return mouse
289+ }
290+ }
291+
292+ Behavior on opacity {
293+ NumberAnimation{ duration: 200; easing.type: Easing.OutCubic}
294+ }
295+ }
296+
297+ Connections {
298+ target: theHud
299+ onShownChanged: bottomBarVisibilityCommunicatorShell.forceHidden = theHud.shown
300+ }
301+
302+ function updateApplicationInFocus() {
303+ if (shell.applicationManager.mainStageFocusedApplication || shell.applicationManager.sideStageFocusedApplication) {
304+ __applicationInFocus = true
305+ } else {
306+ __applicationInFocus = false
307+ }
308+ }
309+
310+ Connections {
311+ target: shell.applicationManager
312+ ignoreUnknownSignals: true
313+ onMainStageFocusedApplicationChanged: updateApplicationInFocus()
314+ onSideStageFocusedApplicationChanged: updateApplicationInFocus()
315+ }
316+
317+ Showable {
318+ id: hudButtonShowable
319+
320+ opacity: 1.0
321+ width: parent.width
322+ height: bottomEdgeShowButtonDistance
323+ shown: false
324+ showAnimation: StandardAnimation { property: "y"; duration: 350; to: hudButtonRevealer.openedValue; easing.type: Easing.OutCubic }
325+ hideAnimation: StandardAnimation { property: "y"; duration: 350; to: hudButtonRevealer.closedValue; easing.type: Easing.OutCubic }
326+ onYChanged: {
327+ if (y == hudButtonRevealer.openedValue)
328+ bottombar.state = "shown"
329+ }
330+
331+ // eater
332+ MouseArea {
333+ anchors.fill: parent
334+ }
335+ }
336+
337+ Revealer {
338+ id: hudButtonRevealer
339+
340+ property double pressedX
341+
342+ enabled: !theHud.shown && bottombar.enabled && __applicationInFocus
343+ direction: Qt.RightToLeft
344+ openedValue: bottombar.height - height
345+ closedValue: bottombar.height
346+ target: hudButtonShowable
347+ width: hudButtonShowable.width
348+ height: hudButtonShowable.height
349+ anchors.bottom: bottombar.bottom
350+ onOpenPressed: {
351+ pressedX = mouseX
352+ }
353+
354+ onOpenReleased: {
355+ if (hudButton.opacity != 0 && hudButton.mouseOver) {
356+ hudButtonShowable.hide()
357+ if (shell.applicationManager.sideStageFocusedApplication &&
358+ ((hudButtonRevealer.pressedX > bottombar.width - bottombar.sideStageWidth) || !shell.applicationManager.mainStageFocusedApplication))
359+ {
360+ theHud.showSideStage()
361+ } else {
362+ theHud.show()
363+ }
364+ } else {
365+ hudButtonShowable.hide()
366+ }
367+ }
368+ }
369+
370+ Connections {
371+ target: hudButtonShowable.hideAnimation
372+ onRunningChanged: {
373+ if (hudButtonShowable.hideAnimation.running) {
374+ bottombar.state = "hidden"
375+ }
376+ }
377+ }
378+
379+ states: [
380+ State {
381+ name: "hidden"
382+ PropertyChanges { target: hudButton; opacity: 0}
383+ PropertyChanges { target: hudButton; bottomMargin: units.gu(-1)}
384+ },
385+ State {
386+ name: "shown"
387+ PropertyChanges { target: hudButton; opacity: 1}
388+ PropertyChanges { target: hudButton; bottomMargin: units.gu(0)}
389+ }
390+ ]
391+
392+}
393
394=== added file 'Bottombar/HudButton.qml'
395--- Bottombar/HudButton.qml 1970-01-01 00:00:00 +0000
396+++ Bottombar/HudButton.qml 2013-03-01 09:12:23 +0000
397@@ -0,0 +1,47 @@
398+import QtQuick 2.0
399+import Ubuntu.Components 0.1
400+
401+Item {
402+ id: item
403+
404+ property int bottomMargin: units.gu(2)
405+ property bool mouseOver: contains(mouse)
406+
407+ property point mouse: Qt.point(-1,-1)
408+
409+ readonly property real scaleOnMouseOver: 1.2
410+
411+ width: hudButton.width * scaleOnMouseOver
412+ height: hudButton.height * scaleOnMouseOver
413+
414+ Item {
415+ id: hudButton
416+ property alias actionButton: actionButton
417+
418+ anchors.centerIn: parent
419+ height: units.gu(12)
420+ width: height
421+ opacity: item.mouseOver ? 1 : 0.7
422+ scale: item.mouseOver ? scaleOnMouseOver : 1
423+ Behavior on opacity {NumberAnimation{duration: 200; easing.type: Easing.OutQuart}}
424+ Behavior on scale {NumberAnimation{duration: 200; easing.type: Easing.OutQuart}}
425+
426+ UbuntuShape {
427+ id: actionButton
428+ anchors.fill: parent
429+
430+ borderSource: ""
431+ image: Image {
432+ source: "graphics/hud_invoke_button_active.png"
433+ }
434+ }
435+
436+ Image {
437+ width: units.gu(4)
438+ height: width
439+ source: "graphics/hud.png"
440+ anchors.centerIn: parent
441+ fillMode: Image.PreserveAspectFit
442+ }
443+ }
444+}
445
446=== added directory 'Bottombar/graphics'
447=== added file 'Bottombar/graphics/hud@20.png'
448Binary files Bottombar/graphics/hud@20.png 1970-01-01 00:00:00 +0000 and Bottombar/graphics/hud@20.png 2013-03-01 09:12:23 +0000 differ
449=== added file 'Bottombar/graphics/hud_invoke_button_active@20.png'
450Binary files Bottombar/graphics/hud_invoke_button_active@20.png 1970-01-01 00:00:00 +0000 and Bottombar/graphics/hud_invoke_button_active@20.png 2013-03-01 09:12:23 +0000 differ
451=== added file 'CMakeLists.txt'
452--- CMakeLists.txt 1970-01-01 00:00:00 +0000
453+++ CMakeLists.txt 2013-03-01 09:12:23 +0000
454@@ -0,0 +1,102 @@
455+project(qml-phone-shell)
456+cmake_minimum_required(VERSION 2.8.9)
457+
458+# Instruct CMake to run moc automatically when needed.
459+set(CMAKE_AUTOMOC ON)
460+
461+# enable QML debugging
462+if(CMAKE_BUILD_TYPE MATCHES DEBUG OR CMAKE_BUILD_TYPE MATCHES "Debug")
463+ add_definitions(-DQT_QML_DEBUG)
464+endif()
465+
466+find_package(Qt5Qml)
467+find_package(Qt5Quick)
468+find_package(Qt5Gui)
469+find_package(Qt5DBus)
470+
471+# Standard install paths
472+include(GNUInstallDirs)
473+
474+set(SHELL_APP_DIR ${CMAKE_INSTALL_DATADIR}/qml-phone-shell)
475+
476+configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
477+
478+include_directories(
479+ ${CMAKE_CURRENT_BINARY_DIR}
480+ ${CMAKE_CURRENT_SOURCE_DIR}
481+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
482+ )
483+
484+# Tests
485+enable_testing()
486+add_custom_target(check make test CTEST_OUTPUT_ON_FAILURE=1)
487+
488+# Autopilot tests
489+include(${CMAKE_SOURCE_DIR}/cmake/autopilot.cmake)
490+declare_autopilot_test(qml_phone_shell ${CMAKE_CURRENT_SOURCE_DIR}/tests/autopilot/)
491+
492+add_subdirectory(tests)
493+
494+set(SHELL_APP qml-phone-shell)
495+
496+set(shell_app_HDRS
497+ )
498+
499+set(shell_app_SRCS
500+ main.cpp)
501+
502+add_executable(${SHELL_APP}
503+ ${shellapplication_MOC_SRCS}
504+ ${shell_app_SRCS}
505+ )
506+
507+qt5_use_modules(${SHELL_APP} Qml Quick)
508+
509+target_link_libraries(${SHELL_APP}
510+ ${Qt5Qml_LIBRARIES}
511+ ${Qt5Quick_LIBRARIES}
512+ )
513+
514+# install binaries
515+install(TARGETS ${SHELL_APP}
516+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
517+ )
518+
519+# install top level qml and js files
520+file(GLOB QML_JS_FILES *.qml *.js)
521+
522+install(FILES ${QML_JS_FILES}
523+ DESTINATION ${SHELL_APP_DIR}
524+ )
525+
526+# add subdirectories to build
527+add_subdirectory(plugins)
528+
529+
530+# install subdirectories
531+set(QML_DIRS
532+ Applications
533+ Bottombar
534+ Components
535+ Dash
536+ graphics
537+ Greeter
538+ Hud
539+ Panel
540+ Launcher
541+ Notifications
542+ OnScreenKeyboard
543+ SideStage
544+ )
545+
546+install(DIRECTORY ${QML_DIRS}
547+ DESTINATION ${SHELL_APP_DIR}
548+ )
549+
550+# generate desktop file
551+configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
552+
553+# install desktop file
554+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
555+ DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
556+ )
557
558=== renamed file 'CMakeLists.txt' => 'CMakeLists.txt.moved'
559=== added file 'COPYING'
560--- COPYING 1970-01-01 00:00:00 +0000
561+++ COPYING 2013-03-01 09:12:23 +0000
562@@ -0,0 +1,674 @@
563+ GNU GENERAL PUBLIC LICENSE
564+ Version 3, 29 June 2007
565+
566+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
567+ Everyone is permitted to copy and distribute verbatim copies
568+ of this license document, but changing it is not allowed.
569+
570+ Preamble
571+
572+ The GNU General Public License is a free, copyleft license for
573+software and other kinds of works.
574+
575+ The licenses for most software and other practical works are designed
576+to take away your freedom to share and change the works. By contrast,
577+the GNU General Public License is intended to guarantee your freedom to
578+share and change all versions of a program--to make sure it remains free
579+software for all its users. We, the Free Software Foundation, use the
580+GNU General Public License for most of our software; it applies also to
581+any other work released this way by its authors. You can apply it to
582+your programs, too.
583+
584+ When we speak of free software, we are referring to freedom, not
585+price. Our General Public Licenses are designed to make sure that you
586+have the freedom to distribute copies of free software (and charge for
587+them if you wish), that you receive source code or can get it if you
588+want it, that you can change the software or use pieces of it in new
589+free programs, and that you know you can do these things.
590+
591+ To protect your rights, we need to prevent others from denying you
592+these rights or asking you to surrender the rights. Therefore, you have
593+certain responsibilities if you distribute copies of the software, or if
594+you modify it: responsibilities to respect the freedom of others.
595+
596+ For example, if you distribute copies of such a program, whether
597+gratis or for a fee, you must pass on to the recipients the same
598+freedoms that you received. You must make sure that they, too, receive
599+or can get the source code. And you must show them these terms so they
600+know their rights.
601+
602+ Developers that use the GNU GPL protect your rights with two steps:
603+(1) assert copyright on the software, and (2) offer you this License
604+giving you legal permission to copy, distribute and/or modify it.
605+
606+ For the developers' and authors' protection, the GPL clearly explains
607+that there is no warranty for this free software. For both users' and
608+authors' sake, the GPL requires that modified versions be marked as
609+changed, so that their problems will not be attributed erroneously to
610+authors of previous versions.
611+
612+ Some devices are designed to deny users access to install or run
613+modified versions of the software inside them, although the manufacturer
614+can do so. This is fundamentally incompatible with the aim of
615+protecting users' freedom to change the software. The systematic
616+pattern of such abuse occurs in the area of products for individuals to
617+use, which is precisely where it is most unacceptable. Therefore, we
618+have designed this version of the GPL to prohibit the practice for those
619+products. If such problems arise substantially in other domains, we
620+stand ready to extend this provision to those domains in future versions
621+of the GPL, as needed to protect the freedom of users.
622+
623+ Finally, every program is threatened constantly by software patents.
624+States should not allow patents to restrict development and use of
625+software on general-purpose computers, but in those that do, we wish to
626+avoid the special danger that patents applied to a free program could
627+make it effectively proprietary. To prevent this, the GPL assures that
628+patents cannot be used to render the program non-free.
629+
630+ The precise terms and conditions for copying, distribution and
631+modification follow.
632+
633+ TERMS AND CONDITIONS
634+
635+ 0. Definitions.
636+
637+ "This License" refers to version 3 of the GNU General Public License.
638+
639+ "Copyright" also means copyright-like laws that apply to other kinds of
640+works, such as semiconductor masks.
641+
642+ "The Program" refers to any copyrightable work licensed under this
643+License. Each licensee is addressed as "you". "Licensees" and
644+"recipients" may be individuals or organizations.
645+
646+ To "modify" a work means to copy from or adapt all or part of the work
647+in a fashion requiring copyright permission, other than the making of an
648+exact copy. The resulting work is called a "modified version" of the
649+earlier work or a work "based on" the earlier work.
650+
651+ A "covered work" means either the unmodified Program or a work based
652+on the Program.
653+
654+ To "propagate" a work means to do anything with it that, without
655+permission, would make you directly or secondarily liable for
656+infringement under applicable copyright law, except executing it on a
657+computer or modifying a private copy. Propagation includes copying,
658+distribution (with or without modification), making available to the
659+public, and in some countries other activities as well.
660+
661+ To "convey" a work means any kind of propagation that enables other
662+parties to make or receive copies. Mere interaction with a user through
663+a computer network, with no transfer of a copy, is not conveying.
664+
665+ An interactive user interface displays "Appropriate Legal Notices"
666+to the extent that it includes a convenient and prominently visible
667+feature that (1) displays an appropriate copyright notice, and (2)
668+tells the user that there is no warranty for the work (except to the
669+extent that warranties are provided), that licensees may convey the
670+work under this License, and how to view a copy of this License. If
671+the interface presents a list of user commands or options, such as a
672+menu, a prominent item in the list meets this criterion.
673+
674+ 1. Source Code.
675+
676+ The "source code" for a work means the preferred form of the work
677+for making modifications to it. "Object code" means any non-source
678+form of a work.
679+
680+ A "Standard Interface" means an interface that either is an official
681+standard defined by a recognized standards body, or, in the case of
682+interfaces specified for a particular programming language, one that
683+is widely used among developers working in that language.
684+
685+ The "System Libraries" of an executable work include anything, other
686+than the work as a whole, that (a) is included in the normal form of
687+packaging a Major Component, but which is not part of that Major
688+Component, and (b) serves only to enable use of the work with that
689+Major Component, or to implement a Standard Interface for which an
690+implementation is available to the public in source code form. A
691+"Major Component", in this context, means a major essential component
692+(kernel, window system, and so on) of the specific operating system
693+(if any) on which the executable work runs, or a compiler used to
694+produce the work, or an object code interpreter used to run it.
695+
696+ The "Corresponding Source" for a work in object code form means all
697+the source code needed to generate, install, and (for an executable
698+work) run the object code and to modify the work, including scripts to
699+control those activities. However, it does not include the work's
700+System Libraries, or general-purpose tools or generally available free
701+programs which are used unmodified in performing those activities but
702+which are not part of the work. For example, Corresponding Source
703+includes interface definition files associated with source files for
704+the work, and the source code for shared libraries and dynamically
705+linked subprograms that the work is specifically designed to require,
706+such as by intimate data communication or control flow between those
707+subprograms and other parts of the work.
708+
709+ The Corresponding Source need not include anything that users
710+can regenerate automatically from other parts of the Corresponding
711+Source.
712+
713+ The Corresponding Source for a work in source code form is that
714+same work.
715+
716+ 2. Basic Permissions.
717+
718+ All rights granted under this License are granted for the term of
719+copyright on the Program, and are irrevocable provided the stated
720+conditions are met. This License explicitly affirms your unlimited
721+permission to run the unmodified Program. The output from running a
722+covered work is covered by this License only if the output, given its
723+content, constitutes a covered work. This License acknowledges your
724+rights of fair use or other equivalent, as provided by copyright law.
725+
726+ You may make, run and propagate covered works that you do not
727+convey, without conditions so long as your license otherwise remains
728+in force. You may convey covered works to others for the sole purpose
729+of having them make modifications exclusively for you, or provide you
730+with facilities for running those works, provided that you comply with
731+the terms of this License in conveying all material for which you do
732+not control copyright. Those thus making or running the covered works
733+for you must do so exclusively on your behalf, under your direction
734+and control, on terms that prohibit them from making any copies of
735+your copyrighted material outside their relationship with you.
736+
737+ Conveying under any other circumstances is permitted solely under
738+the conditions stated below. Sublicensing is not allowed; section 10
739+makes it unnecessary.
740+
741+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
742+
743+ No covered work shall be deemed part of an effective technological
744+measure under any applicable law fulfilling obligations under article
745+11 of the WIPO copyright treaty adopted on 20 December 1996, or
746+similar laws prohibiting or restricting circumvention of such
747+measures.
748+
749+ When you convey a covered work, you waive any legal power to forbid
750+circumvention of technological measures to the extent such circumvention
751+is effected by exercising rights under this License with respect to
752+the covered work, and you disclaim any intention to limit operation or
753+modification of the work as a means of enforcing, against the work's
754+users, your or third parties' legal rights to forbid circumvention of
755+technological measures.
756+
757+ 4. Conveying Verbatim Copies.
758+
759+ You may convey verbatim copies of the Program's source code as you
760+receive it, in any medium, provided that you conspicuously and
761+appropriately publish on each copy an appropriate copyright notice;
762+keep intact all notices stating that this License and any
763+non-permissive terms added in accord with section 7 apply to the code;
764+keep intact all notices of the absence of any warranty; and give all
765+recipients a copy of this License along with the Program.
766+
767+ You may charge any price or no price for each copy that you convey,
768+and you may offer support or warranty protection for a fee.
769+
770+ 5. Conveying Modified Source Versions.
771+
772+ You may convey a work based on the Program, or the modifications to
773+produce it from the Program, in the form of source code under the
774+terms of section 4, provided that you also meet all of these conditions:
775+
776+ a) The work must carry prominent notices stating that you modified
777+ it, and giving a relevant date.
778+
779+ b) The work must carry prominent notices stating that it is
780+ released under this License and any conditions added under section
781+ 7. This requirement modifies the requirement in section 4 to
782+ "keep intact all notices".
783+
784+ c) You must license the entire work, as a whole, under this
785+ License to anyone who comes into possession of a copy. This
786+ License will therefore apply, along with any applicable section 7
787+ additional terms, to the whole of the work, and all its parts,
788+ regardless of how they are packaged. This License gives no
789+ permission to license the work in any other way, but it does not
790+ invalidate such permission if you have separately received it.
791+
792+ d) If the work has interactive user interfaces, each must display
793+ Appropriate Legal Notices; however, if the Program has interactive
794+ interfaces that do not display Appropriate Legal Notices, your
795+ work need not make them do so.
796+
797+ A compilation of a covered work with other separate and independent
798+works, which are not by their nature extensions of the covered work,
799+and which are not combined with it such as to form a larger program,
800+in or on a volume of a storage or distribution medium, is called an
801+"aggregate" if the compilation and its resulting copyright are not
802+used to limit the access or legal rights of the compilation's users
803+beyond what the individual works permit. Inclusion of a covered work
804+in an aggregate does not cause this License to apply to the other
805+parts of the aggregate.
806+
807+ 6. Conveying Non-Source Forms.
808+
809+ You may convey a covered work in object code form under the terms
810+of sections 4 and 5, provided that you also convey the
811+machine-readable Corresponding Source under the terms of this License,
812+in one of these ways:
813+
814+ a) Convey the object code in, or embodied in, a physical product
815+ (including a physical distribution medium), accompanied by the
816+ Corresponding Source fixed on a durable physical medium
817+ customarily used for software interchange.
818+
819+ b) Convey the object code in, or embodied in, a physical product
820+ (including a physical distribution medium), accompanied by a
821+ written offer, valid for at least three years and valid for as
822+ long as you offer spare parts or customer support for that product
823+ model, to give anyone who possesses the object code either (1) a
824+ copy of the Corresponding Source for all the software in the
825+ product that is covered by this License, on a durable physical
826+ medium customarily used for software interchange, for a price no
827+ more than your reasonable cost of physically performing this
828+ conveying of source, or (2) access to copy the
829+ Corresponding Source from a network server at no charge.
830+
831+ c) Convey individual copies of the object code with a copy of the
832+ written offer to provide the Corresponding Source. This
833+ alternative is allowed only occasionally and noncommercially, and
834+ only if you received the object code with such an offer, in accord
835+ with subsection 6b.
836+
837+ d) Convey the object code by offering access from a designated
838+ place (gratis or for a charge), and offer equivalent access to the
839+ Corresponding Source in the same way through the same place at no
840+ further charge. You need not require recipients to copy the
841+ Corresponding Source along with the object code. If the place to
842+ copy the object code is a network server, the Corresponding Source
843+ may be on a different server (operated by you or a third party)
844+ that supports equivalent copying facilities, provided you maintain
845+ clear directions next to the object code saying where to find the
846+ Corresponding Source. Regardless of what server hosts the
847+ Corresponding Source, you remain obligated to ensure that it is
848+ available for as long as needed to satisfy these requirements.
849+
850+ e) Convey the object code using peer-to-peer transmission, provided
851+ you inform other peers where the object code and Corresponding
852+ Source of the work are being offered to the general public at no
853+ charge under subsection 6d.
854+
855+ A separable portion of the object code, whose source code is excluded
856+from the Corresponding Source as a System Library, need not be
857+included in conveying the object code work.
858+
859+ A "User Product" is either (1) a "consumer product", which means any
860+tangible personal property which is normally used for personal, family,
861+or household purposes, or (2) anything designed or sold for incorporation
862+into a dwelling. In determining whether a product is a consumer product,
863+doubtful cases shall be resolved in favor of coverage. For a particular
864+product received by a particular user, "normally used" refers to a
865+typical or common use of that class of product, regardless of the status
866+of the particular user or of the way in which the particular user
867+actually uses, or expects or is expected to use, the product. A product
868+is a consumer product regardless of whether the product has substantial
869+commercial, industrial or non-consumer uses, unless such uses represent
870+the only significant mode of use of the product.
871+
872+ "Installation Information" for a User Product means any methods,
873+procedures, authorization keys, or other information required to install
874+and execute modified versions of a covered work in that User Product from
875+a modified version of its Corresponding Source. The information must
876+suffice to ensure that the continued functioning of the modified object
877+code is in no case prevented or interfered with solely because
878+modification has been made.
879+
880+ If you convey an object code work under this section in, or with, or
881+specifically for use in, a User Product, and the conveying occurs as
882+part of a transaction in which the right of possession and use of the
883+User Product is transferred to the recipient in perpetuity or for a
884+fixed term (regardless of how the transaction is characterized), the
885+Corresponding Source conveyed under this section must be accompanied
886+by the Installation Information. But this requirement does not apply
887+if neither you nor any third party retains the ability to install
888+modified object code on the User Product (for example, the work has
889+been installed in ROM).
890+
891+ The requirement to provide Installation Information does not include a
892+requirement to continue to provide support service, warranty, or updates
893+for a work that has been modified or installed by the recipient, or for
894+the User Product in which it has been modified or installed. Access to a
895+network may be denied when the modification itself materially and
896+adversely affects the operation of the network or violates the rules and
897+protocols for communication across the network.
898+
899+ Corresponding Source conveyed, and Installation Information provided,
900+in accord with this section must be in a format that is publicly
901+documented (and with an implementation available to the public in
902+source code form), and must require no special password or key for
903+unpacking, reading or copying.
904+
905+ 7. Additional Terms.
906+
907+ "Additional permissions" are terms that supplement the terms of this
908+License by making exceptions from one or more of its conditions.
909+Additional permissions that are applicable to the entire Program shall
910+be treated as though they were included in this License, to the extent
911+that they are valid under applicable law. If additional permissions
912+apply only to part of the Program, that part may be used separately
913+under those permissions, but the entire Program remains governed by
914+this License without regard to the additional permissions.
915+
916+ When you convey a copy of a covered work, you may at your option
917+remove any additional permissions from that copy, or from any part of
918+it. (Additional permissions may be written to require their own
919+removal in certain cases when you modify the work.) You may place
920+additional permissions on material, added by you to a covered work,
921+for which you have or can give appropriate copyright permission.
922+
923+ Notwithstanding any other provision of this License, for material you
924+add to a covered work, you may (if authorized by the copyright holders of
925+that material) supplement the terms of this License with terms:
926+
927+ a) Disclaiming warranty or limiting liability differently from the
928+ terms of sections 15 and 16 of this License; or
929+
930+ b) Requiring preservation of specified reasonable legal notices or
931+ author attributions in that material or in the Appropriate Legal
932+ Notices displayed by works containing it; or
933+
934+ c) Prohibiting misrepresentation of the origin of that material, or
935+ requiring that modified versions of such material be marked in
936+ reasonable ways as different from the original version; or
937+
938+ d) Limiting the use for publicity purposes of names of licensors or
939+ authors of the material; or
940+
941+ e) Declining to grant rights under trademark law for use of some
942+ trade names, trademarks, or service marks; or
943+
944+ f) Requiring indemnification of licensors and authors of that
945+ material by anyone who conveys the material (or modified versions of
946+ it) with contractual assumptions of liability to the recipient, for
947+ any liability that these contractual assumptions directly impose on
948+ those licensors and authors.
949+
950+ All other non-permissive additional terms are considered "further
951+restrictions" within the meaning of section 10. If the Program as you
952+received it, or any part of it, contains a notice stating that it is
953+governed by this License along with a term that is a further
954+restriction, you may remove that term. If a license document contains
955+a further restriction but permits relicensing or conveying under this
956+License, you may add to a covered work material governed by the terms
957+of that license document, provided that the further restriction does
958+not survive such relicensing or conveying.
959+
960+ If you add terms to a covered work in accord with this section, you
961+must place, in the relevant source files, a statement of the
962+additional terms that apply to those files, or a notice indicating
963+where to find the applicable terms.
964+
965+ Additional terms, permissive or non-permissive, may be stated in the
966+form of a separately written license, or stated as exceptions;
967+the above requirements apply either way.
968+
969+ 8. Termination.
970+
971+ You may not propagate or modify a covered work except as expressly
972+provided under this License. Any attempt otherwise to propagate or
973+modify it is void, and will automatically terminate your rights under
974+this License (including any patent licenses granted under the third
975+paragraph of section 11).
976+
977+ However, if you cease all violation of this License, then your
978+license from a particular copyright holder is reinstated (a)
979+provisionally, unless and until the copyright holder explicitly and
980+finally terminates your license, and (b) permanently, if the copyright
981+holder fails to notify you of the violation by some reasonable means
982+prior to 60 days after the cessation.
983+
984+ Moreover, your license from a particular copyright holder is
985+reinstated permanently if the copyright holder notifies you of the
986+violation by some reasonable means, this is the first time you have
987+received notice of violation of this License (for any work) from that
988+copyright holder, and you cure the violation prior to 30 days after
989+your receipt of the notice.
990+
991+ Termination of your rights under this section does not terminate the
992+licenses of parties who have received copies or rights from you under
993+this License. If your rights have been terminated and not permanently
994+reinstated, you do not qualify to receive new licenses for the same
995+material under section 10.
996+
997+ 9. Acceptance Not Required for Having Copies.
998+
999+ You are not required to accept this License in order to receive or
1000+run a copy of the Program. Ancillary propagation of a covered work
1001+occurring solely as a consequence of using peer-to-peer transmission
1002+to receive a copy likewise does not require acceptance. However,
1003+nothing other than this License grants you permission to propagate or
1004+modify any covered work. These actions infringe copyright if you do
1005+not accept this License. Therefore, by modifying or propagating a
1006+covered work, you indicate your acceptance of this License to do so.
1007+
1008+ 10. Automatic Licensing of Downstream Recipients.
1009+
1010+ Each time you convey a covered work, the recipient automatically
1011+receives a license from the original licensors, to run, modify and
1012+propagate that work, subject to this License. You are not responsible
1013+for enforcing compliance by third parties with this License.
1014+
1015+ An "entity transaction" is a transaction transferring control of an
1016+organization, or substantially all assets of one, or subdividing an
1017+organization, or merging organizations. If propagation of a covered
1018+work results from an entity transaction, each party to that
1019+transaction who receives a copy of the work also receives whatever
1020+licenses to the work the party's predecessor in interest had or could
1021+give under the previous paragraph, plus a right to possession of the
1022+Corresponding Source of the work from the predecessor in interest, if
1023+the predecessor has it or can get it with reasonable efforts.
1024+
1025+ You may not impose any further restrictions on the exercise of the
1026+rights granted or affirmed under this License. For example, you may
1027+not impose a license fee, royalty, or other charge for exercise of
1028+rights granted under this License, and you may not initiate litigation
1029+(including a cross-claim or counterclaim in a lawsuit) alleging that
1030+any patent claim is infringed by making, using, selling, offering for
1031+sale, or importing the Program or any portion of it.
1032+
1033+ 11. Patents.
1034+
1035+ A "contributor" is a copyright holder who authorizes use under this
1036+License of the Program or a work on which the Program is based. The
1037+work thus licensed is called the contributor's "contributor version".
1038+
1039+ A contributor's "essential patent claims" are all patent claims
1040+owned or controlled by the contributor, whether already acquired or
1041+hereafter acquired, that would be infringed by some manner, permitted
1042+by this License, of making, using, or selling its contributor version,
1043+but do not include claims that would be infringed only as a
1044+consequence of further modification of the contributor version. For
1045+purposes of this definition, "control" includes the right to grant
1046+patent sublicenses in a manner consistent with the requirements of
1047+this License.
1048+
1049+ Each contributor grants you a non-exclusive, worldwide, royalty-free
1050+patent license under the contributor's essential patent claims, to
1051+make, use, sell, offer for sale, import and otherwise run, modify and
1052+propagate the contents of its contributor version.
1053+
1054+ In the following three paragraphs, a "patent license" is any express
1055+agreement or commitment, however denominated, not to enforce a patent
1056+(such as an express permission to practice a patent or covenant not to
1057+sue for patent infringement). To "grant" such a patent license to a
1058+party means to make such an agreement or commitment not to enforce a
1059+patent against the party.
1060+
1061+ If you convey a covered work, knowingly relying on a patent license,
1062+and the Corresponding Source of the work is not available for anyone
1063+to copy, free of charge and under the terms of this License, through a
1064+publicly available network server or other readily accessible means,
1065+then you must either (1) cause the Corresponding Source to be so
1066+available, or (2) arrange to deprive yourself of the benefit of the
1067+patent license for this particular work, or (3) arrange, in a manner
1068+consistent with the requirements of this License, to extend the patent
1069+license to downstream recipients. "Knowingly relying" means you have
1070+actual knowledge that, but for the patent license, your conveying the
1071+covered work in a country, or your recipient's use of the covered work
1072+in a country, would infringe one or more identifiable patents in that
1073+country that you have reason to believe are valid.
1074+
1075+ If, pursuant to or in connection with a single transaction or
1076+arrangement, you convey, or propagate by procuring conveyance of, a
1077+covered work, and grant a patent license to some of the parties
1078+receiving the covered work authorizing them to use, propagate, modify
1079+or convey a specific copy of the covered work, then the patent license
1080+you grant is automatically extended to all recipients of the covered
1081+work and works based on it.
1082+
1083+ A patent license is "discriminatory" if it does not include within
1084+the scope of its coverage, prohibits the exercise of, or is
1085+conditioned on the non-exercise of one or more of the rights that are
1086+specifically granted under this License. You may not convey a covered
1087+work if you are a party to an arrangement with a third party that is
1088+in the business of distributing software, under which you make payment
1089+to the third party based on the extent of your activity of conveying
1090+the work, and under which the third party grants, to any of the
1091+parties who would receive the covered work from you, a discriminatory
1092+patent license (a) in connection with copies of the covered work
1093+conveyed by you (or copies made from those copies), or (b) primarily
1094+for and in connection with specific products or compilations that
1095+contain the covered work, unless you entered into that arrangement,
1096+or that patent license was granted, prior to 28 March 2007.
1097+
1098+ Nothing in this License shall be construed as excluding or limiting
1099+any implied license or other defenses to infringement that may
1100+otherwise be available to you under applicable patent law.
1101+
1102+ 12. No Surrender of Others' Freedom.
1103+
1104+ If conditions are imposed on you (whether by court order, agreement or
1105+otherwise) that contradict the conditions of this License, they do not
1106+excuse you from the conditions of this License. If you cannot convey a
1107+covered work so as to satisfy simultaneously your obligations under this
1108+License and any other pertinent obligations, then as a consequence you may
1109+not convey it at all. For example, if you agree to terms that obligate you
1110+to collect a royalty for further conveying from those to whom you convey
1111+the Program, the only way you could satisfy both those terms and this
1112+License would be to refrain entirely from conveying the Program.
1113+
1114+ 13. Use with the GNU Affero General Public License.
1115+
1116+ Notwithstanding any other provision of this License, you have
1117+permission to link or combine any covered work with a work licensed
1118+under version 3 of the GNU Affero General Public License into a single
1119+combined work, and to convey the resulting work. The terms of this
1120+License will continue to apply to the part which is the covered work,
1121+but the special requirements of the GNU Affero General Public License,
1122+section 13, concerning interaction through a network will apply to the
1123+combination as such.
1124+
1125+ 14. Revised Versions of this License.
1126+
1127+ The Free Software Foundation may publish revised and/or new versions of
1128+the GNU General Public License from time to time. Such new versions will
1129+be similar in spirit to the present version, but may differ in detail to
1130+address new problems or concerns.
1131+
1132+ Each version is given a distinguishing version number. If the
1133+Program specifies that a certain numbered version of the GNU General
1134+Public License "or any later version" applies to it, you have the
1135+option of following the terms and conditions either of that numbered
1136+version or of any later version published by the Free Software
1137+Foundation. If the Program does not specify a version number of the
1138+GNU General Public License, you may choose any version ever published
1139+by the Free Software Foundation.
1140+
1141+ If the Program specifies that a proxy can decide which future
1142+versions of the GNU General Public License can be used, that proxy's
1143+public statement of acceptance of a version permanently authorizes you
1144+to choose that version for the Program.
1145+
1146+ Later license versions may give you additional or different
1147+permissions. However, no additional obligations are imposed on any
1148+author or copyright holder as a result of your choosing to follow a
1149+later version.
1150+
1151+ 15. Disclaimer of Warranty.
1152+
1153+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
1154+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
1155+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
1156+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
1157+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1158+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
1159+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
1160+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
1161+
1162+ 16. Limitation of Liability.
1163+
1164+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
1165+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
1166+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
1167+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
1168+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
1169+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
1170+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
1171+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
1172+SUCH DAMAGES.
1173+
1174+ 17. Interpretation of Sections 15 and 16.
1175+
1176+ If the disclaimer of warranty and limitation of liability provided
1177+above cannot be given local legal effect according to their terms,
1178+reviewing courts shall apply local law that most closely approximates
1179+an absolute waiver of all civil liability in connection with the
1180+Program, unless a warranty or assumption of liability accompanies a
1181+copy of the Program in return for a fee.
1182+
1183+ END OF TERMS AND CONDITIONS
1184+
1185+ How to Apply These Terms to Your New Programs
1186+
1187+ If you develop a new program, and you want it to be of the greatest
1188+possible use to the public, the best way to achieve this is to make it
1189+free software which everyone can redistribute and change under these terms.
1190+
1191+ To do so, attach the following notices to the program. It is safest
1192+to attach them to the start of each source file to most effectively
1193+state the exclusion of warranty; and each file should have at least
1194+the "copyright" line and a pointer to where the full notice is found.
1195+
1196+ <one line to give the program's name and a brief idea of what it does.>
1197+ Copyright (C) <year> <name of author>
1198+
1199+ This program is free software: you can redistribute it and/or modify
1200+ it under the terms of the GNU General Public License as published by
1201+ the Free Software Foundation, either version 3 of the License, or
1202+ (at your option) any later version.
1203+
1204+ This program is distributed in the hope that it will be useful,
1205+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1206+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1207+ GNU General Public License for more details.
1208+
1209+ You should have received a copy of the GNU General Public License
1210+ along with this program. If not, see <http://www.gnu.org/licenses/>.
1211+
1212+Also add information on how to contact you by electronic and paper mail.
1213+
1214+ If the program does terminal interaction, make it output a short
1215+notice like this when it starts in an interactive mode:
1216+
1217+ <program> Copyright (C) <year> <name of author>
1218+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
1219+ This is free software, and you are welcome to redistribute it
1220+ under certain conditions; type `show c' for details.
1221+
1222+The hypothetical commands `show w' and `show c' should show the appropriate
1223+parts of the General Public License. Of course, your program's commands
1224+might be different; for a GUI interface, you would use an "about box".
1225+
1226+ You should also get your employer (if you work as a programmer) or school,
1227+if any, to sign a "copyright disclaimer" for the program, if necessary.
1228+For more information on this, and how to apply and follow the GNU GPL, see
1229+<http://www.gnu.org/licenses/>.
1230+
1231+ The GNU General Public License does not permit incorporating your program
1232+into proprietary programs. If your program is a subroutine library, you
1233+may consider it more useful to permit linking proprietary applications with
1234+the library. If this is what you want to do, use the GNU Lesser General
1235+Public License instead of this License. But first, please read
1236+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
1237
1238=== renamed file 'COPYING' => 'COPYING.moved'
1239=== added directory 'Components'
1240=== added file 'Components/AnimationControllerWithSignals.qml'
1241--- Components/AnimationControllerWithSignals.qml 1970-01-01 00:00:00 +0000
1242+++ Components/AnimationControllerWithSignals.qml 2013-03-01 09:12:23 +0000
1243@@ -0,0 +1,69 @@
1244+/*
1245+ * Copyright (C) 2013 Canonical, Ltd.
1246+ *
1247+ * This program is free software; you can redistribute it and/or modify
1248+ * it under the terms of the GNU General Public License as published by
1249+ * the Free Software Foundation; version 3.
1250+ *
1251+ * This program is distributed in the hope that it will be useful,
1252+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1253+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1254+ * GNU General Public License for more details.
1255+ *
1256+ * You should have received a copy of the GNU General Public License
1257+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1258+ */
1259+
1260+import QtQuick 2.0
1261+
1262+AnimationController {
1263+ signal animationCompletedAtBeginning()
1264+ signal animationCompletedAtEnd()
1265+ property bool completed: true
1266+ property bool completing: false
1267+
1268+ function __completeAtBeginning() {
1269+ completed = true;
1270+ completing = false;
1271+ animationCompletedAtBeginning();
1272+ }
1273+
1274+ function __completeAtEnd() {
1275+ completed = true;
1276+ completing = false;
1277+ animationCompletedAtEnd();
1278+ }
1279+
1280+ function completeToBeginningWithSignal() {
1281+ if (progress == 0.0) {
1282+ __completeAtBeginning()
1283+ } else {
1284+ completing = true;
1285+ completeToBeginning();
1286+ }
1287+ }
1288+
1289+ function completeToEndWithSignal() {
1290+ if (progress == 1.0) {
1291+ __completeAtEnd()
1292+ } else {
1293+ completing = true;
1294+ completeToEnd();
1295+ }
1296+ }
1297+
1298+ onProgressChanged: {
1299+ if (!completing) {
1300+ completed = false;
1301+ return;
1302+ }
1303+
1304+ if (progress == 0.0) {
1305+ __completeAtBeginning()
1306+ } else if (progress == 1.0) {
1307+ __completeAtEnd()
1308+ } else {
1309+ completed = false;
1310+ }
1311+ }
1312+}
1313
1314=== added file 'Components/ApplicationImageFake.qml'
1315--- Components/ApplicationImageFake.qml 1970-01-01 00:00:00 +0000
1316+++ Components/ApplicationImageFake.qml 2013-03-01 09:12:23 +0000
1317@@ -0,0 +1,36 @@
1318+import QtQuick 2.0
1319+
1320+Item {
1321+ property var source
1322+ property alias fillColor: background.color
1323+ property bool ready: image.status != Image.Ready
1324+
1325+ function scheduleUpdate() {
1326+ }
1327+
1328+ function updateFromCache() {
1329+ }
1330+
1331+ property string __icon: (source && source.icon) ? source.icon : ""
1332+ readonly property bool fullscreen: (source && source.fullscreen) ? source.fullscreen : false
1333+
1334+ Rectangle {
1335+ id: background
1336+ anchors.fill: parent
1337+ color: "white"
1338+ }
1339+
1340+ Image {
1341+ id: image
1342+ anchors {
1343+ left: parent.left
1344+ right: parent.right
1345+ top: parent.top
1346+ }
1347+ height: parent.height
1348+
1349+ source: (__icon !== "") ? "../Dash/graphics/phone/screenshots/" + __icon + ".png" : ""
1350+ smooth: true
1351+ fillMode: Image.PreserveAspectCrop
1352+ }
1353+}
1354
1355=== added file 'Components/ApplicationImageWrapper.qml'
1356--- Components/ApplicationImageWrapper.qml 1970-01-01 00:00:00 +0000
1357+++ Components/ApplicationImageWrapper.qml 2013-03-01 09:12:23 +0000
1358@@ -0,0 +1,5 @@
1359+import QtQuick 2.0
1360+import Ubuntu.Application 0.1
1361+
1362+ApplicationImage {
1363+}
1364
1365=== added file 'Components/ApplicationManagerFake.qml'
1366--- Components/ApplicationManagerFake.qml 1970-01-01 00:00:00 +0000
1367+++ Components/ApplicationManagerFake.qml 2013-03-01 09:12:23 +0000
1368@@ -0,0 +1,141 @@
1369+/*
1370+ * Copyright (C) 2013 Canonical, Ltd.
1371+ *
1372+ * This program is free software; you can redistribute it and/or modify
1373+ * it under the terms of the GNU General Public License as published by
1374+ * the Free Software Foundation; version 3.
1375+ *
1376+ * This program is distributed in the hope that it will be useful,
1377+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1378+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1379+ * GNU General Public License for more details.
1380+ *
1381+ * You should have received a copy of the GNU General Public License
1382+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1383+ */
1384+
1385+import QtQuick 2.0
1386+import "../Applications/applications.js" as ApplicationsModel
1387+
1388+QtObject {
1389+ id: applicationManager
1390+
1391+ /* This file fakes the abilities of the ApplicationManagerWrapper for platforms where
1392+ Ubuntu.Application is not available. */
1393+ property ListModel mainStageApplications: ListModel {}
1394+ property ListModel sideStageApplications: ListModel {}
1395+ property var mainStageFocusedApplication
1396+ property var sideStageFocusedApplication
1397+ property bool sideStageEnabled: true
1398+ signal focusRequested(string desktopFile) //unused as not functional on desktop
1399+ property bool keyboardVisible: false
1400+ property int keyboardHeight: 0
1401+
1402+ function activateApplication(desktopFile, argument) {
1403+ var app = ApplicationsModel.createApplicationForDesktopFile(desktopFile);
1404+ if(!app) {
1405+ console.log("ERROR: Application '" + desktopFile + "' not found, unable to activate");
1406+ return false;
1407+ }
1408+
1409+ if (!app.exec || !app.desktopFile) {
1410+ console.log("ERROR: Application '" + desktopFile + "' has no exec or desktop file");
1411+ return false;
1412+ }
1413+
1414+ app.stage = applicationManager.sideStageEnabled ? app.stage : ApplicationsModel.MainStage
1415+ var application;
1416+ application = getApplicationFromDesktopFile(app.desktopFile, app.stage);
1417+ if (application != null) {
1418+ return application;
1419+ }
1420+
1421+ // construct application model, adding info to app needed for ApplicationWindowFake
1422+ application = {
1423+ 'icon': app.icon,
1424+ 'handle': app.desktopFile,
1425+ 'name': app.name,
1426+ 'fullscreen': app.fullscreen,
1427+ 'desktopFile': app.desktopFile,
1428+ 'stage': app.stage,
1429+ 'argument': argument,
1430+ 'window': null
1431+ };
1432+
1433+ // Create window for the application
1434+ var component = Qt.createComponent("ApplicationWindowFake.qml");
1435+ if (component.status === Component.Error) {
1436+ console.log("ERROR: ApplicationWindowFake.qml failed to load", component.errorString());
1437+ return null;
1438+ }
1439+
1440+ var sideStage = applicationManager.sideStageEnabled
1441+ && (application.stage == ApplicationsModel.SideStage);
1442+ // attach window and add to front of running applications model
1443+ __lastUsedLayer += __focusIncrement;
1444+ application.window = component.createObject(fakeWindowContainer, {"application": application,
1445+ "anchors.right": fakeWindowContainer.right,
1446+ "y": (app.fullscreen) ? 0 : shell.panelHeight,
1447+ "width": sideStage ? fakeWindowContainer.sideStageWidth : fakeWindowContainer.width,
1448+ "height": fakeWindowContainer.height,
1449+ "z": __lastUsedLayer
1450+ });
1451+ var applications = sideStage ? applicationManager.sideStageApplications
1452+ : applicationManager.mainStageApplications;
1453+ applications.append(application);
1454+ return application;
1455+ }
1456+
1457+ property int __lastUsedLayer: 0
1458+ property int __focusIncrement: 10
1459+
1460+ function focusApplication(application) {
1461+ if (application == null) {
1462+ return;
1463+ }
1464+
1465+ var sideStage = (application.stage == ApplicationsModel.SideStage
1466+ && applicationManager.sideStageEnabled);
1467+ var applications = sideStage ? applicationManager.sideStageApplications
1468+ : applicationManager.mainStageApplications;
1469+
1470+
1471+ __lastUsedLayer += __focusIncrement;
1472+ application.window.z = __lastUsedLayer;
1473+
1474+ if (sideStage) {
1475+ sideStageFocusedApplication = application;
1476+ } else {
1477+ mainStageFocusedApplication = application;
1478+ }
1479+ }
1480+
1481+ function unfocusCurrentApplication() {
1482+ sideStageFocusedApplication = null;
1483+ mainStageFocusedApplication = null;
1484+ }
1485+
1486+ function moveRunningApplicationStackPosition(from, to, stage) {
1487+ var sideStage = (stage == ApplicationsModel.SideStage);
1488+ var applications = sideStage ? applicationManager.sideStageApplications
1489+ : applicationManager.mainStageApplications;
1490+
1491+ if (from !== to && applications.count > 0 && from >= 0 && to >= 0) {
1492+ applications.move(from, to, 1);
1493+ }
1494+ }
1495+
1496+ function getApplicationFromDesktopFile(desktopFile, stage) {
1497+ var sideStage = (stage == ApplicationsModel.SideStage);
1498+ var applications = sideStage ? applicationManager.sideStageApplications
1499+ : applicationManager.mainStageApplications;
1500+
1501+ for (var i = 0; i < applications.count; i++ ) {
1502+ var application = applications.get(i);
1503+ if (application.desktopFile == desktopFile) {
1504+ return application;
1505+ }
1506+ }
1507+ return null;
1508+ }
1509+}
1510
1511=== added file 'Components/ApplicationManagerWrapper.qml'
1512--- Components/ApplicationManagerWrapper.qml 1970-01-01 00:00:00 +0000
1513+++ Components/ApplicationManagerWrapper.qml 2013-03-01 09:12:23 +0000
1514@@ -0,0 +1,145 @@
1515+/*
1516+ * Copyright (C) 2013 Canonical, Ltd.
1517+ *
1518+ * This program is free software; you can redistribute it and/or modify
1519+ * it under the terms of the GNU General Public License as published by
1520+ * the Free Software Foundation; version 3.
1521+ *
1522+ * This program is distributed in the hope that it will be useful,
1523+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1524+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1525+ * GNU General Public License for more details.
1526+ *
1527+ * You should have received a copy of the GNU General Public License
1528+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1529+ */
1530+
1531+import QtQuick 2.0
1532+import Ubuntu.Application 0.1
1533+import ApplicationLauncher 0.1 //executes apps only
1534+import "../Applications/applications.js" as ApplicationsModel
1535+
1536+Item {
1537+ id: applicationManager
1538+
1539+ property var mainStageApplications: ApplicationManager.mainStageApplications
1540+ property var sideStageApplications: ApplicationManager.sideStageApplications
1541+ property var mainStageFocusedApplication: ApplicationManager.mainStageFocusedApplication
1542+ property var sideStageFocusedApplication: ApplicationManager.sideStageFocusedApplication
1543+ property bool sideStageEnabled: true
1544+ signal focusRequested(string desktopFile)
1545+ property bool keyboardVisible: ApplicationManager.keyboardVisible
1546+ property int keyboardHeight: ApplicationManager.keyboardHeight
1547+
1548+ Component.onCompleted: {
1549+ // Start the watcher so that the ApplicationManager applications model can be populated.
1550+ ApplicationManager.startWatcher();
1551+ }
1552+
1553+ function activateApplication(desktopFile, argument) {
1554+ var application;
1555+ application = getApplicationFromDesktopFile(desktopFile, ApplicationsModel.MainStage);
1556+ if (application == null) {
1557+ application = getApplicationFromDesktopFile(desktopFile, ApplicationsModel.SideStage);
1558+ }
1559+ if (application != null) {
1560+ return application;
1561+ }
1562+
1563+ var app = ApplicationsModel.createApplicationForDesktopFile(desktopFile);
1564+ if(!app) {
1565+ console.log("ERROR: Application '" + desktopFile + "' not found, unable to activate");
1566+ return null;
1567+ }
1568+
1569+ if (!app.exec || !app.desktopFile) {
1570+ console.log("ERROR: Application '" + desktopFile + "' has no exec or desktop file");
1571+ return null;
1572+ }
1573+
1574+ if (argument == undefined) {
1575+ argument = "";
1576+ }
1577+
1578+ var sideStage = applicationManager.sideStageEnabled
1579+ && (app.stage == ApplicationsModel.SideStage);
1580+ var stageHint = sideStage ? "--stage_hint=side_stage" : ""
1581+
1582+ // Application not running, so execute it
1583+ var desktopFileFullPath = "/usr/share/applications/" + app.desktopFile
1584+ var command = "%1 %2 --desktop_file_hint=%3 %4".arg(app.exec).arg(argument).arg(desktopFileFullPath).arg(stageHint);
1585+ if (applicationLauncher.execute(command)) {
1586+ /* FIXME: application is null unfortunately; return app instead that
1587+ has a similar API. This will be fixed by using qtubuntu's
1588+ ApplicationManager.startProcess().
1589+ */
1590+ return app;
1591+ } else {
1592+ console.log("ERROR: Failed to launch", app.exec);
1593+ return null;
1594+ }
1595+ }
1596+
1597+ function focusApplication(application) {
1598+ if (application == null || application == undefined) {
1599+ return;
1600+ }
1601+
1602+ ApplicationManager.focusApplication(application.handle);
1603+ }
1604+
1605+ function unfocusCurrentApplication() {
1606+ ApplicationManager.unfocusCurrentApplication(ApplicationsModel.MainStage);
1607+ }
1608+
1609+ function moveRunningApplicationStackPosition(from, to, stage) {
1610+ var applications;
1611+ if (stage == ApplicationsModel.SideStage) {
1612+ applications = ApplicationManager.sideStageApplications;
1613+ } else {
1614+ applications = ApplicationManager.mainStageApplications;
1615+ }
1616+ // FIXME: applications.move(0, 0) crashes
1617+ if (from !== to && from >= 0 && to >= 0) applications.move(from, to);
1618+ }
1619+
1620+ function getApplicationFromDesktopFile(desktopFile, stage) {
1621+ var applications;
1622+ if (stage == ApplicationsModel.SideStage) {
1623+ applications = ApplicationManager.sideStageApplications;
1624+ } else {
1625+ applications = ApplicationManager.mainStageApplications;
1626+ }
1627+
1628+ desktopFile = "/usr/share/applications/" + desktopFile;
1629+
1630+ for (var i = 0; i < applications.count; i++ ) {
1631+ var application = applications.get(i);
1632+ if (application.desktopFile == desktopFile) {
1633+ return application;
1634+ }
1635+ }
1636+ return null;
1637+ }
1638+
1639+ Connections {
1640+ target: ApplicationManager
1641+ onFocusRequested: {
1642+ // FIXME: hardcoded mapping from ApplicationManager.FavoriteApplications
1643+ // enum to desktop files
1644+ var desktopFile
1645+ if (favoriteApplication == ApplicationManager.CameraApplication) {
1646+ desktopFile = "camera-app.desktop"
1647+ } else if (favoriteApplication == ApplicationManager.GalleryApplication) {
1648+ desktopFile = "ubuntu-gallery.desktop"
1649+ } else if (favoriteApplication == ApplicationManager.ShareApplication) {
1650+ desktopFile = "share-app.desktop"
1651+ } else if (favoriteApplication == ApplicationManager.BrowserApplication) {
1652+ desktopFile = "ubuntu-browser.desktop"
1653+ } else if (favoriteApplication == 4) { // ApplicationManager.TelephonyApplication
1654+ desktopFile = "telephony-app.desktop"
1655+ }
1656+ applicationManager.focusRequested(desktopFile);
1657+ }
1658+ }
1659+}
1660
1661=== added file 'Components/ApplicationScreenshot.qml'
1662--- Components/ApplicationScreenshot.qml 1970-01-01 00:00:00 +0000
1663+++ Components/ApplicationScreenshot.qml 2013-03-01 09:12:23 +0000
1664@@ -0,0 +1,68 @@
1665+/*
1666+ * Copyright (C) 2013 Canonical, Ltd.
1667+ *
1668+ * This program is free software; you can redistribute it and/or modify
1669+ * it under the terms of the GNU General Public License as published by
1670+ * the Free Software Foundation; version 3.
1671+ *
1672+ * This program is distributed in the hope that it will be useful,
1673+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1674+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1675+ * GNU General Public License for more details.
1676+ *
1677+ * You should have received a copy of the GNU General Public License
1678+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1679+ */
1680+
1681+import QtQuick 2.0
1682+import Ubuntu.Components 0.1
1683+
1684+Item {
1685+ id: applicationScreenshot
1686+
1687+ property var application: null
1688+ property bool withBackground: false
1689+ property bool ready: applicationImageLoader.item ? applicationImageLoader.item.ready || withBackground : false
1690+
1691+ function setApplication(application) {
1692+ applicationScreenshot.application = application
1693+ }
1694+
1695+ function clearApplication() {
1696+ applicationScreenshot.withBackground = false;
1697+ applicationScreenshot.application = null
1698+ applicationScreenshot.scheduleUpdate();
1699+ }
1700+
1701+ function scheduleUpdate() {
1702+ if (applicationImageLoader.item) {
1703+ applicationImageLoader.item.scheduleUpdate()
1704+ }
1705+ }
1706+
1707+ function updateFromCache() {
1708+ if (applicationImageLoader.item) {
1709+ applicationImageLoader.item.updateFromCache()
1710+ }
1711+ }
1712+
1713+ Rectangle {
1714+ id: background
1715+ anchors.fill: parent
1716+ color: "white"
1717+ visible: applicationScreenshot.withBackground
1718+ }
1719+
1720+ Loader {
1721+ id: applicationImageLoader
1722+ width: applicationScreenshot.application ? parent.width : 0
1723+ height: applicationScreenshot.application ? parent.height : 0
1724+ asynchronous: true
1725+ visible: applicationScreenshot.application != null && item.ready
1726+ source: shell.importUbuntuApplicationAvailable ? "ApplicationImageWrapper.qml" : "ApplicationImageFake.qml"
1727+ onLoaded: {
1728+ item.source = Qt.binding( function(){ return applicationScreenshot.application });
1729+ item.fillColor = "white";
1730+ }
1731+ }
1732+}
1733
1734=== added file 'Components/ApplicationWindowFake.qml'
1735--- Components/ApplicationWindowFake.qml 1970-01-01 00:00:00 +0000
1736+++ Components/ApplicationWindowFake.qml 2013-03-01 09:12:23 +0000
1737@@ -0,0 +1,53 @@
1738+/*
1739+ * Copyright (C) 2013 Canonical, Ltd.
1740+ *
1741+ * This program is free software; you can redistribute it and/or modify
1742+ * it under the terms of the GNU General Public License as published by
1743+ * the Free Software Foundation; version 3.
1744+ *
1745+ * This program is distributed in the hope that it will be useful,
1746+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1747+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1748+ * GNU General Public License for more details.
1749+ *
1750+ * You should have received a copy of the GNU General Public License
1751+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1752+ */
1753+
1754+import QtQuick 2.0
1755+import Ubuntu.Components 0.1
1756+
1757+Item {
1758+ property var application
1759+
1760+ property string __icon: (application && application.icon) ? application.icon : ""
1761+
1762+ // fallback in case application missing artwork
1763+ Rectangle {
1764+ anchors.fill: image
1765+ visible: image.status === Image.Error
1766+ color: "white"
1767+ }
1768+
1769+ Label {
1770+ anchors.centerIn: parent
1771+ visible: image.status === Image.Error
1772+ fontSize: "large"
1773+ text: (application) ? application.name : ""
1774+ }
1775+
1776+ // preview image (if available)
1777+ Image {
1778+ id: image
1779+ anchors.fill: parent
1780+ source: (__icon !== "") ? "../Dash/graphics/phone/screenshots/" + __icon + ".png" : ""
1781+ smooth: true
1782+ fillMode: Image.PreserveAspectCrop
1783+ }
1784+
1785+ // mouse events eater
1786+ MouseArea {
1787+ anchors.fill: parent
1788+ enabled: parent.visible
1789+ }
1790+}
1791
1792=== added file 'Components/BaseCarouselDelegate.qml'
1793--- Components/BaseCarouselDelegate.qml 1970-01-01 00:00:00 +0000
1794+++ Components/BaseCarouselDelegate.qml 2013-03-01 09:12:23 +0000
1795@@ -0,0 +1,23 @@
1796+/*
1797+ * Copyright (C) 2013 Canonical, Ltd.
1798+ *
1799+ * This program is free software; you can redistribute it and/or modify
1800+ * it under the terms of the GNU General Public License as published by
1801+ * the Free Software Foundation; version 3.
1802+ *
1803+ * This program is distributed in the hope that it will be useful,
1804+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1805+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1806+ * GNU General Public License for more details.
1807+ *
1808+ * You should have received a copy of the GNU General Public License
1809+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1810+ */
1811+
1812+import QtQuick 2.0
1813+import Ubuntu.Components 0.1
1814+
1815+Item {
1816+ property bool explicitlyScaled
1817+ property var model
1818+}
1819
1820=== added file 'Components/Carousel.qml'
1821--- Components/Carousel.qml 1970-01-01 00:00:00 +0000
1822+++ Components/Carousel.qml 2013-03-01 09:12:23 +0000
1823@@ -0,0 +1,257 @@
1824+/*
1825+ * Copyright (C) 2013 Canonical, Ltd.
1826+ *
1827+ * This program is free software; you can redistribute it and/or modify
1828+ * it under the terms of the GNU General Public License as published by
1829+ * the Free Software Foundation; version 3.
1830+ *
1831+ * This program is distributed in the hope that it will be useful,
1832+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1833+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1834+ * GNU General Public License for more details.
1835+ *
1836+ * You should have received a copy of the GNU General Public License
1837+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1838+ */
1839+
1840+import QtQuick 2.0
1841+import Ubuntu.Components 0.1
1842+import "carousel.js" as CarouselJS
1843+
1844+Item {
1845+ id: carousel
1846+
1847+ property Component itemComponent
1848+ property var model
1849+ property alias minimumTileWidth: flickable.minimumTileWidth
1850+ property alias pathItemCount: flickable.pathItemCount
1851+ property alias tileAspectRatio: flickable.tileAspectRatio
1852+ property int cacheBuffer: 0
1853+ property real selectedItemScaleFactor: 1.1
1854+
1855+ signal clicked(int index, var delegateItem)
1856+
1857+ implicitHeight: flickable.tileHeight * selectedItemScaleFactor
1858+
1859+ function itemY(index) {
1860+ return y;
1861+ }
1862+
1863+ /* TODO: evaluate if the component could be more efficient with a ListView,
1864+ using this technique https://bugreports.qt-project.org/browse/QTBUG-29173 */
1865+
1866+ Flickable {
1867+ id: flickable
1868+
1869+ property real minimumTileWidth: 0
1870+ property real newContentX: -1
1871+ property real pathItemCount: referenceWidth / referenceTileWidth
1872+ property real tileAspectRatio: 1
1873+
1874+ /* The positioning and scaling of the items in the carousel is based on the variable
1875+ 'continuousIndex', a continuous real variable between [0, 'carousel.model.count'],
1876+ roughly representing the index of the item that is prioritised over the others.
1877+ 'continuousIndex' is not linear, but is weighted depending on if it is close
1878+ to the beginning of the content (beginning phase), in the middle (middle phase)
1879+ or at the end (end phase).
1880+ Each tile is scaled and transformed in proportion to the difference between
1881+ its own index and continuousIndex.
1882+ To efficiently calculate continuousIndex, we have these values:
1883+ - 'gapToMiddlePhase' gap in pixels between beginning and middle phase
1884+ - 'gapToEndPhase' gap in pixels between middle and end phase
1885+ - 'kGapEnd' constant used to calculate 'continuousIndex' in end phase
1886+ - 'kMiddleIndex' constant used to calculate 'continuousIndex' in middle phase
1887+ - 'kXBeginningEnd' constant used to calculate 'continuousIndex' in beginning and end phase. */
1888+
1889+ readonly property real gapToMiddlePhase: Math.min(width / 2 - tileWidth / 2, (contentWidth - width) / 2)
1890+ readonly property real gapToEndPhase: contentWidth - width - gapToMiddlePhase
1891+ readonly property real kGapEnd: kMiddleIndex * (1 - gapToEndPhase / gapToMiddlePhase)
1892+ readonly property real kMiddleIndex: (width / 2) / tileWidth - 0.5
1893+ readonly property real kXBeginningEnd: 1 / tileWidth + kMiddleIndex / gapToMiddlePhase
1894+ readonly property real realPathItemCount: Math.min(width / tileWidth, pathItemCount)
1895+ readonly property real referenceGapToMiddlePhase: width / 2 - tileWidth / 2
1896+ readonly property real referencePathItemCount: referenceWidth / referenceTileWidth
1897+ readonly property real referenceWidth: 848
1898+ readonly property real referenceTileWidth: 175
1899+ readonly property real scaleFactor: tileWidth / referenceTileWidth
1900+ readonly property real tileWidth: Math.max(width / pathItemCount, minimumTileWidth)
1901+ readonly property real tileHeight: tileWidth / tileAspectRatio
1902+ readonly property real translationXViewFactor: 0.2 * (referenceGapToMiddlePhase / gapToMiddlePhase)
1903+ readonly property real verticalMargin: (parent.height - tileHeight) / 2
1904+ readonly property real visibleTilesScaleFactor: realPathItemCount / referencePathItemCount
1905+
1906+ anchors {
1907+ fill: parent
1908+ topMargin: verticalMargin
1909+ bottomMargin: verticalMargin
1910+ }
1911+ contentWidth: view.width
1912+ contentHeight: height
1913+ boundsBehavior: Flickable.StopAtBounds
1914+ flickDeceleration: Math.max(1500 * Math.pow(width / referenceWidth, 1.5), 1500) // 1500 is platform default
1915+ maximumFlickVelocity: Math.max(2500 * Math.pow(width / referenceWidth, 1.5), 2500) // 2500 is platform default
1916+
1917+ function itemClicked(index, delegateItem) {
1918+ var x = CarouselJS.getXFromContinuousIndex(index,
1919+ width,
1920+ contentWidth,
1921+ tileWidth,
1922+ gapToMiddlePhase,
1923+ gapToEndPhase)
1924+
1925+ if (Math.abs(x - contentX) < 1) {
1926+ /* We're clicking the selected item and
1927+ we're in the neighbourhood of radius 1 pixel from it.
1928+ Let's emit the clicked signal. */
1929+ carousel.clicked(index, delegateItem)
1930+ return
1931+ }
1932+
1933+ stepAnimation.stop()
1934+ newContentXAnimation.stop()
1935+
1936+ newContentX = x
1937+ newContentXAnimation.start()
1938+ }
1939+
1940+ onMovementStarted: {
1941+ stepAnimation.stop()
1942+ newContentXAnimation.stop()
1943+ newContentX = -1
1944+ }
1945+ onMovementEnded: {
1946+ if (contentX > 0 && contentX < contentWidth - width)
1947+ stepAnimation.start()
1948+ }
1949+
1950+ SmoothedAnimation {
1951+ id: stepAnimation
1952+
1953+ target: flickable
1954+ property: "contentX"
1955+ from: flickable.contentX
1956+ to: CarouselJS.getXFromContinuousIndex(view.selectedIndex,
1957+ flickable.width,
1958+ flickable.contentWidth,
1959+ flickable.tileWidth,
1960+ flickable.gapToMiddlePhase,
1961+ flickable.gapToEndPhase)
1962+ duration: 450
1963+ velocity: 200
1964+ easing.type: Easing.InOutQuad
1965+ }
1966+
1967+ SequentialAnimation {
1968+ id: newContentXAnimation
1969+
1970+ NumberAnimation {
1971+ target: flickable
1972+ property: "contentX"
1973+ from: flickable.contentX
1974+ to: flickable.newContentX
1975+ duration: 300
1976+ easing.type: Easing.InOutQuad
1977+ }
1978+ ScriptAction {
1979+ script: flickable.newContentX = -1
1980+ }
1981+ }
1982+
1983+ Row {
1984+ id: view
1985+
1986+ readonly property int selectedIndex: Math.round(continuousIndex)
1987+ readonly property real continuousIndex: CarouselJS.getContinuousIndex(flickable.contentX,
1988+ flickable.tileWidth,
1989+ flickable.gapToMiddlePhase,
1990+ flickable.gapToEndPhase,
1991+ flickable.kGapEnd,
1992+ flickable.kMiddleIndex,
1993+ flickable.kXBeginningEnd)
1994+
1995+ height: parent.height
1996+ anchors.verticalCenter: parent.verticalCenter
1997+
1998+ transform: Translate {
1999+ x: CarouselJS.getViewTranslation(flickable.contentX,
2000+ flickable.tileWidth,
2001+ flickable.gapToMiddlePhase,
2002+ flickable.gapToEndPhase,
2003+ flickable.translationXViewFactor)
2004+ }
2005+
2006+ Repeater {
2007+ id: repeater
2008+
2009+ model: carousel.model
2010+
2011+ Loader {
2012+ property bool explicitlyScaled: explicitScaleFactor == carousel.selectedItemScaleFactor
2013+ property real explicitScaleFactor: explicitScale ? carousel.selectedItemScaleFactor : 1.0
2014+ readonly property bool explicitScale: (!flickable.moving ||
2015+ flickable.contentX <= 0 ||
2016+ flickable.contentX >= flickable.contentWidth - flickable.width) &&
2017+ flickable.newContentX < 0 &&
2018+ index === view.selectedIndex
2019+ readonly property real cachedTiles: flickable.realPathItemCount + carousel.cacheBuffer / flickable.tileWidth
2020+ readonly property real distance: view.continuousIndex - index
2021+ readonly property real itemTranslationScale: CarouselJS.getItemScale(0.5,
2022+ (index + 0.5), // good approximation of scale while changing selected item
2023+ repeater.count,
2024+ flickable.visibleTilesScaleFactor)
2025+ readonly property real itemScale: CarouselJS.getItemScale(distance,
2026+ view.continuousIndex,
2027+ repeater.count,
2028+ flickable.visibleTilesScaleFactor)
2029+ readonly property real translationFactor: (flickable.tileWidth * 3) / flickable.scaleFactor
2030+ readonly property real translationX: index === view.selectedIndex ? 0 :
2031+ CarouselJS.getItemTranslation(distance,
2032+ itemScale,
2033+ itemTranslationScale,
2034+ translationFactor)
2035+
2036+ width: flickable.tileWidth
2037+ height: flickable.tileHeight
2038+ scale: itemScale * explicitScaleFactor
2039+ opacity: scale > 0.02 ? 1 : 0
2040+ sourceComponent: z > 0 ? itemComponent : undefined
2041+ z: cachedTiles - Math.abs(index - view.selectedIndex)
2042+
2043+ transform: Translate {
2044+ x: translationX * flickable.scaleFactor
2045+ }
2046+
2047+ Behavior on explicitScaleFactor {
2048+ SequentialAnimation {
2049+ ScriptAction {
2050+ script: if (!explicitScale)
2051+ explicitlyScaled = false
2052+ }
2053+ NumberAnimation {
2054+ duration: explicitScaleFactor === 1.0 ? 250 : 150
2055+ easing.type: Easing.InOutQuad
2056+ }
2057+ ScriptAction {
2058+ script: if (explicitScale)
2059+ explicitlyScaled = true
2060+ }
2061+ }
2062+ }
2063+
2064+ onLoaded: {
2065+ item.explicitlyScaled = Qt.binding(function() { return explicitlyScaled; })
2066+ item.model = Qt.binding(function() { return model; })
2067+ }
2068+
2069+ MouseArea {
2070+ id: mouseArea
2071+
2072+ anchors.fill: parent
2073+
2074+ onClicked: flickable.itemClicked(index, item)
2075+ }
2076+ }
2077+ }
2078+ }
2079+ }
2080+}
2081
2082=== added file 'Components/CrossFadeImage.qml'
2083--- Components/CrossFadeImage.qml 1970-01-01 00:00:00 +0000
2084+++ Components/CrossFadeImage.qml 2013-03-01 09:12:23 +0000
2085@@ -0,0 +1,142 @@
2086+/*
2087+ * Copyright (C) 2013 Canonical, Ltd.
2088+ *
2089+ * This program is free software; you can redistribute it and/or modify
2090+ * it under the terms of the GNU General Public License as published by
2091+ * the Free Software Foundation; version 3.
2092+ *
2093+ * This program is distributed in the hope that it will be useful,
2094+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2095+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2096+ * GNU General Public License for more details.
2097+ *
2098+ * You should have received a copy of the GNU General Public License
2099+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2100+ */
2101+
2102+import QtQuick 2.0
2103+
2104+Item {
2105+ property url source
2106+ property size sourceSize: __currentImage.sourceSize
2107+ property var status: __currentImage ? __currentImage.status : Image.Null
2108+ property Image __currentImage: image1
2109+ property Image __nextImage: image2
2110+
2111+ /*
2112+ * true: fade out old image in parallel with fading in the new one.
2113+ * false: fade in new image above old one.
2114+ *
2115+ * The reason why this is required is that crossfading has the isse that in
2116+ * the middle of the animation, both images are only 50% opaque which make
2117+ * any background shine through. Not wanted for background images etc, but
2118+ * wanted for overlays.
2119+ */
2120+ property bool crossFade: true
2121+
2122+ property bool fadeInFirst: true
2123+
2124+ function swapImages() {
2125+ __currentImage.z = 0
2126+ __nextImage.z = 1
2127+ if (crossFade) {
2128+ crossFadeImages.start();
2129+ } else {
2130+ nextImageFadeIn.start();
2131+ }
2132+
2133+ var tmpImage = __currentImage
2134+ __currentImage = __nextImage
2135+ __nextImage = tmpImage
2136+ }
2137+
2138+ onSourceChanged: {
2139+ // On creation, the souce handler is called before image pointers are set.
2140+ if (__currentImage === null) {
2141+ __currentImage = image1;
2142+ __nextImage = image2;
2143+ }
2144+
2145+ if (crossFadeImages.running || nextImageFadeIn.running) {
2146+ crossFadeImages.stop();
2147+ nextImageFadeIn.stop();
2148+ }
2149+
2150+ // Don't fade in initial picture, only fade changes
2151+ if (__currentImage.source == "" && !fadeInFirst) {
2152+ __currentImage.source = source;
2153+ } else {
2154+ nextImageFadeIn.stop();
2155+ __nextImage.opacity = 0.0;
2156+ __nextImage.source = source;
2157+
2158+ // If case the image is still in QML's cache, status will be "Ready" immediately
2159+ if (__nextImage.status == Image.Ready || __nextImage.source == "") {
2160+ swapImages();
2161+ }
2162+ }
2163+ }
2164+
2165+ Connections {
2166+ target: __nextImage
2167+ onStatusChanged: {
2168+ if (__nextImage.status == Image.Ready) {
2169+ swapImages();
2170+ }
2171+ }
2172+ }
2173+
2174+ Image {
2175+ id: image1
2176+ anchors.fill: parent
2177+ cache: false
2178+ asynchronous: true
2179+ }
2180+
2181+ Image {
2182+ id: image2
2183+ anchors.fill: parent
2184+ cache: false
2185+ asynchronous: true
2186+ }
2187+
2188+ NumberAnimation {
2189+ id: nextImageFadeIn
2190+ target: __nextImage
2191+ property: "opacity"
2192+ duration: 400
2193+ to: 1.0
2194+ easing.type: Easing.InOutQuad
2195+
2196+ onRunningChanged: {
2197+ if (!running) {
2198+ __nextImage.source = "";
2199+ }
2200+ }
2201+ }
2202+
2203+ ParallelAnimation {
2204+ id: crossFadeImages
2205+ NumberAnimation {
2206+ target: __nextImage
2207+ property: "opacity"
2208+ duration: 400
2209+ to: 1.0
2210+ easing.type: Easing.InOutQuad
2211+ }
2212+
2213+ NumberAnimation {
2214+ target: __currentImage
2215+ property: "opacity"
2216+ duration: 400
2217+ to: 0
2218+ easing.type: Easing.InOutQuad
2219+ }
2220+
2221+ onRunningChanged: {
2222+ if (!running) {
2223+ __nextImage.source = "";
2224+ }
2225+ }
2226+ }
2227+}
2228
2229=== added file 'Components/DraggingArea.qml'
2230--- Components/DraggingArea.qml 1970-01-01 00:00:00 +0000
2231+++ Components/DraggingArea.qml 2013-03-01 09:12:23 +0000
2232@@ -0,0 +1,115 @@
2233+/*
2234+ * Copyright (C) 2013 Canonical, Ltd.
2235+ *
2236+ * This program is free software; you can redistribute it and/or modify
2237+ * it under the terms of the GNU General Public License as published by
2238+ * the Free Software Foundation; version 3.
2239+ *
2240+ * This program is distributed in the hope that it will be useful,
2241+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2242+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2243+ * GNU General Public License for more details.
2244+ *
2245+ * You should have received a copy of the GNU General Public License
2246+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2247+ */
2248+
2249+import QtQuick 2.0
2250+import Ubuntu.Components 0.1
2251+import "Math.js" as MathLocal
2252+
2253+MouseArea {
2254+ id: draggingArea
2255+
2256+ property int orientation: Qt.Vertical
2257+ property bool dragging
2258+ property real dragVelocity: 0
2259+ property real dragValue: (orientation == Qt.Vertical ? (mouseY - __pressedPosition.y)
2260+ : (mouseX - __pressedPosition.x))
2261+ property real lateralPosition: orientation == Qt.Horizontal ? MathLocal.clamp(mouseY, 0, height) : MathLocal.clamp(mouseX, 0, width)
2262+ property point __pressedPosition: Qt.point(0, 0)
2263+ property var __dragEvents: []
2264+ property bool clickValidated: true
2265+ property bool zeroVelocityCounts: false
2266+
2267+
2268+ signal dragStart
2269+ signal dragEnd
2270+
2271+ onDragValueChanged: {
2272+ if (dragValue != 0 && pressed) {
2273+ dragging = true
2274+ }
2275+ }
2276+
2277+ onDraggingChanged: {
2278+ if (dragging) {
2279+ dragStart()
2280+ }
2281+ else {
2282+ dragEnd()
2283+ }
2284+ }
2285+
2286+ function updateSpeed() {
2287+ var totalSpeed = 0
2288+ for (var i=0; i<__dragEvents.length; i++) {
2289+ totalSpeed += __dragEvents[i][3]
2290+ }
2291+
2292+ if (zeroVelocityCounts || Math.abs(totalSpeed) > 0.001) {
2293+ dragVelocity = totalSpeed / __dragEvents.length * 1000
2294+ }
2295+ }
2296+
2297+ function cullOldDragEvents(currentTime) {
2298+ // cull events older than 50 ms but always keep the latest 2 events
2299+ for (var numberOfCulledEvents=0; numberOfCulledEvents<__dragEvents.length-2; numberOfCulledEvents++) {
2300+ // __dragEvents[numberOfCulledEvents][0] is the dragTime
2301+ if (currentTime - __dragEvents[numberOfCulledEvents][0] <= 50) break
2302+ }
2303+
2304+ __dragEvents.splice(0, numberOfCulledEvents)
2305+ }
2306+
2307+ function getEventSpeed(currentTime, event) {
2308+ if (__dragEvents.length != 0) {
2309+ var lastDrag = __dragEvents[__dragEvents.length-1]
2310+ var duration = Math.max(1, currentTime - lastDrag[0])
2311+ if (orientation == Qt.Vertical) {
2312+ return (event.y - lastDrag[2]) / duration
2313+ } else {
2314+ return (event.x - lastDrag[1]) / duration
2315+ }
2316+ } else {
2317+ return 0
2318+ }
2319+ }
2320+
2321+ function pushDragEvent(event) {
2322+ var currentTime = new Date().getTime()
2323+ __dragEvents.push([currentTime, event.x, event.y, getEventSpeed(currentTime, event)])
2324+ cullOldDragEvents(currentTime)
2325+ updateSpeed()
2326+ }
2327+
2328+ onPositionChanged: {
2329+ if (dragging) {
2330+ pushDragEvent(mouse)
2331+ }
2332+ if (!draggingArea.containsMouse)
2333+ clickValidated = false
2334+ }
2335+
2336+ onPressed: {
2337+ __pressedPosition = Qt.point(mouse.x, mouse.y)
2338+ __dragEvents = []
2339+ pushDragEvent(mouse)
2340+ clickValidated = true
2341+ }
2342+
2343+ onReleased: {
2344+ dragging = false
2345+ __pressedPosition = Qt.point(mouse.x, mouse.y)
2346+ }
2347+}
2348
2349=== added file 'Components/FilterGrid.qml'
2350--- Components/FilterGrid.qml 1970-01-01 00:00:00 +0000
2351+++ Components/FilterGrid.qml 2013-03-01 09:12:23 +0000
2352@@ -0,0 +1,138 @@
2353+/*
2354+ * Copyright (C) 2013 Canonical, Ltd.
2355+ *
2356+ * This program is free software; you can redistribute it and/or modify
2357+ * it under the terms of the GNU General Public License as published by
2358+ * the Free Software Foundation; version 3.
2359+ *
2360+ * This program is distributed in the hope that it will be useful,
2361+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2362+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2363+ * GNU General Public License for more details.
2364+ *
2365+ * You should have received a copy of the GNU General Public License
2366+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2367+ */
2368+
2369+import QtQuick 2.0
2370+import Ubuntu.Components 0.1
2371+import Utils 0.1
2372+import "../Components"
2373+
2374+Item {
2375+ id: root
2376+ property bool filter: true
2377+ property bool expandable: true
2378+ property var model: null
2379+ property int collapsedRowCount: 2
2380+
2381+ property alias minimumHorizontalSpacing: iconTileGrid.minimumHorizontalSpacing
2382+ property alias maximumNumberOfColumns: iconTileGrid.maximumNumberOfColumns
2383+ property alias columns: iconTileGrid.columns
2384+ property alias delegateWidth: iconTileGrid.delegateWidth
2385+ property alias delegateHeight: iconTileGrid.delegateHeight
2386+ property alias verticalSpacing: iconTileGrid.verticalSpacing
2387+ property alias delegate: iconTileGrid.delegate
2388+ property alias cellWidth: iconTileGrid.cellWidth
2389+ property alias cellHeight: iconTileGrid.cellHeight
2390+
2391+ height: childrenRect.height
2392+
2393+ // TODO: Evaluate better ways how to know where to split to show the Preview
2394+ function itemX(index) {
2395+ var col = index % iconTileGrid.columns;
2396+ return (delegateWidth + horizontalCenter) * col;
2397+ }
2398+
2399+ function itemY(index) {
2400+ var row = Math.floor(index / iconTileGrid.columns);
2401+ return (delegateHeight + verticalSpacing) * row;
2402+ }
2403+
2404+ ResponsiveGridView {
2405+ id: iconTileGrid
2406+
2407+ anchors { left: parent.left; right: parent.right }
2408+ height: totalContentHeight
2409+ Behavior on height { NumberAnimation { id: heightAnimation; duration: 200; easing.type: Easing.InOutQuad } }
2410+ interactive: false
2411+
2412+ minimumHorizontalSpacing: units.gu(0.5)
2413+ maximumNumberOfColumns: 6
2414+ delegateWidth: units.gu(11)
2415+ delegateHeight: units.gu(9.5)
2416+ verticalSpacing: units.gu(2)
2417+
2418+ model: SortFilterProxyModel {
2419+ model: root.model
2420+ limit: (filter) ? collapsedRowCount * iconTileGrid.columns : -1
2421+ }
2422+
2423+ delegate: Tile {
2424+ width: iconTileGrid.cellWidth
2425+ height: iconTileGrid.cellHeight
2426+ text: name
2427+ imageWidth: units.gu(8)
2428+ imageHeight: units.gu(8)
2429+ source: "../graphics/applicationIcons/" + icon + ".png"
2430+ onClicked: shell.activateApplication(desktopFile)
2431+ }
2432+ }
2433+
2434+ Item {
2435+ anchors {
2436+ left: parent.left
2437+ right: parent.right
2438+ top: iconTileGrid.bottom
2439+ }
2440+ visible: (expandable && filter && model.count > collapsedRowCount * iconTileGrid.columns)
2441+ height: (visible) ? childrenRect.height + units.gu(2) : 0
2442+
2443+ AbstractButton {
2444+ id: button
2445+
2446+ anchors {
2447+ top: parent.top
2448+ horizontalCenter: parent.horizontalCenter
2449+ }
2450+ width: units.gu(22)
2451+ height: units.gu(4)
2452+
2453+ UbuntuShape {
2454+ anchors.fill: parent
2455+ color: "#33ffffff"
2456+ radius: "small"
2457+ }
2458+
2459+ UbuntuShape {
2460+ id: borderPressed
2461+
2462+ anchors.fill: parent
2463+ radius: "small"
2464+ borderSource: ItemStyle.style.borderPressed
2465+ opacity: button.pressed ? 1.0 : 0.0
2466+ Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
2467+ }
2468+
2469+ Label {
2470+ anchors {
2471+ verticalCenter: parent.verticalCenter
2472+ left: parent.left
2473+ right: parent.right
2474+ leftMargin: units.gu(1)
2475+ rightMargin: units.gu(1)
2476+ }
2477+ text: (filter) ? "+ View all (" + model.count + ")" : "- Show fewer"
2478+ fontSize: "small"
2479+ color: "#f3f3e7"
2480+ opacity: 0.6
2481+ style: Text.Raised
2482+ styleColor: "black"
2483+ elide: Text.ElideMiddle
2484+ horizontalAlignment: Text.AlignHCenter
2485+ }
2486+
2487+ onClicked: filter = !filter
2488+ }
2489+ }
2490+}
2491
2492=== added file 'Components/InputFilterArea.qml'
2493--- Components/InputFilterArea.qml 1970-01-01 00:00:00 +0000
2494+++ Components/InputFilterArea.qml 2013-03-01 09:12:23 +0000
2495@@ -0,0 +1,29 @@
2496+/*
2497+ * Copyright (C) 2013 Canonical, Ltd.
2498+ *
2499+ * This program is free software; you can redistribute it and/or modify
2500+ * it under the terms of the GNU General Public License as published by
2501+ * the Free Software Foundation; version 3.
2502+ *
2503+ * This program is distributed in the hope that it will be useful,
2504+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2505+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2506+ * GNU General Public License for more details.
2507+ *
2508+ * You should have received a copy of the GNU General Public License
2509+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2510+ */
2511+
2512+import QtQuick 2.0
2513+
2514+Item {
2515+ id: inputFilterArea
2516+
2517+ property bool blockInput: false
2518+
2519+ Component.onCompleted: {
2520+ if (shell.importUbuntuApplicationAvailable) {
2521+ Qt.createQmlObject('import Ubuntu.Application 0.1; import QtQuick 2.0; InputFilterArea {anchors.fill: parent; blockInput: inputFilterArea.blockInput}', inputFilterArea, "");
2522+ }
2523+ }
2524+}
2525
2526=== added directory 'Components/ListItems'
2527=== added file 'Components/ListItems/Base.qml'
2528--- Components/ListItems/Base.qml 1970-01-01 00:00:00 +0000
2529+++ Components/ListItems/Base.qml 2013-03-01 09:12:23 +0000
2530@@ -0,0 +1,127 @@
2531+/*
2532+ * Copyright (C) 2012 Canonical, Ltd.
2533+ *
2534+ * This program is free software; you can redistribute it and/or modify
2535+ * it under the terms of the GNU General Public License as published by
2536+ * the Free Software Foundation; version 3.
2537+ *
2538+ * This program is distributed in the hope that it will be useful,
2539+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2540+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2541+ * GNU General Public License for more details.
2542+ *
2543+ * You should have received a copy of the GNU General Public License
2544+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2545+ */
2546+
2547+import QtQuick 2.0
2548+import Ubuntu.Components 0.1
2549+
2550+AbstractButton {
2551+ id: emptyListItem
2552+ width: parent ? parent.width : units.gu(31)
2553+ height: body.height + bottomDividerLine.height
2554+
2555+ /*!
2556+ \preliminary
2557+ Specifies whether the list item is selected.
2558+ */
2559+ property bool selected: false
2560+
2561+ /*!
2562+ \preliminary
2563+ Highlight the list item when it is pressed.
2564+ This is used to disable the highlighting of the full list item
2565+ when custom highlighting needs to be implemented (for example in
2566+ ListItem.Standard which can have a split).
2567+ */
2568+ property bool highlightWhenPressed: true
2569+
2570+ /*!
2571+ \preliminary
2572+ Set to show or hide the thin bottom divider line (drawn by the \l ThinDivider component).
2573+ This line is shown by default except in cases where this item is the delegate of a ListView.
2574+ */
2575+ property bool showDivider: __showDivider()
2576+
2577+ /*!
2578+ \internal
2579+ Method to automatically determine if the bottom divider line should be drawn.
2580+ This always returns true, unless item is a delegate in a ListView. If in a ListView
2581+ it will return false only when:
2582+ + if this is the final item in the list, and ListView.footer is set (again as thin
2583+ divider line won't look well with footer below it)
2584+ */
2585+ function __showDivider() {
2586+ // if we're not in ListView, always show a thin dividing line at the bottom
2587+ if (ListView.view !== null) {
2588+
2589+ // if we're last item in ListView don't show divider
2590+ if (index === ListView.view.model.count - 1) return false;
2591+ }
2592+ return true;
2593+ }
2594+
2595+ property bool __clippingRequired: ListView.view !== null
2596+ && ListView.view.section.labelPositioning & ViewSection.CurrentLabelAtStart
2597+
2598+ property real __yPositionRelativeToListView: ListView.view ? y - ListView.view.contentY : y
2599+
2600+ property real __heightToClip: {
2601+ // Check this is in position where clipping is needed
2602+ if (__clippingRequired && __yPositionRelativeToListView <= __sectionDelegateHeight
2603+ && __yPositionRelativeToListView > -height) {
2604+ return Math.min(__sectionDelegateHeight - __yPositionRelativeToListView, height);
2605+ } else {
2606+ return 0;
2607+ }
2608+ }
2609+
2610+ property int __sectionDelegateHeight: {
2611+ if (__clippingRequired && ListView.view.hasOwnProperty("__sectionDelegateHeight")) {
2612+ return ListView.view.__sectionDelegateHeight;
2613+ } else {
2614+ return 0;
2615+ }
2616+ }
2617+
2618+ /*!
2619+ \internal
2620+ Reparent so that the visuals of the children does not
2621+ occlude the bottom divider line.
2622+ */
2623+ default property alias children: body.children
2624+
2625+ Item {
2626+ id: clippingContainer
2627+ height: parent.height - __heightToClip
2628+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
2629+ clip: __heightToClip > 0
2630+
2631+ Item {
2632+ id: body
2633+ anchors {
2634+ left: parent.left
2635+ right: parent.right
2636+ bottom: bottomDividerLine.top
2637+ }
2638+ height: childrenRect.height
2639+ }
2640+
2641+ ThinDivider {
2642+ id: bottomDividerLine
2643+ anchors.bottom: parent.bottom
2644+ visible: showDivider
2645+ }
2646+
2647+ Highlight {
2648+ anchors {
2649+ top: parent.top
2650+ left: parent.left
2651+ right: parent.right
2652+ bottom: bottomDividerLine.top
2653+ }
2654+ pressed: (emptyListItem.selected || (emptyListItem.highlightWhenPressed && emptyListItem.pressed)) ? "pressed" : ""
2655+ }
2656+ }
2657+}
2658
2659=== added file 'Components/ListItems/Header.qml'
2660--- Components/ListItems/Header.qml 1970-01-01 00:00:00 +0000
2661+++ Components/ListItems/Header.qml 2013-03-01 09:12:23 +0000
2662@@ -0,0 +1,73 @@
2663+/*
2664+ * Copyright (C) 2013 Canonical, Ltd.
2665+ *
2666+ * This program is free software; you can redistribute it and/or modify
2667+ * it under the terms of the GNU General Public License as published by
2668+ * the Free Software Foundation; version 3.
2669+ *
2670+ * This program is distributed in the hope that it will be useful,
2671+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2672+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2673+ * GNU General Public License for more details.
2674+ *
2675+ * You should have received a copy of the GNU General Public License
2676+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2677+ */
2678+
2679+import QtQuick 2.0
2680+import Ubuntu.Components 0.1
2681+
2682+Item {
2683+ /*!
2684+ \preliminary
2685+ The text that is shown as the header text.
2686+ \qmlproperty string text
2687+ */
2688+ property alias text: label.text
2689+
2690+ /* When this header is used in a ListViewWithPageHeader with CurrentLabelAtStart mode, to stop
2691+ the list's delegates contents being visible through this header, they clip themselves
2692+ depending on their position. However to allow delegates underlap the bottom X pixels of this
2693+ header (so delegate appears through ThinDivider say) we set an offset property here. */
2694+ readonly property int bottomBorderAllowedOverlap: bottomBorder.allowedBottomOverlap
2695+
2696+ height: units.gu(4.5)
2697+
2698+ Item {
2699+ anchors {
2700+ left: parent.left
2701+ right: parent.right
2702+ top: parent.top
2703+ bottom: bottomBorder.top
2704+ }
2705+
2706+ Label {
2707+ id: label
2708+ anchors {
2709+ left: parent.left
2710+ leftMargin: units.gu(2)
2711+ right: parent.right
2712+ rightMargin: units.gu(0.5)
2713+ verticalCenter: parent.verticalCenter
2714+ }
2715+
2716+ color: "#f3f3e7" //at 60%
2717+ opacity: 0.6
2718+ font.family: "Ubuntu"
2719+ fontSize: "medium"
2720+ elide: Text.ElideRight
2721+ textFormat: Text.PlainText
2722+ style: Text.Raised
2723+ styleColor: "black"
2724+ }
2725+ }
2726+
2727+ ThinDivider {
2728+ id: bottomBorder
2729+ anchors {
2730+ left: parent.left
2731+ right: parent.right
2732+ bottom: parent.bottom
2733+ }
2734+ }
2735+}
2736
2737=== added file 'Components/ListItems/Highlight.qml'
2738--- Components/ListItems/Highlight.qml 1970-01-01 00:00:00 +0000
2739+++ Components/ListItems/Highlight.qml 2013-03-01 09:12:23 +0000
2740@@ -0,0 +1,46 @@
2741+/*
2742+ * Copyright (C) 2013 Canonical, Ltd.
2743+ *
2744+ * This program is free software; you can redistribute it and/or modify
2745+ * it under the terms of the GNU General Public License as published by
2746+ * the Free Software Foundation; version 3.
2747+ *
2748+ * This program is distributed in the hope that it will be useful,
2749+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2750+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2751+ * GNU General Public License for more details.
2752+ *
2753+ * You should have received a copy of the GNU General Public License
2754+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2755+ */
2756+
2757+import QtQuick 2.0
2758+
2759+Rectangle {
2760+ id: highlight
2761+
2762+ property bool pressed: false
2763+ property real pressedOpacity: 0.3
2764+
2765+ color: "black"
2766+ opacity: 0
2767+ state: pressed ? "pressed" : ""
2768+ states: [
2769+ State {
2770+ name: "pressed"
2771+ PropertyChanges { target: highlight; opacity: pressedOpacity}
2772+ }
2773+ ]
2774+ transitions: [
2775+ Transition {
2776+ from: ""
2777+ to: "pressed"
2778+ NumberAnimation { target: highlight; property: "opacity"; duration: 50}
2779+ },
2780+ Transition {
2781+ from: "pressed"
2782+ to: ""
2783+ NumberAnimation { target: highlight; property: "opacity"; duration: 100}
2784+ }
2785+ ]
2786+}
2787
2788=== added file 'Components/ListItems/ThinDivider.qml'
2789--- Components/ListItems/ThinDivider.qml 1970-01-01 00:00:00 +0000
2790+++ Components/ListItems/ThinDivider.qml 2013-03-01 09:12:23 +0000
2791@@ -0,0 +1,31 @@
2792+/*
2793+ * Copyright (C) 2012 Canonical, Ltd.
2794+ *
2795+ * This program is free software; you can redistribute it and/or modify
2796+ * it under the terms of the GNU General Public License as published by
2797+ * the Free Software Foundation; version 3.
2798+ *
2799+ * This program is distributed in the hope that it will be useful,
2800+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2801+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2802+ * GNU General Public License for more details.
2803+ *
2804+ * You should have received a copy of the GNU General Public License
2805+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2806+ */
2807+
2808+import QtQuick 2.0
2809+
2810+Image {
2811+ anchors {
2812+ left: (parent) ? parent.left : null
2813+ right: (parent) ? parent.right : null
2814+ }
2815+ height: (visible) ? units.dp(2) : 0
2816+
2817+ /* Relevant really only for ListViewWithPageHeader with Base delegates: should this image
2818+ be overlapping content, specify how many pixels from the bottom should be transparent */
2819+ readonly property int allowedBottomOverlap: units.dp(1)
2820+
2821+ source: "graphics/ListItemDividerHorizontal.png"
2822+}
2823
2824=== added file 'Components/ListItems/VerticalThinDivider.qml'
2825--- Components/ListItems/VerticalThinDivider.qml 1970-01-01 00:00:00 +0000
2826+++ Components/ListItems/VerticalThinDivider.qml 2013-03-01 09:12:23 +0000
2827@@ -0,0 +1,26 @@
2828+/*
2829+ * Copyright (C) 2012 Canonical, Ltd.
2830+ *
2831+ * This program is free software; you can redistribute it and/or modify
2832+ * it under the terms of the GNU General Public License as published by
2833+ * the Free Software Foundation; version 3.
2834+ *
2835+ * This program is distributed in the hope that it will be useful,
2836+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2838+ * GNU General Public License for more details.
2839+ *
2840+ * You should have received a copy of the GNU General Public License
2841+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2842+ */
2843+
2844+import QtQuick 2.0
2845+
2846+Image {
2847+ anchors {
2848+ top: (parent) ? parent.top : null
2849+ bottom: (parent) ? parent.bottom : null
2850+ }
2851+ width: (visible) ? units.dp(2) : 0
2852+ source: "graphics/ListItemDividerVertical.png"
2853+}
2854
2855=== added directory 'Components/ListItems/graphics'
2856=== added file 'Components/ListItems/graphics/ListItemDividerHorizontal@18.png'
2857Binary files Components/ListItems/graphics/ListItemDividerHorizontal@18.png 1970-01-01 00:00:00 +0000 and Components/ListItems/graphics/ListItemDividerHorizontal@18.png 2013-03-01 09:12:23 +0000 differ
2858=== added file 'Components/ListItems/graphics/ListItemDividerVertical@18.png'
2859Binary files Components/ListItems/graphics/ListItemDividerVertical@18.png 1970-01-01 00:00:00 +0000 and Components/ListItems/graphics/ListItemDividerVertical@18.png 2013-03-01 09:12:23 +0000 differ
2860=== added file 'Components/ListViewWithPageHeader.qml'
2861--- Components/ListViewWithPageHeader.qml 1970-01-01 00:00:00 +0000
2862+++ Components/ListViewWithPageHeader.qml 2013-03-01 09:12:23 +0000
2863@@ -0,0 +1,180 @@
2864+/*
2865+ * Copyright (C) 2013 Canonical, Ltd.
2866+ *
2867+ * This program is free software; you can redistribute it and/or modify
2868+ * it under the terms of the GNU General Public License as published by
2869+ * the Free Software Foundation; version 3.
2870+ *
2871+ * This program is distributed in the hope that it will be useful,
2872+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2873+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2874+ * GNU General Public License for more details.
2875+ *
2876+ * You should have received a copy of the GNU General Public License
2877+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2878+ */
2879+
2880+import QtQuick 2.0
2881+import "Math.js" as MathLocal
2882+
2883+Item {
2884+ id: root
2885+ property Item pageHeader: null
2886+ property Component sectionDelegate: null
2887+ property string sectionProperty: ""
2888+ property alias model: listView.model
2889+ property alias delegate: listView.delegate
2890+ property ListView view: listView
2891+ property alias moving: flicker.moving
2892+ property alias atYEnd: flicker.atYEnd
2893+ property bool clipListView: true
2894+
2895+ readonly property real __headerHeight: (pageHeader) ? pageHeader.implicitHeight : 0
2896+ property real __headerVisibleHeight: __headerHeight
2897+ readonly property real __overshootHeight: (flicker.contentY < 0) ? -flicker.contentY : 0
2898+
2899+
2900+ // TODO move to AnimationController
2901+ ParallelAnimation {
2902+ id: headerAnimation
2903+ property real targetContentY
2904+ NumberAnimation {
2905+ target: root
2906+ property: "__headerVisibleHeight"
2907+ to: root.__headerHeight
2908+ duration: 200
2909+ easing.type: Easing.OutQuad
2910+ }
2911+ NumberAnimation {
2912+ target: listView
2913+ property: "contentY"
2914+ to: headerAnimation.targetContentY
2915+ duration: 200
2916+ easing.type: Easing.OutQuad
2917+ }
2918+ }
2919+
2920+ function showHeader() {
2921+ headerAnimation.targetContentY = listView.contentY + (__headerHeight - __headerVisibleHeight)
2922+ headerAnimation.start()
2923+ }
2924+
2925+ onPageHeaderChanged: {
2926+ pageHeader.parent = pageHeaderContainer;
2927+ pageHeader.anchors.fill = pageHeaderContainer;
2928+ }
2929+
2930+ Item {
2931+ id: pageHeaderClipper
2932+ parent: flicker // parent to Flickable so mouse click events passed through to the header component
2933+ anchors {
2934+ top: parent.top
2935+ left: parent.left
2936+ right: parent.right
2937+ }
2938+ height: __headerVisibleHeight + __overshootHeight
2939+
2940+ Item {
2941+ id: pageHeaderContainer
2942+ anchors {
2943+ left: parent.left
2944+ right: parent.right
2945+ bottom: parent.bottom
2946+ }
2947+ height: __headerHeight + __overshootHeight
2948+ }
2949+ }
2950+
2951+ ListView {
2952+ id: listView
2953+ parent: flicker // parent to Flickable so mouse click events passed through to List delegates
2954+ anchors {
2955+ left: parent.left
2956+ right: parent.right
2957+ top: parent.top
2958+ topMargin: __headerVisibleHeight
2959+ }
2960+ height: root.height
2961+
2962+ // FIXME scrolling workaround, see below
2963+ cacheBuffer: height*10
2964+
2965+ section.property: sectionProperty
2966+ section.criteria: ViewSection.FullString
2967+ section.labelPositioning: ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart
2968+ section.delegate: sectionDelegate
2969+
2970+ interactive: false
2971+ clip: root.clipListView
2972+
2973+ property int __sectionDelegateHeight: __getHeight(section.delegate)
2974+ function __getHeight(component) {
2975+ // want height (minus allowed overlap) of the section delegate as is needed for clipping
2976+ if (component === null) return 0;
2977+ var object = component.createObject(); //FIXME: throws 'section' not defined error
2978+ var value = object.height - object.bottomBorderAllowedOverlap;
2979+ object.destroy();
2980+ return value;
2981+ }
2982+
2983+ property real previousOriginY: 0
2984+ onOriginYChanged: {
2985+ var deltaOriginY = originY - previousOriginY;
2986+ previousOriginY = originY;
2987+ /* When originY changes, it causes the top of the flicker and the top of the list to fall
2988+ out of sync - and thus the contentY positioning will be broken. To correct for this we
2989+ manually change the flickable's contentY here */
2990+ flicker.contentY -= deltaOriginY;
2991+ }
2992+
2993+ /* For case when list content greater than container height and list scrolled down so header
2994+ hidden. If content shrinks to be smaller than the container height, we want the header to
2995+ re-appear */
2996+ property real __previousContentHeight: 0
2997+ onContentHeightChanged: {
2998+ var deltaContentHeight = contentHeight - __previousContentHeight;
2999+ __previousContentHeight = contentHeight;
3000+ if (contentHeight < height && deltaContentHeight < 0 && __headerVisibleHeight < height - contentHeight) {
3001+ __headerVisibleHeight = Math.min(height - contentHeight, __headerHeight);
3002+ }
3003+ }
3004+ }
3005+
3006+ Flickable {
3007+ id: flicker
3008+ anchors.fill: parent
3009+ contentHeight: listView.contentHeight + __headerHeight
3010+ maximumFlickVelocity: height * 10
3011+ flickDeceleration: height * 2
3012+ onContentYChanged: {
3013+ var deltaContentY = contentY - __previousContentY;
3014+ __previousContentY = contentY;
3015+
3016+ // first decide if movement will prompt the page header to change height
3017+ if ((deltaContentY < 0 && __headerVisibleHeight >= 0) ||
3018+ (deltaContentY > 0 && __headerVisibleHeight <= __headerHeight)) {
3019+
3020+ // calculate header height - but prevent bounce from changing it
3021+ if (contentY > 0 && contentY < contentHeight - height) {
3022+ __headerVisibleHeight = MathLocal.clamp(__headerVisibleHeight - deltaContentY, 0, __headerHeight);
3023+ }
3024+ }
3025+
3026+ // now we move list position, taking into account page header height
3027+
3028+ // BUG: With section headers enabled, the values of originY and contentY appear not
3029+ // correct at the exact point originY changes. originY changes when the ListView
3030+ // deletes/creates hidden delegates which are above the visible delegates.
3031+ // As a result of this bug, you experience jittering scrolling when rapidly moving
3032+ // around in large lists. See https://bugreports.qt-project.org/browse/QTBUG-27997
3033+ // A workaround is to use a large enough cacheBuffer to prevent deletions/creations
3034+ // so effectively originY is always zero.
3035+ var newContentY = flicker.contentY + listView.originY - __headerHeight + __headerVisibleHeight
3036+ if (newContentY < listView.contentHeight) {
3037+ listView.contentY = newContentY;
3038+ }
3039+ }
3040+
3041+ property real __previousContentY: 0
3042+ }
3043+}
3044
3045=== added file 'Components/Math.js'
3046--- Components/Math.js 1970-01-01 00:00:00 +0000
3047+++ Components/Math.js 2013-03-01 09:12:23 +0000
3048@@ -0,0 +1,26 @@
3049+/*
3050+ * Copyright (C) 2013 Canonical, Ltd.
3051+ *
3052+ * This program is free software; you can redistribute it and/or modify
3053+ * it under the terms of the GNU General Public License as published by
3054+ * the Free Software Foundation; version 3.
3055+ *
3056+ * This program is distributed in the hope that it will be useful,
3057+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3058+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3059+ * GNU General Public License for more details.
3060+ *
3061+ * You should have received a copy of the GNU General Public License
3062+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3063+ */
3064+
3065+.pragma library
3066+
3067+function clamp(value, min, max) {
3068+ if (min <= max) {
3069+ return Math.max(min, Math.min(max, value))
3070+ } else {
3071+ // swap min/max if min > max
3072+ return clamp(value, max, min)
3073+ }
3074+}
3075
3076=== added file 'Components/OpenEffect.qml'
3077--- Components/OpenEffect.qml 1970-01-01 00:00:00 +0000
3078+++ Components/OpenEffect.qml 2013-03-01 09:12:23 +0000
3079@@ -0,0 +1,124 @@
3080+/*
3081+ * Copyright (C) 2013 Canonical, Ltd.
3082+ *
3083+ * This program is free software; you can redistribute it and/or modify
3084+ * it under the terms of the GNU General Public License as published by
3085+ * the Free Software Foundation; version 3.
3086+ *
3087+ * This program is distributed in the hope that it will be useful,
3088+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3089+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3090+ * GNU General Public License for more details.
3091+ *
3092+ * You should have received a copy of the GNU General Public License
3093+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3094+ */
3095+
3096+import QtQuick 2.0
3097+
3098+Item {
3099+ id: effect
3100+ property bool enabled: topGapPx != positionPx || bottomGapPx != positionPx
3101+ property Item sourceItem
3102+ property ShaderEffectSource source: ShaderEffectSource {
3103+ sourceItem: effect.enabled ? effect.sourceItem : null
3104+ hideSource: effect.enabled
3105+ live: effect.enabled
3106+ sourceRect: Qt.rect(0, -effect.topOverflow, sourceItem.width, sourceItem.height + effect.topOverflow + effect.bottomOverflow)
3107+ }
3108+
3109+ /*!
3110+ \qmlproperty real positionPx
3111+ The y coordinate of where to perform the split.
3112+
3113+ \qmlproperty real topGapPx
3114+ Gap's top edge.
3115+
3116+ \qmlproperty real bottomGapPx
3117+ Gap's bottom edge.
3118+
3119+ \qmlproperty real topOverflow
3120+ How much of the sourceItem should be sourced above its bounds.
3121+
3122+ \qmlproperty real bottomOverflow
3123+ How much of the sourceItem should be sourced below its bounds.
3124+ */
3125+
3126+ property real positionPx: 0
3127+ property real topGapPx: 0
3128+ property real bottomGapPx: height
3129+ property real topOverflow: 0.0
3130+ property real bottomOverflow: 0.0
3131+ property real topOpacity: 1.0
3132+ property real bottomOpacity: 1.0
3133+
3134+ property real __roundedPositionPx: Math.round(positionPx)
3135+
3136+ ShaderEffect {
3137+ id: top
3138+ visible: effect.enabled
3139+ opacity: topOpacity
3140+ property ShaderEffectSource source: effect.source
3141+ property real positionPx: __roundedPositionPx
3142+ property real factor: effect.height / height
3143+
3144+ clip: true
3145+
3146+ anchors {
3147+ top: parent.top
3148+ left: parent.left
3149+ right: parent.right
3150+ topMargin: -topOverflow - positionPx + topGapPx
3151+ }
3152+ height: topOverflow + positionPx
3153+
3154+ vertexShader: "
3155+ uniform highp mat4 qt_Matrix;
3156+ attribute highp vec4 qt_Vertex;
3157+ attribute highp vec2 qt_MultiTexCoord0;
3158+ varying highp vec2 qt_TexCoord0;
3159+ uniform highp float factor;
3160+
3161+ void main() {
3162+ highp vec4 pos = qt_Vertex;
3163+ pos.y *= factor;
3164+ gl_Position = qt_Matrix * pos;
3165+ qt_TexCoord0 = qt_MultiTexCoord0;
3166+ }
3167+ "
3168+ }
3169+
3170+ ShaderEffect {
3171+ id: bottom
3172+ visible: effect.enabled
3173+ opacity: bottomOpacity
3174+ property ShaderEffectSource source: effect.source
3175+ property real offset: effect.topOverflow + __roundedPositionPx
3176+ property real factor: effect.height / height
3177+
3178+ clip: true
3179+
3180+ anchors {
3181+ left: parent.left
3182+ right: parent.right
3183+ }
3184+ y: topOverflow + bottomGapPx
3185+ height: sourceItem.height - positionPx + bottomOverflow
3186+
3187+ vertexShader: "
3188+ uniform highp mat4 qt_Matrix;
3189+ attribute highp vec4 qt_Vertex;
3190+ attribute highp vec2 qt_MultiTexCoord0;
3191+ varying highp vec2 qt_TexCoord0;
3192+ uniform highp float factor;
3193+ uniform highp float offset;
3194+
3195+ void main() {
3196+ highp vec4 pos = qt_Vertex;
3197+ pos.y = (pos.y * factor) - offset;
3198+ gl_Position = qt_Matrix * pos;
3199+ qt_TexCoord0 = qt_MultiTexCoord0;
3200+ }
3201+ "
3202+ }
3203+}
3204
3205=== added file 'Components/PageHeader.qml'
3206--- Components/PageHeader.qml 1970-01-01 00:00:00 +0000
3207+++ Components/PageHeader.qml 2013-03-01 09:12:23 +0000
3208@@ -0,0 +1,338 @@
3209+/*
3210+ * Copyright (C) 2013 Canonical, Ltd.
3211+ *
3212+ * This program is free software; you can redistribute it and/or modify
3213+ * it under the terms of the GNU General Public License as published by
3214+ * the Free Software Foundation; version 3.
3215+ *
3216+ * This program is distributed in the hope that it will be useful,
3217+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3218+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3219+ * GNU General Public License for more details.
3220+ *
3221+ * You should have received a copy of the GNU General Public License
3222+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3223+ */
3224+
3225+import QtQuick 2.0
3226+import Ubuntu.Components 0.1
3227+import Ubuntu.Components.Popups 0.1
3228+import Ubuntu.Components.ListItems 0.1 as ListItem
3229+
3230+Item {
3231+ /*!
3232+ \preliminary
3233+ The text that is shown inside the Page Header
3234+ \qmlproperty string text
3235+ */
3236+ property alias text: label.text
3237+
3238+ property bool searchEntryEnabled: false
3239+ property alias searchQuery: searchField.text
3240+
3241+ height: units.gu(8.5)
3242+ implicitHeight: units.gu(8.5)
3243+
3244+ function triggerSearch() { searchField.forceActiveFocus() }
3245+ function resetSearch() {
3246+ shell.searchHistory.addQuery(searchField.text);
3247+ searchField.text = "";
3248+ searchField.focus = false;
3249+ }
3250+
3251+ Connections {
3252+ target: greeter
3253+ onShownChanged: if (shown) resetSearch()
3254+ }
3255+
3256+ Flickable {
3257+ id: header
3258+ anchors {
3259+ left: parent.left
3260+ right: parent.right
3261+ top: parent.top
3262+ }
3263+ height: units.gu(6.5)
3264+
3265+ interactive: false
3266+ contentHeight: headerContainer.height
3267+ clip: true
3268+
3269+ contentY: searchField.activeFocus || searchField.text != "" ? searchContainer.y : headerContainer.y
3270+
3271+ Behavior on contentY { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } }
3272+
3273+ // FIXME this could potentially be simplified to avoid all the containers
3274+ Item {
3275+ id: headerContainer
3276+
3277+ width: parent.width
3278+ height: childrenRect.height
3279+
3280+ Item {
3281+ id: textContainer
3282+ width: header.width
3283+ height: header.height
3284+
3285+ Label {
3286+ id: label
3287+ anchors {
3288+ left: parent.left
3289+ leftMargin: units.gu(2)
3290+ right: parent.right
3291+ verticalCenter: parent.verticalCenter
3292+ }
3293+
3294+ color: "#f3f3e7"
3295+ opacity: 0.8
3296+ font.family: "Ubuntu"
3297+ font.weight: Font.Light
3298+ fontSize: "x-large"
3299+ elide: Text.ElideRight
3300+ style: Text.Raised
3301+ styleColor: "black"
3302+ }
3303+ }
3304+
3305+ Item {
3306+ id: searchContainer
3307+
3308+ visible: searchEntryEnabled
3309+
3310+ property bool narrowMode: parent.width < units.gu(60)
3311+ property bool active: searchField.text != "" || searchField.activeFocus
3312+ property var popover: null
3313+
3314+ anchors.right: textContainer.right
3315+ height: header.height
3316+
3317+ state:
3318+ if (active && narrowMode) "narrowActive"
3319+ else if (!active && narrowMode) "narrowInactive"
3320+ else if (active && !narrowMode) "active"
3321+ else if (!active && !narrowMode) "inactive"
3322+
3323+ function openPopover() {
3324+ if (shell.searchHistory.count > 0) {
3325+ searchContainer.popover = PopupUtils.open(popoverComponent, searchField,
3326+ {
3327+ "pointerTarget": pointerPositioner,
3328+ "contentWidth": searchField.width,
3329+ "edgeMargins": units.gu(1)
3330+ }
3331+ )
3332+ }
3333+ }
3334+
3335+ function closePopover() {
3336+ if (searchContainer.popover) PopupUtils.close(searchContainer.popover)
3337+ }
3338+
3339+ onActiveFocusChanged: if (!activeFocus) { shell.searchHistory.addQuery(searchField.text) }
3340+
3341+ TextField {
3342+ id: searchField
3343+
3344+ anchors.fill: parent
3345+ anchors.margins: units.gu(1)
3346+
3347+ hasClearButton: false
3348+
3349+ primaryItem: Button {
3350+ enabled: searchField.text != ""
3351+ ItemStyle.class: "transparent-button"
3352+ onClicked: {
3353+ if (searchField.text != "") {
3354+ shell.searchHistory.addQuery(searchField.text)
3355+ searchField.text = ""
3356+ }
3357+ }
3358+ height: parent.height
3359+ width: height
3360+
3361+ Image {
3362+ id: primaryImage
3363+ anchors {
3364+ verticalCenter: parent.verticalCenter
3365+ left: parent.left
3366+ leftMargin: units.gu(0.5)
3367+ }
3368+ width: units.gu(3)
3369+ height: units.gu(3)
3370+ }
3371+
3372+ Item {
3373+ id: pointerPositioner
3374+ anchors.left: parent.right
3375+ anchors.leftMargin: units.gu(0.5)
3376+ anchors.top: parent.bottom
3377+ }
3378+ }
3379+
3380+ onTextChanged: {
3381+ if (text != "") searchContainer.closePopover()
3382+ else if (text == "" && activeFocus) searchContainer.openPopover()
3383+ }
3384+
3385+ onActiveFocusChanged: {
3386+ if (!activeFocus) searchContainer.closePopover()
3387+ }
3388+ }
3389+
3390+ states: [
3391+ State {
3392+ name: "wide"
3393+ AnchorChanges { target: textContainer; anchors.top: headerContainer.top }
3394+ AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: textContainer.top }
3395+ },
3396+ State {
3397+ name: "narrow"
3398+ PropertyChanges { target: searchField; highlighted: true }
3399+ AnchorChanges { target: textContainer; anchors.top: searchContainer.bottom }
3400+ AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
3401+ },
3402+ State {
3403+ name: "active"
3404+ extend: "wide"
3405+ PropertyChanges { target: searchContainer; width: units.gu(40) }
3406+ PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
3407+ PropertyChanges { target: searchField; highlighted: true }
3408+ },
3409+ State {
3410+ name: "inactive"
3411+ extend: "wide"
3412+ PropertyChanges { target: searchContainer; width: units.gu(25) }
3413+ PropertyChanges { target: primaryImage; source: "../Dash/graphics/icon_search_inactive.png" }
3414+ PropertyChanges { target: searchField; highlighted: false }
3415+ },
3416+ State {
3417+ name: "narrowActive"
3418+ extend: "narrow"
3419+ PropertyChanges { target: header; contentY: 0 }
3420+ PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
3421+ },
3422+ State {
3423+ name: "narrowInactive"
3424+ extend: "narrow"
3425+ PropertyChanges { target: header; contentY: header.height }
3426+ PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
3427+ }
3428+ ]
3429+
3430+ transitions: [
3431+ Transition {
3432+ to: "active"
3433+ SequentialAnimation {
3434+ ParallelAnimation {
3435+ NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
3436+ PropertyAction { target: primaryImage; property: "source" }
3437+ AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
3438+ }
3439+ ScriptAction { script: searchContainer.openPopover() }
3440+ }
3441+ },
3442+ Transition {
3443+ to: "inactive"
3444+ ScriptAction { script: searchContainer.closePopover() }
3445+ NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
3446+ AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
3447+ },
3448+ Transition {
3449+ to: "narrowActive"
3450+ SequentialAnimation {
3451+ ParallelAnimation {
3452+ NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
3453+ AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
3454+ }
3455+ ScriptAction { script: searchContainer.openPopover() }
3456+ }
3457+ },
3458+ Transition {
3459+ to: "narrowInactive"
3460+ ScriptAction { script: searchContainer.closePopover() }
3461+ NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
3462+ AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
3463+ }
3464+ ]
3465+
3466+ Component {
3467+ id: popoverComponent
3468+ Popover {
3469+ id: popover
3470+
3471+ // FIXME: this should go into the first item below, but enable: false
3472+ // prevents mouse events propagation
3473+ Button {
3474+ ItemStyle.class: "transparent-button"
3475+ anchors {
3476+ top: parent.top
3477+ right: parent.right
3478+ }
3479+ height: units.gu(6)
3480+ width: height
3481+
3482+ onClicked: searchContainer.closePopover()
3483+
3484+ Image {
3485+ anchors.centerIn: parent
3486+ width: units.gu(2)
3487+ height: units.gu(2)
3488+ source: "../Dash/graphics/icon_listview_clear.png"
3489+ }
3490+ }
3491+
3492+ Column {
3493+ anchors {
3494+ top: parent.top
3495+ left: parent.left
3496+ right: parent.right
3497+ }
3498+
3499+ ListItem.Standard { enabled: false; text: "Recent searches" }
3500+
3501+ Repeater {
3502+ id: recentSearches
3503+ model: shell.searchHistory
3504+
3505+ delegate: ListItem.Standard {
3506+ showDivider: index < recentSearches.count - 1
3507+ text: query
3508+ onClicked: {
3509+ shell.searchHistory.addQuery(text)
3510+ searchField.text = text
3511+ }
3512+ }
3513+ }
3514+ }
3515+ }
3516+ }
3517+
3518+ InverseMouseArea {
3519+ enabled: searchField.activeFocus
3520+
3521+ anchors {
3522+ top: parent.top
3523+ left: parent.left
3524+ right: parent.right
3525+ }
3526+
3527+ height: searchContainer.popover ? parent.height + searchContainer.popover.contentHeight + units.gu(2) : parent.height
3528+
3529+ onPressed: searchField.focus = false
3530+ }
3531+ }
3532+ }
3533+ }
3534+
3535+ BorderImage {
3536+ id: bottomBorder
3537+ anchors {
3538+ top: header.bottom
3539+ left: parent.left
3540+ right: parent.right
3541+ bottom: parent.bottom
3542+ }
3543+
3544+ source: "graphics/PageHeaderBaseDivider.sci"
3545+ }
3546+}
3547
3548=== added file 'Components/QuitResetDialog.qml'
3549--- Components/QuitResetDialog.qml 1970-01-01 00:00:00 +0000
3550+++ Components/QuitResetDialog.qml 2013-03-01 09:12:23 +0000
3551@@ -0,0 +1,99 @@
3552+/*
3553+ * Copyright (C) 2013 Canonical, Ltd.
3554+ *
3555+ * This program is free software; you can redistribute it and/or modify
3556+ * it under the terms of the GNU General Public License as published by
3557+ * the Free Software Foundation; version 3.
3558+ *
3559+ * This program is distributed in the hope that it will be useful,
3560+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3561+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3562+ * GNU General Public License for more details.
3563+ *
3564+ * You should have received a copy of the GNU General Public License
3565+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3566+ */
3567+
3568+import QtQuick 2.0
3569+import Ubuntu.Components 0.1
3570+
3571+Rectangle {
3572+ id: quitDialog
3573+
3574+ property real openedOpacity: 0.9
3575+
3576+ width: units.gu(40)
3577+ height: units.gu(71)
3578+ color: "black"
3579+ opacity: 0
3580+ visible: opacity != 0
3581+
3582+ Behavior on opacity {NumberAnimation {duration: 150}}
3583+
3584+ function hide() {
3585+ quitDialog.opacity = 0;
3586+ }
3587+
3588+ function show () {
3589+ quitDialog.opacity = openedOpacity
3590+ }
3591+
3592+ // eater
3593+ MouseArea {
3594+ visible: quitDialog.opacity > 0
3595+ anchors.fill: parent
3596+ }
3597+
3598+ Column {
3599+ anchors.centerIn: parent
3600+ spacing: units.gu(3)
3601+ Rectangle {
3602+ color: "transparent"
3603+ width: quitText.width + units.gu(1)
3604+ height: units.gu(4)
3605+ border.color: "white"
3606+ border.width: units.dp(1)
3607+ radius: units.gu(1)
3608+ anchors.horizontalCenter: parent.horizontalCenter
3609+ Label {
3610+ id: quitText
3611+ text: "Quit ?"
3612+ color: "white"
3613+ anchors.centerIn: parent
3614+ fontSize: "medium"
3615+ }
3616+ MouseArea {
3617+ enabled: quitDialog.opacity > openedOpacity / 2
3618+ anchors.fill: parent
3619+ anchors.margins: -units.gu(1)
3620+ onClicked: {
3621+ Qt.quit()
3622+ }
3623+ }
3624+ }
3625+ Rectangle {
3626+ color: "transparent"
3627+ width: cancelText.width + units.gu(1)
3628+ height: units.gu(4)
3629+ border.color: "white"
3630+ border.width: units.dp(1)
3631+ radius: units.gu(1)
3632+ anchors.horizontalCenter: parent.horizontalCenter
3633+ Label {
3634+ id: cancelText
3635+ text: "Cancel ?"
3636+ color: "white"
3637+ anchors.centerIn: parent
3638+ fontSize: "medium"
3639+ }
3640+ MouseArea {
3641+ enabled: quitDialog.opacity > openedOpacity / 2
3642+ anchors.fill: parent
3643+ anchors.margins: -units.gu(1)
3644+ onClicked: {
3645+ quitDialog.hide();
3646+ }
3647+ }
3648+ }
3649+ }
3650+}
3651
3652=== added file 'Components/RatingStars.qml'
3653--- Components/RatingStars.qml 1970-01-01 00:00:00 +0000
3654+++ Components/RatingStars.qml 2013-03-01 09:12:23 +0000
3655@@ -0,0 +1,42 @@
3656+/*
3657+ * Copyright (C) 2013 Canonical, Ltd.
3658+ *
3659+ * This program is free software; you can redistribute it and/or modify
3660+ * it under the terms of the GNU General Public License as published by
3661+ * the Free Software Foundation; version 3.
3662+ *
3663+ * This program is distributed in the hope that it will be useful,
3664+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3665+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3666+ * GNU General Public License for more details.
3667+ *
3668+ * You should have received a copy of the GNU General Public License
3669+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3670+ */
3671+
3672+import QtQuick 2.0
3673+
3674+Row {
3675+ id: root
3676+ property int rating
3677+ property int maximumRating: 5
3678+ property int starCount: 5
3679+ height: childrenRect.height
3680+ width: childrenRect.width
3681+
3682+ readonly property int effectiveRating: Math.min(root.starCount * root.rating / root.maximumRating, root.maximumRating)
3683+
3684+ Repeater {
3685+ model: root.effectiveRating
3686+ Image {
3687+ source: "graphics/icon_star_on.png"
3688+ }
3689+ }
3690+ Repeater {
3691+ model: root.starCount - root.effectiveRating
3692+ Image {
3693+ source: "graphics/icon_star_off.png"
3694+ }
3695+ }
3696+}
3697+
3698
3699=== added file 'Components/ResponsiveFlowView.qml'
3700--- Components/ResponsiveFlowView.qml 1970-01-01 00:00:00 +0000
3701+++ Components/ResponsiveFlowView.qml 2013-03-01 09:12:23 +0000
3702@@ -0,0 +1,62 @@
3703+import QtQuick 2.0
3704+import Ubuntu.Components 0.1
3705+
3706+Item {
3707+ id: root
3708+
3709+ property int minimumHorizontalSpacing: units.gu(0.5)
3710+ // property int minimumNumberOfColumns: 2 // FIXME: not implemented
3711+ property int maximumNumberOfColumns: 6
3712+ readonly property int columns: flow.columns
3713+ property alias verticalSpacing: flow.verticalSpacing
3714+ property alias horizontalSpacing: flow.horizontalSpacing
3715+ property int referenceDelegateWidth
3716+ property alias firstModel: repeater1.model
3717+ property alias secondModel: repeater2.model
3718+ property alias delegate: repeater1.delegate
3719+
3720+ height: flow.height + flow.anchors.topMargin
3721+
3722+ Flow {
3723+ id: flow
3724+ anchors {
3725+ left: parent.left
3726+ right: parent.right
3727+ top: parent.top
3728+ leftMargin: margin/2
3729+ rightMargin: margin/2
3730+ topMargin: verticalSpacing
3731+ }
3732+
3733+ function pixelToGU(value) {
3734+ return Math.floor(value / units.gu(1));
3735+ }
3736+
3737+ function spacingForColumns(columns) {
3738+ // spacing between columns as an integer number of GU, the remainder goes in the margins
3739+ var spacingGU = pixelToGU(allocatableVerticalSpace / columns);
3740+ return units.gu(spacingGU);
3741+ }
3742+
3743+ function columnsForSpacing(space) {
3744+ // minimum margin is half of the spacing
3745+ return Math.floor((parent.width - space/2) / (referenceDelegateWidth + space));
3746+ }
3747+
3748+ property real allocatableVerticalSpace: parent.width - columns * referenceDelegateWidth
3749+ property int columns: Math.min(columnsForSpacing(minimumHorizontalSpacing), maximumNumberOfColumns)
3750+ property real horizontalSpacing: spacingForColumns(columns)
3751+ property real verticalSpacing: horizontalSpacing
3752+ property int margin: allocatableVerticalSpace - columns * horizontalSpacing
3753+
3754+ Repeater {
3755+ id: repeater1
3756+ model: (root.model) ? root.model[0] : null
3757+ }
3758+ Repeater {
3759+ id: repeater2
3760+ model: (root.model) ? root.model[1] : null
3761+ delegate: repeater1.delegate
3762+ }
3763+ }
3764+}
3765
3766=== added file 'Components/ResponsiveGridView.qml'
3767--- Components/ResponsiveGridView.qml 1970-01-01 00:00:00 +0000
3768+++ Components/ResponsiveGridView.qml 2013-03-01 09:12:23 +0000
3769@@ -0,0 +1,69 @@
3770+/*
3771+ * Copyright (C) 2013 Canonical, Ltd.
3772+ *
3773+ * This program is free software; you can redistribute it and/or modify
3774+ * it under the terms of the GNU General Public License as published by
3775+ * the Free Software Foundation; version 3.
3776+ *
3777+ * This program is distributed in the hope that it will be useful,
3778+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3779+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3780+ * GNU General Public License for more details.
3781+ *
3782+ * You should have received a copy of the GNU General Public License
3783+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3784+ */
3785+
3786+import QtQuick 2.0
3787+import Ubuntu.Components 0.1
3788+
3789+Item {
3790+ property int minimumHorizontalSpacing: units.gu(0.5)
3791+ // property int minimumNumberOfColumns: 2 // FIXME: not implemented
3792+ property int maximumNumberOfColumns: 6
3793+ readonly property int columns: gridView.columns
3794+ property alias verticalSpacing: gridView.verticalSpacing
3795+ property int delegateWidth
3796+ property int delegateHeight
3797+ property alias model: gridView.model
3798+ property alias delegate: gridView.delegate
3799+ readonly property int cellWidth: gridView.cellWidth
3800+ readonly property int cellHeight: gridView.cellHeight
3801+ readonly property int totalContentHeight: Math.ceil(gridView.model.count / columns) * cellHeight + verticalSpacing
3802+ property alias interactive: gridView.interactive
3803+
3804+ GridView {
3805+ id: gridView
3806+ anchors {
3807+ fill: parent
3808+ leftMargin: margin/2
3809+ rightMargin: margin/2
3810+ topMargin: verticalSpacing
3811+ }
3812+ clip: parent.height != totalContentHeight
3813+
3814+ function pixelToGU(value) {
3815+ return Math.floor(value / units.gu(1));
3816+ }
3817+
3818+ function spacingForColumns(columns) {
3819+ // spacing between columns as an integer number of GU, the remainder goes in the margins
3820+ var spacingGU = pixelToGU(allocatableVerticalSpace / columns);
3821+ return units.gu(spacingGU);
3822+ }
3823+
3824+ function columnsForSpacing(spacing) {
3825+ // minimum margin is half of the spacing
3826+ return Math.floor((parent.width - spacing/2) / (delegateWidth + spacing));
3827+ }
3828+
3829+ property real allocatableVerticalSpace: parent.width - columns * delegateWidth
3830+ property int columns: Math.min(columnsForSpacing(minimumHorizontalSpacing), maximumNumberOfColumns)
3831+ property real horizontalSpacing: spacingForColumns(columns)
3832+ property real verticalSpacing: horizontalSpacing
3833+ property int margin: allocatableVerticalSpace - columns * horizontalSpacing
3834+
3835+ cellWidth: delegateWidth + horizontalSpacing
3836+ cellHeight: delegateHeight + verticalSpacing
3837+ }
3838+}
3839
3840=== added file 'Components/Revealer.qml'
3841--- Components/Revealer.qml 1970-01-01 00:00:00 +0000
3842+++ Components/Revealer.qml 2013-03-01 09:12:23 +0000
3843@@ -0,0 +1,232 @@
3844+/*
3845+ * Copyright (C) 2013 Canonical, Ltd.
3846+ *
3847+ * This program is free software; you can redistribute it and/or modify
3848+ * it under the terms of the GNU General Public License as published by
3849+ * the Free Software Foundation; version 3.
3850+ *
3851+ * This program is distributed in the hope that it will be useful,
3852+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3853+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3854+ * GNU General Public License for more details.
3855+ *
3856+ * You should have received a copy of the GNU General Public License
3857+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3858+ */
3859+
3860+import QtQuick 2.0
3861+import Ubuntu.Components 0.1
3862+import "Math.js" as MathLocal
3863+
3864+Item {
3865+ id: revealer
3866+
3867+ property Showable target
3868+ property var hintingAnimation: hintingAnimation
3869+ property string boundProperty: orientation == Qt.Vertical ? "y" : "x"
3870+ property int orientation: Qt.Vertical
3871+ property int direction: Qt.LeftToRight
3872+ property real openedValue: orientation == Qt.Vertical ? y : x
3873+ property real closedValue: orientation == Qt.Vertical ? y + (direction == Qt.LeftToRight ? -height : height) : x + (direction == Qt.LeftToRight ? -width : width)
3874+ property real hintDisplacement: 0
3875+ property real handleSize: units.gu(2)
3876+ property real dragVelocity: draggingArea.dragVelocity != 0 ? Math.abs(draggingArea.dragVelocity) : -1
3877+ property real dragVelocityThreshold: units.gu(5)
3878+ property bool dragging: false
3879+ property bool pressed: draggingArea.pressed
3880+ property int lateralPosition: draggingArea.lateralPosition
3881+ property real dragPosition
3882+ property bool openOnPress: true
3883+
3884+ signal openPressed(int mouseX, int mouseY)
3885+ signal openReleased(int mouseX, int mouseY)
3886+ signal closePressed
3887+ signal openClicked
3888+ signal closeClicked
3889+
3890+ dragPosition: {
3891+ var value
3892+ if (orientation == Qt.Vertical) {
3893+ value = draggingArea.dragValue + draggingArea.y
3894+ if (direction == Qt.RightToLeft) {
3895+ value += draggingArea.height - height
3896+ }
3897+ } else {
3898+ value = draggingArea.dragValue + draggingArea.x
3899+ if (direction == Qt.RightToLeft) {
3900+ value += draggingArea.width - width
3901+ }
3902+ }
3903+ if (__opened) {
3904+ if (direction == Qt.LeftToRight) {
3905+ value += handleSize
3906+ } else {
3907+ value -= handleSize
3908+ }
3909+ } else if (dragging) {
3910+ if (direction == Qt.LeftToRight) {
3911+ value += hintDisplacement
3912+ } else {
3913+ value -= hintDisplacement
3914+ }
3915+ }
3916+
3917+ return value
3918+ }
3919+ property var draggingArea: leftDraggingArea.enabled ? leftDraggingArea : rightDraggingArea
3920+
3921+ property real __hintValue: closedValue + (direction == Qt.LeftToRight ? hintDisplacement : -hintDisplacement)
3922+
3923+ function dragToValue(dragPosition) {
3924+ return dragPosition + closedValue
3925+ }
3926+
3927+ property bool __opened: target.shown
3928+ enabled: target.available
3929+
3930+ Component.onCompleted: target[boundProperty] = __opened ? openedValue : closedValue
3931+ onOpenedValueChanged: if (__opened && !dragging) target[boundProperty] = openedValue
3932+ onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
3933+
3934+ function __computeValue(dragPosition) {
3935+ return MathLocal.clamp(dragToValue(dragPosition), __hintValue, openedValue)
3936+ }
3937+
3938+ function __open() {
3939+ hintingAnimation.stop()
3940+ target.show()
3941+ }
3942+
3943+ function __close() {
3944+ hintingAnimation.stop()
3945+ target.hide()
3946+ }
3947+
3948+ function __hint() {
3949+ target.showAnimation.stop()
3950+ target.hideAnimation.stop()
3951+ hintingAnimation.restart()
3952+ }
3953+
3954+ function __settle() {
3955+ hintingAnimation.stop()
3956+ if (__opened) target.show()
3957+ else target.hide()
3958+ }
3959+
3960+ function __startDragging() {
3961+ hintingAnimation.stop()
3962+ dragging = true
3963+ }
3964+
3965+ function __endDragging(dragVelocity) {
3966+ dragging = false
3967+ if (revealer.direction == Qt.RightToLeft) {
3968+ dragVelocity = -dragVelocity
3969+ }
3970+ if (Math.abs(dragVelocity) >= dragVelocityThreshold) {
3971+ if (dragVelocity > 0) __open()
3972+ else __close()
3973+ } else {
3974+ __settle()
3975+ }
3976+ }
3977+
3978+ Binding {
3979+ id: dragBinding
3980+
3981+ target: revealer.target
3982+ property: revealer.boundProperty
3983+ value: __computeValue(dragPosition)
3984+ when: dragging
3985+ }
3986+
3987+ SmoothedAnimation {
3988+ id: hintingAnimation
3989+
3990+ target: revealer.target
3991+ property: revealer.boundProperty
3992+ duration: 150
3993+ to: revealer.__hintValue
3994+ }
3995+
3996+ DraggingArea {
3997+ id: leftDraggingArea
3998+
3999+ property bool isOpeningArea: revealer.direction == Qt.LeftToRight
4000+
4001+ height: orientation == Qt.Vertical ? handleSize : parent.height
4002+ width: orientation == Qt.Horizontal ? handleSize : parent.width
4003+ orientation: revealer.orientation
4004+ enabled: isOpeningArea ? !revealer.__opened : revealer.__opened
4005+
4006+ onPressed: {
4007+ if (isOpeningArea) {
4008+ if (revealer.openOnPress) {
4009+ revealer.openPressed(mouseX, mouseY)
4010+ __hint()
4011+ }
4012+ } else {
4013+ revealer.closePressed()
4014+ }
4015+ }
4016+ onReleased: {
4017+ if (isOpeningArea && revealer.openOnPress) {
4018+ revealer.openReleased(mouseX, mouseY)
4019+ __settle()
4020+ }
4021+ }
4022+ onDragStart: __startDragging()
4023+ onDragEnd: __endDragging(dragVelocity)
4024+ onClicked: {
4025+ if (clickValidated) {
4026+ if (isOpeningArea) {
4027+ if (revealer.openOnPress) revealer.openClicked()
4028+ } else {
4029+ revealer.closeClicked()
4030+ }
4031+ }
4032+ }
4033+ }
4034+
4035+ DraggingArea {
4036+ id: rightDraggingArea
4037+
4038+ property bool isOpeningArea: revealer.direction == Qt.RightToLeft
4039+
4040+ x: orientation == Qt.Vertical ? 0 : parent.width - width
4041+ y: orientation == Qt.Vertical ? parent.height - height : 0
4042+ height: orientation == Qt.Vertical ? handleSize : parent.height
4043+ width: orientation == Qt.Horizontal ? handleSize : parent.width
4044+ orientation: revealer.orientation
4045+ enabled: isOpeningArea ? !revealer.__opened : revealer.__opened
4046+
4047+ onPressed: {
4048+ if (isOpeningArea) {
4049+ if (revealer.openOnPress) {
4050+ revealer.openPressed(mouseX, mouseY)
4051+ __hint()
4052+ }
4053+ } else {
4054+ revealer.closePressed()
4055+ }
4056+ }
4057+ onReleased: {
4058+ if (isOpeningArea && revealer.openOnPress) {
4059+ revealer.openReleased(mouseX, mouseY)
4060+ __settle()
4061+ }
4062+ }
4063+ onDragStart: __startDragging()
4064+ onDragEnd: __endDragging(dragVelocity)
4065+ onClicked: {
4066+ if (clickValidated) {
4067+ if (isOpeningArea) {
4068+ if (revealer.openOnPress) revealer.openClicked()
4069+ } else {
4070+ revealer.closeClicked()
4071+ }
4072+ }
4073+ }
4074+ }
4075+}
4076
4077=== added file 'Components/RevealingRectangle.qml'
4078--- Components/RevealingRectangle.qml 1970-01-01 00:00:00 +0000
4079+++ Components/RevealingRectangle.qml 2013-03-01 09:12:23 +0000
4080@@ -0,0 +1,75 @@
4081+/*
4082+ * Copyright (C) 2013 Canonical, Ltd.
4083+ *
4084+ * This program is free software; you can redistribute it and/or modify
4085+ * it under the terms of the GNU General Public License as published by
4086+ * the Free Software Foundation; version 3.
4087+ *
4088+ * This program is distributed in the hope that it will be useful,
4089+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4090+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4091+ * GNU General Public License for more details.
4092+ *
4093+ * You should have received a copy of the GNU General Public License
4094+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4095+ */
4096+
4097+import QtQuick 2.0
4098+import Ubuntu.Components 0.1
4099+
4100+Item {
4101+ id: revealingRectangle
4102+
4103+ property int orientation: Qt.Vertical
4104+ property int direction: Qt.LeftToRight
4105+
4106+ Revealer {
4107+ id: revealer
4108+
4109+ target: showable
4110+ width: target.width
4111+ height: target.height
4112+ x: orientation == Qt.Vertical ? 0 : direction == Qt.LeftToRight ? 0 : parent.width - width
4113+ y: orientation == Qt.Horizontal ? 0 : direction == Qt.LeftToRight ? 0 : parent.height - height
4114+ handleSize: orientation == Qt.Vertical ? handle.height : handle.width
4115+ hintDisplacement: handleSize
4116+ orientation: revealingRectangle.orientation
4117+ direction: revealingRectangle.direction
4118+ }
4119+
4120+ Showable {
4121+ id: showable
4122+
4123+ width: orientation == Qt.Horizontal ? units.gu(13) : parent.width
4124+ height: orientation == Qt.Vertical ? units.gu(13) : parent.height
4125+
4126+ shown: false
4127+ showAnimation: SmoothedAnimation {
4128+ property: orientation == Qt.Horizontal ? "x" : "y"
4129+ velocity: revealer.dragVelocity
4130+ duration: 200
4131+ to: revealer.openedValue
4132+ }
4133+ hideAnimation: SmoothedAnimation {
4134+ property: orientation == Qt.Horizontal ? "x" : "y"
4135+ velocity: revealer.dragVelocity
4136+ duration: 200
4137+ to: revealer.closedValue
4138+ }
4139+
4140+ Rectangle {
4141+ anchors.fill: parent
4142+ color: "red"
4143+ }
4144+
4145+ Rectangle {
4146+ id: handle
4147+
4148+ x: orientation == Qt.Vertical ? 0 : direction == Qt.LeftToRight ? parent.width - width : 0
4149+ y: orientation == Qt.Horizontal ? 0 : direction == Qt.LeftToRight ? parent.height - height : 0
4150+ width: orientation == Qt.Horizontal ? units.gu(2) : parent.width
4151+ height: orientation == Qt.Vertical ? units.gu(2) : parent.height
4152+ color: "black"
4153+ }
4154+ }
4155+}
4156
4157=== added file 'Components/Showable.qml'
4158--- Components/Showable.qml 1970-01-01 00:00:00 +0000
4159+++ Components/Showable.qml 2013-03-01 09:12:23 +0000
4160@@ -0,0 +1,124 @@
4161+/*
4162+ * Copyright (C) 2013 Canonical, Ltd.
4163+ *
4164+ * This program is free software; you can redistribute it and/or modify
4165+ * it under the terms of the GNU General Public License as published by
4166+ * the Free Software Foundation; version 3.
4167+ *
4168+ * This program is distributed in the hope that it will be useful,
4169+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4170+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4171+ * GNU General Public License for more details.
4172+ *
4173+ * You should have received a copy of the GNU General Public License
4174+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4175+ */
4176+
4177+import QtQuick 2.0
4178+
4179+Item {
4180+ id: showable
4181+
4182+ property bool available: true
4183+ property bool shown: true
4184+
4185+ /* If your showable supports on demand content creation/destruction,
4186+ set this to false when destroyed and true when ready to be shown.
4187+ NOTE: You should load your content when "required" is true and
4188+ destroy when "required" is false
4189+ */
4190+ property bool created: true
4191+ property bool required
4192+ property bool __shouldShow: false
4193+
4194+ property list<QtObject> hides
4195+ property var showAnimation
4196+ property var hideAnimation
4197+
4198+ // automatically set the target on showAnimation and hideAnimation to be the
4199+ // showable itself
4200+ onShowAnimationChanged: if (showAnimation) showAnimation["target"] = showable
4201+ onHideAnimationChanged: if (hideAnimation) hideAnimation["target"] = showable
4202+
4203+ Component.onCompleted: required = shown;
4204+
4205+ function __hideOthers() {
4206+ var i
4207+ for (i=0; i<hides.length; i++) {
4208+ hides[i].hide()
4209+ }
4210+ }
4211+
4212+ function show() {
4213+ required = true;
4214+ if (created) {
4215+ __reallyShow(true);
4216+ } else {
4217+ __shouldShow = true;
4218+ }
4219+ }
4220+
4221+ onCreatedChanged: {
4222+ if (created && __shouldShow) {
4223+ __reallyShow(true);
4224+ __shouldShow = false;
4225+ }
4226+ }
4227+
4228+ function showWithoutAnimation() {
4229+ __reallyShow(false);
4230+ }
4231+
4232+ function __reallyShow(animated) {
4233+ if (!available) {
4234+ return false;
4235+ }
4236+
4237+ __hideOthers();
4238+
4239+ if (hideAnimation != undefined && hideAnimation.running) {
4240+ hideAnimation.stop();
4241+ }
4242+
4243+ if (showAnimation != undefined) {
4244+ if (animated) {
4245+ if (!showAnimation.running) {
4246+ showAnimation.restart()
4247+ }
4248+ } else {
4249+ showAnimation.start();
4250+ showAnimation.complete();
4251+ }
4252+ } else {
4253+ visible = true;
4254+ }
4255+
4256+ shown = true;
4257+ return true;
4258+ }
4259+
4260+ function hide() {
4261+ if (showAnimation != undefined && showAnimation.running) {
4262+ showAnimation.stop()
4263+ }
4264+ if (hideAnimation != undefined) {
4265+ if (!hideAnimation.running) {
4266+ hideAnimation.restart()
4267+ }
4268+ } else {
4269+ visible = false
4270+ required = false
4271+ }
4272+
4273+ shown = false
4274+ }
4275+
4276+ Connections {
4277+ target: hideAnimation ? hideAnimation: null
4278+ onRunningChanged: {
4279+ if (!hideAnimation.running) {
4280+ required = false;
4281+ }
4282+ }
4283+ }
4284+}
4285
4286=== added file 'Components/Stage.qml'
4287--- Components/Stage.qml 1970-01-01 00:00:00 +0000
4288+++ Components/Stage.qml 2013-03-01 09:12:23 +0000
4289@@ -0,0 +1,481 @@
4290+/*
4291+ * Copyright (C) 2013 Canonical, Ltd.
4292+ *
4293+ * This program is free software; you can redistribute it and/or modify
4294+ * it under the terms of the GNU General Public License as published by
4295+ * the Free Software Foundation; version 3.
4296+ *
4297+ * This program is distributed in the hope that it will be useful,
4298+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4299+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4300+ * GNU General Public License for more details.
4301+ *
4302+ * You should have received a copy of the GNU General Public License
4303+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4304+ */
4305+
4306+import QtQuick 2.0
4307+import Ubuntu.Components 0.1
4308+import "../Applications/applications.js" as ApplicationsModel
4309+
4310+Showable {
4311+ id: stage
4312+
4313+ width: units.gu(40)
4314+ height: units.gu(71)
4315+
4316+ property int type: ApplicationsModel.MainStage
4317+ property var applications: type == ApplicationsModel.MainStage ? shell.applicationManager.mainStageApplications
4318+ : shell.applicationManager.sideStageApplications
4319+ property bool fullyShown: false
4320+ property var focusedApplication: type == ApplicationsModel.MainStage ? shell.applicationManager.mainStageFocusedApplication
4321+ : shell.applicationManager.sideStageFocusedApplication
4322+ property bool shouldUseScreenshots: true
4323+ property bool usingScreenshots: {
4324+ if (newApplicationScreenshot.application != null && oldApplicationScreenshot.application != null) {
4325+ return newApplicationScreenshot.ready && oldApplicationScreenshot.ready;
4326+ } else {
4327+ return newApplicationScreenshot.ready || oldApplicationScreenshot.ready;
4328+ }
4329+ }
4330+
4331+ property bool rightEdgeEnabled: true
4332+ property bool switchingFromFullscreenToFullscreen: false
4333+
4334+ function activateApplication(desktopFile) {
4335+ var application = shell.applicationManager.getApplicationFromDesktopFile(desktopFile, stage.type);
4336+ if (application != null && application == stage.focusedApplication) {
4337+ stage.show();
4338+ return;
4339+ }
4340+
4341+ showStartingApplicationAnimation.prepare(application);
4342+ if (!stage.fullyShown) {
4343+ stage.show();
4344+ } else {
4345+ showStartingApplicationAnimation.start();
4346+ }
4347+
4348+ if (application == null) {
4349+ stage.__startingApplicationDesktopFile = desktopFile;
4350+ }
4351+ }
4352+
4353+ /* Keep a reference to the focused application so that we can safely
4354+ unfocus it when the stage is not fully shown and refocus it when the stage
4355+ is fully shown again.
4356+ */
4357+ property var focusedApplicationWhenUsingScreenshots
4358+ onShouldUseScreenshotsChanged: {
4359+ if (showStartingApplicationAnimation.running || switchToApplicationAnimation.running) {
4360+ return;
4361+ }
4362+
4363+ if (shouldUseScreenshots) {
4364+ stage.__focusApplicationUsingScreenshots(stage.focusedApplication);
4365+ } else {
4366+ stage.__focusActualApplication(stage.focusedApplicationWhenUsingScreenshots);
4367+ }
4368+ }
4369+
4370+
4371+ ApplicationScreenshot {
4372+ id: newApplicationScreenshot
4373+ width: parent.width
4374+ height: parent.height - y
4375+ }
4376+
4377+ ApplicationScreenshot {
4378+ id: oldApplicationScreenshot
4379+ width: parent.width
4380+ height: parent.height - y
4381+ }
4382+
4383+ function __getApplicationIndex(application) {
4384+ for (var i = 0; i < stage.applications.count; i++ ) {
4385+ if (stage.applications.get(i) == application) {
4386+ return i
4387+ }
4388+ }
4389+ return -1
4390+ }
4391+
4392+
4393+ property string __startingApplicationDesktopFile
4394+
4395+ Timer {
4396+ id: delayedHideScreenshots
4397+ interval: 150
4398+ onTriggered: {
4399+ __hideScreenshots();
4400+ }
4401+ }
4402+
4403+ function __hideScreenshots() {
4404+ newApplicationScreenshot.clearApplication();
4405+ oldApplicationScreenshot.clearApplication();
4406+ newApplicationScreenshot.visible = false;
4407+ oldApplicationScreenshot.visible = false;
4408+ }
4409+
4410+ function __focusApplication(application) {
4411+ if (shouldUseScreenshots) {
4412+ stage.__focusApplicationUsingScreenshots(application);
4413+ } else {
4414+ stage.__focusActualApplication(application);
4415+ }
4416+ }
4417+
4418+
4419+ function __focusActualApplication(application) {
4420+ if (application == null) {
4421+ return;
4422+ }
4423+
4424+ if (stage.focusedApplication == application) {
4425+ /* FIXME: this case is reached when showing the sidestage, we
4426+ need to refocus the side stage app in order to show it.
4427+ FIXME: this case is reached when doing a right edge swipe
4428+ while in the dash to bring back the stage.
4429+ FIXME: this case is reached when showStartingApplicationAnimation
4430+ finishes after the newly started application has been focused
4431+ automatically by the ApplicationManager.
4432+ */
4433+ if (stage.type == ApplicationsModel.SideStage) {
4434+ shell.applicationManager.focusApplication(application);
4435+ }
4436+ if (!delayedHideScreenshots.running) {
4437+ stage.__hideScreenshots();
4438+ }
4439+ } else {
4440+ /* FIXME: calling ApplicationManager::focusApplication does not focus
4441+ the application immediately nor show the application's surface
4442+ immediately. Delay hiding the screenshots until it has done so.
4443+ */
4444+ delayedHideScreenshots.stop();
4445+ shell.applicationManager.focusApplication(application);
4446+ }
4447+ stage.focusedApplicationWhenUsingScreenshots = null;
4448+ }
4449+
4450+ function __focusApplicationUsingScreenshots(application) {
4451+ delayedHideScreenshots.stop();
4452+ if (application == null) {
4453+ return;
4454+ }
4455+
4456+ if (newApplicationScreenshot.application != null) {
4457+ stage.focusedApplicationWhenUsingScreenshots = application;
4458+ return;
4459+ }
4460+
4461+ newApplicationScreenshot.setApplication(application);
4462+ newApplicationScreenshot.scheduleUpdate();
4463+ newApplicationScreenshot.opacity = 1.0;
4464+ newApplicationScreenshot.x = 0.0;
4465+ newApplicationScreenshot.y = __getApplicationY(application);
4466+ newApplicationScreenshot.scale = 1.0;
4467+ newApplicationScreenshot.visible = true;
4468+ stage.focusedApplicationWhenUsingScreenshots = application;
4469+ stage.switchingFromFullscreenToFullscreen = false;
4470+ }
4471+
4472+ function __getApplicationY(application) {
4473+ return Qt.binding( function(){
4474+ return (application && application.fullscreen
4475+ && application.stage !== ApplicationsModel.SideStage) ? 0 : shell.panelHeight;
4476+ } )
4477+ }
4478+
4479+ /* FIXME: should hide the screenshots when the focused application's surface
4480+ is visible. There is no API in QtUbuntu to support that yet.
4481+ */
4482+ Connections {
4483+ target: stage
4484+ onFocusedApplicationChanged: {
4485+ if (stage.focusedApplication != null) {
4486+ /* Move application to the beginning of the list of running applications */
4487+ var index = stage.__getApplicationIndex(stage.focusedApplication);
4488+ shell.applicationManager.moveRunningApplicationStackPosition(index, 0, stage.type);
4489+
4490+ var startingApplication = shell.applicationManager.getApplicationFromDesktopFile(stage.__startingApplicationDesktopFile, stage.type);
4491+ if (stage.focusedApplication == startingApplication) {
4492+ stage.__startingApplicationDesktopFile = "";
4493+
4494+ /* Screenshots might still be in use at this point and their
4495+ use can be stopped before delayedHideScreenshots is complete.
4496+ Prepare for that case by setting appropriately
4497+ stage.focusedApplicationWhenUsingScreenshots.
4498+ */
4499+ stage.focusedApplicationWhenUsingScreenshots = stage.focusedApplication;
4500+
4501+ /* FIXME: should hide the screenshots when the focused application's window
4502+ is visible. There is no API in qtubuntu to support that yet. Therefore
4503+ we delay their hiding to avoid a state where neither the screenshot nor
4504+ the application's window is visible.
4505+ */
4506+ delayedHideScreenshots.start();
4507+ } else {
4508+ stage.__hideScreenshots();
4509+ }
4510+ }
4511+ }
4512+ }
4513+
4514+
4515+ SequentialAnimation {
4516+ id: showStartingApplicationAnimation
4517+
4518+ function prepare(newApplication) {
4519+ var oldApplication = stage.focusedApplication;
4520+ newApplicationScreenshot.setApplication(newApplication);
4521+ newApplicationScreenshot.updateFromCache();
4522+ oldApplicationScreenshot.setApplication(oldApplication);
4523+ oldApplicationScreenshot.scheduleUpdate();
4524+ newApplicationScreenshot.withBackground = (newApplication == null);
4525+ newApplicationScreenshot.y = __getApplicationY(newApplication);
4526+ oldApplicationScreenshot.y = __getApplicationY(oldApplication);
4527+ stage.focusedApplicationWhenUsingScreenshots = newApplication;
4528+ stage.switchingFromFullscreenToFullscreen = false;
4529+ }
4530+
4531+ PropertyAction {target: newApplicationScreenshot; property: "visible"; value: false}
4532+ PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: false}
4533+ PropertyAction {target: newApplicationScreenshot; property: "z"; value: 0}
4534+ PropertyAction {target: oldApplicationScreenshot; property: "z"; value: 1}
4535+ PropertyAction {target: newApplicationScreenshot; property: "scale"; value: 0.8}
4536+ PropertyAction {target: oldApplicationScreenshot; property: "scale"; value: 1.0}
4537+ PropertyAction {target: newApplicationScreenshot; property: "opacity"; value: 0.0}
4538+ PropertyAction {target: oldApplicationScreenshot; property: "opacity"; value: 1.0}
4539+ PropertyAction {target: newApplicationScreenshot; property: "x"; value: 0.0}
4540+ PropertyAction {target: oldApplicationScreenshot; property: "x"; value: 0.0}
4541+
4542+ ParallelAnimation {
4543+ PropertyAction {target: newApplicationScreenshot; property: "visible"; value: true}
4544+ NumberAnimation {
4545+ target: newApplicationScreenshot
4546+ property: "scale"
4547+ duration: 500
4548+ easing.type: Easing.OutQuad
4549+ to: 1.0
4550+ }
4551+ NumberAnimation {
4552+ target: newApplicationScreenshot
4553+ property: "opacity"
4554+ duration: 500
4555+ easing.type: Easing.OutQuad
4556+ to: 1.0
4557+ }
4558+
4559+ PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: true}
4560+
4561+ NumberAnimation {
4562+ target: oldApplicationScreenshot
4563+ property: "x"
4564+ duration: 400
4565+ easing.type: Easing.OutQuad
4566+ to: stage.width
4567+ }
4568+ }
4569+
4570+ ScriptAction {
4571+ script: {
4572+ if (!stage.focusedApplicationWhenUsingScreenshots) {
4573+ // FIXME: only here to support case where application does
4574+ // not exist yet but is about to
4575+ return;
4576+ }
4577+
4578+ stage.__focusApplication(stage.focusedApplicationWhenUsingScreenshots);
4579+ }
4580+ }
4581+ }
4582+
4583+
4584+ SequentialAnimation {
4585+ id: switchToApplicationAnimation
4586+
4587+ function prepare(newApplication) {
4588+ var oldApplication = stage.focusedApplication;
4589+ newApplicationScreenshot.setApplication(newApplication);
4590+ newApplicationScreenshot.updateFromCache();
4591+ oldApplicationScreenshot.setApplication(oldApplication);
4592+ oldApplicationScreenshot.scheduleUpdate();
4593+ newApplicationScreenshot.withBackground = false;
4594+ newApplicationScreenshot.y = __getApplicationY(newApplication);
4595+ oldApplicationScreenshot.y = __getApplicationY(oldApplication);
4596+ stage.focusedApplicationWhenUsingScreenshots = newApplication;
4597+ stage.switchingFromFullscreenToFullscreen = newApplication && newApplication.fullscreen;
4598+ }
4599+
4600+ PropertyAction {target: newApplicationScreenshot; property: "visible"; value: false}
4601+ PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: false}
4602+ PropertyAction {target: newApplicationScreenshot; property: "z"; value: 1}
4603+ PropertyAction {target: oldApplicationScreenshot; property: "z"; value: 0}
4604+ PropertyAction {target: newApplicationScreenshot; property: "scale"; value: 1.0}
4605+ PropertyAction {target: oldApplicationScreenshot; property: "scale"; value: 1.0}
4606+ PropertyAction {target: newApplicationScreenshot; property: "opacity"; value: 1.0}
4607+ PropertyAction {target: oldApplicationScreenshot; property: "opacity"; value: 1.0}
4608+ PropertyAction {target: newApplicationScreenshot; property: "x"; value: stage.width}
4609+ PropertyAction {target: oldApplicationScreenshot; property: "x"; value: 0.0}
4610+ PropertyAction {target: newApplicationScreenshot; property: "visible"; value: true}
4611+ PropertyAction {target: oldApplicationScreenshot; property: "visible"; value: true}
4612+
4613+ ParallelAnimation {
4614+ NumberAnimation {
4615+ target: oldApplicationScreenshot
4616+ property: "scale"
4617+ duration: 500
4618+ easing.type: Easing.OutQuad
4619+ to: 0.8
4620+ }
4621+ NumberAnimation {
4622+ target: oldApplicationScreenshot
4623+ property: "opacity"
4624+ duration: 500
4625+ easing.type: Easing.OutQuad
4626+ to: 0.0
4627+ }
4628+
4629+ NumberAnimation {
4630+ target: newApplicationScreenshot
4631+ property: "x"
4632+ duration: 400
4633+ easing.type: Easing.OutQuad
4634+ to: 0
4635+ }
4636+ }
4637+
4638+ ScriptAction {
4639+ script: {
4640+ // move previously focused application to the end of the list of running applications
4641+ var oldApplication = oldApplicationScreenshot.application;
4642+ if (oldApplication != null) {
4643+ var oldApplicationIndex = stage.__getApplicationIndex(oldApplicationScreenshot.application);
4644+ shell.applicationManager.moveRunningApplicationStackPosition(oldApplicationIndex, stage.applications.count - 1, stage.type);
4645+ }
4646+
4647+ stage.__focusApplication(stage.focusedApplicationWhenUsingScreenshots);
4648+ }
4649+ }
4650+ }
4651+
4652+
4653+ function __dragValueToProgress(dragValue, startValue, applicationsCount) {
4654+ if (applicationsCount == 0) {
4655+ return 0;
4656+ } else if (applicationsCount == 1) {
4657+ // prevent the current app from moving more than 1/4 of the screen
4658+ var elasticValue = __elastic(dragValue, startValue/4);
4659+ return elasticValue / startValue;
4660+ } else {
4661+ return dragValue / startValue;
4662+ }
4663+ }
4664+
4665+ function __elastic(x, limit) {
4666+ return limit * ( 1 - Math.pow( ( limit - 1 ) / limit, x ) )
4667+ }
4668+
4669+ property real __startValue: stage.width
4670+ property real __hintValue: units.gu(4)
4671+
4672+ Binding {
4673+ target: switchToApplicationAnimationController
4674+ property: "progress"
4675+ value: stage.__dragValueToProgress(stage.__hintValue - rightEdgeDraggingArea.dragValue,
4676+ stage.__startValue, stage.applications.count)
4677+ when: rightEdgeDraggingArea.dragging
4678+ }
4679+
4680+
4681+ NumberAnimation {
4682+ id: hintProgressAnimation
4683+ target: switchToApplicationAnimationController
4684+ property: "progress"
4685+ easing.type: Easing.OutQuad
4686+ from: 0.0
4687+ to: stage.__dragValueToProgress(stage.__hintValue,
4688+ stage.__startValue,
4689+ stage.applications.count)
4690+ duration: 150
4691+
4692+ }
4693+
4694+ AnimationControllerWithSignals {
4695+ id: switchToApplicationAnimationController
4696+
4697+ onAnimationCompletedAtBeginning: {
4698+ animation = null;
4699+ stage.__focusApplication(oldApplicationScreenshot.application);
4700+ }
4701+ }
4702+
4703+ DraggingArea {
4704+ id: rightEdgeDraggingArea
4705+
4706+ enabled: switchToApplicationAnimationController.completed && stage.applications.count > 0
4707+ && stage.rightEdgeEnabled && !delayedHideScreenshots.running
4708+ height: parent.height
4709+ width: shell.edgeSize
4710+ orientation: Qt.Horizontal
4711+ anchors.bottom: parent.bottom
4712+ anchors.right: parent.right
4713+
4714+ onPressed: {
4715+ var nextApplication = null;
4716+ if (stage.applications.count > 1) {
4717+ nextApplication = stage.applications.get(1);
4718+ }
4719+
4720+ switchToApplicationAnimation.prepare(nextApplication);
4721+ switchToApplicationAnimationController.animation = switchToApplicationAnimation;
4722+ hintProgressAnimation.start();
4723+ }
4724+
4725+ onReleased: {
4726+ if (!switchToApplicationAnimationController.completing && !switchToApplicationAnimationController.completed) {
4727+ hintProgressAnimation.stop();
4728+ switchToApplicationAnimationController.completeToBeginningWithSignal();
4729+ }
4730+ }
4731+
4732+ onDragStart: {
4733+ hintProgressAnimation.stop();
4734+ }
4735+
4736+ onDragEnd: {
4737+ if (stage.applications.count > 1 && dragVelocity < 0) {
4738+ switchToApplicationAnimationController.completeToEndWithSignal();
4739+ } else {
4740+ switchToApplicationAnimationController.completeToBeginningWithSignal();
4741+ }
4742+ }
4743+ }
4744+
4745+
4746+ // FIXME: very bad hack to detect when an application was closed or crashed
4747+ property var __previouslyFocusedApplication
4748+ Connections {
4749+ target: stage
4750+ onFocusedApplicationChanged: {
4751+ if (stage.focusedApplication == null
4752+ && __getApplicationIndex(stage.__previouslyFocusedApplication) == -1) {
4753+ stage.__onFocusedApplicationClosed();
4754+ }
4755+ stage.__previouslyFocusedApplication = stage.focusedApplication;
4756+ }
4757+ }
4758+
4759+ function __onFocusedApplicationClosed() {
4760+ if (!stage.shown) {
4761+ return;
4762+ }
4763+
4764+ if (stage.applications.count > 0) {
4765+ stage.__focusApplication(stage.applications.get(0));
4766+ } else {
4767+ stage.hide();
4768+ }
4769+ }
4770+}
4771
4772=== added file 'Components/StandardAnimation.qml'
4773--- Components/StandardAnimation.qml 1970-01-01 00:00:00 +0000
4774+++ Components/StandardAnimation.qml 2013-03-01 09:12:23 +0000
4775@@ -0,0 +1,22 @@
4776+/*
4777+ * Copyright (C) 2013 Canonical, Ltd.
4778+ *
4779+ * This program is free software; you can redistribute it and/or modify
4780+ * it under the terms of the GNU General Public License as published by
4781+ * the Free Software Foundation; version 3.
4782+ *
4783+ * This program is distributed in the hope that it will be useful,
4784+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4785+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4786+ * GNU General Public License for more details.
4787+ *
4788+ * You should have received a copy of the GNU General Public License
4789+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4790+ */
4791+
4792+import QtQuick 2.0
4793+
4794+NumberAnimation {
4795+ duration: 200
4796+ easing.type: Easing.InOutQuad
4797+}
4798
4799=== added file 'Components/Tile.qml'
4800--- Components/Tile.qml 1970-01-01 00:00:00 +0000
4801+++ Components/Tile.qml 2013-03-01 09:12:23 +0000
4802@@ -0,0 +1,90 @@
4803+/*
4804+ * Copyright (C) 2013 Canonical, Ltd.
4805+ *
4806+ * This program is free software; you can redistribute it and/or modify
4807+ * it under the terms of the GNU General Public License as published by
4808+ * the Free Software Foundation; version 3.
4809+ *
4810+ * This program is distributed in the hope that it will be useful,
4811+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4812+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4813+ * GNU General Public License for more details.
4814+ *
4815+ * You should have received a copy of the GNU General Public License
4816+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4817+ */
4818+
4819+import QtQuick 2.0
4820+import Ubuntu.Components 0.1
4821+
4822+AbstractButton {
4823+ id: root
4824+ property alias source: image.source
4825+ property alias fillMode: image.fillMode
4826+ property alias horizontalAlignment: image.horizontalAlignment
4827+ property alias verticalAlignment: image.verticalAlignment
4828+ property alias text: label.text
4829+ property int imageWidth
4830+ property int imageHeight
4831+
4832+ UbuntuShape {
4833+ id: icon
4834+ anchors {
4835+ top: parent.top
4836+ horizontalCenter: parent.horizontalCenter
4837+ }
4838+ radius: "medium"
4839+ width: imageWidth
4840+ height: imageHeight
4841+ image: Image {
4842+ id: image
4843+ sourceSize { width: icon.width; height: icon.height }
4844+ asynchronous: true
4845+ cache: false
4846+ }
4847+ }
4848+
4849+ UbuntuShape {
4850+ id: borderPressed
4851+
4852+ anchors.fill: icon
4853+ radius: "medium"
4854+ borderSource: ItemStyle.style.borderPressed
4855+ opacity: root.pressed ? 1.0 : 0.0
4856+ Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
4857+ }
4858+
4859+ Item {
4860+ anchors {
4861+ left: parent.left
4862+ right: parent.right
4863+ top: icon.bottom
4864+ }
4865+ height: units.gu(2)
4866+
4867+ Label {
4868+ id: label
4869+ anchors {
4870+ baseline: parent.bottom
4871+ left: parent.left
4872+ right: parent.right
4873+ leftMargin: units.gu(1)
4874+ rightMargin: units.gu(1)
4875+ }
4876+
4877+ color: "#f3f3e7"
4878+ opacity: 0.9
4879+ style: Text.Raised
4880+ styleColor: "black"
4881+ fontSize: "small"
4882+ elide: Text.ElideMiddle
4883+ horizontalAlignment: Text.AlignHCenter
4884+ }
4885+ }
4886+
4887+ GridView.onRemove: SequentialAnimation {
4888+ PropertyAction { target: root; property: "GridView.delayRemove"; value: true }
4889+ NumberAnimation { target: root; property: "opacity"; from: 1; to: 0; duration: 200; easing.type: Easing.InOutQuad }
4890+ PropertyAction { target: root; property: "GridView.delayRemove"; value: false }
4891+ }
4892+}
4893
4894=== added file 'Components/Time.js'
4895--- Components/Time.js 1970-01-01 00:00:00 +0000
4896+++ Components/Time.js 2013-03-01 09:12:23 +0000
4897@@ -0,0 +1,47 @@
4898+/*
4899+ * Copyright (C) 2013 Canonical, Ltd.
4900+ *
4901+ * This program is free software; you can redistribute it and/or modify
4902+ * it under the terms of the GNU General Public License as published by
4903+ * the Free Software Foundation; version 3.
4904+ *
4905+ * This program is distributed in the hope that it will be useful,
4906+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4907+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4908+ * GNU General Public License for more details.
4909+ *
4910+ * You should have received a copy of the GNU General Public License
4911+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4912+ */
4913+
4914+.pragma library
4915+
4916+function readableFromNow(date) {
4917+ if (!date) return "";
4918+ var then = new Date(date);
4919+ if (isNaN(then)) return "";
4920+ var now = new Date();
4921+
4922+ var factors = {
4923+ "second": [ 1000, "a second ago", "%1 seconds ago" ],
4924+ "minute": [ 60, "a minute ago", "%1 minutes ago" ],
4925+ "hour": [ 60, "an hour ago", "%1 hours ago" ],
4926+ "day": [ 24, "yesterday", "%1 days ago" ],
4927+ "week": [ 7, "a week ago", "%1 weeks ago" ],
4928+ "month": [ 4.35, "a month ago", "%1 months ago" ], // == 365.25 days / 12 months / 7 days
4929+ "year": [ 12, "a year ago", "%1 years ago" ]
4930+ }
4931+
4932+ var diff = now - then;
4933+ var humanDiff;
4934+
4935+ for (var k in factors) {
4936+ diff /= factors[k][0];
4937+ if (Math.floor(diff) == 1)
4938+ humanDiff = factors[k][1];
4939+ else if (Math.floor(diff) > 1) {
4940+ humanDiff = factors[k][2].arg(Math.round(diff));
4941+ } else break;
4942+ }
4943+ return humanDiff;
4944+}
4945
4946=== added file 'Components/UbuntuShapeForItem.qml'
4947--- Components/UbuntuShapeForItem.qml 1970-01-01 00:00:00 +0000
4948+++ Components/UbuntuShapeForItem.qml 2013-03-01 09:12:23 +0000
4949@@ -0,0 +1,89 @@
4950+/*
4951+ * Copyright (C) 2012 Canonical, Ltd.
4952+ *
4953+ * This program is free software; you can redistribute it and/or modify
4954+ * it under the terms of the GNU General Public License as published by
4955+ * the Free Software Foundation; version 3.
4956+ *
4957+ * This program is distributed in the hope that it will be useful,
4958+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4959+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4960+ * GNU General Public License for more details.
4961+ *
4962+ * You should have received a copy of the GNU General Public License
4963+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4964+ */
4965+
4966+import QtQuick 2.0
4967+import Ubuntu.Components 0.1 as Theming
4968+
4969+/* FIXME: This component is duplicating the UbuntuShape from the SDK, but shapes more
4970+ * general (Item-based) components. This ability should be incorporated into the SDK's
4971+ * UbuntuShape so this file can be removed.
4972+ * Bug: https://bugs.launchpad.net/tavastia/+bug/1089595
4973+ */
4974+
4975+Item {
4976+ id: shape
4977+
4978+ Theming.ItemStyle.class: "UbuntuShape-radius-" + radius
4979+
4980+ property string radius: "small"
4981+ property url maskSource: Theming.ComponentUtils.style(shape, "maskSource", "")
4982+ property url borderSource: Theming.ComponentUtils.style(shape, "borderIdle", "")
4983+ property Item image
4984+
4985+ implicitWidth: units.gu(8)
4986+ implicitHeight: units.gu(8)
4987+
4988+ onWidthChanged: __updateImageDimensions()
4989+ onHeightChanged: __updateImageDimensions()
4990+ onImageChanged: __updateImageDimensions()
4991+
4992+ function __updateImageDimensions() {
4993+ if (!image) return;
4994+ image.width = shape.width;
4995+ image.height = shape.height;
4996+ image.visible = false;
4997+ }
4998+
4999+ ShaderEffect {
5000+ anchors.fill: parent
The diff has been truncated for viewing.