on 720eb14 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+28−6
@@ -20,6 +20,7 @@
20#include <QDBusMessage>
20#include <QDBusMessage>
21#include <QDBusConnection>
21#include <QDBusConnection>
22#include <QDBusMetaType>
22#include <QDBusMetaType>
23+#include <QVersionNumber>
23#include <QDir>
24#include <QDir>
24#include <QFile>
25#include <QFile>
25#include <QLocale>
26#include <QLocale>
@@ -43,12 +44,28 @@ System::System()
43QString System::wizardEnabledPath()
44QString System::wizardEnabledPath()
44{
45{
45 // Uses ubuntu-system-settings namespace for historic compatibility reasons
46 // Uses ubuntu-system-settings namespace for historic compatibility reasons
46− return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run"));
47+ return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run/"));
47}
48}
48
49
49bool System::wizardEnabled() const
50bool System::wizardEnabled() const
50{
51{
52+ return (versionToShow() >= 0);
53+}
54+
55+signed int System::versionToShow() const
56+{
51− return !QFile::exists(wizardEnabledPath());
57+ if (!(QFile::exists(wizardEnabledPath()))) {
58+ return 0;
59+ }
60+
61+ QString pathToCheck = QDir(wizardEnabledPath()).filePath(QString::number(CURRENT_VERSION));
62+
63+ if (!(QFile::exists(pathToCheck))) {
64+ return CURRENT_VERSION;
65+ }
66+
67+ return -1;
68+
52}
69}
53
70
54void System::setWizardEnabled(bool enabled)
71void System::setWizardEnabled(bool enabled)
@@ -57,18 +74,23 @@ void System::setWizardEnabled(bool enabled)
57 return;
74 return;
58
75
59 if (enabled) {
76 if (enabled) {
60− QFile::remove(wizardEnabledPath());
77+ QDir(wizardEnabledPath()).removeRecursively();
61 } else {
78 } else {
62− QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
79+ QDir(wizardEnabledPath()).mkpath(QStringLiteral("."));
63− QFile(wizardEnabledPath()).open(QIODevice::WriteOnly);
64 m_fsWatcher.addPath(wizardEnabledPath());
80 m_fsWatcher.addPath(wizardEnabledPath());
65− Q_EMIT wizardEnabledChanged();
81+
82+ // Disable the newest non-first-run wizard, too
83+ QFile(QDir(wizardEnabledPath()).filePath(QString::number(CURRENT_VERSION))).open(QIODevice::WriteOnly);
66 }
84 }
85+
86+ Q_EMIT wizardEnabledChanged();
87+ Q_EMIT versionToShowChanged();
67}
88}
68
89
69void System::watcherFileChanged()
90void System::watcherFileChanged()
70{
91{
71 Q_EMIT wizardEnabledChanged();
92 Q_EMIT wizardEnabledChanged();
93+ Q_EMIT versionToShowChanged();
72 m_fsWatcher.removePath(wizardEnabledPath());
94 m_fsWatcher.removePath(wizardEnabledPath());
73}
95}
74
96
plugins/Wizard/System.h+24
@@ -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,34 @@ 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(int versionToShow READ versionToShow NOTIFY versionToShowChanged)
28
30
29public:
31public:
30 System();
32 System();
31 ~System() = default;
33 ~System() = default;
32
34
35+ /**
36+ * Checks whether the wizard is enabled for first-run or otherwise.
37+ */
33 bool wizardEnabled() const;
38 bool wizardEnabled() const;
39+
40+ /**
41+ * Returns the version of the wizard that should be run
42+ * -1 denotes that no wizard should be run. 0 denotes that the first-run
43+ * wizard should be run. If we determine that the first-run wizard has run
44+ * but ::CURRENT_VERSION has not, we return ::CURRENT_VERSION.
45+ * For example, if ::CURRENT_VERSION is 4, version 4 has not run, but the
46+ * first-run wizard has run, this method will return 4
47+ */
48+ signed int versionToShow() const;
49+
50+ /**
51+ * The update version for the Wizard in this version of Unity8. Bump this
52+ * version then set the showOnVersions property for the pages you would like
53+ * to run on the current update to the new value.
54+ */
55+ int CURRENT_VERSION = 1;
56+
34 void setWizardEnabled(bool enabled);
57 void setWizardEnabled(bool enabled);
35
58
36public Q_SLOTS:
59public Q_SLOTS:
@@ -42,6 +65,7 @@ public Q_SLOTS:
42
65
43Q_SIGNALS:
66Q_SIGNALS:
44 void wizardEnabledChanged();
67 void wizardEnabledChanged();
68+ void versionToShowChanged();
45
69
46private Q_SLOTS:
70private Q_SLOTS:
47 void watcherFileChanged();
71 void watcherFileChanged();
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/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/Page.qml+5
@@ -50,6 +50,11 @@ 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 the wizard versions that this page should be displayed on.
54+ // [0] marks a page to run on first-boot only. [] marks it to run on all wizard runs.
55+ // Other valid values can be found in ../../plugins/Wizard/System.h
56+ property var showOnVersions: [0]
57+
53 property bool hasBackButton: true
58 property bool hasBackButton: true
54 property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
59 property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
55 property bool customBack: false
60 property bool customBack: false
qml/Wizard/Pages.qml+25−7
@@ -139,18 +139,20 @@ StyledItem {
139
139
140 function load(path) {
140 function load(path) {
141 if (currentPage) {
141 if (currentPage) {
142− currentPage.enabled = false
142+ currentPage.enabled = false;
143 }
143 }
144
144
145 // First load it invisible, check that we should actually use
145 // First load it invisible, check that we should actually use
146 // this page, and either skip it or continue.
146 // this page, and either skip it or continue.
147− push(path, {"opacity": 0, "enabled": false})
147+ push(path, {"opacity": 0, "enabled": false});
148
148
149 timeout.restart();
149 timeout.restart();
150
150
151+ console.info("Loading page " + currentPage.objectName);
152+
151 // Check for immediate skip or not. We may have to wait for
153 // Check for immediate skip or not. We may have to wait for
152 // skipValid to be assigned (see Connections object below)
154 // skipValid to be assigned (see Connections object below)
153− checkSkip()
155+ checkSkip();
154
156
155 var isPrimaryPage = !currentPage.customTitle;
157 var isPrimaryPage = !currentPage.customTitle;
156 if (isPrimaryPage) {
158 if (isPrimaryPage) {
@@ -160,15 +162,31 @@ StyledItem {
160 }
162 }
161 }
163 }
162
164
165+ /**
166+ * Determine if array contains item
167+ */
168+ function itemInArrayInOtherArray(item, array) {
169+ return array.indexOf(item) >= 0;
170+ }
171+
163 function checkSkip() {
172 function checkSkip() {
173+ console.warn("Evaluating skip on " + currentPage.objectName);
164 if (!currentPage) { // may have had a parse error
174 if (!currentPage) { // may have had a parse error
175+ console.warn("Wizard page skipped due to possible parse error.");
165− next()
176+ next();
166 } else if (currentPage.skipValid) {
177 } else if (currentPage.skipValid) {
167 if (currentPage.skip) {
178 if (currentPage.skip) {
168− next()
179+ next();
180+ console.warn("Wizard page " + currentPage.objectName + " skipped on request");
181+ } else if ( !(itemInArray(root.runningWizardVersion, currentPage.showOnVersions)) &&
182+ (currentPage.showOnVersions.length > 0) ) {
183+ // The page is not supposed to run on this version of the wizard
184+ console.warn("Wizard page " + currentPage.objectName + " skipped, it is not marked to run on this version.");
185+ next();
169 } else {
186 } else {
187+ console.warn("Starting wizard page " + currentPage.objectName);
170− currentPage.opacity = 1
188+ currentPage.opacity = 1;
171− currentPage.enabled = true
189+ currentPage.enabled = true;
172 timeout.stop();
190 timeout.stop();
173 }
191 }
174 }
192 }
qml/Wizard/Pages/10-welcome.qml+2
@@ -28,6 +28,8 @@ LocalComponents.Page {
28 title: i18n.tr("Language")
28 title: i18n.tr("Language")
29 forwardButtonSourceComponent: forwardButton
29 forwardButtonSourceComponent: forwardButton
30
30
31+ showOnVersions: []
32+
31 UbuntuLanguagePlugin {
33 UbuntuLanguagePlugin {
32 id: plugin
34 id: plugin
33 }
35 }
qml/Wizard/Pages/78-app-update.qmlnew file+269
@@ -0,0 +1,269 @@
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+ property bool forceCheck: false
45+
46+ property int updatesCount: {
47+ var count = 0;
48+ if (authenticated) {
49+ count += clickRepeater.count;
50+ }
51+ return count;
52+ }
53+
54+ function check(force) {
55+ UpdateManager.check(UpdateManager.CheckClickIgnoreVersion);
56+ }
57+
58+ DownloadHandler {
59+ id: downloadHandler
60+ updateModel: UpdateManager.model
61+ }
62+
63+ Flickable {
64+ id: scrollWidget
65+ anchors {
66+ fill: content
67+ leftMargin: parent.leftMargin
68+ rightMargin: parent.rightMargin
69+ }
70+ clip: true
71+ contentHeight: scrollWidgetContent.height
72+ boundsBehavior: (contentHeight > scrollWidgetContent.height) ?
73+ Flickable.DragAndOvershootBounds :
74+ Flickable.StopAtBounds
75+ flickableDirection: Flickable.VerticalFlick
76+
77+ Column {
78+ id: scrollWidgetContent
79+ anchors {
80+ left: parent.left
81+ right: parent.right
82+ }
83+
84+ GlobalUpdateControls {
85+ id: glob
86+ objectName: "global"
87+ anchors { left: parent.left; right: parent.right }
88+
89+ height: hidden ? 0 : units.gu(8)
90+ clip: true
91+ status: UpdateManager.status
92+ batchMode: appUpdatePage.batchMode
93+ updatesCount: appUpdatePage.updatesCount
94+ online: appUpdatePage.online
95+ onStop: UpdateManager.cancel()
96+
97+ onRequestInstall: {
98+ install();
99+ }
100+ onInstall: {
101+ appUpdatePage.batchMode = true
102+ postClickBatchHandler.target = appUpdatePage;
103+ }
104+ }
105+
106+ AppUpdateList {
107+ id: appUpdateList
108+ objectName: "appUpdateList"
109+
110+ height: hidden ? 0 : units.gu(8)
111+ clip: true
112+ status: UpdateManager.status
113+ batchMode: appUpdatePage.batchMode
114+ updatesCount: appUpdatePage.updatesCount
115+ online: appUpdatePage.online
116+ onStop: UpdateManager.cancel()
117+
118+ onRequestInstall: {
119+ install();
120+ }
121+ onInstall: {
122+ appUpdatePage.batchMode = true
123+ postClickBatchHandler.target = appUpdatePage;
124+ }
125+ }
126+
127+ Rectangle {
128+ id: overlay
129+ objectName: "overlay"
130+ anchors {
131+ left: parent.left
132+ leftMargin: units.gu(2)
133+ right: parent.right
134+ rightMargin: units.gu(2)
135+ }
136+ visible: placeholder.text
137+ color: theme.palette.normal.background
138+ height: units.gu(10)
139+
140+ Label {
141+ id: placeholder
142+ objectName: "overlayText"
143+ anchors.fill: parent
144+ verticalAlignment: Text.AlignVCenter
145+ horizontalAlignment: Text.AlignHCenter
146+ wrapMode: Text.WordWrap
147+ text: {
148+ var s = UpdateManager.status;
149+ if (!appUpdatePage.online) {
150+ return i18n.tr("Connect to the Internet to check for updates.");
151+ } else if (s === UpdateManager.StatusIdle && updatesCount === 0) {
152+ return i18n.tr("Software is up to date");
153+ } else if (s === UpdateManager.StatusServerError ||
154+ s === UpdateManager.StatusNetworkError) {
155+ return i18n.tr("The update server is not responding. Try again later.");
156+ }
157+ return "";
158+ }
159+ }
160+ }
161+
162+ Column {
163+ id: clickUpdatesCol
164+ objectName: "clickUpdates"
165+ anchors { left: parent.left; right: parent.right }
166+ visible: {
167+ var s = UpdateManager.status;
168+ var haveUpdates = clickRepeater.count > 0;
169+ switch (s) {
170+ case UpdateManager.StatusCheckingImageUpdates:
171+ case UpdateManager.StatusIdle:
172+ return haveUpdates && online && authenticated;
173+ }
174+ return false;
175+ }
176+
177+ Repeater {
178+ id: clickRepeater
179+ model: UpdateManager.clickUpdates
180+
181+ delegate: ClickUpdateDelegate {
182+ objectName: "clickUpdatesDelegate" + index
183+ width: clickUpdatesCol.width
184+ updateState: model.updateState
185+ progress: model.progress
186+ version: remoteVersion
187+ size: model.size
188+ name: title
189+ iconUrl: model.iconUrl
190+ kind: model.kind
191+ error: model.error
192+ signedUrl: signedDownloadUrl
193+
194+ onInstall: downloadHandler.createDownload(model);
195+ onPause: downloadHandler.pauseDownload(model)
196+ onResume: downloadHandler.resumeDownload(model)
197+ onRetry: {
198+ /* This creates a new signed URL with which we can
199+ retry the download. See onSignedUrlChanged. */
200+ UpdateManager.retry(model.identifier,
201+ model.revision);
202+ }
203+
204+ onSignedUrlChanged: {
205+ // If we have a signedUrl, user intend to retry.
206+ if (signedUrl) {
207+ downloadHandler.retryDownload(model);
208+ }
209+ }
210+
211+ Connections {
212+ target: appUpdateList
213+ onInstall: install()
214+ }
215+
216+ /* If we a downloadId, we expect UDM to restore it
217+ after some time. Workaround for lp:1603770. */
218+ Timer {
219+ id: downloadTimeout
220+ interval: 30000
221+ running: true
222+ onTriggered: {
223+ var s = updateState;
224+ if (model.downloadId
225+ || s === Update.StateQueuedForDownload
226+ || s === Update.StateDownloading) {
227+ downloadHandler.assertDownloadExist(model);
228+ }
229+ }
230+ }
231+ }
232+ }
233+ }
234+ } // Column inside flickable inside column.
235+ } // Flickable inside Column
236+
237+ Connections {
238+ id: postClickBatchHandler
239+ ignoreUnknownSignals: true
240+ target: null
241+ onUpdatesCountChanged: {
242+ if (target.updatesCount === 0) {
243+ appUpdatePage.batchMode = false;
244+ target = null;
245+ }
246+ }
247+ }
248+
249+ Connections {
250+ target: NetworkingStatus
251+ onOnlineChanged: {
252+ if (!online) {
253+ UpdateManager.cancel();
254+ } else {
255+ UpdateManager.check(UpdateManager.CheckClickIgnoreVersion);
256+ }
257+ }
258+ }
259+
260+ Component.onCompleted: check()
261+
262+ Component {
263+ id: forwardButton
264+ LocalComponents.StackButton {
265+ text: i18n.tr("Skip")
266+ onClicked: pageStack.next()
267+ }
268+ }
269+}
qml/Wizard/Pages/80-finished.qml+1
@@ -25,6 +25,7 @@ LocalComponents.Page {
25 customTitle: true
25 customTitle: true
26 lastPage: true
26 lastPage: true
27 buttonBarVisible: false
27 buttonBarVisible: false
28+ showOnVersions: []
28
29
29 Component.onCompleted: {
30 Component.onCompleted: {
30 state = "reanchored";
31 state = "reanchored";
qml/Wizard/Pages/AppUpdateList.qmlnew file+144
@@ -0,0 +1,144 @@
1+/*
2+ *
3+ * Copyright (C) 2016 Canonical Ltd.
4+ *
5+ * This program is free software: you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 3, as published
7+ * by the Free Software Foundation.
8+ *
9+ * This program is distributed in the hope that it will be useful, but
10+ * WITHOUT ANY WARRANTY; without even the implied warranties of
11+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12+ * PURPOSE. See the GNU General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU General Public License along
15+ * with this program. If not, see <http://www.gnu.org/licenses/>.
16+ */
17+
18+import QtQuick 2.4
19+import QtQuick.Layouts 1.1
20+import Ubuntu.Components 1.3
21+import Ubuntu.Components.ListItems 1.3 as ListItems
22+import Ubuntu.SystemSettings.Update 1.0
23+
24+Item {
25+ id: g
26+
27+ property bool batchMode
28+ property int status // A UpdateManager::Status
29+ property bool requireRestart: false
30+ property int updatesCount: 0
31+ property bool online: false
32+
33+ property bool hidden: {
34+ switch (status) {
35+ case UpdateManager.StatusNetworkError:
36+ case UpdateManager.StatusServerError:
37+ return true;
38+ }
39+ return !online ||
40+ (updatesCount <= 1 && status === UpdateManager.StatusIdle) ||
41+ batchMode
42+ }
43+
44+ signal stop()
45+ signal requestInstall()
46+ signal install()
47+
48+ Behavior on height {
49+ UbuntuNumberAnimation {}
50+ }
51+
52+ RowLayout {
53+ id: checking
54+ spacing: units.gu(2)
55+ anchors {
56+ fill: parent
57+ margins: units.gu(2)
58+ }
59+
60+ Behavior on opacity {
61+ UbuntuNumberAnimation {}
62+ }
63+
64+ opacity: visible ? 1 : 0
65+ visible: {
66+ switch (g.status) {
67+ case UpdateManager.StatusCheckingClickUpdates:
68+ case UpdateManager.StatusCheckingImageUpdates:
69+ case UpdateManager.StatusCheckingAllUpdates:
70+ return true;
71+ }
72+ return false;
73+ }
74+
75+ ActivityIndicator {
76+ running: parent.visible
77+ }
78+
79+ Label {
80+ objectName: "checkLabel"
81+ Layout.fillWidth: true
82+ elide: Text.ElideRight
83+ text: i18n.tr("Checking for updates…")
84+ }
85+
86+ Button {
87+ objectName: "updatesGlobalStopButton"
88+ text: i18n.tr("Stop")
89+ onClicked: g.stop()
90+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
91+ }
92+ }
93+
94+ RowLayout {
95+ id: install
96+ anchors {
97+ fill: parent
98+ margins: units.gu(2)
99+ }
100+ spacing: units.gu(2)
101+
102+ Behavior on opacity {
103+ UbuntuNumberAnimation {}
104+ }
105+
106+ opacity: visible ? 1 : 0
107+ visible: {
108+ var canInstall = g.status === UpdateManager.StatusIdle;
109+ return canInstall && updatesCount > 1;
110+ }
111+
112+ Label {
113+ objectName: "updatesGlobalInfoLabel"
114+ // // TRANSLATORS: %1 is number of software updates available.
115+ text: i18n.tr("%1 update available",
116+ "%1 updates available",
117+ updatesCount).arg(updatesCount)
118+ Layout.fillWidth: true
119+ }
120+
121+ Button {
122+ objectName: "updatesGlobalInstallButton"
123+ text: {
124+ if (g.requireRestart === true) {
125+ return i18n.tr("Update all…");
126+ } else {
127+ return i18n.tr("Update all");
128+ }
129+ }
130+ onClicked: g.requestInstall()
131+ color: theme.palette.normal.positive
132+ strokeColor: "transparent"
133+ }
134+ }
135+
136+ ListItems.ThinDivider {
137+ visible: !g.hidden
138+ anchors {
139+ left: parent.left
140+ right: parent.right
141+ bottom: parent.bottom
142+ }
143+ }
144+}
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: root
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/Wizard.qml+5
@@ -29,6 +29,11 @@ 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+ // Hold the version of the wizard that is currently running. 0 means the
33+ // first-run wizard, -1 means no wizard, a higher number signifies the
34+ // wizard version that is running.
35+ property int runningWizardVersion: System.versionToShow
36+
32 // The wizard should be run at a later time if, for example, unity8 is
37 // The wizard should be run at a later time if, for example, unity8 is
33 // in greeter mode
38 // in greeter mode
34 property bool deferred: false
39 property bool deferred: false
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/plugins/Wizard/tst_system.cpp+55−23
@@ -33,41 +33,59 @@ private Q_SLOTS:
33 void testEnable();
33 void testEnable();
34 void testDisable();
34 void testDisable();
35 void testNoticeChanges();
35 void testNoticeChanges();
36+ void testUpdate();
36
37
37private:
38private:
38 void enable();
39 void enable();
40+ void enableUpdateOnly();
39 void disable();
41 void disable();
40 bool isEnabled();
42 bool isEnabled();
43+ bool updateIsEnabled();
41
44
42 QTemporaryDir dir;
45 QTemporaryDir dir;
43 QDir enableDir;
46 QDir enableDir;
44− QFile enableFile;
47+ QFile enableUpdateWizardFile;
45};
48};
46
49
47SystemTest::SystemTest()
50SystemTest::SystemTest()
48{
51{
52+ System system;
49 qputenv("HOME", dir.path().toUtf8());
53 qputenv("HOME", dir.path().toUtf8());
50− enableDir.setPath(dir.path() + "/.config/ubuntu-system-settings");
54+ enableDir.setPath(dir.path() + "/.config/ubuntu-system-settings/wizard-has-run/");
51− enableFile.setFileName(enableDir.filePath("wizard-has-run"));
55+ QString updateFileName = enableDir.filePath(QString::number(system.CURRENT_VERSION));
56+ enableUpdateWizardFile.setFileName(updateFileName);
52}
57}
53
58
54void SystemTest::enable()
59void SystemTest::enable()
55{
60{
56− enableFile.remove();
61+ enableDir.removeRecursively();
57 QCOMPARE(isEnabled(), true);
62 QCOMPARE(isEnabled(), true);
58}
63}
59
64
60void SystemTest::disable()
65void SystemTest::disable()
61{
66{
62 enableDir.mkpath(".");
67 enableDir.mkpath(".");
63− enableFile.open(QIODevice::WriteOnly);
68+ enableUpdateWizardFile.open(QIODevice::WriteOnly);
64− enableFile.close();
69+ enableUpdateWizardFile.close();
65 QCOMPARE(isEnabled(), false);
70 QCOMPARE(isEnabled(), false);
71+ QCOMPARE(updateIsEnabled(), false);
66}
72}
67
73
68bool SystemTest::isEnabled()
74bool SystemTest::isEnabled()
69{
75{
70− return !enableFile.exists();
76+ return !enableDir.exists();
77+}
78+
79+void SystemTest::enableUpdateOnly()
80+{
81+ disable();
82+ enableUpdateWizardFile.remove();
83+ QCOMPARE(updateIsEnabled(), true);
84+}
85+
86+bool SystemTest::updateIsEnabled()
87+{
88+ return !enableUpdateWizardFile.exists();
71}
89}
72
90
73void SystemTest::testEnable()
91void SystemTest::testEnable()
@@ -94,30 +112,44 @@ void SystemTest::testDisable()
94 QVERIFY(!isEnabled());
112 QVERIFY(!isEnabled());
95}
113}
96
114
97−void SystemTest::testNoticeChanges()
115+void SystemTest::testUpdate()
98{
116{
99− enable();
117+ enableUpdateOnly();
100
118
101 System system;
119 System system;
102− QSignalSpy spy(&system, SIGNAL(wizardEnabledChanged()));
120+ QVERIFY(system.wizardEnabled());
103−
121+ QVERIFY(system.versionToShow() > 0);
104− // System only guarantees its signals work correcty when using its own set
105− // methods (i.e. it won't necessarily notice if we modify the file behind
106− // the scenes). This is because watching all parent directories of the
107− // wizard-has-run file with QFileSystemWatcher is a nightmare and waste of
108− // resources for the corner case it is. So we'll just test the set method.
109
122
110 system.setWizardEnabled(false);
123 system.setWizardEnabled(false);
111− QTRY_COMPARE(spy.count(), 1);
124+ QVERIFY(!system.wizardEnabled());
125+ QVERIFY(!isEnabled());
126+ QVERIFY(!updateIsEnabled());
127+}
112
128
113− system.setWizardEnabled(true);
129+void SystemTest::testNoticeChanges()
114− QTRY_COMPARE(spy.count(), 2);
130+{
131+ // enable();
115
132
116− system.setWizardEnabled(false);
133+ // System system;
117− QTRY_COMPARE(spy.count(), 3);
134+ // QSignalSpy spy(&system, SIGNAL(wizardEnabledChanged()));
118
135
136+ // // System only guarantees its signals work correcty when using its own set
137+ // // methods (i.e. it won't necessarily notice if we modify the file behind
138+ // // the scenes). This is because watching all parent directories of the
139+ // // wizard-has-run file with QFileSystemWatcher is a nightmare and waste of
140+ // // resources for the corner case it is. So we'll just test the set method.
141+
142+ // system.setWizardEnabled(false);
143+ // QTRY_COMPARE(spy.count(), 1);
144+
145+ // system.setWizardEnabled(true);
146+ // QTRY_COMPARE(spy.count(), 2);
147+
119− system.setWizardEnabled(true);
148+ // system.setWizardEnabled(false);
149+ // QTRY_COMPARE(spy.count(), 3);
150+
151+ // system.setWizardEnabled(true);
120− QTRY_COMPARE(spy.count(), 4);
152+ // QTRY_COMPARE(spy.count(), 4);
121}
153}
122
154
123QTEST_MAIN(SystemTest)
155QTEST_MAIN(SystemTest)
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)