on 8fdf96c help sign in
Jenkinsfile+29−12
since splitsnapshots
unifiedsplit
@@ -12,25 +12,40 @@ pipeline {
12 steps {
12 steps {
13 parallel(
13 parallel(
14 "Build binary - armhf": {
14 "Build binary - armhf": {
15− node(label: 'xenial-arm64') {
15+ node(label: 'arm64') {
16+ cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
16 unstash 'source'
17 unstash 'source'
17 sh '''export architecture="armhf"
18 sh '''export architecture="armhf"
19+ export DEBBUILDOPTS="-sa"
20+ export SKIP_ARCH_BUILD=false
21+ export SKIP_SOURCE_REMOVAL=true
18build-binary.sh'''
22build-binary.sh'''
19− stash(includes: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo,lintian.txt', name: 'build')
23+ stash(includes: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo,lintian.txt', name: 'build-armhf')
20 cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
24 cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
21 }
25 }
22
26
23
27
24 },
28 },
25− "Build binary - all": {
29+ "Build binary - arm64": {
26− node(label: 'xenial-arm64') {
30+ node(label: 'arm64') {
31+ cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
27 unstash 'source'
32 unstash 'source'
28− sh '''export architecture="armhf"
33+ sh '''export architecture="arm64"
29− export DEBBUILDOPTS="-A"
34+ export DEBBUILDOPTS="-sa"
30 export SKIP_ARCH_BUILD=false
35 export SKIP_ARCH_BUILD=false
31 export SKIP_SOURCE_REMOVAL=true
36 export SKIP_SOURCE_REMOVAL=true
37+ #build-binary.sh'''
38+ stash(includes: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo,lintian.txt', name: 'build-arm64')
39+ cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
40+ }
41+ },
42+ "Build binary - amd64": {
43+ node(label: 'amd64') {
44+ cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
45+ unstash 'source'
46+ sh '''export architecture="amd64"
32− build-binary.sh'''
47+ #build-binary.sh'''
33− stash(includes: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo,lintian.txt', name: 'build-all')
48+ stash(includes: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo,lintian.txt', name: 'build-amd64')
34 cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
49 cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
35 }
50 }
36 }
51 }
@@ -39,11 +54,12 @@ build-binary.sh'''
39 }
54 }
40 stage('Results') {
55 stage('Results') {
41 steps {
56 steps {
57+ cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenNotBuilt: true, cleanWhenSuccess: true, cleanWhenUnstable: true, deleteDirs: true)
42− unstash 'build'
58+ unstash 'build-armhf'
43− unstash 'build-all'
59+ unstash 'build-arm64'
60+ unstash 'build-amd64'
44 archiveArtifacts(artifacts: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo', fingerprint: true, onlyIfSuccessful: true)
61 archiveArtifacts(artifacts: '*.gz,*.bz2,*.xz,*.deb,*.dsc,*.changes,*.buildinfo', fingerprint: true, onlyIfSuccessful: true)
45− sh '''export architecture="armhf"
46−/usr/bin/build-repo.sh'''
62+ sh '''/usr/bin/build-repo.sh'''
47 }
63 }
48 }
64 }
49 stage('Cleanup') {
65 stage('Cleanup') {
@@ -53,3 +69,4 @@ build-binary.sh'''
53 }
69 }
54 }
70 }
55}
71}
72+
README.mdnew file+16
@@ -0,0 +1,16 @@
1+# Unity8
2+
3+A convergent desktop environment.
4+
5+Only issues with this (the latest) version of Unity8 should be reported in [the issue tracker](https://github.com/ubports/unity8/issues) on this repository. Issues with the version of Unity8 that's currently running on Ubuntu Touch devices should be reported on [the Ubuntu Touch tracker](https://github.com/ubports/unity8/issues). This will change once Ubuntu Touch moves to the latest version of Unity8.
6+
7+[![Unity 8](http://ubuntufun.de/wp-content/uploads/2016/05/screenshot20160518_232322980.png)](https://unity8.io)
8+
9+See [CODING](CODING) for build instructions. The latest development preview can be [installed on Ubuntu 16.04 and 18.04](https://github.com/ubports/unity8-desktop-install-tools).
10+
11+### Get involved
12+
13+* [Kanban-Board](https://github.com/ubports/unity8/projects/1)
14+* If you are interesting in helping us in any way you can join [Unity8 Forum](https://forums.ubports.com/category/36/unity8).
15+* For reporting bugs or filing feature-requests, please use the project’s [issues page](https://github.com/ubports/unity8/issues).
16+* For IM you can join our Telegram group [for Developer users](https://t.me/UBports_Unity8).
data/CMakeLists.txt+1
@@ -31,5 +31,6 @@ install(FILES
31add_custom_target(pkgversion ALL COMMAND dpkg-parsechangelog -l${CMAKE_SOURCE_DIR}/debian/changelog --show-field version > ${CMAKE_CURRENT_BINARY_DIR}/version)
31add_custom_target(pkgversion ALL COMMAND dpkg-parsechangelog -l${CMAKE_SOURCE_DIR}/debian/changelog --show-field version > ${CMAKE_CURRENT_BINARY_DIR}/version)
32
32
33install(FILES com.canonical.Unity8.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
33install(FILES com.canonical.Unity8.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
34+install(FILES com.canonical.Unity.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
34install(FILES unity8-dash.url-dispatcher DESTINATION ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
35install(FILES unity8-dash.url-dispatcher DESTINATION ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
35install(FILES ${CMAKE_CURRENT_BINARY_DIR}/version DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/lib/unity8)
36install(FILES ${CMAKE_CURRENT_BINARY_DIR}/version DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/lib/unity8)
data/com.canonical.Unity.gschema.xmlnew file+255
@@ -0,0 +1,255 @@
1+<schemalist>
2+ <enum id="form-factor-enum">
3+ <value nick="Automatic" value="0" />
4+ <value nick="Desktop" value="1" />
5+ <value nick="Netbook" value="2" />
6+ <value nick="TV" value="3" />
7+ </enum>
8+ <enum id="home-expanded-enum">
9+ <value nick="Not Expanded" value="0" />
10+ <value nick="Expanded" value="1" />
11+ </enum>
12+ <enum id="launcher-position-enum">
13+ <value nick="Left" value="0" />
14+ <value nick="Bottom" value="1" />
15+ </enum>
16+ <enum id="desktop-type-enum">
17+ <value nick="Ubuntu" value="0" />
18+ <value nick="UbuntuKylin" value="1" />
19+ </enum>
20+
21+ <schema path="/com/canonical/unity/" id="com.canonical.Unity" gettext-domain="unity">
22+ <key enum="form-factor-enum" name="form-factor">
23+ <default>"Automatic"</default>
24+ <summary>The form factor Unity should target.</summary>
25+ <description>The form factor chosen will affect the size and appearance of the Dash, Launcher and also the Window Management behaviour.</description>
26+ </key>
27+ <key enum="home-expanded-enum" name="home-expanded">
28+ <default>"Expanded"</default>
29+ <summary>Whether the home screen should be expanded.</summary>
30+ <description>Whether the home screen should be expanded.</description>
31+ </key>
32+ <key enum="desktop-type-enum" name="desktop-type">
33+ <default>"Ubuntu"</default>
34+ <summary>The current desktop name.</summary>
35+ <description>The current desktop name.</description>
36+ </key>
37+ <key type="i" name="minimize-count">
38+ <default>0</default>
39+ <summary>Number of times a normal window has been minimized.</summary>
40+ <description>This is used to adjust the animation speed by making it progressively faster the more it is used.</description>
41+ </key>
42+ <key type="i" name="minimize-fast-duration">
43+ <default>300</default>
44+ <summary>The duration for the minimize animation when it is at its fastest setting.</summary>
45+ <description>This is the duration that the minimize animation will have when it has been used more than an number of times equal minimize-speed-threshold.</description>
46+ </key>
47+ <key type="i" name="minimize-slow-duration">
48+ <default>800</default>
49+ <summary>The duration for the minimize animation when it is at its slowest setting.</summary>
50+ <description>This is the duration that the minimize animation will have when it has never been used.</description>
51+ </key>
52+ <key type="i" name="minimize-speed-threshold">
53+ <default>100</default>
54+ <summary>The number of minimizations required to reach maximum speed.</summary>
55+ <description>The speed of the minimize animation will progressively get faster as minimize-count approaches this value.</description>
56+ </key>
57+ <key type="b" name="double-click-activate">
58+ <default>true</default>
59+ <summary>Enable/Disable dash result double-click activation.</summary>
60+ <description>This is used to enable/disable double-click result activation in the dash. Double-click to activate, single click preview</description>
61+ </key>
62+ <key type="b" name="integrated-menus">
63+ <default>false</default>
64+ <summary>Enable/Disable the integrated menus in Unity.</summary>
65+ <description>When this is enabled, the application menus will be shown
66+ on the window decoration, otherwise they will be always shown on the
67+ unity top panel</description>
68+ </key>
69+ <key type="u" name="show-menus-now-delay">
70+ <default>180</default>
71+ <range min="0" max="5000"/>
72+ <summary>Delay (in ms) before showing the menus when pressing Alt</summary>
73+ <description>This allows tune the delay before presenting unity menus
74+ (in non always-show-menus mode).</description>
75+ </key>
76+ <key type="b" name="always-show-menus">
77+ <default>false</default>
78+ <summary>Toggle the menu visibility based on mouse hovering.</summary>
79+ <description>When this is enabled, the application menus will be always
80+ shown (on the window decoration or in the unity panel, depending whether
81+ integrated menus are enabled), otherwise they will be shown only when
82+ the mouse cursor is over the relative mouse area.</description>
83+ </key>
84+ <key type="as" name="whitelist-repeated-keys">
85+ <default>[
86+ 'XF86KbdBrightnessUp',
87+ 'XF86KbdBrightnessDown',
88+ 'XF86MonBrightnessUp',
89+ 'XF86MonBrightnessDown',
90+ 'XF86AudioRaiseVolume',
91+ 'XF86AudioLowerVolume'
92+ ]</default>
93+ <summary>List of keycodes that should be processed even if auto-repated.</summary>
94+ <description>These keycodes are processed even if they are auto-repeated.</description>
95+ </key>
96+ <key type="b" name="pam-check-account-type">
97+ <default>false</default>
98+ <summary>Enable/Disable PAM account checking</summary>
99+ <description>Whether PAM should check the result of account modules
100+ when authenticating. Only do this if you have account
101+ configured properly on your system.</description>
102+ </key>
103+ <key type="b" name="lowgfx">
104+ <default>false</default>
105+ <summary>Enable/Disable Low Graphics Mode</summary>
106+ <description>Whether Unity runs in Low Graphics Mode.</description>
107+ </key>
108+ </schema>
109+ <schema path="/com/canonical/unity/interface/" id="com.canonical.Unity.Interface" gettext-domain="unity">
110+ <key type="d" name="text-scale-factor">
111+ <default>1.0</default>
112+ <range min="0.5" max="3.0"/>
113+ <summary>Font scaling for unity and applications.</summary>
114+ <description>This value defines the global font scaling used by both
115+ unity and applications. It will match the current system font scaling.</description>
116+ </key>
117+ <key type="d" name="cursor-scale-factor">
118+ <default>1.0</default>
119+ <range min="0.5" max="3.0"/>
120+ <summary>Mouse cursor scaling.</summary>
121+ <description>This value defines the global mouse cursor scaling used by both
122+ unity and applications. Changing this value allows to use a custom scaling
123+ for the mouse cursor.</description>
124+ </key>
125+ <key type="s" name="app-scale-factor-monitor">
126+ <default>''</default>
127+ <summary>The name of the monitor that controls the global app scaling factor.</summary>
128+ <description>This value defines the monitor that unity will use (if found) as reference
129+ for scaling all the applications.</description>
130+ </key>
131+ <key type="b" name="app-fallback-to-maximum-scale-factor">
132+ <default>true</default>
133+ <summary>Use the maximum per-monitor scale-factor as application scale factor if no target monitor is found.</summary>
134+ <description>When this is enabled, the applications scale factor will match
135+ the scale factor of the monitor with the greater value, in case the monitor
136+ defined in 'app-scale-factor-monitor' is not provided or available.</description>
137+ </key>
138+ </schema>
139+ <schema path="/com/canonical/unity/launcher/" id="com.canonical.Unity.Launcher" gettext-domain="unity">
140+ <key type="as" name="favorites">
141+ <default>[
142+ 'application://ubiquity.desktop',
143+ 'application://org.gnome.Nautilus.desktop',
144+ 'application://firefox.desktop',
145+ 'application://libreoffice-writer.desktop',
146+ 'application://libreoffice-calc.desktop',
147+ 'application://libreoffice-impress.desktop',
148+ 'application://org.gnome.Software.desktop',
149+ 'application://ubuntu-amazon-default.desktop',
150+ 'application://unity-control-center.desktop',
151+ 'unity://running-apps',
152+ 'unity://expo-icon',
153+ 'unity://devices'
154+ ]</default>
155+ <summary>List of items that should be shown by default in the launcher</summary>
156+ <description>These items can be: application://desktop-id.desktop, device://uiid and unity://special-id (including: unity://running-apps (icons of running applications) unity://devices (icons of attached devices), unity://expo-icon (icon of the workspace switcher) and unity://desktop-icon (the show-desktop icon)); the order of this list determines the launcher item's position.</description>
157+ </key>
158+ <key type="as" name="items">
159+ <default>[
160+ 'application:///dialer-app.desktop',
161+ 'application:///messaging-app.desktop',
162+ 'application:///address-book-app.desktop',
163+ 'application:///ubuntu-system-settings.desktop',
164+ 'appid://openstore.openstore-team/openstore/current-user-version',
165+ 'appid://com.ubuntu.camera/camera/current-user-version',
166+ 'appid://com.ubuntu.gallery/gallery/current-user-version',
167+ 'application:///webbrowser-app.desktop'
168+ ]</default>
169+ <summary>List of items that should be shown by default in the launcher</summary>
170+ <description>These items can be: application:///desktop-id.desktop or appid://package/app/current-user-version.</description>
171+ </key>
172+ <key type="s" name="favorite-migration">
173+ <default>''</default>
174+ <summary>Version of last migration done</summary>
175+ <description>This is a detection key for the favorite migration script to know whether the needed migration is done or not.</description>
176+ </key>
177+ <key enum="launcher-position-enum" name="launcher-position">
178+ <default>"Left"</default>
179+ <summary>The position of launcher.</summary>
180+ <description>The position of launcher.</description>
181+ </key>
182+ </schema>
183+ <schema path="/com/canonical/unity/devices/" id="com.canonical.Unity.Devices" gettext-domain="unity">
184+ <key type="as" name="blacklist">
185+ <default>[]</default>
186+ <summary>List of device uuid blacklist from the launcher.</summary>
187+ <description>These devices are not shown in the launcher by default.</description>
188+ </key>
189+ </schema>
190+ <schema path="/com/canonical/unity/dash/" id="com.canonical.Unity.Dash" gettext-domain="unity">
191+ <key type="as" name="scopes">
192+ <default>[ 'home.scope', 'applications.scope', 'files.scope', 'video.scope', 'music.scope', 'photos.scope', 'social.scope' ]</default>
193+ <summary>List of scope ids specifying which scopes should be created and the order to display them in.</summary>
194+ <description>The scopes listed in the scope bar will be ordered according to this list.</description>
195+ </key>
196+ <key type="as" name="favorite-scopes">
197+ <default>[ 'scope://clickscope', 'scope://musicaggregator', 'scope://videoaggregator' ]</default>
198+ <summary>List of scope queries specifying what should be displayed in the dash.</summary>
199+ <description>List of favorite scopes displayed in the dash.</description>
200+ </key>
201+ </schema>
202+ <schema path="/com/canonical/unity/decorations/" id="com.canonical.Unity.Decorations" gettext-domain="unity">
203+ <key type="u" name="grab-wait">
204+ <default>175</default>
205+ <range min="0" max="1000"/>
206+ <summary>Milliseconds to wait before considering a mouse pressure a grab</summary>
207+ <description>The number of ms to wait before starting the window movement (and then
208+ showing the proper mouse cursor, and grabbing the window)</description>
209+ </key>
210+ </schema>
211+ <schema path="/com/canonical/unity/integrated-menus/" id="com.canonical.Unity.IntegratedMenus" gettext-domain="unity">
212+ <key type="u" name="click-movement-threshold">
213+ <default>15</default>
214+ <range min="0" max="30"/>
215+ <summary>Number of pixels to ignore on mouse pressure</summary>
216+ <description>This value define how many pixels the user can move the mouse
217+ when holding the mouse button, before we consider his action a movement
218+ (to grab the window).</description>
219+ </key>
220+ <key type="u" name="double-click-wait">
221+ <default>0</default>
222+ <range min="0" max="300"/>
223+ <summary>Milliseconds to wait before activating a menu after mouse release</summary>
224+ <description>The number of ms to wait after a mouse button release event before considering
225+ it a click. When this value is greater than 0, then it's possible to maximize
226+ a window by double-clicking on its menus if the second click happens before the
227+ specified value of ms is elapsed</description>
228+ </key>
229+ <key type="b" name="unfocused-windows-popup">
230+ <default>true</default>
231+ <summary>Whether to pop-up a menu when clicking over unfocused windows entries</summary>
232+ <description>By disabling this setting you can make unity to only focus a window
233+ when clicking over unfocused menu entries</description>
234+ </key>
235+ </schema>
236+ <schema path="/com/canonical/unity/gestures/" id="com.canonical.Unity.Gestures" gettext-domain="unity">
237+ <key type="b" name="launcher-drag">
238+ <default>true</default>
239+ <summary>Multi-touch gesture to reveal the launcher.</summary>
240+ <description>When this is enabled, a 4 finger swipe from left to right will reveal launcher,
241+ provided that the launcher is set to auto-hide.</description>
242+ </key>
243+ <key type="b" name="dash-tap">
244+ <default>true</default>
245+ <summary>Multi-touch gesture to open the dash.</summary>
246+ <description>When this is enabled, a 4 finger tap will open the dash.</description>
247+ </key>
248+ <key type="b" name="windows-drag-pinch">
249+ <default>true</default>
250+ <summary>Multi-touch gestures to manage the windows.</summary>
251+ <description>When this is enabled, 3 finger gestures such as drag, and pinch, will
252+ help manage the windows.</description>
253+ </key>
254+ </schema>
255+</schemalist>
data/unity8.conf+33−32
@@ -8,31 +8,44 @@ stop on desktop-end
8
8
9kill timeout 120
9kill timeout 120
10
10
11+#
12+# Ensure the shell always gets unthrottled touch events, so that applications
13+# who want full speed low-latency input can get it (LP: #1497105) and so that
14+# apps can use QML touch compression safely (the QML touch compression
15+# algorithm does not support nesting well - LP: #1486341, LP: #1556763 - so
16+# must be fed by the raw input event stream from Unity8).
17+#
18+env QML_NO_TOUCH_COMPRESSION=1
19+
11respawn
20respawn
12expect stop
21expect stop
13
22
23+# FIXME Create an autopilot test that makes sure start+stop and restart
24+# work fine at least 2 times
25+
14pre-start script
26pre-start script
15 # Tell unity-mir to raise SIGSTOP after we start
27 # Tell unity-mir to raise SIGSTOP after we start
16 initctl set-env UNITY_MIR_EMITS_SIGSTOP=1
28 initctl set-env UNITY_MIR_EMITS_SIGSTOP=1
17
29
18− if [ -n "$MIR_SOCKET" ]; then
19− # FIXME Create an autopilot test that makes sure start+stop and restart
20− # work fine at least 2 times
21− # Save original value of MIR_SOCKET in case we are stopped,
30+ # Save original value of MIR_SOCKET so that we can restore it when stopped,
22− # as we modify the variable for future jobs, including ourself.
31+ # as we modify the variable for future jobs, including ourself.
23− UNITY_MIR_SOCKET=$(initctl get-env --global MIR_SOCKET)
24− initctl set-env --global UNITY_MIR_SOCKET=$UNITY_MIR_SOCKET
32+ initctl set-env UNITY_MIR_SOCKET=$MIR_SOCKET
25
33
26− # Point unity8 at unity-system-compositor
34+ # Decide where we are going to put our own socket file
35+ if [ -n "$SNAP" ]; then
36+ # In snappy, we want to hard code our path because our apparmor profile
37+ # only lets us put the socket in one place. And consumers expect it
38+ # there.
39+ MIR_SERVER_FILE=/run/user/$(id -u)/mir_socket
40+ else
27 MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
41 MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
28− initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
29− initctl set-env MIR_SERVER_HOST_SOCKET=$UNITY_MIR_SOCKET
30−
31− # Point all future jobs in this session to our Mir socket instead of
32− # unity-system-compositor's socket.
33− initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
34− gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
35 fi
42 fi
43+ initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
44+
45+ # Point all future jobs in this session to our Mir socket instead of
46+ # unity-system-compositor's socket.
47+ initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
48+ gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
36
49
37 # Remove the normal and trusted sockets if still there
50 # Remove the normal and trusted sockets if still there
38 if [ -S "$MIR_SERVER_FILE" ]; then
51 if [ -S "$MIR_SERVER_FILE" ]; then
@@ -46,6 +59,7 @@ pre-start script
46 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
59 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
47
60
48 # Disable Qt's stuttering 'touch compression' to fix scrolling smoothness
61 # Disable Qt's stuttering 'touch compression' to fix scrolling smoothness
62+
49 # issues (LP: #1486341, LP: #1556763). As a bonus, this eliminates most of
63 # issues (LP: #1486341, LP: #1556763). As a bonus, this eliminates most of
50 # the lag seen in the indicator panel pull-down (LP: #1488327) and also
64 # the lag seen in the indicator panel pull-down (LP: #1488327) and also
51 # reduces lag seen in apps:
65 # reduces lag seen in apps:
@@ -54,7 +68,6 @@ pre-start script
54 # Workaround for text not rendering correctly
68 # Workaround for text not rendering correctly
55 initctl set-env --global QT_ENABLE_GLYPH_CACHE_WORKAROUND=1
69 initctl set-env --global QT_ENABLE_GLYPH_CACHE_WORKAROUND=1
56
70
57−
58 if [ "$XDG_SESSION_DESKTOP" = "ubuntu-touch" ]; then
71 if [ "$XDG_SESSION_DESKTOP" = "ubuntu-touch" ]; then
59 # On Ubuntu Touch, we currently use a trick where we auto-login the
72 # On Ubuntu Touch, we currently use a trick where we auto-login the
60 # user without a LightDM greeter at all. In this case, we want to
73 # user without a LightDM greeter at all. In this case, we want to
@@ -66,32 +79,20 @@ pre-start script
66 fi
79 fi
67
80
68 # HACK! WORKAROUND FOR HALIUM MISSING UBUNTU_PLATFORM_API
81 # HACK! WORKAROUND FOR HALIUM MISSING UBUNTU_PLATFORM_API
82+ if [ ! -f /system/lib/libubuntu_application_api.so ]; then
69− initctl set-env --global UBUNTU_PLATFORM_API_BACKEND=test.so.3
83+ initctl set-env --global UBUNTU_PLATFORM_API_BACKEND=test.so.3
70− initctl set-env --global UBUNTU_PLATFORM_API_SENSOR_TEST=/etc/ubuntusensors/test.sensors
84+ initctl set-env --global UBUNTU_PLATFORM_API_SENSOR_TEST=/etc/ubuntusensors/test.sensors
85+ fi
71end script
86end script
72
87
73exec ${BINARY:-unity8} --mode=$MODE $ARGS
88exec ${BINARY:-unity8} --mode=$MODE $ARGS
74
89
75post-start script
90post-start script
76− # If no MIR_SOCKET was defined on launch, we try to set one here
77− if [ -z "$(initctl get-env --global UNITY_MIR_SOCKET)" ]; then
78− if [ -S "$XDG_RUNTIME_DIR/mir_socket" ]; then
79− mir_socket=$XDG_RUNTIME_DIR/mir_socket
80− elif [ -S "/tmp/mir_socket" ]; then
81− mir_socket=/tmp/mir_socket
82− fi
83−
84− if [ -n "$mir_socket" ]; then
85− initctl set-env --global MIR_SOCKET="$mir_socket"
86− fi
87− fi
88−
89 initctl emit --no-wait indicator-services-start
91 initctl emit --no-wait indicator-services-start
90end script
92end script
91
93
92post-stop script
94post-stop script
93 initctl set-env --global MIR_SOCKET=$UNITY_MIR_SOCKET
95 initctl set-env --global MIR_SOCKET=$UNITY_MIR_SOCKET
94− initctl unset-env --global UNITY_MIR_SOCKET
95 initctl unset-env --global MIR_SERVER_PROMPT_FILE
96 initctl unset-env --global MIR_SERVER_PROMPT_FILE
96 initctl emit application-end
97 initctl emit application-end
97end script
98end script
debian/changelog+12
@@ -1,3 +1,15 @@
1+unity8 (8.17+ubports2) xenial; urgency=medium
2+
3+ * Fix for https://github.com/ubports/ubuntu-touch/issues/624
4+
5+ -- Dalton Durst <dalton@ubports.com> Fri, 1 Jun 2018 16:14:11 -0500
6+
7+unity8 (8.17+ubports1) UNRELEASED; urgency=medium
8+
9+ * No change rebuild to generate sources in ubports repo
10+
11+ -- Dan Chapman <dan@ubports.com> Tue, 20 Feb 2018 07:09:11 +0000
12+
1unity8 (8.16+ubports) xenial; urgency=medium
13unity8 (8.16+ubports) xenial; urgency=medium
2
14
3 * Imported to UBports
15 * Imported to UBports
debian/control+14−3
@@ -26,7 +26,6 @@ Build-Depends: cmake,
26 libhardware-dev,
26 libhardware-dev,
27 liblightdm-qt5-3-dev,
27 liblightdm-qt5-3-dev,
28 libpam0g-dev,
28 libpam0g-dev,
29− libpay2-dev,
30 libpulse-dev,
29 libpulse-dev,
31 libqmenumodel-dev (>= 0.2.10),
30 libqmenumodel-dev (>= 0.2.10),
32 libqt5svg5-dev,
31 libqt5svg5-dev,
@@ -165,6 +164,7 @@ Depends: qml-module-qtquick-layouts,
165 unity-plugin-scopes | unity-scopes-impl,
164 unity-plugin-scopes | unity-scopes-impl,
166 unity-scopes-impl-12,
165 unity-scopes-impl-12,
167 unity8-fake-env | unity-application-impl,
166 unity8-fake-env | unity-application-impl,
167+ unity8-schemas,
168 ${misc:Depends},
168 ${misc:Depends},
169Breaks: unity8 (<< 7.86),
169Breaks: unity8 (<< 7.86),
170Replaces: unity8 (<< 7.86),
170Replaces: unity8 (<< 7.86),
@@ -219,8 +219,7 @@ Pre-Depends: ${misc:Pre-Depends},
219Depends: accountsservice-ubuntu-schemas (>= 0.0.7),
219Depends: accountsservice-ubuntu-schemas (>= 0.0.7),
220 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
220 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
221 libhardware2,
221 libhardware2,
222− pay-service,
222+ unity8-schemas,
223− unity-schemas (>= 7.3.1+14.10.20140915),
224 qtdeclarative5-gsettings1.0,
223 qtdeclarative5-gsettings1.0,
225 qml-module-qtmultimedia,
224 qml-module-qtmultimedia,
226 ${misc:Depends},
225 ${misc:Depends},
@@ -233,6 +232,18 @@ Description: Unity 8 private libs
233 This package contains the private libraries for QML and other components
232 This package contains the private libraries for QML and other components
234 only used by the shell.
233 only used by the shell.
235
234
235+
236+Package: unity8-schemas
237+Architecture: all
238+Multi-Arch: foreign
239+Depends: ${misc:Depends},
240+Replaces: unity-schemas (>= 7.3.1+14.10.20140915),
241+Breaks: unity-schemas (>= 7.3.1+14.10.20140915),
242+Description: Unity 8 schemas
243+ The Unity 8 shell is the primary user interface for Ubuntu devices.
244+ .
245+ This package contains the configuration schemas used by unity.
246+
236Package: unity8-doc
247Package: unity8-doc
237Section: doc
248Section: doc
238Architecture: all
249Architecture: all
debian/unity8-common.install−1
@@ -1,4 +1,3 @@
1−usr/share/glib-2.0/schemas
2usr/share/locale
1usr/share/locale
3usr/share/unity8/Components
2usr/share/unity8/Components
4usr/share/unity8/Dash
3usr/share/unity8/Dash
debian/unity8-schemas.installnew file+1
@@ -0,0 +1 @@
1+usr/share/glib-2.0/schemas
plugins/Dash/abstractdashview.cpp+1−1
@@ -236,7 +236,7 @@ QQuickItem *AbstractDashView::createItem(int modelIndex, bool asynchronous)
236 return nullptr;
236 return nullptr;
237
237
238 m_asyncRequestedIndex = -1;
238 m_asyncRequestedIndex = -1;
239− QObject* object = m_delegateModel->object(modelIndex, asynchronous);
239+ QObject* object = m_delegateModel->object(modelIndex, asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
240 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
240 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
241 if (!item) {
241 if (!item) {
242 if (object) {
242 if (object) {
plugins/Dash/listviewwithpageheader.cpp+4−6
@@ -871,7 +871,7 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
871 return nullptr;
871 return nullptr;
872
872
873 m_asyncRequestedIndex = -1;
873 m_asyncRequestedIndex = -1;
874− QObject* object = m_delegateModel->object(modelIndex, asynchronous);
874+ QObject* object = m_delegateModel->object(modelIndex, asynchronous ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
875 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
875 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
876 if (!item) {
876 if (!item) {
877 if (object) {
877 if (object) {
@@ -1141,11 +1141,10 @@ void ListViewWithPageHeader::contentYAnimationRunningChanged(bool running)
1141 }
1141 }
1142}
1142}
1143
1143
1144−/*
1145−void ListViewWithPageHeader::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
1144+void ListViewWithPageHeader::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry)
1146{
1145{
1146+ if (change.heightChange()) {
1147− const qreal heightDiff = newGeometry.height() - oldGeometry.height();
1147+ const qreal heightDiff = height() - oldGeometry.height();
1148− if (heightDiff != 0) {
1149 if (!m_visibleItems.isEmpty()) {
1148 if (!m_visibleItems.isEmpty()) {
1150 ListItem *firstItem = m_visibleItems.first();
1149 ListItem *firstItem = m_visibleItems.first();
1151 const auto prevFirstItemY = firstItem->y();
1150 const auto prevFirstItemY = firstItem->y();
@@ -1166,7 +1165,6 @@ void ListViewWithPageHeader::itemGeometryChanged(QQuickItem *item, const QRectF
1166 m_contentHeightDirty = true;
1165 m_contentHeightDirty = true;
1167 }
1166 }
1168}
1167}
1169−*/
1170
1168
1171void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item)
1169void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item)
1172{
1170{
plugins/Dash/listviewwithpageheader.h+1−1
@@ -116,7 +116,7 @@ protected:
116 void viewportMoved(Qt::Orientations orient) override;
116 void viewportMoved(Qt::Orientations orient) override;
117 qreal minYExtent() const override;
117 qreal minYExtent() const override;
118 qreal maxYExtent() const override;
118 qreal maxYExtent() const override;
119− //void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
119+ void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) override;
120 void itemImplicitHeightChanged(QQuickItem *item) override;
120 void itemImplicitHeightChanged(QQuickItem *item) override;
121 void updatePolish() override;
121 void updatePolish() override;
122
122
plugins/Dash/verticaljournal.cpp+6−8
@@ -271,11 +271,9 @@ void VerticalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &
271 }
271 }
272}
272}
273
273
274−
275−//void VerticalJournal::itemGeometryChanged(QQuickItem * /*item*/, const QRectF &newGeometry, const QRectF &oldGeometry)
274+void VerticalJournal::itemGeometryChanged(QQuickItem * /*item*/, QQuickGeometryChange change, const QRectF &)
276−//{
275+{
277−// const qreal heightDiff = newGeometry.height() - oldGeometry.height();
276+ if (change.verticalChange()) {
278−// if (heightDiff != 0) {
279−// relayout();
277+ relayout();
280−// }
278+ }
281−//}
279+}
plugins/Dash/verticaljournal.h+1−1
@@ -66,7 +66,7 @@ public:
66 void setColumnWidth(qreal columnWidth);
66 void setColumnWidth(qreal columnWidth);
67
67
68protected:
68protected:
69−// void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
69+ void itemGeometryChanged(QQuickItem * /*item*/, QQuickGeometryChange change, const QRectF &oldGeometry) override;
70
70
71Q_SIGNALS:
71Q_SIGNALS:
72 void columnWidthChanged();
72 void columnWidthChanged();
plugins/Ubuntu/CMakeLists.txt+1−1
@@ -1,4 +1,4 @@
1add_subdirectory(Gestures)
1add_subdirectory(Gestures)
2add_subdirectory(DownloadDaemonListener)
2add_subdirectory(DownloadDaemonListener)
3−add_subdirectory(Payments)
3+#add_subdirectory(Payments)
4add_subdirectory(SystemImage)
4add_subdirectory(SystemImage)
plugins/Wizard/System.cpp+55−3
@@ -46,29 +46,81 @@ QString System::wizardEnabledPath()
46 return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run"));
46 return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run"));
47}
47}
48
48
49+QString System::currentFrameworkPath()
50+{
51+ return QDir::home().filePath(QStringLiteral("/usr/share/click/frameworks/current"));
52+}
53+
54+/*
55+wizardEnabled and isUpdate logic
56+
57+if wizard-has-run does NOT exists == is new install
58+if wizard-has-run does exists but does NOT match current framework == is update
59+if wizard-has-run does exists but does match current framework == show no wizard
60+*/
61+
62+bool System::wizardPathExists() {
63+ return QFile::exists(wizardEnabledPath());
64+}
65+
49bool System::wizardEnabled() const
66bool System::wizardEnabled() const
50{
67{
68+ if (!wizardPathExists())
69+ return true;
70+ return isUpdate();
71+}
72+
73+QString System::readCurrentFramework()
74+{
75+ QFile f(currentFrameworkPath());
76+ if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
77+ QTextStream in(&f);
78+ return in.readAll();
79+}
80+
81+QString System::readWizardEnabled()
82+{
51− return !QFile::exists(wizardEnabledPath());
83+ QFile f(wizardEnabledPath());
84+ if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
85+ QTextStream in(&f);
86+ return in.readAll();
87+}
88+
89+QString System::version() const
90+{
91+ return readCurrentFramework();
92+}
93+
94+bool System::isUpdate() const
95+{
96+ if (!wizardPathExists())
97+ return false;
98+
99+ return readCurrentFramework() != readWizardEnabled();
52}
100}
53
101
54void System::setWizardEnabled(bool enabled)
102void System::setWizardEnabled(bool enabled)
55{
103{
56− if (wizardEnabled() == enabled)
104+ if (wizardEnabled() == enabled && !isUpdate())
57 return;
105 return;
58
106
59 if (enabled) {
107 if (enabled) {
60 QFile::remove(wizardEnabledPath());
108 QFile::remove(wizardEnabledPath());
61 } else {
109 } else {
62 QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
110 QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
63− QFile(wizardEnabledPath()).open(QIODevice::WriteOnly);
111+ if (QFile::exists(wizardEnabledPath()))
112+ QFile::remove(wizardEnabledPath());
113+ QFile::copy(currentFrameworkPath(), wizardEnabledPath());
64 m_fsWatcher.addPath(wizardEnabledPath());
114 m_fsWatcher.addPath(wizardEnabledPath());
65 Q_EMIT wizardEnabledChanged();
115 Q_EMIT wizardEnabledChanged();
116+ Q_EMIT isUpdateChanged();
66 }
117 }
67}
118}
68
119
69void System::watcherFileChanged()
120void System::watcherFileChanged()
70{
121{
71 Q_EMIT wizardEnabledChanged();
122 Q_EMIT wizardEnabledChanged();
123+ Q_EMIT isUpdateChanged();
72 m_fsWatcher.removePath(wizardEnabledPath());
124 m_fsWatcher.removePath(wizardEnabledPath());
73}
125}
74
126
plugins/Wizard/System.h+16
@@ -18,6 +18,7 @@
18#define WIZARD_SYSTEM_H
18#define WIZARD_SYSTEM_H
19
19
20#include <QFileSystemWatcher>
20#include <QFileSystemWatcher>
21+#include <QVersionNumber>
21#include <QObject>
22#include <QObject>
22#include <QString>
23#include <QString>
23
24
@@ -25,12 +26,21 @@ class System : public QObject
25{
26{
26 Q_OBJECT
27 Q_OBJECT
27 Q_PROPERTY(bool wizardEnabled READ wizardEnabled WRITE setWizardEnabled NOTIFY wizardEnabledChanged)
28 Q_PROPERTY(bool wizardEnabled READ wizardEnabled WRITE setWizardEnabled NOTIFY wizardEnabledChanged)
29+ Q_PROPERTY(QString version READ version NOTIFY versionChanged)
30+ Q_PROPERTY(bool isUpdate READ isUpdate NOTIFY isUpdateChanged)
28
31
29public:
32public:
30 System();
33 System();
31 ~System() = default;
34 ~System() = default;
32
35
36+ /**
37+ * Checks whether the wizard is enabled for first-run or otherwise.
38+ */
33 bool wizardEnabled() const;
39 bool wizardEnabled() const;
40+
41+ QString version() const;
42+ bool isUpdate() const;
43+
34 void setWizardEnabled(bool enabled);
44 void setWizardEnabled(bool enabled);
35
45
36public Q_SLOTS:
46public Q_SLOTS:
@@ -42,6 +52,8 @@ public Q_SLOTS:
42
52
43Q_SIGNALS:
53Q_SIGNALS:
44 void wizardEnabledChanged();
54 void wizardEnabledChanged();
55+ void versionChanged();
56+ void isUpdateChanged();
45
57
46private Q_SLOTS:
58private Q_SLOTS:
47 void watcherFileChanged();
59 void watcherFileChanged();
@@ -50,7 +62,11 @@ private:
50 Q_DISABLE_COPY(System)
62 Q_DISABLE_COPY(System)
51
63
52 static QString wizardEnabledPath();
64 static QString wizardEnabledPath();
65+ static QString currentFrameworkPath();
53 static void setSessionVariable(const QString &variable, const QString &value);
66 static void setSessionVariable(const QString &variable, const QString &value);
67+ static QString readCurrentFramework();
68+ static QString readWizardEnabled();
69+ static bool wizardPathExists();
54
70
55 QFileSystemWatcher m_fsWatcher;
71 QFileSystemWatcher m_fsWatcher;
56};
72};
qml/Dash/DashBackground.qml+1−1
@@ -31,6 +31,6 @@ Rectangle {
31 source: AccountsService.backgroundFile
31 source: AccountsService.backgroundFile
32 anchors.fill: parent
32 anchors.fill: parent
33 fillMode: Image.PreserveAspectCrop
33 fillMode: Image.PreserveAspectCrop
34− opacity: 0.6
34+ opacity: settings.backgroundOpacity
35 }
35 }
36}
36}
qml/Dash/Previews/PreviewWidgetFactory.qml−1
@@ -67,7 +67,6 @@ Loader {
67 case "icon-actions": return "PreviewIconActions.qml";
67 case "icon-actions": return "PreviewIconActions.qml";
68 case "image": return "PreviewZoomableImage.qml";
68 case "image": return "PreviewZoomableImage.qml";
69 case "progress": return "PreviewProgress.qml";
69 case "progress": return "PreviewProgress.qml";
70− case "payments": return "PreviewPayments.qml";
71 case "rating-input": return "PreviewRatingInput.qml";
70 case "rating-input": return "PreviewRatingInput.qml";
72 case "rating-edit": return "PreviewRatingEdit.qml";
71 case "rating-edit": return "PreviewRatingEdit.qml";
73 case "reviews": return "PreviewRatingDisplay.qml";
72 case "reviews": return "PreviewRatingDisplay.qml";
qml/Shell.qml+1−1
@@ -346,7 +346,7 @@ StyledItem {
346 hides: [launcher, panel.indicators]
346 hides: [launcher, panel.indicators]
347 tabletMode: shell.usageScenario != "phone"
347 tabletMode: shell.usageScenario != "phone"
348 launcherOffset: launcher.progress
348 launcherOffset: launcher.progress
349− forcedUnlock: wizard.active || shell.mode === "full-shell"
349+ forcedUnlock: wizard.active && !wizard.isUpdate || shell.mode === "full-shell"
350 background: wallpaperResolver.cachedBackground
350 background: wallpaperResolver.cachedBackground
351 hasCustomBackground: wallpaperResolver.hasCustomBackground
351 hasCustomBackground: wallpaperResolver.hasCustomBackground
352 allowFingerprint: !dialogs.hasActiveDialog &&
352 allowFingerprint: !dialogs.hasActiveDialog &&
qml/Stage/Stage.qml+8−2
@@ -1726,11 +1726,12 @@ FocusScope {
1726
1726
1727 property int scrollAreaWidth: width / 3
1727 property int scrollAreaWidth: width / 3
1728 property bool progressiveScrollingEnabled: false
1728 property bool progressiveScrollingEnabled: false
1729+ property bool wasTouchPress: false
1729
1730
1730 onMouseXChanged: {
1731 onMouseXChanged: {
1731 mouse.accepted = false
1732 mouse.accepted = false
1732
1733
1733− if (hoverMouseArea.pressed) {
1734+ if (hoverMouseArea.pressed || wasTouchPress) {
1734 return;
1735 return;
1735 }
1736 }
1736
1737
@@ -1766,7 +1767,12 @@ FocusScope {
1766 }
1767 }
1767 }
1768 }
1768
1769
1770+ onPressed: {
1769− onPressed: mouse.accepted = false
1771+ mouse.accepted = false;
1772+ wasTouchPress = mouse.source === Qt.MouseEventSynthesizedByQt;
1773+ }
1774+
1775+ onExited: wasTouchPress = false;
1770 }
1776 }
1771
1777
1772 FloatingFlickable {
1778 FloatingFlickable {
qml/Stage/WindowResizeArea.qml+4−1
@@ -101,7 +101,10 @@ MouseArea {
101 state = WindowStateStorage.WindowStateNormal;
101 state = WindowStateStorage.WindowStateNormal;
102 }
102 }
103 windowStateStorage.saveState(root.windowId, state & ~WindowStateStorage.WindowStateMinimized); // clear the minimized bit when saving
103 windowStateStorage.saveState(root.windowId, state & ~WindowStateStorage.WindowStateMinimized); // clear the minimized bit when saving
104+ // do not store window sizes if they are zero. this happens in staged mode
105+ if ( priv.normalWidth && priv.normalHeight ) {
104− windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight));
106+ windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight));
107+ }
105 }
108 }
106
109
107 QtObject {
110 QtObject {
qml/Wizard/Components/InputMethod.qml+9−9
@@ -21,19 +21,19 @@ import Ubuntu.Components 0.1
21// TODO: try to share this code with that from the unity8 shell
21// TODO: try to share this code with that from the unity8 shell
22
22
23Item {
23Item {
24− id: root
24+ id: inputMethodRoot
25
25
26 Connections {
26 Connections {
27 target: SurfaceManager
27 target: SurfaceManager
28 onSurfaceCreated: {
28 onSurfaceCreated: {
29 if (surface.type == MirSurfaceItem.InputMethod) {
29 if (surface.type == MirSurfaceItem.InputMethod) {
30− root.surface = surface;
30+ inputMethodRoot.surface = surface;
31 }
31 }
32 }
32 }
33
33
34 onSurfaceDestroyed: {
34 onSurfaceDestroyed: {
35− if (root.surface == surface) {
35+ if (inputMethodRoot.surface == surface) {
36− root.surface = null;
36+ inputMethodRoot.surface = null;
37 surface.parent = null;
37 surface.parent = null;
38 }
38 }
39 if (!surface.parent) {
39 if (!surface.parent) {
@@ -71,7 +71,7 @@ Item {
71 visible: false
71 visible: false
72 // half-way down because the vkb occupies only the lower half of the surface
72 // half-way down because the vkb occupies only the lower half of the surface
73 // TODO: consider keyboard rotation
73 // TODO: consider keyboard rotation
74− y: root.parent.height / 2.0
74+ y: inputMethodRoot.parent.height / 2.0
75 }
75 }
76 }
76 }
77 ]
77 ]
@@ -89,17 +89,17 @@ Item {
89 ignoreUnknownSignals: true // don't wanna spam the log when surface is null
89 ignoreUnknownSignals: true // don't wanna spam the log when surface is null
90 onStateChanged: {
90 onStateChanged: {
91 if (state == MirSurfaceItem.Minimized) {
91 if (state == MirSurfaceItem.Minimized) {
92− root.hide();
92+ inputMethodRoot.hide();
93 } else if (state == MirSurfaceItem.Maximized) {
93 } else if (state == MirSurfaceItem.Maximized) {
94− root.show();
94+ inputMethodRoot.show();
95 }
95 }
96 }
96 }
97 }
97 }
98
98
99 onSurfaceChanged: {
99 onSurfaceChanged: {
100 if (surface) {
100 if (surface) {
101− surface.parent = root;
101+ surface.parent = inputMethodRoot;
102− surface.anchors.fill = root;
102+ surface.anchors.fill = inputMethodRoot;
103 }
103 }
104 }
104 }
105
105
qml/Wizard/Page.qml+4
@@ -50,6 +50,10 @@ Item {
50 property bool skipValid: true
50 property bool skipValid: true
51 property bool skip: false
51 property bool skip: false
52
52
53+ // Marks if should be only shown if update or install
54+ property bool onlyOnUpdate: false
55+ property bool onlyOnInstall: false
56+
53 property bool hasBackButton: true
57 property bool hasBackButton: true
54 property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
58 property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
55 property bool customBack: false
59 property bool customBack: false
qml/Wizard/Pages.qml+50−8
@@ -105,6 +105,39 @@ StyledItem {
105 id: pageList
105 id: pageList
106 }
106 }
107
107
108+ ActivityIndicator {
109+ id: pagesSpinner
110+ anchors.centerIn: parent
111+ z: 100
112+ running: false
113+ visible: running
114+
115+ NumberAnimation on opacity {
116+ id: fadeInAnimation
117+ from: 0
118+ to: 1
119+ duration: 200
120+ }
121+
122+ onVisibleChanged: {
123+ if (visible) {
124+ opacity = 0;
125+ fadeInAnimation.start();
126+ } else {
127+ // impatientLoadingLabel.text = ""
128+ }
129+ }
130+ }
131+
132+ Timer {
133+ id: impatientLoadingTimer
134+ interval: 1700
135+ onTriggered: {
136+ console.warn("Impatient timer going off. Fix the wizard, it's too slow at skipping pages.")
137+ pagesSpinner.running = true;
138+ }
139+ }
140+
108 PageStack {
141 PageStack {
109 id: pageStack
142 id: pageStack
110 objectName: "pageStack"
143 objectName: "pageStack"
@@ -139,18 +172,21 @@ StyledItem {
139
172
140 function load(path) {
173 function load(path) {
141 if (currentPage) {
174 if (currentPage) {
142− currentPage.enabled = false
175+ currentPage.enabled = false;
143 }
176 }
144
177
145 // First load it invisible, check that we should actually use
178 // First load it invisible, check that we should actually use
146 // this page, and either skip it or continue.
179 // this page, and either skip it or continue.
147− push(path, {"opacity": 0, "enabled": false})
180+ push(path, {"opacity": 0, "enabled": false});
148
181
149 timeout.restart();
182 timeout.restart();
183+ impatientLoadingTimer.start();
184+
185+ console.info("Loading page " + currentPage.objectName);
150
186
151 // Check for immediate skip or not. We may have to wait for
187 // Check for immediate skip or not. We may have to wait for
152 // skipValid to be assigned (see Connections object below)
188 // skipValid to be assigned (see Connections object below)
153− checkSkip()
189+ checkSkip();
154
190
155 var isPrimaryPage = !currentPage.customTitle;
191 var isPrimaryPage = !currentPage.customTitle;
156 if (isPrimaryPage) {
192 if (isPrimaryPage) {
@@ -159,16 +195,22 @@ StyledItem {
159 currentPage.aboutToShowSecondary(UbuntuAnimation.BriskDuration);
195 currentPage.aboutToShowSecondary(UbuntuAnimation.BriskDuration);
160 }
196 }
161 }
197 }
162−
198+
163 function checkSkip() {
199 function checkSkip() {
164 if (!currentPage) { // may have had a parse error
200 if (!currentPage) { // may have had a parse error
201+ console.warn("Wizard page skipped due to possible parse error.");
165− next()
202+ next();
166 } else if (currentPage.skipValid) {
203 } else if (currentPage.skipValid) {
167 if (currentPage.skip) {
204 if (currentPage.skip) {
168− next()
205+ next();
206+ } else if ((currentPage.onlyOnUpdate && !wizard.isUpdate) ||
207+ (currentPage.onlyOnInstall && wizard.isUpdate)) {
208+ next();
169 } else {
209 } else {
210+ impatientLoadingTimer.stop()
211+ pagesSpinner.running = false;
170− currentPage.opacity = 1
212+ currentPage.opacity = 1;
171− currentPage.enabled = true
213+ currentPage.enabled = true;
172 timeout.stop();
214 timeout.stop();
173 }
215 }
174 }
216 }
qml/Wizard/Pages/10-welcome-update.qmlnew file+135
@@ -0,0 +1,135 @@
1+/*
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+import Wizard 0.1
20+import ".." as LocalComponents
21+
22+LocalComponents.Page {
23+ objectName: "welcomeUpdate"
24+
25+ hasBackButton: false
26+ customTitle: true
27+ buttonBarVisible: false
28+ onlyOnUpdate: true
29+
30+ Component.onCompleted: {
31+ state = "reanchored";
32+ }
33+
34+ states: State {
35+ name: "reanchored"
36+ AnchorChanges { target: bgImage; anchors.top: parent.top; anchors.bottom: parent.bottom }
37+ AnchorChanges { target: column;
38+ anchors.verticalCenter: parent.verticalCenter;
39+ anchors.top: undefined
40+ }
41+ }
42+
43+ SequentialAnimation {
44+ id: splashAnimation
45+ PauseAnimation { duration: UbuntuAnimation.BriskDuration }
46+ SmoothedAnimation {
47+ target: bgImage
48+ property: "height"
49+ to: units.gu(16)
50+ duration: UbuntuAnimation.BriskDuration
51+ }
52+ NumberAnimation {
53+ target: bgImage
54+ property: 'opacity'
55+ from: 1
56+ to: 0
57+ }
58+ }
59+
60+ Image {
61+ id: bgImage
62+ source: wideMode ? "data/Desktop_splash_screen_bkg.png" : "data/Phone_splash_screen_bkg.png"
63+ scale: Image.PreserveAspectFit
64+ anchors.left: parent.left
65+ anchors.right: parent.right
66+ anchors.bottom: parent.top // outside to let it slide down
67+ visible: opacity > 0
68+ }
69+
70+ Item {
71+ id: column
72+ anchors.leftMargin: leftMargin
73+ anchors.rightMargin: rightMargin
74+ anchors.left: parent.left
75+ anchors.right: parent.right
76+ anchors.top: parent.bottom // outside to let it slide in
77+ height: childrenRect.height
78+ visible: opacity > 0
79+
80+ Label {
81+ id: welcomeLabel
82+ anchors.left: parent.left
83+ anchors.right: parent.right
84+ horizontalAlignment: Text.AlignHCenter
85+ wrapMode: Text.Wrap
86+ fontSize: "x-large"
87+ font.weight: Font.Light
88+ lineHeight: 1.2
89+ text: i18n.tr("Welcome to ") + System.version.split("Base-Version: ")[1]
90+ color: whiteColor
91+ }
92+
93+ Label {
94+ id: welcomeText
95+ anchors.left: parent.left
96+ anchors.right: parent.right
97+ anchors.top: welcomeLabel.bottom
98+ anchors.topMargin: units.gu(2)
99+ horizontalAlignment: Text.AlignHCenter
100+ wrapMode: Text.Wrap
101+ fontSize: "large"
102+ font.weight: Font.Light
103+ lineHeight: 1.2
104+ text: i18n.tr("We will make sure your device is ready to use ") + System.version.split("Base-Version: ")[1]
105+ color: whiteColor
106+ }
107+
108+ Rectangle {
109+ anchors {
110+ top: welcomeText.bottom
111+ horizontalCenter: parent.horizontalCenter
112+ topMargin: units.gu(4)
113+ }
114+ color: "transparent"
115+ border.width: units.dp(1)
116+ border.color: whiteColor
117+ radius: units.dp(4)
118+ width: buttonLabel.paintedWidth + units.gu(6)
119+ height: buttonLabel.paintedHeight + units.gu(1.8)
120+
121+ Label {
122+ id: buttonLabel
123+ color: whiteColor
124+ text: i18n.tr("Next")
125+ fontSize: "medium"
126+ anchors.centerIn: parent
127+ }
128+ AbstractButton {
129+ objectName: "nextButton"
130+ anchors.fill: parent
131+ onClicked: pageStack.next();
132+ }
133+ }
134+ }
135+}
qml/Wizard/Pages/10-welcome.qml+1
@@ -27,6 +27,7 @@ LocalComponents.Page {
27
27
28 title: i18n.tr("Language")
28 title: i18n.tr("Language")
29 forwardButtonSourceComponent: forwardButton
29 forwardButtonSourceComponent: forwardButton
30+ onlyOnInstall: true
30
31
31 UbuntuLanguagePlugin {
32 UbuntuLanguagePlugin {
32 id: plugin
33 id: plugin
qml/Wizard/Pages/11-changelog.qmlnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2015-2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+import AccountsService 0.1
20+import ".." as LocalComponents
21+
22+LocalComponents.Page {
23+ objectName: "changelogPage"
24+ title: i18n.tr("What's new")
25+
26+ forwardButtonSourceComponent: forwardButton
27+ onlyOnUpdate: true
28+
29+
30+ Column {
31+ id: column
32+ spacing: units.gu(2)
33+
34+ anchors {
35+ fill: content
36+ leftMargin: wideMode ? parent.leftMargin : staticMargin
37+ rightMargin: wideMode ? parent.rightMargin : staticMargin
38+ topMargin: staticMargin
39+ }
40+
41+ Label {
42+ text: "This is where cool stuff would go"
43+ }
44+ }
45+
46+ Component {
47+ id: forwardButton
48+ LocalComponents.StackButton {
49+ text: i18n.tr("Next")
50+ onClicked: {
51+ if (d.validName) {
52+ AccountsService.realName = d.validName;
53+ }
54+ pageStack.next();
55+ }
56+ }
57+ }
58+}
qml/Wizard/Pages/30-wifi.qml+1
@@ -32,6 +32,7 @@ LocalComponents.Page {
32 forwardButtonSourceComponent: forwardButton
32 forwardButtonSourceComponent: forwardButton
33
33
34 readonly property bool connected: Connectivity.online
34 readonly property bool connected: Connectivity.online
35+ skip: connected
35
36
36 function getExtendedProperty(object, propertyName, defaultValue) {
37 function getExtendedProperty(object, propertyName, defaultValue) {
37 if (object && object.hasOwnProperty(propertyName)) {
38 if (object && object.hasOwnProperty(propertyName)) {
qml/Wizard/Pages/40-location.qmldeleted−290
@@ -1,290 +0,0 @@
1−/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import AccountsService 0.1
19−import QMenuModel 0.1 as QMenuModel
20−import Qt.labs.folderlistmodel 2.1
21−import Ubuntu.Components 1.3
22−import ".." as LocalComponents
23−
24−LocalComponents.Page {
25− objectName: "locationPage"
26−
27− title: i18n.tr("Location Services")
28− forwardButtonSourceComponent: forwardButton
29−
30− readonly property bool pathSet: AccountsService.hereLicensePathValid
31− skipValid: pathSet && (AccountsService.hereLicensePath === "" || termsModel.count > 0)
32− skip: skipValid && (AccountsService.hereLicensePath === "" || termsModel.count === 2) // no files but . and ..
33−
34− FolderListModel {
35− id: termsModel
36− folder: AccountsService.hereLicensePath
37− nameFilters: ["*.html"]
38− showOnlyReadable: true
39− showDotAndDotDot: true // so that count == 0 means we're not done scanning yet
40− }
41−
42− QMenuModel.QDBusActionGroup {
43− id: locationActionGroup
44− objectName: "locationActionGroup"
45− busType: QMenuModel.DBus.SessionBus
46− busName: "com.canonical.indicator.location"
47− objectPath: "/com/canonical/indicator/location"
48− property variant location: action("location-detection-enabled")
49− property variant gps: action("gps-detection-enabled")
50− Component.onCompleted: start()
51− }
52−
53− Item {
54− id: column
55− anchors.fill: content
56− anchors.topMargin: customMargin
57− anchors.leftMargin: wideMode ? parent.leftMargin : 0
58− anchors.rightMargin: wideMode ? parent.rightMargin : 0
59−
60− Item {
61− id: hereCheckGroup
62− anchors {
63− left: parent.left
64− right: parent.right
65− top: parent.top
66− }
67− height: hereCheckLabel.height + hereTermsLabel.height
68−
69− Label {
70− id: hereCheckLabel
71− objectName: "hereCheckLabel"
72− anchors {
73− left: parent.left
74− right: hereTermsCheck.left
75− top: parent.top
76− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
77− rightMargin: units.gu(2)
78− }
79− lineHeight: 1.2
80− wrapMode: Text.WordWrap
81− color: textColor
82− font.weight: checked ? Font.Normal : Font.Light
83− text: i18n.tr("Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location (recommended)")
84− property bool checked: true
85− }
86−
87− Label {
88− id: hereTermsLabel
89− objectName: "hereTermsLabel"
90− anchors {
91− left: parent.left
92− right: hereTermsCheck.left
93− top: hereCheckLabel.bottom
94− topMargin: units.gu(1)
95− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
96− rightMargin: units.gu(2)
97− }
98−
99− wrapMode: Text.WordWrap
100− color: textColor
101− font.weight: Font.Light
102− fontSize: "small"
103− lineHeight: 1.2
104− linkColor: UbuntuColors.orange
105− text: i18n.tr("By selecting this option you agree to the Nokia HERE %1.")
106− .arg("<a href='#'>" + i18n.ctr("part of: Nokia HERE terms and conditions", "terms and conditions") + "</a>")
107− Mouse.forwardTo: hereCheckArea // clicking on the link also selects this group
108− Mouse.priority: Mouse.AfterItem
109− onLinkActivated: {
110− pageStack.load(Qt.resolvedUrl("here-terms.qml"));
111− }
112− }
113−
114− Image {
115− id: hereTermsCheck
116− fillMode: Image.PreserveAspectFit
117− height: units.gu(1.5)
118− source: "data/Tick@30.png"
119− opacity: hereCheckLabel.checked ? 1 : 0
120− anchors.right: parent.right
121− anchors.verticalCenter: hereCheckLabel.verticalCenter
122− anchors.rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
123− }
124−
125− MouseArea {
126− id: hereCheckArea
127− anchors.fill: parent
128− z: hereCheckGroup.z - 1 // so that the link can be activated
129− onClicked: {
130− if (!hereCheckLabel.checked) {
131− hereCheckLabel.checked = true;
132− gpsCheckLabel.checked = false;
133− nopeCheckLabel.checked = false;
134− }
135− }
136− }
137− }
138−
139− Rectangle {
140− id: divider
141− anchors.left: parent.left
142− anchors.right: parent.right
143− anchors.top: hereCheckGroup.bottom
144− anchors.topMargin: units.gu(3)
145− height: units.dp(1)
146− color: dividerColor
147− }
148−
149− Label {
150− id: gpsCheckLabel
151− objectName: "gpsCheckLabel"
152− anchors {
153− left: parent.left
154− right: parent.right
155− top: divider.bottom
156− topMargin: units.gu(3)
157− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
158− rightMargin: units.gu(2)
159− }
160− text: i18n.tr("GPS only")
161− wrapMode: Text.WordWrap
162− color: textColor
163− font.weight: checked ? Font.Normal : Font.Light
164− width: content.width
165− property bool checked: false
166−
167− MouseArea {
168− anchors.fill: parent
169− onClicked: {
170− if (!gpsCheckLabel.checked) {
171− hereCheckLabel.checked = false;
172− gpsCheckLabel.checked = true;
173− nopeCheckLabel.checked = false;
174− }
175− }
176− }
177− }
178−
179− Image {
180− fillMode: Image.PreserveAspectFit
181− height: units.gu(1.5)
182− source: "data/Tick@30.png"
183− opacity: gpsCheckLabel.checked ? 1 : 0
184− anchors.right: parent.right
185− anchors.verticalCenter: gpsCheckLabel.verticalCenter
186− anchors.rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
187− }
188−
189− Rectangle {
190− id: divider2
191− anchors.left: parent.left
192− anchors.right: parent.right
193− anchors.top: gpsCheckLabel.bottom
194− anchors.topMargin: units.gu(3)
195− height: units.dp(1)
196− color: dividerColor
197− }
198−
199− Label {
200− id: nopeCheckLabel
201− objectName: "nopeCheckLabel"
202− anchors {
203− left: parent.left
204− right: parent.right
205− top: divider2.bottom
206− topMargin: units.gu(3)
207− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
208− rightMargin: units.gu(2)
209− }
210− wrapMode: Text.WordWrap
211− color: textColor
212− font.weight: checked ? Font.Normal : Font.Light
213− width: content.width
214− text: i18n.tr("Don't use my location")
215− property bool checked: false
216−
217− MouseArea {
218− anchors.fill: parent
219− onClicked: {
220− if (!nopeCheckLabel.checked) {
221− hereCheckLabel.checked = false;
222− gpsCheckLabel.checked = false;
223− nopeCheckLabel.checked = true;
224− }
225− }
226− }
227− }
228−
229− Image {
230− fillMode: Image.PreserveAspectFit
231− height: units.gu(1.5)
232− source: "data/Tick@30.png"
233− opacity: nopeCheckLabel.checked ? 1 : 0
234− anchors.right: parent.right
235− anchors.verticalCenter: nopeCheckLabel.verticalCenter
236− anchors.rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
237− }
238−
239− Rectangle {
240− id: divider3
241− anchors.left: parent.left
242− anchors.right: parent.right
243− anchors.top: nopeCheckLabel.bottom
244− anchors.topMargin: units.gu(3)
245− height: units.dp(1)
246− color: dividerColor
247− }
248−
249− Label {
250− id: infoLabel
251− anchors {
252− left: parent.left
253− right: parent.right
254− top: divider3.bottom
255− topMargin: units.gu(4)
256− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
257− rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
258− }
259− wrapMode: Text.Wrap
260− text: i18n.tr("You can change it later in System Settings.")
261− color: textColor
262− fontSize: "small"
263− font.weight: Font.Light
264− width: content.width
265− }
266− }
267−
268− Component {
269− id: forwardButton
270− LocalComponents.StackButton {
271− text: i18n.tr("Next")
272− onClicked: {
273− var locationOn = gpsCheckLabel.checked || hereCheckLabel.checked;
274− var gpsOn = gpsCheckLabel.checked || hereCheckLabel.checked;
275− var hereOn = hereCheckLabel.checked;
276−
277− // location service doesn't currently listen to updateState
278− // requests, so we activate the actions if needed.
279− if (locationActionGroup.location.state != locationOn) {
280− locationActionGroup.location.activate();
281− }
282− if (locationActionGroup.gps.state != gpsOn) {
283− locationActionGroup.gps.activate();
284− }
285− AccountsService.hereEnabled = hereOn;
286− pageStack.next();
287− }
288− }
289− }
290−}
qml/Wizard/Pages/50-timezone.qml+1
@@ -36,6 +36,7 @@ LocalComponents.Page {
36
36
37 // for testing
37 // for testing
38 readonly property alias tdModule: timeDatePanel
38 readonly property alias tdModule: timeDatePanel
39+ onlyOnInstall: true
39
40
40 function highlightTimezone(offset) {
41 function highlightTimezone(offset) {
41 highlightImage.source = "data/timezonemap/timezone_" + offset + ".png";
42 highlightImage.source = "data/timezonemap/timezone_" + offset + ".png";
qml/Wizard/Pages/60-account.qml+1
@@ -24,6 +24,7 @@ LocalComponents.Page {
24 title: i18n.tr("Personalize Your Device")
24 title: i18n.tr("Personalize Your Device")
25
25
26 forwardButtonSourceComponent: forwardButton
26 forwardButtonSourceComponent: forwardButton
27+ onlyOnInstall: true
27
28
28 QtObject {
29 QtObject {
29 id: d
30 id: d
qml/Wizard/Pages/70-passwd-type.qml+1
@@ -44,6 +44,7 @@ LocalComponents.Page {
44 // or this isn't the first time the wizard has been run, etc). We can't
44 // or this isn't the first time the wizard has been run, etc). We can't
45 // properly set the password again, so let's not pretend we can.
45 // properly set the password again, so let's not pretend we can.
46 skip: securityPrivacy.securityType !== UbuntuSecurityPrivacyPanel.Swipe
46 skip: securityPrivacy.securityType !== UbuntuSecurityPrivacyPanel.Swipe
47+ onlyOnInstall: true
47
48
48 function indexToMethod(index) {
49 function indexToMethod(index) {
49 if (index === 0/* || index === 1*/)
50 if (index === 0/* || index === 1*/)
qml/Wizard/Pages/75-report-check.qml+1
@@ -27,6 +27,7 @@ LocalComponents.Page {
27 forwardButtonSourceComponent: !webview.visible ? forwardButton : null
27 forwardButtonSourceComponent: !webview.visible ? forwardButton : null
28 customBack: true
28 customBack: true
29 customTitle: webview.visible
29 customTitle: webview.visible
30+ onlyOnInstall: true
30
31
31 skip: !diagnostics.reportCrashes // skip the page when the system is configured not to report crashes
32 skip: !diagnostics.reportCrashes // skip the page when the system is configured not to report crashes
32
33
qml/Wizard/Pages/78-app-update.qmlnew file+238
@@ -0,0 +1,238 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2013-2016 Canonical Ltd.
5+ *
6+ * Contact: Didier Roche <didier.roches@canonical.com>
7+ * Diego Sarmentero <diego.sarmentero@canonical.com>
8+ * Jonas G. Drange <jonas.drange@canonical.com>
9+ *
10+ * This program is free software: you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License version 3, as published
12+ * by the Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but
15+ * WITHOUT ANY WARRANTY; without even the implied warranties of
16+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17+ * PURPOSE. See the GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along
20+ * with this program. If not, see <http://www.gnu.org/licenses/>.
21+ */
22+
23+import QMenuModel 0.1
24+import QtQuick 2.4
25+import QtQuick.Layouts 1.1
26+import Ubuntu.Components 1.3
27+import Ubuntu.Components.ListItems 1.3 as ListItem
28+import Ubuntu.Components.Popups 1.3
29+import Ubuntu.SystemSettings.Update 1.0
30+import Ubuntu.Connectivity 1.0
31+import Wizard 0.1
32+import ".." as LocalComponents
33+
34+LocalComponents.Page {
35+ id: appUpdatePage
36+ objectName: "appUpdatePage"
37+
38+ title: i18n.tr("Update Apps")
39+ forwardButtonSourceComponent: forwardButton
40+
41+ property bool batchMode: false
42+ property bool online: NetworkingStatus.online
43+ property bool authenticated: UpdateManager.authenticated
44+
45+ onlyOnUpdate: true
46+
47+ property int updatesCount: {
48+ var count = 0;
49+ if (authenticated) {
50+ count += clickRepeater.count;
51+ }
52+ return count;
53+ }
54+
55+ function check(force) {
56+ UpdateManager.check(UpdateManager.CheckClickIgnoreVersion);
57+ }
58+
59+ DownloadHandler {
60+ id: downloadHandler
61+ updateModel: UpdateManager.model
62+ }
63+
64+ Flickable {
65+ id: scrollWidget
66+ anchors {
67+ fill: content
68+ leftMargin: parent.leftMargin
69+ rightMargin: parent.rightMargin
70+ }
71+ clip: true
72+ contentHeight: scrollWidgetContent.height
73+ boundsBehavior: (contentHeight > scrollWidgetContent.height) ?
74+ Flickable.DragAndOvershootBounds :
75+ Flickable.StopAtBounds
76+ flickableDirection: Flickable.VerticalFlick
77+
78+ Column {
79+ id: scrollWidgetContent
80+ anchors {
81+ left: parent.left
82+ right: parent.right
83+ }
84+
85+ GlobalUpdateControls {
86+ id: g
87+ objectName: "global"
88+ anchors { left: parent.left; right: parent.right }
89+
90+ height: hidden ? 0 : units.gu(8)
91+ clip: true
92+ status: UpdateManager.status
93+ batchMode: appUpdatePage.batchMode
94+ updatesCount: appUpdatePage.updatesCount
95+ online: appUpdatePage.online
96+ onStop: UpdateManager.cancel()
97+
98+ onRequestInstall: {
99+ install();
100+ }
101+ onInstall: {
102+ appUpdatePage.batchMode = true
103+ postClickBatchHandler.target = appUpdatePage;
104+ }
105+ }
106+
107+ Rectangle {
108+ id: overlay
109+ objectName: "overlay"
110+ anchors {
111+ left: parent.left
112+ leftMargin: units.gu(2)
113+ right: parent.right
114+ rightMargin: units.gu(2)
115+ }
116+ visible: placeholder.text
117+ color: theme.palette.normal.background
118+ height: units.gu(10)
119+
120+ Label {
121+ id: placeholder
122+ objectName: "overlayText"
123+ anchors.fill: parent
124+ verticalAlignment: Text.AlignVCenter
125+ horizontalAlignment: Text.AlignHCenter
126+ wrapMode: Text.WordWrap
127+ text: {
128+ var s = UpdateManager.status;
129+ if (!appUpdatePage.online) {
130+ return i18n.tr("Connect to the Internet to check for updates.");
131+ } else if (s === UpdateManager.StatusIdle && updatesCount === 0) {
132+ return i18n.tr("Software is up to date");
133+ } else if (s === UpdateManager.StatusServerError ||
134+ s === UpdateManager.StatusNetworkError) {
135+ return i18n.tr("The update server is not responding. Try again later.");
136+ }
137+ return "";
138+ }
139+ }
140+ }
141+
142+ Column {
143+ id: clickUpdatesCol
144+ objectName: "clickUpdates"
145+ anchors { left: parent.left; right: parent.right }
146+ visible: {
147+ var s = UpdateManager.status;
148+ var haveUpdates = clickRepeater.count > 0;
149+ switch (s) {
150+ case UpdateManager.StatusCheckingImageUpdates:
151+ case UpdateManager.StatusIdle:
152+ return haveUpdates && online && authenticated;
153+ }
154+ return false;
155+ }
156+
157+ Repeater {
158+ id: clickRepeater
159+ model: UpdateManager.clickUpdates
160+
161+ delegate: ClickUpdateDelegate {
162+ objectName: "clickUpdatesDelegate" + index
163+ width: clickUpdatesCol.width
164+ updateState: model.updateState
165+ progress: model.progress
166+ version: remoteVersion
167+ size: model.size
168+ name: title
169+ iconUrl: model.iconUrl
170+ kind: model.kind
171+ error: model.error
172+ signedUrl: signedDownloadUrl
173+
174+ onInstall: downloadHandler.createDownload(model);
175+ onPause: downloadHandler.pauseDownload(model)
176+ onResume: downloadHandler.resumeDownload(model)
177+ onRetry: {
178+ /* This creates a new signed URL with which we can
179+ retry the download. See onSignedUrlChanged. */
180+ UpdateManager.retry(model.identifier,
181+ model.revision);
182+ }
183+
184+ onSignedUrlChanged: {
185+ // If we have a signedUrl, user intend to retry.
186+ if (signedUrl) {
187+ downloadHandler.retryDownload(model);
188+ }
189+ }
190+
191+ Connections {
192+ target: g
193+ onInstall: install()
194+ }
195+
196+ /* If we a downloadId, we expect UDM to restore it
197+ after some time. Workaround for lp:1603770. */
198+ Timer {
199+ id: downloadTimeout
200+ interval: 30000
201+ running: true
202+ onTriggered: {
203+ var s = updateState;
204+ if (model.downloadId
205+ || s === Update.StateQueuedForDownload
206+ || s === Update.StateDownloading) {
207+ downloadHandler.assertDownloadExist(model);
208+ }
209+ }
210+ }
211+ }
212+ }
213+ }
214+ } // Column inside flickable
215+ } // Flickable
216+
217+ Connections {
218+ id: postClickBatchHandler
219+ ignoreUnknownSignals: true
220+ target: null
221+ onUpdatesCountChanged: {
222+ if (target.updatesCount === 0) {
223+ appUpdatePage.batchMode = false;
224+ target = null;
225+ }
226+ }
227+ }
228+
229+ Component.onCompleted: check()
230+
231+ Component {
232+ id: forwardButton
233+ LocalComponents.StackButton {
234+ text: (UpdateManager.status === UpdateManager.StatusIdle && updatesCount === 0) ? i18n.tr("Next") : i18n.tr("Skip")
235+ onClicked: pageStack.next()
236+ }
237+ }
238+}
qml/Wizard/Pages/80-finished.qml+3−2
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
19+import Wizard 0.1
19import ".." as LocalComponents
20import ".." as LocalComponents
20
21
21LocalComponents.Page {
22LocalComponents.Page {
@@ -86,7 +87,7 @@ LocalComponents.Page {
86 fontSize: "x-large"
87 fontSize: "x-large"
87 font.weight: Font.Light
88 font.weight: Font.Light
88 lineHeight: 1.2
89 lineHeight: 1.2
89− text: i18n.tr("Welcome to Ubuntu")
90+ text: (System.isUpdate) ? i18n.tr("Welcome Back") : i18n.tr("Welcome to Ubuntu")
90 color: whiteColor
91 color: whiteColor
91 }
92 }
92
93
@@ -121,7 +122,7 @@ LocalComponents.Page {
121 Label {
122 Label {
122 id: buttonLabel
123 id: buttonLabel
123 color: whiteColor
124 color: whiteColor
124− text: i18n.tr("Get Started")
125+ text: (System.isUpdate) ? i18n.tr("Continue") : i18n.tr("Get Started")
125 fontSize: "medium"
126 fontSize: "medium"
126 anchors.centerIn: parent
127 anchors.centerIn: parent
127 }
128 }
qml/Wizard/Pages/ClickUpdateDelegate.qmlnew file+26
@@ -0,0 +1,26 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * This program is free software: you can redistribute it and/or modify it
7+ * under the terms of the GNU General Public License version 3, as published
8+ * by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope that it will be useful, but
11+ * WITHOUT ANY WARRANTY; without even the implied warranties of
12+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13+ * PURPOSE. See the GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+import QtQuick 2.4
20+import Ubuntu.SystemSettings.Update 1.0
21+
22+UpdateDelegate {
23+ id: update
24+
25+ property string signedUrl
26+}
qml/Wizard/Pages/DownloadHandler.qmlnew file+204
@@ -0,0 +1,204 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * This program is free software: you can redistribute it and/or modify it
7+ * under the terms of the GNU General Public License version 3, as published
8+ * by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope that it will be useful, but
11+ * WITHOUT ANY WARRANTY; without even the implied warranties of
12+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13+ * PURPOSE. See the GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17+ *
18+ */
19+import QtQuick 2.4
20+import Ubuntu.DownloadManager 1.2
21+
22+Item {
23+ id: downloadHandler
24+ property var updateModel
25+ property alias downloads: downloadManager.downloads
26+ property var udm: DownloadManager {
27+ id: downloadManager
28+ onDownloadFinished: {
29+ updateModel.setInstalled(download.metadata.custom.identifier,
30+ download.metadata.custom.revision);
31+ }
32+ onDownloadPaused: {
33+ updateModel.pauseUpdate(download.metadata.custom.identifier,
34+ download.metadata.custom.revision)
35+ }
36+ onDownloadResumed: {
37+ updateModel.resumeUpdate(download.metadata.custom.identifier,
38+ download.metadata.custom.revision)
39+ }
40+ onDownloadCanceled: {
41+ updateModel.cancelUpdate(download.metadata.custom.identifier,
42+ download.metadata.custom.revision)
43+ }
44+ onErrorFound: {
45+ updateModel.setError(download.metadata.custom.identifier,
46+ download.metadata.custom.revision,
47+ download.errorMessage)
48+ }
49+ onDownloadsChanged: restoreDownloads()
50+ Component.onCompleted: restoreDownloads()
51+ }
52+
53+ function downloadAll() {
54+
55+ }
56+
57+ function restoreDownloads() {
58+ var dl;
59+ for (var i = 0; i<downloads.length; i++) {
60+ dl = downloads[i];
61+ if (!dl._bound) {
62+ /* We only bind those signals here, that the UDM does not
63+ receive, i.e. processing and progressChanged. */
64+ dl.progressChanged.connect(onDownloadProgress.bind(dl));
65+ dl.processing.connect(onDownloadProcessing.bind(dl));
66+ dl._bound = true;
67+ }
68+ }
69+ }
70+
71+ function resumeDownload(click) {
72+ var download = getDownloadFor(click);
73+ if (download && !download.downloading && !download.isCompleted) {
74+ download.resume();
75+ }
76+ }
77+
78+ function pauseDownload(click) {
79+ var download = getDownloadFor(click);
80+ if (download && download.downloading) {
81+ download.pause();
82+ }
83+ }
84+
85+ // Return download for a click update.
86+ function getDownloadFor(click) {
87+ var cust;
88+ var dl;
89+
90+ for (var i = 0; i<downloads.length; i++) {
91+ dl = downloads[i];
92+ if (dl.errorMessage || dl.isCompleted) {
93+ // Ignore failed and completed downloads.
94+ continue;
95+ }
96+
97+ cust = downloads[i].metadata.custom;
98+ if (cust.identifier === click.identifier && cust.revision === click.revision) {
99+ return downloads[i];
100+ }
101+ }
102+ return null;
103+ }
104+
105+ function hasExistingDownload(click) {
106+ var existingDownload = getDownloadFor(click);
107+ return (existingDownload !== null &&
108+ !existingDownload.errorMessage &&
109+ !existingDownload.isCompleted);
110+ }
111+
112+ function retryDownload(click) {
113+ return createDownload(click, true);
114+ }
115+
116+ function createDownload(click, useSignedUrl) {
117+ if (hasExistingDownload(click)) {
118+ return null;
119+ }
120+ var downloadUrl = click.downloadUrl;
121+ var metadata = {
122+ "command": click.command,
123+ "title": click.title,
124+ "showInIndicator": false
125+ };
126+ var metadataObj = mdt.createObject(root, metadata);
127+ metadataObj.custom = {
128+ "identifier": click.identifier,
129+ "package-name": click.identifier,
130+ "revision": click.revision,
131+ };
132+
133+ var hdrs = {}
134+ if (useSignedUrl) {
135+ if (!click.signedDownloadUrl) {
136+ console.warn('The signed download URL was empty.');
137+ }
138+ downloadUrl = click.signedDownloadUrl;
139+ } else {
140+ // If we're using an unsigned URL, we need to provide this header.
141+ hdrs["X-Click-Token"] = click.token;
142+ }
143+
144+ var singleDownloadObj = sdl.createObject(root, {
145+ "autoStart": true,
146+ "hash": click.downloadHash,
147+ "algorithm": "sha512",
148+ "headers": hdrs,
149+ "metadata": metadataObj,
150+ "revision": click.revision,
151+ "identifier": click.identifier
152+ });
153+ singleDownloadObj.download(downloadUrl);
154+ return singleDownloadObj;
155+ }
156+
157+ function onDownloadProgress(progress) {
158+ updateModel.setProgress(this.metadata.custom.identifier,
159+ this.metadata.custom.revision,
160+ this.progress);
161+ }
162+
163+ function onDownloadProcessing() {
164+ updateModel.processUpdate(this.metadata.custom.identifier,
165+ this.metadata.custom.revision);
166+ }
167+
168+ /* If a update's model has a downloadId, check if UDM knows it. If not,
169+ treat this as a failure. Workaround for lp:1603770. */
170+ function assertDownloadExist(click) {
171+ if (!getDownloadFor(click)) {
172+ updateModel.setError(
173+ click.identifier, click.revision,
174+ i18n.tr("Installation failed")
175+ );
176+ }
177+ }
178+
179+ Component {
180+ id: sdl
181+ SingleDownload {
182+ id: download
183+ objectName: "singleDownload"
184+ property bool _bound: true
185+
186+ onDownloadIdChanged: {
187+ updateModel.queueUpdate(metadata.custom.identifier,
188+ metadata.custom.revision,
189+ downloadId);
190+ }
191+ onStarted: {
192+ updateModel.startUpdate(metadata.custom.identifier,
193+ metadata.custom.revision);
194+ }
195+ onProgressChanged: onDownloadProgress.call(download)
196+ onProcessing: onDownloadProcessing.call(download)
197+ }
198+ }
199+
200+ Component {
201+ id: mdt
202+ Metadata {}
203+ }
204+}
qml/Wizard/Pages/GlobalUpdateControls.qmlnew file+145
@@ -0,0 +1,145 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * This program is free software: you can redistribute it and/or modify it
7+ * under the terms of the GNU General Public License version 3, as published
8+ * by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope that it will be useful, but
11+ * WITHOUT ANY WARRANTY; without even the implied warranties of
12+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13+ * PURPOSE. See the GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+import QtQuick 2.4
20+import QtQuick.Layouts 1.1
21+import Ubuntu.Components 1.3
22+import Ubuntu.Components.ListItems 1.3 as ListItems
23+import Ubuntu.SystemSettings.Update 1.0
24+
25+Item {
26+ id: g
27+
28+ property bool batchMode
29+ property int status // A UpdateManager::Status
30+ property bool requireRestart: false
31+ property int updatesCount: 0
32+ property bool online: false
33+
34+ property bool hidden: {
35+ switch (status) {
36+ case UpdateManager.StatusNetworkError:
37+ case UpdateManager.StatusServerError:
38+ return true;
39+ }
40+ return !online ||
41+ (updatesCount <= 1 && status === UpdateManager.StatusIdle) ||
42+ batchMode
43+ }
44+
45+ signal stop()
46+ signal requestInstall()
47+ signal install()
48+
49+ Behavior on height {
50+ UbuntuNumberAnimation {}
51+ }
52+
53+ RowLayout {
54+ id: checking
55+ spacing: units.gu(2)
56+ anchors {
57+ fill: parent
58+ margins: units.gu(2)
59+ }
60+
61+ Behavior on opacity {
62+ UbuntuNumberAnimation {}
63+ }
64+
65+ opacity: visible ? 1 : 0
66+ visible: {
67+ switch (g.status) {
68+ case UpdateManager.StatusCheckingClickUpdates:
69+ case UpdateManager.StatusCheckingImageUpdates:
70+ case UpdateManager.StatusCheckingAllUpdates:
71+ return true;
72+ }
73+ return false;
74+ }
75+
76+ ActivityIndicator {
77+ running: parent.visible
78+ }
79+
80+ Label {
81+ objectName: "checkLabel"
82+ Layout.fillWidth: true
83+ elide: Text.ElideRight
84+ text: i18n.tr("Checking for updates…")
85+ }
86+
87+ Button {
88+ objectName: "updatesGlobalStopButton"
89+ text: i18n.tr("Stop")
90+ onClicked: g.stop()
91+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
92+ }
93+ }
94+
95+ RowLayout {
96+ id: install
97+ anchors {
98+ fill: parent
99+ margins: units.gu(2)
100+ }
101+ spacing: units.gu(2)
102+
103+ Behavior on opacity {
104+ UbuntuNumberAnimation {}
105+ }
106+
107+ opacity: visible ? 1 : 0
108+ visible: {
109+ var canInstall = g.status === UpdateManager.StatusIdle;
110+ return canInstall && updatesCount > 1;
111+ }
112+
113+ Label {
114+ objectName: "updatesGlobalInfoLabel"
115+ // // TRANSLATORS: %1 is number of software updates available.
116+ text: i18n.tr("%1 update available",
117+ "%1 updates available",
118+ updatesCount).arg(updatesCount)
119+ Layout.fillWidth: true
120+ }
121+
122+ Button {
123+ objectName: "updatesGlobalInstallButton"
124+ text: {
125+ if (g.requireRestart === true) {
126+ return i18n.tr("Update all…");
127+ } else {
128+ return i18n.tr("Update all");
129+ }
130+ }
131+ onClicked: g.requestInstall()
132+ color: theme.palette.normal.positive
133+ strokeColor: "transparent"
134+ }
135+ }
136+
137+ ListItems.ThinDivider {
138+ visible: !g.hidden
139+ anchors {
140+ left: parent.left
141+ right: parent.right
142+ bottom: parent.bottom
143+ }
144+ }
145+}
qml/Wizard/Pages/UpdateDelegate.qmlnew file+389
@@ -0,0 +1,389 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * Contact: Jonas G. Drange <jonas.drange@canonical.com>
7+ *
8+ * This program is free software: you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License version 3, as published
10+ * by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful, but
13+ * WITHOUT ANY WARRANTY; without even the implied warranties of
14+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15+ * PURPOSE. See the GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License along
18+ * with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ */
21+
22+import QtQuick 2.4
23+import QtQuick.Layouts 1.1
24+import Ubuntu.Components 1.3
25+import Ubuntu.Components.ListItems 1.3 as ListItems
26+import Ubuntu.Components.Themes 1.3
27+import Ubuntu.SystemSettings.Update 1.0
28+
29+ListItem {
30+ id: update
31+
32+ property int updateState // This is an Update::State
33+ property int kind // This is an Update::Kind
34+ property real size
35+ property string version
36+ property string downloadId
37+ property date updatedAt
38+ property bool launchable: false
39+
40+ property alias name: nameLabel.text
41+ property alias error: errorElementDetail.text
42+ property alias iconUrl: icon.source
43+ property alias progress: progressBar.value
44+
45+ signal retry()
46+ signal download()
47+ signal pause()
48+ signal resume()
49+ signal install()
50+ signal launch()
51+
52+ height: layout.height + (divider.visible ? divider.height : 0)
53+ Behavior on height {
54+ animation: UbuntuNumberAnimation {}
55+ }
56+
57+ SlotsLayout {
58+ id: layout
59+ mainSlot: ColumnLayout {
60+ spacing: units.gu(1)
61+ // Width the parent, minus the icon and some padding
62+ width: parent.width - (icon.width + (layout.padding.top * 3))
63+
64+ RowLayout {
65+ spacing: units.gu(2)
66+
67+ Label {
68+ id: nameLabel
69+ verticalAlignment: Text.AlignVCenter
70+ elide: Text.ElideMiddle
71+ Layout.fillWidth: true
72+ Layout.fillHeight: true
73+ }
74+
75+ Button {
76+ id: button
77+ objectName: "updateButton"
78+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
79+ visible: {
80+ switch (updateState) {
81+ case Update.StateInstalled:
82+ return launchable;
83+ default:
84+ return true;
85+ }
86+ }
87+ enabled: {
88+ switch(updateState) {
89+ case Update.StateAvailable:
90+ case Update.StateDownloading:
91+ case Update.StateDownloadingAutomatically:
92+ case Update.StateDownloadPaused:
93+ case Update.StateAutomaticDownloadPaused:
94+ case Update.StateInstallPaused:
95+ case Update.StateDownloaded:
96+ case Update.StateFailed:
97+ return true;
98+
99+ // Enabled if installed and a click app (can launch).
100+ case Update.StateInstalled:
101+ return kind === Update.KindClick;
102+
103+ case Update.StateInstalling:
104+ case Update.StateInstallingAutomatically:
105+ case Update.StateUnavailable:
106+ case Update.StateInstallFinished:
107+ case Update.StateQueuedForDownload:
108+ case Update.StateUnknown:
109+ default:
110+ return false;
111+ }
112+ }
113+ text: {
114+ switch(updateState) {
115+ case Update.StateUnknown:
116+ case Update.StateUnavailable:
117+ case Update.StateFailed:
118+ return i18n.tr("Retry");
119+
120+ case Update.StateAvailable:
121+ case Update.StateQueuedForDownload:
122+ if (update.kind === Update.KindClick) {
123+ return i18n.tr("Update");
124+ } else {
125+ return i18n.tr("Download");
126+ }
127+
128+ case Update.StateDownloadPaused:
129+ case Update.StateAutomaticDownloadPaused:
130+ case Update.StateInstallPaused:
131+ return i18n.tr("Resume");
132+
133+ case Update.StateDownloading:
134+ case Update.StateDownloadingAutomatically:
135+ case Update.StateInstalling:
136+ case Update.StateInstallingAutomatically:
137+ case Update.StateInstallFinished:
138+ return i18n.tr("Pause");
139+
140+ case Update.StateDownloaded:
141+ if (kind === Update.KindImage) {
142+ return i18n.tr("Install…");
143+ } else {
144+ return i18n.tr("Install");
145+ }
146+
147+ case Update.StateInstalled:
148+ return i18n.tr("Open");
149+
150+ default:
151+ console.error("Unknown update state", updateState);
152+ }
153+ }
154+
155+ onClicked: {
156+ switch (updateState) {
157+
158+ // Retries.
159+ case Update.StateUnknown:
160+ case Update.StateUnavailable:
161+ case Update.StateFailed:
162+ update.retry();
163+ break;
164+
165+ case Update.StateDownloadPaused:
166+ case Update.StateAutomaticDownloadPaused:
167+ case Update.StateInstallPaused:
168+ update.resume();
169+ break;
170+
171+ case Update.StateAvailable:
172+ if (kind === Update.KindClick) {
173+ update.install();
174+ } else {
175+ update.download();
176+ }
177+ break;
178+
179+ case Update.StateDownloaded:
180+ update.install();
181+ break;
182+
183+ case Update.StateDownloading:
184+ case Update.StateDownloadingAutomatically:
185+ case Update.StateInstalling:
186+ case Update.StateInstallingAutomatically:
187+ update.pause();
188+ break;
189+
190+ case Update.StateInstalled:
191+ update.launch();
192+ break;
193+ }
194+ }
195+ } // Button
196+ } // Name/button RowLayout
197+
198+ RowLayout {
199+ spacing: units.gu(2)
200+
201+ Label {
202+ id: downloadLabel
203+ objectName: "updateDownloadLabel"
204+
205+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
206+
207+ visible: text !== ""
208+
209+ fontSize: "small"
210+ text: {
211+ switch (updateState) {
212+
213+ case Update.StateInstalling:
214+ case Update.StateInstallingAutomatically:
215+ case Update.StateInstallPaused:
216+ return i18n.tr("Installing");
217+
218+ case Update.StateInstallPaused:
219+ case Update.StateDownloadPaused:
220+ return i18n.tr("Paused");
221+
222+ case Update.StateQueuedForDownload:
223+ return i18n.tr("Waiting to download");
224+
225+ case Update.StateDownloading:
226+ return i18n.tr("Downloading");
227+
228+ default:
229+ return "";
230+ }
231+ }
232+ }
233+
234+ Label {
235+ id: statusLabel
236+ objectName: "updateStatusLabel"
237+
238+ visible: text !== ""
239+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
240+ Layout.fillWidth: true
241+
242+ horizontalAlignment: Text.AlignRight
243+ fontSize: "small"
244+
245+ text: {
246+
247+ function humanFileSize(bytes, si) {
248+ var thresh = si ? 1000 : 1024;
249+ if(Math.abs(bytes) < thresh) {
250+ return bytes + ' B';
251+ }
252+ var units = si
253+ ? ['kB','MB','GB','TB','PB','EB','ZB','YB']
254+ : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
255+ var u = -1;
256+ do {
257+ bytes /= thresh;
258+ ++u;
259+ } while(Math.abs(bytes) >= thresh && u < units.length - 1);
260+ return bytes.toFixed(1)+' '+units[u];
261+ }
262+
263+ switch (updateState) {
264+ case Update.StateAvailable:
265+ return humanFileSize(size, 1000);
266+
267+ case Update.StateDownloading:
268+ case Update.StateDownloadingAutomatically:
269+ case Update.StateDownloadPaused:
270+ case Update.StateAutomaticDownloadPaused:
271+ var down = humanFileSize((size / 100) * progress, 1000);
272+ var left = humanFileSize(size, 1000);
273+ if (progress > 100) {
274+ return left;
275+ } else {
276+ /* TRANSLATORS: %1 is the human readable amount
277+ of bytes downloaded, and %2 is the total to be
278+ downloaded. */
279+ return i18n.tr("%1 of %2").arg(down).arg(left);
280+ }
281+
282+ case Update.StateDownloaded:
283+ return i18n.tr("Downloaded");
284+
285+ case Update.StateInstallFinished:
286+ return i18n.tr("Installed");
287+
288+ case Update.StateInstalled:
289+ /* TRANSLATORS: %1 is the date at which this
290+ update was applied. */
291+ return i18n.tr("Updated %1").arg(
292+ updatedAt.toLocaleDateString(Qt.locale(), "d MMMM")
293+ );
294+ default:
295+ return "";
296+ }
297+ }
298+
299+ /* Seems AlignRight causes a rendering issue that can be
300+ fixed by doing an explicit doLayout. */
301+ Component.onCompleted: doLayout()
302+ }
303+ }
304+
305+ Column {
306+ id: error
307+ objectName: "updateError"
308+ spacing: units.gu(1)
309+ height: childrenRect.height
310+ Layout.fillWidth: true
311+ visible: errorElementDetail.text
312+
313+ Label {
314+ id: errorElementTitle
315+ text: i18n.tr("Update failed")
316+ color: UbuntuColors.red
317+ }
318+
319+ Label {
320+ id: errorElementDetail
321+ anchors { left: parent.left; right: parent.right }
322+ fontSize: "small"
323+ wrapMode: Text.WrapAnywhere
324+ }
325+ } // Error column
326+
327+ ProgressBar {
328+ id: progressBar
329+ objectName: "updateProgressbar"
330+
331+ visible: {
332+ switch (updateState) {
333+ case Update.StateQueuedForDownload:
334+ case Update.StateDownloading:
335+ case Update.StateDownloadPaused:
336+ case Update.StateInstalling:
337+ case Update.StateInstallPaused:
338+ return true;
339+
340+ default:
341+ return false;
342+ }
343+ }
344+ Layout.maximumHeight: units.gu(0.5)
345+ Layout.fillWidth: true
346+ indeterminate: update.progress < 0 || update.progress > 100
347+ minimumValue: 0
348+ maximumValue: 100
349+ showProgressPercentage: false
350+
351+ Behavior on value {
352+ animation: UbuntuNumberAnimation {}
353+ }
354+ } // Progress bar
355+ } // Layout for the rest of the stuff
356+
357+ Item {
358+ SlotsLayout.position: SlotsLayout.Leading;
359+ width: units.gu(4)
360+ height: width
361+
362+ Image {
363+ id: icon
364+ visible: kind === Update.KindImage && !fallback.visible
365+ anchors.fill: parent
366+ asynchronous: true
367+ smooth: true
368+ mipmap: true
369+ }
370+
371+ UbuntuShape {
372+ id: shape
373+ visible: kind !== Update.KindImage && !fallback.visible
374+ anchors.fill: parent
375+ source: icon
376+ }
377+
378+ Image {
379+ id: fallback
380+ visible: icon.status === Image.Error
381+ source : Qt.resolvedUrl("/usr/share/icons/suru/apps/scalable/ubuntu-logo-symbolic.svg")
382+ anchors.fill: parent
383+ asynchronous: true
384+ smooth: true
385+ mipmap: true
386+ }
387+ }
388+ }
389+}
qml/Wizard/Pages/here-terms.qmldeleted−126
@@ -1,126 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Web 0.2
20−import ".." as LocalComponents
21−
22−LocalComponents.Page {
23− objectName: "hereTermsPage"
24−
25− title: i18n.tr("Terms & Conditions")
26− customBack: true
27− customTitle: true
28−
29− onBackClicked: {
30− if (webview.visible) {
31− showBrowser(false);
32− } else {
33− pageStack.prev();
34− }
35− }
36−
37− function showBrowser(show) {
38− if (show) {
39− label1.visible = false;
40− label2.visible = false;
41− label3.visible = false;
42− label4.visible = false;
43− webview.visible = true;
44− } else {
45− webview.visible = false;
46− label1.visible = true;
47− label2.visible = true;
48− label3.visible = true;
49− label4.visible = true;
50− }
51− }
52−
53− Column {
54− id: column
55− anchors.fill: content
56− anchors.leftMargin: staticMargin
57− anchors.rightMargin: wideMode ? parent.rightMargin : staticMargin
58− spacing: units.gu(3)
59−
60− Label {
61− id: label1
62− anchors.left: parent.left
63− anchors.right: parent.right
64− wrapMode: Text.Wrap
65− color: textColor
66− fontSize: "small"
67− font.weight: Font.Light
68− lineHeight: 1.2
69− text: i18n.tr("Your device uses positioning technologies provided by HERE.")
70− }
71−
72− Label {
73− id: label2
74− anchors.left: parent.left
75− anchors.right: parent.right
76− wrapMode: Text.Wrap
77− color: textColor
78− fontSize: "small"
79− font.weight: Font.Light
80− lineHeight: 1.2
81− text: i18n.tr("To provide you with positioning services and to improve their quality, HERE collects information about nearby cell towers and Wi-Fi hotspots around your current location whenever your position is being found.")
82− }
83−
84− Label {
85− id: label3
86− anchors.left: parent.left
87− anchors.right: parent.right
88− wrapMode: Text.Wrap
89− color: textColor
90− fontSize: "small"
91− font.weight: Font.Light
92− lineHeight: 1.2
93− text: i18n.tr("The information collected is used to analyze the service and to improve the use of service, but not to identify you personally.")
94− }
95−
96− Label {
97− id: label4
98− anchors.left: parent.left
99− anchors.right: parent.right
100− wrapMode: Text.Wrap
101− color: textColor
102− fontSize: "small"
103− font.weight: Font.Light
104− lineHeight: 1.2
105− linkColor: UbuntuColors.orange
106− text: i18n.tr("By continuing, you agree to the HERE platform %1 and %2.")
107− .arg("<a href=\"http://here.com/terms/service-terms\">" + i18n.tr("Service Terms") + "</a>")
108− .arg("<a href=\"http://here.com/privacy/privacy-policy\">" + i18n.tr("Privacy Policy") + "</a>");
109− onLinkActivated: {
110− showBrowser(true);
111− webview.url = link;
112− }
113− }
114−
115− WebView {
116− id: webview
117− objectName: "webview"
118− anchors.left: parent.left
119− anchors.right: parent.right
120− anchors.leftMargin: -leftMargin
121− anchors.rightMargin: -rightMargin
122− height: parent.height
123− visible: false
124− }
125− }
126−}
qml/Wizard/Wizard.qml+4−2
@@ -20,7 +20,7 @@ import Wizard 0.1
20import "../Components"
20import "../Components"
21
21
22Showable {
22Showable {
23− id: root
23+ id: wizard
24
24
25 // This is a bool instead of an alias because Loader classes like to emit
25 // This is a bool instead of an alias because Loader classes like to emit
26 // changed signals for 'active' during startup even if they aren't actually
26 // changed signals for 'active' during startup even if they aren't actually
@@ -29,6 +29,8 @@ Showable {
29 // expected behavior of no emission on startup.
29 // expected behavior of no emission on startup.
30 readonly property bool active: loader.active
30 readonly property bool active: loader.active
31
31
32+ property bool isUpdate: System.isUpdate
33+
32 // The wizard should be run at a later time if, for example, unity8 is
34 // The wizard should be run at a later time if, for example, unity8 is
33 // in greeter mode
35 // in greeter mode
34 property bool deferred: false
36 property bool deferred: false
@@ -49,7 +51,7 @@ Showable {
49
51
50 Connections {
52 Connections {
51 target: loader.item
53 target: loader.item
52− onQuit: root.hide()
54+ onQuit: wizard.hide()
53 }
55 }
54 }
56 }
55}
57}
tests/plugins/CMakeLists.txt+1−1
@@ -8,5 +8,5 @@ add_subdirectory(LightDM)
8add_subdirectory(SessionBroadcast)
8add_subdirectory(SessionBroadcast)
9add_subdirectory(Ubuntu)
9add_subdirectory(Ubuntu)
10add_subdirectory(Unity)
10add_subdirectory(Unity)
11−#add_subdirectory(Utils) #FIXME broken with qt 5.9
11+add_subdirectory(Utils)
12add_subdirectory(Wizard)
12add_subdirectory(Wizard)
tests/plugins/Ubuntu/CMakeLists.txt+1−1
@@ -1 +1 @@
1−#add_subdirectory(Gestures) #FIXME broken with qt 5.9
1+add_subdirectory(Gestures)
tests/plugins/Ubuntu/Gestures/GestureTest.cpp+1−1
@@ -107,7 +107,7 @@ void GestureTest::sendTouch(qint64 timestamp, int id, QPointF pos,
107 QCoreApplication::sendEvent(m_view, &touchEvent);
107 QCoreApplication::sendEvent(m_view, &touchEvent);
108
108
109 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(m_view);
109 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(m_view);
110− windowPrivate->flushDelayedTouchEvent();
110+ windowPrivate->flushFrameSynchronousEvents();
111}
111}
112
112
113void GestureTest::passTime(qint64 timeSpanMs)
113void GestureTest::passTime(qint64 timeSpanMs)
tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+1−1
@@ -189,7 +189,7 @@ void tst_TouchGate::holdsEventsUntilGainsOwnership()
189 if (!ownershipAfterTouchEnd) {
189 if (!ownershipAfterTouchEnd) {
190 touchRegistry->removeCandidateOwnerForTouch(0, candidateItem);
190 touchRegistry->removeCandidateOwnerForTouch(0, candidateItem);
191 QQuickWindowPrivate *wp = QQuickWindowPrivate::get(testItem->window());
191 QQuickWindowPrivate *wp = QQuickWindowPrivate::get(testItem->window());
192− wp->flushDelayedTouchEvent();
192+ wp->flushFrameSynchronousEvents();
193 // TouchGate should now open its flood gates and let testItem get all
193 // TouchGate should now open its flood gates and let testItem get all
194 // events from touch 0 produced so far
194 // events from touch 0 produced so far
195 QCOMPARE(testItem->touchEventsReceived.count(), 2);
195 QCOMPARE(testItem->touchEventsReceived.count(), 2);
tests/plugins/Utils/ModelTest.cpp+1−1
@@ -441,7 +441,7 @@ void ModelTest::data()
441 QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
441 QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
442 if ( textAlignmentVariant.isValid() ) {
442 if ( textAlignmentVariant.isValid() ) {
443 int alignment = textAlignmentVariant.toInt();
443 int alignment = textAlignmentVariant.toInt();
444− QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
444+ QCOMPARE( alignment, (int) ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ));
445 }
445 }
446
446
447 // General Purpose roles that should return a QColor
447 // General Purpose roles that should return a QColor
tests/qmltests/CMakeLists.txt+2−2
@@ -1,5 +1,5 @@
1
1
2−#add_subdirectory(Components) #FIXME broken with qt 5.9
2+add_subdirectory(Components)
3
3
4add_unity8_qmltest(. OrientedShell)
4add_unity8_qmltest(. OrientedShell)
5add_unity8_qmltest(. DisabledScreenNotice)
5add_unity8_qmltest(. DisabledScreenNotice)
@@ -44,7 +44,7 @@ add_unity8_qmltest(Dash/Previews PreviewIconActions)
44add_unity8_qmltest(Dash/Previews PreviewImageGallery)
44add_unity8_qmltest(Dash/Previews PreviewImageGallery)
45add_unity8_qmltest(Dash/Previews PreviewInlineVideo)
45add_unity8_qmltest(Dash/Previews PreviewInlineVideo)
46add_unity8_qmltest(Dash/Previews PreviewMediaToolbar)
46add_unity8_qmltest(Dash/Previews PreviewMediaToolbar)
47−add_unity8_qmltest(Dash/Previews PreviewPayments)
47+#add_unity8_qmltest(Dash/Previews PreviewPayments)
48add_unity8_qmltest(Dash/Previews PreviewProgress)
48add_unity8_qmltest(Dash/Previews PreviewProgress)
49add_unity8_qmltest(Dash/Previews PreviewRatingDisplay)
49add_unity8_qmltest(Dash/Previews PreviewRatingDisplay)
50add_unity8_qmltest(Dash/Previews PreviewRatingDisplayCreationRanges)
50add_unity8_qmltest(Dash/Previews PreviewRatingDisplayCreationRanges)
tests/qmltests/Components/tst_DragHandle.cpp+2−2
@@ -177,7 +177,7 @@ void tst_DragHandle::flickAndHold(QQuickItem *dragHandle,
177 QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
177 QTest::touchEvent(m_view, m_device).release(0, touchPoint.toPoint());
178
178
179 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(m_view);
179 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(m_view);
180− windowPrivate->flushDelayedTouchEvent();
180+ windowPrivate->flushFrameSynchronousEvents();
181}
181}
182
182
183void tst_DragHandle::drag(QPointF &touchPoint, const QPointF& direction, qreal distance,
183void tst_DragHandle::drag(QPointF &touchPoint, const QPointF& direction, qreal distance,
@@ -192,7 +192,7 @@ void tst_DragHandle::drag(QPointF &touchPoint, const QPointF& direction, qreal d
192 m_fakeTimeSource->m_msecsSinceReference += timeStep;
192 m_fakeTimeSource->m_msecsSinceReference += timeStep;
193 QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
193 QTest::touchEvent(m_view, m_device).move(0, touchPoint.toPoint());
194
194
195− windowPrivate->flushDelayedTouchEvent();
195+ windowPrivate->flushFrameSynchronousEvents();
196 }
196 }
197}
197}
198
198
tests/utils/CMakeLists.txt+1−1
@@ -1 +1 @@
1−#add_subdirectory(modules) #FIXME broken with qt 5.9
1+add_subdirectory(modules)
tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp−9
@@ -26,16 +26,7 @@ TouchEventSequenceWrapper::TouchEventSequenceWrapper(QTest::QTouchEventSequence
26
26
27void TouchEventSequenceWrapper::commit(bool processEvents)
27void TouchEventSequenceWrapper::commit(bool processEvents)
28{
28{
29− // Item might be deleted as a consequence of this event sequence being handled
30− // So store its window beforehand
31− QQuickWindow *window = m_item->window();
32−
33 m_eventSequence.commit(processEvents);
29 m_eventSequence.commit(processEvents);
34−
35− if (window) {
36− QQuickWindowPrivate *wp = QQuickWindowPrivate::get(window);
37− wp->flushDelayedTouchEvent();
38− }
39}
30}
40
31
41void TouchEventSequenceWrapper::move(int touchId, int x, int y)
32void TouchEventSequenceWrapper::move(int touchId, int x, int y)