1393 files changed+95331−104346
.bazaar/Makefilenew file+6
@@ -0,0 +1,6 @@
1+install:
2+ mkdir -p ~/.bazaar/plugins
3+ cp plugins/* ~/.bazaar/plugins
4+
5+uninstall:
6+ rm ~/.bazaar/plugins/makecheck_unity_phablet.py*
.bazaar/plugins/makecheck_unity_phablet.pynew file+51
@@ -0,0 +1,51 @@
1+#!/usr/bin/python
2+# Copyright 2013, 2014 Canonical Ltd.
3+#
4+# This program is free software; you can redistribute it and/or modify
5+# it under the terms of the GNU Lesser General Public License as published by
6+# the Free Software Foundation; version 3.
7+#
8+# This program is distributed in the hope that it will be useful,
9+# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+# GNU Lesser General Public License for more details.
12+#
13+# You should have received a copy of the GNU Lesser General Public License
14+# along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
16+import os
17+import subprocess
18+from bzrlib import branch
19+from bzrlib.urlutils import local_path_from_url
20+
21+
22+def execute_makecheck(
23+ local_branch, master_branch, old_revision_number, old_revision_id,
24+ future_revision_number, future_revision_id, tree_delta, future_tree):
25+ if not master_branch.basis_tree().has_filename("qml/Shell.qml"):
26+ return
27+
28+ os.chdir(local_path_from_url(master_branch.base))
29+
30+ print "Executing 'make -C builddir test'.."
31+ os.environ['CTEST_OUTPUT_ON_FAILURE'] = "1"
32+ if (subprocess.call("make -C builddir test", shell=True) != 0):
33+
34+ print("\n\n*** Warning ***\n\n"
35+ "Basic tests failed. This commit will not pass continuous "
36+ "integration.")
37+
38+ branch = local_branch or master_branch
39+ revision = branch.repository.get_revision(future_revision_id)
40+ msg_file = open('message.txt', 'w')
41+ msg_file.write(revision.message)
42+ msg_file.close()
43+
44+ print("\n\nSaved commit message to $SRC_DIR/message.txt.")
45+ print("You can uncommit this revision, fix the tests and reuse your "
46+ "message running:\n\nbzr commit -F message.txt\n\n")
47+ elif os.path.isfile("message.txt"):
48+ os.remove("message.txt")
49+
50+branch.Branch.hooks.install_named_hook(
51+ 'pre_commit', execute_makecheck, 'make check pre-commit')
.bzr-builddeb/default.confnew file+2
@@ -0,0 +1,2 @@
1+[BUILDDEB]
2+split = True
.bzrignorenew file+7
@@ -0,0 +1,7 @@
1+# default build dir
2+/builddir
3+# QtCreator project files
4+/*.user
5+# Eclipse project files
6+.settings
7+message.txt
.crossbuilder/post_deploydeleted−1
@@ -1 +0,0 @@
1−restart unity8
.gitignore−7
@@ -2,15 +2,8 @@
22/builddir
33# QtCreator project files
44/*.user
5−*.qmlc
6−*.jsc
75# Eclipse project files
86/.project
97/.cproject
108/.settings
119/.pydevproject
12−# KDevelop project Files
13−/.kdev4/
14−/build/
15−/*.kdev4
16−.clickable/
CMakeLists.txt+14−34
@@ -40,19 +40,6 @@ if(cmake_build_type_lower MATCHES coverage)
4040 ENABLE_COVERAGE_REPORT(TARGETS ${SHELL_APP} FILTER /usr/include ${CMAKE_SOURCE_DIR}/tests/* ${CMAKE_BINARY_DIR}/*)
4141endif()
4242
43−find_package (ECM 1.7.0 QUIET NO_MODULE)
44−if (ECM_FOUND)
45− # Provides us with -DECM_ENABLE_SANITIZERS='X'
46− # Where X can be address, thread, memory, leak, undefined
47− include("${ECM_MODULE_DIR}/ECMEnableSanitizers.cmake")
48−endif()
49−
50−if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
51− if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0")
52− set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override" )
53− endif()
54−endif()
55−
5643# Make sure we have all the needed symbols
5744set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
5845set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,defs")
@@ -62,31 +49,21 @@ add_custom_target(cppcheck COMMAND cppcheck --enable=all -q --error-exitcode=2
6249 ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/tests)
6350
6451include(FindPkgConfig)
65−find_package(Qt5Core 5.6 REQUIRED)
66−find_package(Qt5Qml 5.6 REQUIRED)
67−find_package(Qt5Quick 5.6 REQUIRED)
68−find_package(Qt5Gui 5.6 REQUIRED)
69−find_package(Qt5DBus 5.6 REQUIRED)
70−find_package(Qt5Concurrent 5.6 REQUIRED)
71−find_package(Qt5Sql 5.6 REQUIRED)
72−find_package(Qt5Test 5.6 REQUIRED)
73−find_package(Qt5Svg 5.6 REQUIRED)
74−find_package(Qt5Network 5.6 REQUIRED)
75−find_package(Qt5Xml 5.6 REQUIRED)
76−
77−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=27)
52+find_package(Qt5Core 5.4 REQUIRED)
53+find_package(Qt5Qml 5.4 REQUIRED)
54+find_package(Qt5Quick 5.4 REQUIRED)
55+find_package(Qt5Gui 5.4 REQUIRED)
56+find_package(Qt5DBus 5.4 REQUIRED)
57+find_package(Qt5Concurrent 5.4 REQUIRED)
58+find_package(Qt5Sql 5.4 REQUIRED)
59+
60+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=16)
7861pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
7962pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
8063pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
81−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=13)
8264pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
83−pkg_check_modules(GD3 REQUIRED gnome-desktop-3.0)
84−pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2)
65+
8566pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
86−pkg_check_modules(QTDBUSTEST REQUIRED
87− libqtdbustest-1
88− libqtdbusmock-1
89− )
9067
9168### Check UbuntuGestures private headers. No pkg-config (.pc) file is provided for them
9269find_path(UBUNTUGESTUREPRIV
@@ -148,8 +125,9 @@ include(autopilot)
148125declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
149126
150127set(SHELL_APP unity8)
128+set(DASH_APP unity8-dash)
129+set(SCOPE_TOOL unity-scope-tool)
151130set(INDICATORS_CLIENT_APP indicators-client)
152−set(GREETER_APP unity8-greeter)
153131set(MOCK_INDICATOR_SERVICE_APP unity-mock-indicator-service)
154132
155133include_directories(
@@ -158,6 +136,8 @@ include_directories(
158136 ${APPLICATION_API_INCLUDE_DIRS}
159137)
160138
139+set(ARTIFACTS_DIR "" CACHE PATH "Store test artifacts in this directory.")
140+
161141# Quiet logger
162142set(QUIET_LOGGER OFF CACHE BOOL "Disable test output on stdout.")
163143if(NOT QUIET_LOGGER)
CODING+59−44
@@ -15,17 +15,23 @@ download source
1515 $ bzr branch lp:unity8 ~/unity8/trunk
1616 $ cd ~/unity8/trunk
1717
18−install dependencies and build Unity 8
18+install dependencies
1919--------------------
20+If its your first time, install build dependencies
2021
2122$ cd ~/unity8/trunk
22−$ ./build.sh
23+$ ./build.sh --setup
24+
25+ this will:
26+ - install the required dependencies to build, as well as run on the desktop
27+ - it should also install unity-scope-home and unity-lens-application which
28+ are technically "recommends", not strict dependencies
2329
24− If its your first time, this will install the required dependencies to build and
25− build it.
30+build Unity 8
31+-------------
2632
27− You might want to also install unity-scope-home and unity-scope-click which
28− are technically "recommends", not strict dependencies
33+$ cd ~/unity8/trunk
34+$ ./build.sh
2935
3036You may also rebuild with the -c for clean, which just deletes the build
3137directory.
@@ -37,15 +43,13 @@ Running Unity 8 on your desktop
3743run the Unity 8 shell
3844---------------------
3945$ cd ~/unity8/trunk
40−$ cd builddir
46+$ ./run.sh
4147
42−Each component of unity8 can be ran independently for development and testing
43−For example:
44−$ make tryShell
45−$ make tryLauncher
46−$ make tryLockscreen
48+Options can be passed to test the lock screen
49+$ ./run.sh -p OR -k
4750
48−Check out the tests/qmltests/ directory for a list of things that can be ran.
51+-p is for pin lock, for which the default prompt answer is "1234"
52+-k is for keylock passphrase, for which the default prompt answer is "password"
4953
5054Notes
5155-----
@@ -66,15 +70,50 @@ Notes
6670
6771Running Unity 8 on devices
6872==========================
73+- Ubuntu Touch builds are currently only available in 14.04 flavour
74+- supported hardware should match one of those listed here
75+ https://wiki.ubuntu.com/Touch/Devices#Running_fine
76+- follow the Ubuntu Touch install instructions for your chosen device
77+ https://wiki.ubuntu.com/Touch/Install
78+- make sure your device is connected to a network
79+- also make sure you have your SSH key in ~/.ssh/id_rsa.pub (or install one
80+ on the device yourself)
81+
82+$ cd ~/unity/trunk
83+$ ./run_on_device.sh --setup
84+ this will:
85+ - install your public SSH key on the device
86+ - install the needed dependencies
6987
70−Running unity8 on a device should be done using crossbuilder.
71−Go to
72−* https://launchpad.net/crossbuilder and
73−* https://wiki.ubuntu.com/Touch/Crossbuilder
74−for more details on crossbuilder.
88+$ ./run_on_device.sh
89+ this will:
90+ - rsync the code to the device
91+ - build on the device
92+ - replace the running shell
93+
94+Options can be passed to test the lock screen
95+$ ./run_on_device.sh -p OR -k
96+
97+-p is for pin lock, for which the default prompt answer is "1234"
98+-k is for keylock passphrase, for which the default prompt answer is "password"
99+
100+Notes
101+-----
102+- using adb over TCP has some advantages, Google will be of help here
103+ - NOTE: this is not yet available for flipped images
104+ - TL;DR: `adb tcpip 5555; adb connect $your_device_ip`
105+ - you can persist the above via `adb shell setprop persist.adb.tcp.port 5555`
106+ - it's unsafe - anyone can connect to your device
107+ - with TCP the Nexus 10 doesn't drop the adb connection when locking
108+ the screen
109+- exporting ANDROID_SERIAL=$your_device_serial or
110+ ANDROID_SERIAL=$your_device_ip:5555 will make adb not complain about
111+ multiple devices
112+- you can export TARGET_IP=$your_device_ip TARGET_SSH_PORT=22 for run_on_device.sh
113+ to not use adb forwarding - useful if you use multiple devices
114+- using Ninja (package ninja-build - run_on_device.sh -s installs this now)
115+ will improve build times (especially in the nothing-to-build case)
75116
76−unity8 will automatically restart on the phone once deployment
77−has finished due to post-build-steps set up in this repository.
78117
79118Coding guidelines
80119=================
@@ -162,27 +201,3 @@ $ PYTHONPATH=../tests/autopilot autopilot3 run unity8.some.very.long.test.name
162201or run them all with
163202
164203$ PYTHONPATH=../tests/autopilot autopilot3 run unity8
165−
166−Debugging techniques
167−====================
168−
169−Unity8 heavily uses Qt and with that Qt debugging techniques mostly apply in the
170−same fashion. There are, however, some additional unity8-specific notes:
171−
172−* Enable/disable Qt scenegraph visualizer on the fly:
173−
174− $ qdbus com.canonical.Unity8.Debugging /com/canonical/Unity8/Debugging SetSceneGraphVisualizer <mode>
175−
176− This is equivalent to exporting QSG_VISUALIZE=<mode> before running unity8, except it does it on the
177− fly.
178−
179−* Toggle slow animations on the fly:
180−
181− $ qdbus com.canonical.Unity8.Debugging /com/canonical/Unity8/Debugging SetSlowAnimations <true|false>
182−
183−* Change logging filter rules on the fly:
184−
185− $ qdbus com.canonical.Unity8.Debugging /com/canonical/Unity8/Debugging SetLoggingFilterRules <filter>
186−
187− This is equivalent to exporting QT_LOGGING_RULES or defining them in QT_LOGGING_CONF, except it does
188− it on the fly.
Jenkinsfiledeleted−2
@@ -1,2 +0,0 @@
1−@Library('ubports-build-tools') _
2−buildAndProvideDebianPackage()
README.mddeleted−31
@@ -1,31 +0,0 @@
1−# Lomiri
2−
3−Lomiri is the operating environment for everywhere. It is able to span the gaps between touch, mouse, and keyboard; between phones, tablets, and workstations; and look good doing it.
4−
5−If you want to contribute to Lomiri on Ubuntu Touch, you've come to the right place. If you want to package Lomiri for other operating systems, you'll be better served by the main branch on the repository that we're migrating to: https://gitlab.com/ubports/core/lomiri
6−
7−Lomiri has been renamed from Unity8. Most of the software on-device in Ubuntu Touch based on Ubuntu 16.04 is still called `unity8`.
8−
9−## Where to report issues
10−
11−Issues related to the version of Lomiri that currently runs on Ubuntu Touch devices may still be reported on this repository. We will move these reports to the GitLab repository as part of our final migration.
12−
13−## Developing Lomiri on Ubuntu Touch
14−
15−This repository contains the code for Lomiri currently running on Ubuntu Touch. If you would like to modify this version of Lomiri, follow the steps below. If you would like to modify Lomiri in another operating system, check out our new repository: https://gitlab.com/ubports/core/lomiri
16−
17−Lomiri can be built and its test suite run using [`clickable`](https://clickable-ut.dev). This is a convenient method to try out most graphical changes to Lomiri without an annoying redeployment process. If you wish to test your changes on your device or make changes that are more difficult to test without real hardware, check out [Making changes and testing locally on the UBports documentation](https://docs.ubports.com/en/latest/systemdev/testing-locally.html). If not, read on.
18−
19−Before you start, [install Clickable](https://clickable-ut.dev/en/latest/install.html).
20−
21−Now, clone this repository to your computer: `git clone https://github.com/ubports/unity8.git`
22−
23−Move into this directory: `cd unity8`
24−
25−Now you can use the full suite of tools provided by this repository's [clickable.yaml](clickable.yaml). For example:
26−
27−* `clickable ide qtcreator` will open QtCreator with this repository open as a project. You can edit and build the project this way, but running the tests will be a bit difficult.
28−* `clickable build --libs --verbose` will build Lomiri in the same environment as it would receive in Ubuntu Touch.
29−* `clickable test --libs` will run the entire Lomiri test suite. This test suite includes graphical tests (which are run on a virtual, invisible desktop) and non-graphical unit tests. These tests make sure Lomiri functions as prescribed and prevents new bugs from being added. You should run them before you create a PR on this repository. This command takes about 7 minutes on an Intel i7-8550U, so plan your time accordingly and use the next two options to reduce the number of times you need to run the whole test suite...
30−* `clickable ide 'cd build/x86_64-linux-gnu/unity8/ && make tryShell'` and similar commands that replace the `Shell` with another test target defined in [tests/qmltests/CMakeLists.txt](tests/qmltests/CMakeLists.txt) allow trying out some Lomiri components in a mock environment. You can use this to try out your changes to Lomiri as you develop.
31−* `clickable ide 'cd build/x86_64-linux-gnu/unity8/ && make xvfbtestShell'` and similar commands that replace the `Shell` with another test target defined in [tests/qmltests/CMakeLists.txt](tests/qmltests/CMakeLists.txt) allow running a single TestCase. You can remove the `xvfb` part of the make target to run the test case graphically, which might help you see what is causing the test to fail.
build.sh+37−22
@@ -1,21 +1,5 @@
11#!/bin/sh
22
3−#
4−# Copyright (C) 2017 Canonical Ltd
5−#
6−# This program is free software: you can redistribute it and/or modify
7−# it under the terms of the GNU General Public License version 3 as
8−# published by the Free Software Foundation.
9−#
10−# This program is distributed in the hope that it will be useful,
11−# but WITHOUT ANY WARRANTY; without even the implied warranty of
12−# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13−# GNU General Public License for more details.
14−#
15−# You should have received a copy of the GNU General Public License
16−# along with this program. If not, see <http://www.gnu.org/licenses/>.
17−#
18−
193SETUP=false
204CLEAN=false
215NUM_JOBS=$(( `grep -c ^processor /proc/cpuinfo` + 1 ))
@@ -25,6 +9,7 @@ usage() {
259 echo "usage: build [OPTIONS] [BUILD_TYPE]\n" >&2
2610 echo "Script to build the shell. If BUILD_TYPE is not specified, it defaults to \"debug\".\n" >&2
2711 echo "OPTIONS:" >&2
12+ echo " -s, --setup Setup the build environment and branch Unity" >&2
2813 echo " -c, --clean Clean the build tree before building" >&2
2914 echo >&2
3015 exit 1
@@ -37,6 +22,7 @@ eval set -- "$ARGS"
3722while [ $# -gt 0 ]
3823do
3924 case "$1" in
25+ -s|--setup) SETUP=true;;
4026 -c|--clean) CLEAN=true;;
4127 -h|--help) usage;;
4228 --) shift;break;;
@@ -49,6 +35,31 @@ done
4935BUILD_TYPE="debug"
5036[ $# -eq 1 ] && BUILD_TYPE="$1"
5137
38+install_dependencies() {
39+ sudo apt-get update || exit 4
40+ echo "Installing Unity 8 dependencies.."
41+ sudo apt-get install devscripts \
42+ equivs \
43+ gsettings-desktop-schemas \
44+ gsettings-ubuntu-schemas \
45+ pay-service \
46+ qmenumodel-qml \
47+ qml-module-qtquick-layouts \
48+ qml-module-qtquick-xmllistmodel \
49+ qtdeclarative5-gsettings1.0 \
50+ qtdeclarative5-ubuntu-ui-toolkit-plugin \
51+ qtdeclarative5-ubuntu-settings-components \
52+ qtdeclarative5-ubuntu-telephony0.1 \
53+ qtdeclarative5-ubuntu-thumbnailer0.1 \
54+ qtdeclarative5-unity-notifications-plugin \
55+ qml-module-ubuntu-connectivity \
56+ ubuntu-mobile-icons \
57+ ubuntu-system-settings \
58+ unity-plugin-scopes \
59+ xvfb \
60+ || exit 5
61+}
62+
5263mk_build_deps() {
5364 if [ ! -f control -o $CODE_DIR/debian/control -nt control ]; then
5465 sed 's/\:native//g' $CODE_DIR/debian/control > control
@@ -74,9 +85,13 @@ else
7485 BUILD_COMMAND="make -j$NUM_JOBS"
7586fi
7687
77−if $CLEAN; then rm -rf builddir; fi
78−mkdir -p builddir
79−cd builddir
80−mk_build_deps
81−cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CODE_DIR ${GENERATOR} || exit 6
82−${BUILD_COMMAND} || exit 7
88+if $SETUP; then
89+ install_dependencies
90+else
91+ if $CLEAN; then rm -rf builddir; fi
92+ mkdir -p builddir
93+ cd builddir
94+ mk_build_deps
95+ cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CODE_DIR ${GENERATOR} || exit 6
96+ ${BUILD_COMMAND} || exit 7
97+fi
clickable.yamldeleted−153
@@ -1,153 +0,0 @@
1−clickable_minimum_required: '7'
2−builder: custom
3−build: echo Run \'clickable build --libs --verbose\' to build && false
4−restrict_arch: amd64
5−libraries:
6− unity8:
7− builder: cmake
8− src_dir: "${ROOT}"
9− test: make xvfballtests -j${NUM_PROCS}
10− dependencies_host:
11− - android-headers
12− - cmake
13− - cmake-extras
14− - dbus-test-runner
15− - debhelper
16− - dh-apparmor
17− - doxyqml
18− - g++:native
19− - gdb
20− - graphviz
21− - gsettings-ubuntu-schemas
22− - libandroid-properties-dev
23− - libconnectivity-qt1-dev
24− - libevdev-dev
25− - libgeonames-dev
26− - libgl1-mesa-dev
27− - libgl1-mesa-dri
28− - libgles2-mesa-dev
29− - libglib2.0-dev
30− - libgnome-desktop-3-12
31− - libgnome-desktop-3-dev
32− - libgsettings-qt-dev
33− - libhardware-dev
34− - liblightdm-qt5-3-dev
35− - libpam0g-dev
36− - libpulse-dev
37− - libqmenumodel-dev
38− - libqt5sql5-sqlite
39− - libqt5svg5-dev
40− - libqt5xmlpatterns5-dev
41− - libqtdbusmock1-dev
42− - libqtdbustest1-dev
43− - libsystemsettings-dev
44− - libubuntu-app-launch2-dev
45− - libubuntu-download-manager-common-dev
46− - libubuntugestures5-dev
47− - libubuntugestures5-private-dev
48− - libudev-dev
49− - libudm-common-dev
50− - libunity-api-dev
51− - libusermetricsoutput1-dev
52− - libx11-dev
53− - libxcb1-dev
54− - libxi-dev
55− - pkg-config
56− - python3-all:any
57− - python3-setuptools:native
58− - qml-module-qt-labs-folderlistmodel
59− - qml-module-qt-labs-settings
60− - qml-module-qtmultimedia
61− - qml-module-qtqml-statemachine
62− - qml-module-qtquick-layouts
63− - qml-module-qtquick-xmllistmodel
64− - qml-module-qtquick2
65− - qml-module-qtsysteminfo
66− - qml-module-qttest
67− - qml-module-ubuntu-components
68− - qml-module-ubuntu-layouts
69− - qml-module-ubuntu-settings-components
70− - qml-module-ubuntu-test
71− - qtbase5-dev
72− - qtbase5-dev-tools
73− - qtbase5-private-dev
74− - qtdbustest-runner
75− - qtdeclarative5-dev
76− - qtdeclarative5-dev-tools
77− - qtdeclarative5-private-dev
78− - qtdeclarative5-ubuntu-content1
79− - ttf-ubuntu-font-family
80− - ubports-wallpapers
81− - xvfb
82−dependencies_target:
83− - android-headers
84− - cmake
85− - cmake-extras
86− - dbus-test-runner
87− - debhelper
88− - dh-apparmor
89− - doxyqml
90− - g++:native
91− - gdb
92− - graphviz
93− - gsettings-ubuntu-schemas
94− - libandroid-properties-dev
95− - libconnectivity-qt1-dev
96− - libevdev-dev
97− - libgeonames-dev
98− - libgl1-mesa-dev
99− - libgl1-mesa-dri
100− - libgles2-mesa-dev
101− - libglib2.0-dev
102− - libgnome-desktop-3-12
103− - libgnome-desktop-3-dev
104− - libgsettings-qt-dev
105− - libhardware-dev
106− - liblightdm-qt5-3-dev
107− - libpam0g-dev
108− - libpulse-dev
109− - libqmenumodel-dev
110− - libqt5sql5-sqlite
111− - libqt5svg5-dev
112− - libqt5xmlpatterns5-dev
113− - libqtdbusmock1-dev
114− - libqtdbustest1-dev
115− - libsystemsettings-dev
116− - libubuntu-app-launch2-dev
117− - libubuntu-download-manager-common-dev
118− - libubuntugestures5-dev
119− - libubuntugestures5-private-dev
120− - libudev-dev
121− - libudm-common-dev
122− - libunity-api-dev
123− - libusermetricsoutput1-dev
124− - libx11-dev
125− - libxcb1-dev
126− - libxi-dev
127− - pkg-config
128− - python3-all:any
129− - python3-setuptools:native
130− - qml-module-qt-labs-folderlistmodel
131− - qml-module-qt-labs-settings
132− - qml-module-qtmultimedia
133− - qml-module-qtqml-statemachine
134− - qml-module-qtquick-layouts
135− - qml-module-qtquick-xmllistmodel
136− - qml-module-qtquick2
137− - qml-module-qtsysteminfo
138− - qml-module-qttest
139− - qml-module-ubuntu-components
140− - qml-module-ubuntu-layouts
141− - qml-module-ubuntu-settings-components
142− - qml-module-ubuntu-test
143− - qtbase5-dev
144− - qtbase5-dev-tools
145− - qtbase5-private-dev
146− - qtdbustest-runner
147− - qtdeclarative5-dev
148− - qtdeclarative5-dev-tools
149− - qtdeclarative5-private-dev
150− - qtdeclarative5-ubuntu-content1
151− - ttf-ubuntu-font-family
152− - ubports-wallpapers
153− - xvfb
cmake/modules/QmlPlugins.cmakenew file+148
@@ -0,0 +1,148 @@
1+# If you need to override the qmlplugindump binary, create the qmlplugin executable
2+# target before loading this plugin.
3+
4+if(NOT TARGET qmlplugindump)
5+ find_program(qmlplugindump_exe qmlplugindump)
6+
7+ if(NOT qmlplugindump_exe)
8+ msg(FATAL_ERROR "Could not locate qmlplugindump.")
9+ endif()
10+
11+ add_executable(qmlplugindump IMPORTED)
12+ set_target_properties(qmlplugindump PROPERTIES IMPORTED_LOCATION ${qmlplugindump_exe})
13+endif()
14+
15+#
16+# A custom target for building the qmltypes files manually.
17+#
18+if (NOT TARGET qmltypes)
19+ add_custom_target(qmltypes)
20+endif()
21+
22+# Creates a target for copying resource files into build dir and optionally installing them.
23+#
24+# Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed
25+# into ${DESTINATION}/${path}.
26+#
27+# Resource file names are matched against {*.{qml,js,jpg,png,sci,svg},qmldir}.
28+#
29+# export_qmlfiles(plugin path
30+# [SEARCH_PATH path] # Path to search for resources in (defaults to ${CMAKE_CURRENT_SOURCE_DIR})
31+# [BINARY_DIR path]
32+# [DESTINATION path]
33+# [TARGET_PREFIX string] # Will be prefixed to the target name
34+# )
35+#
36+# Created target:
37+# - ${TARGET_PREFIX}${plugin}-qmlfiles - Copies resources into the binary dir.
38+
39+macro(export_qmlfiles PLUGIN PATH)
40+ set(single SEARCH_PATH BINARY_DIR DESTINATION TARGET_PREFIX)
41+ cmake_parse_arguments(QMLFILES "" "${single}" "" ${ARGN})
42+
43+ if(NOT QMLFILES_SEARCH_PATH)
44+ set(QMLFILES_SEARCH_PATH ${CMAKE_CURRENT_SOURCE_DIR})
45+ endif()
46+
47+ if(QMLFILES_BINARY_DIR)
48+ set(qmlfiles_dir ${QMLFILES_BINARY_DIR}/${PATH})
49+ else()
50+ set(qmlfiles_dir ${CMAKE_CURRENT_BINARY_DIR})
51+ endif()
52+
53+ file(GLOB QMLFILES
54+ ${QMLFILES_SEARCH_PATH}/*.qml
55+ ${QMLFILES_SEARCH_PATH}/*.js
56+ ${QMLFILES_SEARCH_PATH}/*.jpg
57+ ${QMLFILES_SEARCH_PATH}/*.png
58+ ${QMLFILES_SEARCH_PATH}/*.sci
59+ ${QMLFILES_SEARCH_PATH}/*.svg
60+ ${QMLFILES_SEARCH_PATH}/*.qmltypes
61+ ${QMLFILES_SEARCH_PATH}/qmldir
62+ )
63+
64+ execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${qmlfiles_dir})
65+
66+ # copy the files
67+ add_custom_target(${QMLFILES_TARGET_PREFIX}${PLUGIN}-qmlfiles ALL
68+ COMMAND cp ${QMLFILES} ${qmlfiles_dir}
69+ DEPENDS ${QMLFILES}
70+ SOURCES ${QMLFILES}
71+ )
72+
73+ if(QMLFILES_DESTINATION)
74+ # install the qmlfiles file.
75+ install(FILES ${QMLFILES}
76+ DESTINATION ${QMLFILES_DESTINATION}/${PATH}
77+ )
78+ endif()
79+endmacro()
80+
81+
82+# Creates a target for generating the typeinfo file for a QML plugin and/or installs the plugin
83+# targets.
84+#
85+# Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed
86+# into ${DESTINATION}/${path}. If you don't pass BINARY_DIR, it's assumed that current source
87+# path ends with ${path}.
88+#
89+# The generated file will be named after the last segment of the plugin name, e.g. Foo.qmltypes.
90+#
91+# export_qmlplugin(plugin version path
92+# [BINARY_DIR path]
93+# [DESTINATION path]
94+# [TARGET_PREFIX string] # Will be prefixed to the target name
95+# [ENVIRONMENT string] # Will be added to qmlplugindump's env
96+# [TARGETS target1 [target2 ...]] # Targets to depend on and install (e.g. the plugin shared object)
97+# [NO_TYPES] # Do not create the qmltypes target
98+# )
99+#
100+# Created target:
101+# - ${TARGET_PREFIX}${plugin}-qmltypes - Generates the qmltypes file in the source dir.
102+# It will be made a dependency of the "qmltypes" target.
103+
104+macro(export_qmlplugin PLUGIN VERSION PATH)
105+ set(options NO_TYPES)
106+ set(single BINARY_DIR DESTINATION TARGET_PREFIX ENVIRONMENT)
107+ set(multi TARGETS)
108+ cmake_parse_arguments(QMLPLUGIN "${options}" "${single}" "${multi}" ${ARGN})
109+
110+ if(QMLPLUGIN_BINARY_DIR)
111+ set(qmlplugin_dir ${QMLPLUGIN_BINARY_DIR}/${PATH})
112+ else()
113+ # Find import path to point qmlplugindump at
114+ string(REGEX REPLACE "/${PATH}$" "" QMLPLUGIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
115+ set(qmlplugin_dir ${CMAKE_CURRENT_BINARY_DIR})
116+ endif()
117+
118+ if(NOT QMLPLUGIN_NO_TYPES)
119+ # Relative path for the module
120+ string(REPLACE "${CMAKE_BINARY_DIR}/" "" QMLPLUGIN_MODULE_DIR "${QMLPLUGIN_BINARY_DIR}")
121+
122+ # Find the last segment of the plugin name to use as qmltypes basename
123+ string(REGEX MATCH "[^.]+$" plugin_suffix ${PLUGIN})
124+ set(target_prefix ${QMLPLUGIN_TARGET_PREFIX}${PLUGIN})
125+ set(qmltypes_path ${CMAKE_CURRENT_SOURCE_DIR}/${plugin_suffix}.qmltypes)
126+
127+ add_custom_target(${target_prefix}-qmltypes
128+ COMMAND env ${QMLPLUGIN_ENVIRONMENT} $<TARGET_FILE:qmlplugindump> -notrelocatable
129+ ${PLUGIN} ${VERSION} ${QMLPLUGIN_MODULE_DIR} > ${qmltypes_path}
130+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
131+ )
132+ add_dependencies(${target_prefix}-qmltypes ${target_prefix}-qmlfiles ${QMLPLUGIN_TARGETS})
133+ add_dependencies(qmltypes ${target_prefix}-qmltypes)
134+ endif()
135+
136+ set_target_properties(${QMLPLUGIN_TARGETS} PROPERTIES
137+ ARCHIVE_OUTPUT_DIRECTORY ${qmlplugin_dir}
138+ LIBRARY_OUTPUT_DIRECTORY ${qmlplugin_dir}
139+ RUNTIME_OUTPUT_DIRECTORY ${qmlplugin_dir}
140+ )
141+
142+ if (QMLPLUGIN_DESTINATION)
143+ # Install additional targets
144+ install(TARGETS ${QMLPLUGIN_TARGETS}
145+ DESTINATION ${QMLPLUGIN_DESTINATION}/${PATH}
146+ )
147+ endif()
148+endmacro()
cmake/modules/QmlTest.cmake+12−188
@@ -55,55 +55,6 @@ function(add_qml_test PATH COMPONENT_NAME)
5555endfunction()
5656
5757
58−# add_qml_test_data(path component_name
59−# [...]
60−# )
61−#
62−# Install file called ${component_name} (or ${component_name}.qml) under
63−# ${path}.
64−
65−function(add_qml_test_data PATH COMPONENT_NAME)
66− cmake_parse_arguments(TEST "" "DESTINATION" "" ${ARGN})
67−
68− set(filename "${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/${COMPONENT_NAME}")
69−
70− if (IS_DIRECTORY "${filename}")
71− # As a convenience, allow specifying a directory and we will install
72− # all files in the dir. We do it this way rather than passing
73− # DIRECTORY to install() because we want to process any qml files.
74− file(GLOB subfiles RELATIVE "${filename}" "${filename}/*")
75− foreach(subfile ${subfiles})
76− add_qml_test_data("${PATH}/${COMPONENT_NAME}" "${subfile}")
77− endforeach()
78− return()
79− endif()
80−
81− if (NOT EXISTS "${filename}")
82− set(filename "${filename}.qml")
83− set(COMPONENT_NAME "${COMPONENT_NAME}.qml")
84− endif()
85−
86− if ("${filename}" MATCHES "\\.qml$")
87− file(READ "${filename}" contents)
88− string(REGEX REPLACE "(\"[./]*)/qml(/|\")" "\\1\\2" contents "${contents}")
89− # this is for (at least) cardcreatortest which pulls in an architecture-specific
90− # import into the plugins directory (which is a 'qml' once installed).
91− string(REGEX REPLACE "(import \"[./]*)/plugins(/|\")" "\\1/qml\\2" contents "${contents}")
92− set(filename "${CMAKE_CURRENT_BINARY_DIR}/${PATH}/${COMPONENT_NAME}")
93− file(WRITE "${filename}" "${contents}")
94− endif()
95−
96− if (TEST_DESTINATION)
97− set(DESTINATION "${TEST_DESTINATION}")
98− else()
99− file(RELATIVE_PATH relcurpath "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
100− set(DESTINATION "${SHELL_APP_DIR}/${relcurpath}/${PATH}")
101− endif()
102−
103− install(FILES "${filename}" DESTINATION "${DESTINATION}")
104−endfunction()
105−
106−
10758# add_qml_unittest(path component_name
10859# [...]
10960# )
@@ -120,10 +71,6 @@ function(add_qml_unittest PATH COMPONENT_NAME)
12071 ${ARGN}
12172 ARGS -input ${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml ${QMLTEST_ARGS}
12273 )
123−
124− if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml")
125− add_qml_test_data("${PATH}" "tst_${COMPONENT_NAME}.qml")
126− endif()
12774endfunction()
12875
12976
@@ -144,10 +91,6 @@ function(add_manual_qml_test PATH COMPONENT_NAME)
14491 ${ARGN}
14592 ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml ${QMLTEST_ARGS}
14693 )
147−
148− if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PATH}/tst_${COMPONENT_NAME}.qml")
149− add_qml_test_data("${PATH}" "tst_${COMPONENT_NAME}.qml")
150− endif()
15194endfunction()
15295
15396
@@ -165,7 +108,8 @@ endfunction()
165108#
166109# Logging options in the standard form of "-o filename,format"
167110# will be appended to the arguments list, prefixed with ARG_PREFIX.
168−# XUnitXML files will be stored in current binary dir.
111+# XUnitXML files will be stored in current binary dir or under
112+# ARTIFACTS_DIR, if set.
169113#
170114# Three targets will be created:
171115# - test${component_name} - Runs the test
@@ -178,8 +122,14 @@ function(add_executable_test COMPONENT_NAME TARGET)
178122 cmake_parse_arguments(QMLTEST "${QMLTEST_OPTIONS}" "${QMLTEST_SINGLE}" "${QMLTEST_MULTI}" ${ARGN})
179123 mangle_arguments()
180124
181− file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
182− set(file_logger -o ${CMAKE_CURRENT_BINARY_DIR}/test${COMPONENT_NAME}.xml,xunitxml)
125+ if(ARTIFACTS_DIR)
126+ file(RELATIVE_PATH path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
127+ file(MAKE_DIRECTORY ${ARTIFACTS_DIR}/${path})
128+ set(file_logger -o ${ARTIFACTS_DIR}/${path}/test${COMPONENT_NAME}.xml,xunitxml)
129+ else()
130+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
131+ set(file_logger -o ${CMAKE_CURRENT_BINARY_DIR}/test${COMPONENT_NAME}.xml,xunitxml)
132+ endif()
183133
184134 bake_arguments("${QMLTEST_ARG_PREFIX}" args ${iterations} ${file_logger} ${STDOUT_LOGGER})
185135
@@ -201,7 +151,7 @@ function(add_executable_test COMPONENT_NAME TARGET)
201151 add_qmltest_target(xvfbtest${COMPONENT_NAME} ${TARGET}
202152 COMMAND $<TARGET_FILE:xvfb-run> --server-args "-screen 0 1024x768x24" --auto-servernum ${qmltest_command}
203153 ${depends}
204− ENVIRONMENT QT_QPA_PLATFORM=xcb QML2_IMPORT_PATH=${imports} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1 ${QMLTEST_ENVIRONMENT}
154+ ENVIRONMENT QML2_IMPORT_PATH=${imports} ${QMLTEST_ENVIRONMENT} LD_PRELOAD=/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/mesa/libGL.so.1
205155 TARGETS ${xvfb_targets}
206156 )
207157 endif()
@@ -257,129 +207,8 @@ function(add_manual_test COMPONENT_NAME TARGET)
257207endfunction()
258208
259209
260−# add_meta_test(target)
261−#
262−# Adds a test target that will run one of our "meta" test targets, like
263−# xvfbuitests. This script will run the specified suite of tests on an
264−# installed system.
265−
266−function(add_meta_test TARGET_NAME)
267− cmake_parse_arguments(TEST "SERIAL" "" "DEPENDS" ${ARGN})
268−
269− add_custom_target(${TARGET_NAME})
270−
271− set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${TARGET_NAME}.sh")
272− if(TEST_SERIAL)
273− file(WRITE "${filename}" "#!/bin/sh\n\n")
274− else()
275− file(WRITE "${filename}" "#!/usr/bin/parallel --shebang --no-notice\n\n")
276− endif()
277−
278− add_meta_dependencies(${TARGET_NAME} DEPENDS ${TEST_DEPENDS})
279− # else we will write the rest of the script as we add cmake targets
280−
281− install(FILES "${filename}"
282− PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE
283− GROUP_EXECUTE GROUP_READ
284− WORLD_EXECUTE WORLD_READ
285− DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/scripts"
286− )
287−endfunction()
288−
289−
290210################### INTERNAL ####################
291211
292−function(install_test_script TARGET_NAME)
293− cmake_parse_arguments(TEST "" "" "COMMAND;ENVIRONMENT" ${ARGN})
294−
295− # Now write the above test into a shell script that we can run on an
296− # installed system.
297− set(script "#!/bin/sh\n\nset -x\n\n")
298− foreach(ONE_ENV ${TEST_ENVIRONMENT})
299− set(script "${script}export ${ONE_ENV}\n")
300− endforeach()
301− set(script "${script}export UNITY_TESTING_DATADIR=\"${CMAKE_INSTALL_PREFIX}/${SHELL_APP_DIR}\"\n")
302− set(script "${script}export UNITY_TESTING_LIBDIR=\"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}\"\n")
303− set(script "${script}\n")
304− set(script "${script}XML_ARGS=\n")
305− set(script "${script}if [ -n \"\$ARTIFACTS_DIR\" ]; then\n")
306− set(script "${script} XML_ARGS=\"@XML_ARGS@\"\n")
307− set(script "${script} mkdir -p \"@XML_DIR@\"\n")
308− set(script "${script} touch \"@XML_FILE@\"\n")
309− set(script "${script}fi\n")
310− set(script "${script}\n")
311− foreach(ONE_CMD ${TEST_COMMAND})
312− set(script "${script}'${ONE_CMD}' ")
313− endforeach()
314− set(script "${script}\"\$@\"") # Allow passing arguments if desired
315−
316− set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${TARGET_NAME}.sh")
317−
318− # Generate script to file then read it back to resolve any generator
319− # expressions before we try to replace paths.
320− file(GENERATE
321− OUTPUT "${filename}"
322− CONTENT "${script}"
323− )
324−
325− # Do replacement at install time to save needless work and to make sure
326− # we are modifying file after generate step above (which doesn't happen
327− # immediately). We can't use a custom-defined function or macro here...
328− # So instead we use a giant ugly code block.
329−
330− # START OF CODE BLOCK --------------------------------------------------
331− install(CODE "
332− file(READ \"${filename}\" replacestr)
333−
334− # Now some replacements...
335− # tests like to write xml output to our builddir; we don't need that, but we do want them in ARTIFACTS_DIR
336− string(REGEX MATCH \"( '--parameter')? '-o'( '--parameter')? '[^']*,xunitxml' \" xmlargs \"\${replacestr}\")
337− string(REGEX REPLACE \"( '--parameter')? '-o'( '--parameter')? '[^']*,xunitxml' \" \" \\\$XML_ARGS \" replacestr \"\${replacestr}\")
338− string(REGEX REPLACE \"'[^']*/tests/\" \"'\\\$ARTIFACTS_DIR/tests/\" xmlargs \"\${xmlargs}\")
339− string(REGEX REPLACE \".*'([^']*),xunitxml'.*\" \"\\\\1\" xmlfile \"\${xmlargs}\")
340− string(REGEX REPLACE \"(.*)/[^/]*\" \"\\\\1\" xmldir \"\${xmlfile}\")
341− string(REGEX REPLACE \"'\" \"\" xmlargs \"\${xmlargs}\") # strip single quotes
342− string(REGEX REPLACE \"@XML_ARGS@\" \"\${xmlargs}\" replacestr \"\${replacestr}\")
343− string(REGEX REPLACE \"@XML_DIR@\" \"\${xmldir}\" replacestr \"\${replacestr}\")
344− string(REGEX REPLACE \"@XML_FILE@\" \"\${xmlfile}\" replacestr \"\${replacestr}\")
345− # replace build/source roots with their install paths
346− string(REPLACE \"${CMAKE_BINARY_DIR}/libs\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}\" replacestr \"\${replacestr}\")
347− string(REPLACE \"${CMAKE_BINARY_DIR}/plugins\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_INSTALL_QML}\" replacestr \"\${replacestr}\")
348− string(REPLACE \"${CMAKE_BINARY_DIR}/tests/libs\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/libs\" replacestr \"\${replacestr}\")
349− string(REPLACE \"${CMAKE_BINARY_DIR}/tests/mocks\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_INSTALL_QML}/mocks\" replacestr \"\${replacestr}\")
350− string(REPLACE \"${CMAKE_BINARY_DIR}/tests/plugins\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/plugins\" replacestr \"\${replacestr}\")
351− string(REPLACE \"${CMAKE_BINARY_DIR}/tests/qmltests\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/qmltests\" replacestr \"\${replacestr}\")
352− string(REPLACE \"${CMAKE_BINARY_DIR}/tests/uqmlscene\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}\" replacestr \"\${replacestr}\")
353− string(REPLACE \"${CMAKE_BINARY_DIR}/tests/utils/modules\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_INSTALL_QML}/utils\" replacestr \"\${replacestr}\")
354− string(REPLACE \"${CMAKE_SOURCE_DIR}/tests/plugins\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_APP_DIR}/tests/plugins\" replacestr \"\${replacestr}\")
355− string(REPLACE \"${CMAKE_SOURCE_DIR}/tests/qmltests\" \"${CMAKE_INSTALL_PREFIX}/${SHELL_APP_DIR}/tests/qmltests\" replacestr \"\${replacestr}\")
356−
357− file(WRITE \"${filename}\" \"\${replacestr}\")
358− ")
359− # END OF CODE BLOCK --------------------------------------------------
360−
361− install(FILES "${filename}"
362− PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE
363− GROUP_EXECUTE GROUP_READ
364− WORLD_EXECUTE WORLD_READ
365− DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/scripts"
366− )
367−endfunction()
368−
369−function(add_meta_dependencies UPSTREAM_TARGET)
370− cmake_parse_arguments(TEST "" "" "DEPENDS" ${ARGN})
371−
372− foreach(depend ${TEST_DEPENDS})
373− add_dependencies(${UPSTREAM_TARGET} ${depend})
374−
375− # add depend to the meta test script that we will install on system
376− set(filename "${CMAKE_BINARY_DIR}/tests/scripts/${UPSTREAM_TARGET}.sh")
377− if (EXISTS "${filename}")
378− file(APPEND "${filename}" "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}/tests/scripts/${depend}.sh \"\$@\" 2>&1\n")
379− endif()
380− endforeach()
381−endfunction()
382−
383212# add_qmltest_target(target_name target
384213# COMMAND test_exe [arg1 [...]] # execute this test with arguments
385214# [...] # see above for available arguments:
@@ -402,11 +231,6 @@ function(add_qmltest_target TARGET_NAME TARGET)
402231 DEPENDS ${TARGET} ${QMLTEST_DEPENDS}
403232 )
404233
405− install_test_script(${TARGET_NAME}
406− ENVIRONMENT ${QMLTEST_ENVIRONMENT}
407− COMMAND ${QMLTEST_COMMAND}
408− )
409−
410234 if(QMLTEST_ADD_TEST)
411235 add_test(
412236 NAME ${TARGET_NAME}
@@ -424,7 +248,7 @@ function(add_qmltest_target TARGET_NAME TARGET)
424248 endif()
425249
426250 foreach(UPSTREAM_TARGET ${QMLTEST_TARGETS})
427− add_meta_dependencies(${UPSTREAM_TARGET} DEPENDS ${TARGET_NAME})
251+ add_dependencies(${UPSTREAM_TARGET} ${TARGET_NAME})
428252 endforeach()
429253endfunction()
430254
data/51-unity8-greeter.confdeleted−2
@@ -1,2 +0,0 @@
1−[Seat:*]
2−greeter-session=unity8-greeter
data/CMakeLists.txt+6−9
@@ -1,27 +1,24 @@
11# generate desktop files
22configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
3+configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
34configure_file(${INDICATORS_CLIENT_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop @ONLY)
4−configure_file(${GREETER_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${GREETER_APP}.desktop @ONLY)
55
66# install desktop files
77install(FILES
88 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
9+ ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
910 ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop
1011 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
1112 )
1213
14+# install dash icon
1315install(FILES
14− ${CMAKE_CURRENT_BINARY_DIR}/${GREETER_APP}.desktop
15− DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/greeters
16− )
17−
18−install(FILES
19− 51-unity8-greeter.conf
20− DESTINATION ${CMAKE_INSTALL_DATADIR}/lightdm/lightdm.conf.d
16+ ${CMAKE_CURRENT_SOURCE_DIR}/${DASH_APP}.png
17+ DESTINATION ${SHELL_APP_DIR}/Dash/
2118 )
2219
2320add_custom_target(pkgversion ALL COMMAND dpkg-parsechangelog -l${CMAKE_SOURCE_DIR}/debian/changelog --show-field version > ${CMAKE_CURRENT_BINARY_DIR}/version)
2421
2522install(FILES com.canonical.Unity8.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
26−install(FILES com.canonical.Unity.gschema.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/glib-2.0/schemas)
23+install(FILES unity8-dash.url-dispatcher DESTINATION ${CMAKE_INSTALL_DATADIR}/url-dispatcher/urls)
2724install(FILES ${CMAKE_CURRENT_BINARY_DIR}/version DESTINATION ${CMAKE_INSTALL_LOCALSTATEDIR}/lib/unity8)
data/com.canonical.Unity.gschema.xmldeleted−255
@@ -1,255 +0,0 @@
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:///morph-browser.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/com.canonical.Unity8.gschema.xml+4−24
@@ -11,8 +11,8 @@
1111 <summary>The usage mode.</summary>
1212 <description>The usage mode chosen will affect the Window Management behaviour.</description>
1313 </key>
14− <key type="u" name="edge-barrier-sensitivity">
15− <default>50</default>
14+ <key type="y" name="edge-barrier-sensitivity">
15+ <default>35</default>
1616 <range min="1" max="100"/>
1717 <summary>Sensitivity of screen edge barriers for the mouse pointer.</summary>
1818 <description>Some UI actions like revealing the launcher or the applications spread are triggered by pushing the mouse pointer against a screen edge. This key defines how much you have to push in order to trigger the associated action.</description>
@@ -23,7 +23,7 @@
2323 <description>How much you have to push (in grid units)the mouse against an edge barrier when sensibility is 100.</description>
2424 </key>
2525 <key type="u" name="edge-barrier-max-push">
26− <default>120</default>
26+ <default>60</default>
2727 <summary>Maximum push needed to overcome edge barrier</summary>
2828 <description>How much you have to push (in grid units) the mouse against an edge barrier when sensibility is 1.</description>
2929 </key>
@@ -33,7 +33,7 @@
3333 <description>How big (in grid units) the edge-drag sensitive area should be.</description>
3434 </key>
3535 <key type="b" name="autohide-launcher">
36− <default>false</default>
36+ <default>true</default>
3737 <summary>Autohide the launcher</summary>
3838 <description>This will only be applied in windowed mode. In staged mode, the launcher will always hide.</description>
3939 </key>
@@ -43,26 +43,6 @@
4343 <summary>Width of the launcher in grid units.</summary>
4444 <description>Changes the width of the launcher in all usage modes.</description>
4545 </key>
46− <key type="b" name="enable-indicator-menu">
47− <default>true</default>
48− <summary>Enable or disable the indicator pull down menus</summary>
49− <description>Toggle the availability of the indicator pull down menus</description>
50− </key>
51− <key type="s" name="appstore-uri">
52− <default>'appid://openstore.openstore-team/openstore/current-user-version'</default>
53− <summary>The uri to the app store</summary>
54− <description>This will be used whenever the user triggers an action to open the app store.</description>
55− </key>
56− <key type="b" name="always-show-osk">
57− <default>false</default>
58− <summary>Force showing/hiding the OSK</summary>
59− <description>Toggle the visibility of the On Screen Keyboard unconditionally</description>
60− </key>
61− <key type="b" name="osk-switch-visible">
62− <default>false</default>
63− <summary>Whether the OSK switch should be visible</summary>
64− <description>Toggle the visibility of the OSK switch</description>
65− </key>
6646 </schema>
6747
6848 <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
data/test.sensorsdeleted−12
@@ -1,12 +0,0 @@
1−create light 0 10 1
2−create accel 0 1000 0.1
3−create proximity
4−
5−200 proximity near
6−500 light 5
7−# simulate crash on the ground
8−500 accel 0.2 0.1 10
9−100 accel 0.2 0.2 1000
10−20 accel 0 0 0
11−10 proximity far
12−10 light 10
data/unity8-dash.confnew file+25
@@ -0,0 +1,25 @@
1+description "Unity Shell v8 Dash"
2+author "Michael Zanetti <michael.zanetti@canonical.com>"
3+
4+emits scope-ui-starting
5+
6+start on started unity8
7+stop on stopping unity8
8+
9+kill timeout 120
10+
11+# Focused app is 100 so we want to be less likely to get
12+# killed than the focused app but more than Unity8
13+
14+oom score 50
15+
16+respawn
17+respawn limit unlimited
18+
19+env APP_ID=unity8-dash
20+
21+pre-start script
22+ initctl emit scope-ui-starting
23+end script
24+
25+exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop
data/unity8-dash.desktop.innew file+9
@@ -0,0 +1,9 @@
1+[Desktop Entry]
2+Type=Application
3+Name=Scopes
4+Comment=An interface for using the Scopes system
5+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash
6+Terminal=false
7+Icon=@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/Dash/unity8-dash.png
8+NoDisplay=true
9+X-Ubuntu-Touch=true
data/unity8-dash.pngnew file
Binary file not shown.
data/unity8-dash.svgnew file+326
@@ -0,0 +1,326 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<!-- Created with Inkscape (http://www.inkscape.org/) -->
3+
4+<svg
5+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6+ xmlns:cc="http://creativecommons.org/ns#"
7+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8+ xmlns:svg="http://www.w3.org/2000/svg"
9+ xmlns="http://www.w3.org/2000/svg"
10+ xmlns:xlink="http://www.w3.org/1999/xlink"
11+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
12+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13+ viewBox="0 0 512 512"
14+ style="enable-background:new"
15+ inkscape:export-ydpi="180"
16+ inkscape:export-xdpi="180"
17+ inkscape:export-filename="app_shape02.png"
18+ sodipodi:docname="apps-scope.svg"
19+ inkscape:version="0.91+devel r"
20+ version="1.1"
21+ id="svg3336"
22+ height="512"
23+ width="512">
24+ <sodipodi:namedview
25+ inkscape:snap-global="false"
26+ fit-margin-bottom="18"
27+ fit-margin-right="0"
28+ fit-margin-left="0"
29+ fit-margin-top="18"
30+ inkscape:snap-grids="true"
31+ inkscape:guide-bbox="true"
32+ showguides="false"
33+ inkscape:snap-center="true"
34+ inkscape:snap-object-midpoints="true"
35+ inkscape:snap-midpoints="true"
36+ inkscape:snap-smooth-nodes="true"
37+ inkscape:snap-intersection-paths="true"
38+ inkscape:object-nodes="true"
39+ inkscape:object-paths="true"
40+ inkscape:snap-bbox-midpoints="true"
41+ inkscape:snap-bbox-edge-midpoints="true"
42+ inkscape:bbox-nodes="true"
43+ inkscape:bbox-paths="true"
44+ inkscape:snap-bbox="true"
45+ showborder="true"
46+ inkscape:showpageshadow="false"
47+ inkscape:snap-page="true"
48+ inkscape:window-maximized="1"
49+ inkscape:window-y="24"
50+ inkscape:window-x="0"
51+ inkscape:window-height="1029"
52+ inkscape:window-width="1920"
53+ showgrid="false"
54+ inkscape:current-layer="layer3"
55+ inkscape:document-units="px"
56+ inkscape:cy="204.04409"
57+ inkscape:cx="-384.5809"
58+ inkscape:zoom="0.64"
59+ inkscape:pageshadow="2"
60+ inkscape:pageopacity="0"
61+ borderopacity="1.0"
62+ bordercolor="#666666"
63+ pagecolor="#4f4f4f"
64+ id="base">
65+ <inkscape:grid
66+ type="xygrid"
67+ id="grid811"
68+ originx="0"
69+ originy="15.999999"
70+ visible="true"
71+ enabled="true" />
72+ <sodipodi:guide
73+ orientation="1,0"
74+ position="104,176"
75+ id="guide819" />
76+ <sodipodi:guide
77+ orientation="1,0"
78+ position="120,160"
79+ id="guide821" />
80+ <sodipodi:guide
81+ orientation="1,0"
82+ position="392,144"
83+ id="guide823" />
84+ <sodipodi:guide
85+ orientation="1,0"
86+ position="408,144"
87+ id="guide825" />
88+ <sodipodi:guide
89+ orientation="0,1"
90+ position="328,408"
91+ id="guide827" />
92+ <sodipodi:guide
93+ orientation="0,1"
94+ position="336,392"
95+ id="guide829" />
96+ <sodipodi:guide
97+ orientation="0,1"
98+ position="176,120"
99+ id="guide831" />
100+ <sodipodi:guide
101+ orientation="0,1"
102+ position="216,104"
103+ id="guide833" />
104+ <inkscape:grid
105+ type="axonomgrid"
106+ id="grid835"
107+ units="px"
108+ empspacing="60"
109+ gridanglex="42.9"
110+ gridanglez="42.9"
111+ spacingy="3.522px"
112+ enabled="false"
113+ originx="0"
114+ originy="16.999996" />
115+ <sodipodi:guide
116+ orientation="0,1"
117+ position="344,376"
118+ id="guide4126" />
119+ <sodipodi:guide
120+ orientation="0,1"
121+ position="160,136"
122+ id="guide4128" />
123+ <sodipodi:guide
124+ orientation="1,0"
125+ position="136,96"
126+ id="guide4130" />
127+ <sodipodi:guide
128+ orientation="1,0"
129+ position="376,136"
130+ id="guide4134" />
131+ <sodipodi:guide
132+ orientation="-0.70710678,0.70710678"
133+ position="544,544"
134+ id="guide4136" />
135+ <sodipodi:guide
136+ orientation="1,0"
137+ position="256,-32.000001"
138+ id="guide4138" />
139+ <sodipodi:guide
140+ orientation="0,1"
141+ position="544,256"
142+ id="guide4140" />
143+ <sodipodi:guide
144+ orientation="0.70710678,0.70710678"
145+ position="544,-32.000001"
146+ id="guide4142" />
147+ <sodipodi:guide
148+ orientation="0,1"
149+ position="248,15.999999"
150+ id="guide4152" />
151+ <sodipodi:guide
152+ orientation="0,1"
153+ position="336,496"
154+ id="guide4154" />
155+ <sodipodi:guide
156+ position="344,96"
157+ orientation="1,0"
158+ id="guide4361" />
159+ <sodipodi:guide
160+ position="576,168"
161+ orientation="0,1"
162+ id="guide4363" />
163+ <sodipodi:guide
164+ position="168,192"
165+ orientation="1,0"
166+ id="guide4229" />
167+ <sodipodi:guide
168+ position="312,344"
169+ orientation="0,1"
170+ id="guide4233" />
171+ <sodipodi:guide
172+ position="180.48,-96"
173+ orientation="0,1"
174+ id="guide4235" />
175+ </sodipodi:namedview>
176+ <defs
177+ id="defs3338">
178+ <linearGradient
179+ inkscape:collect="always"
180+ id="linearGradient4203">
181+ <stop
182+ style="stop-color:#ea5420;stop-opacity:1"
183+ offset="0"
184+ id="stop4205" />
185+ <stop
186+ style="stop-color:#f37e40;stop-opacity:1"
187+ offset="1"
188+ id="stop4207" />
189+ </linearGradient>
190+ <clipPath
191+ clipPathUnits="userSpaceOnUse"
192+ id="clipPath4755">
193+ <path
194+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.24899998;fill:#5e2c73;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
195+ d="M 360,50 594,284 V 215.89844 C 594,70.73665 573.2426,50 427.94531,50 Z"
196+ id="path4757"
197+ inkscape:connector-curvature="0" />
198+ </clipPath>
199+ <clipPath
200+ clipPathUnits="userSpaceOnUse"
201+ id="clipPath4767">
202+ <path
203+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#f6f6f6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
204+ d="M 543.8125,454.1875 312.18945,685.81055 367.94531,681 C 512.70468,668.50896 526.55393,654.72881 539,510.10156 Z"
205+ id="path4769"
206+ inkscape:connector-curvature="0" />
207+ </clipPath>
208+ <linearGradient
209+ inkscape:collect="always"
210+ xlink:href="#linearGradient4203"
211+ id="linearGradient4209"
212+ x1="167.5"
213+ y1="17.25"
214+ x2="343.25"
215+ y2="491"
216+ gradientUnits="userSpaceOnUse" />
217+ <filter
218+ inkscape:collect="always"
219+ style="color-interpolation-filters:sRGB"
220+ id="filter4220"
221+ x="-0.012"
222+ width="1.024"
223+ y="-0.012"
224+ height="1.024">
225+ <feGaussianBlur
226+ inkscape:collect="always"
227+ stdDeviation="1.4390401"
228+ id="feGaussianBlur4222" />
229+ </filter>
230+ <linearGradient
231+ inkscape:collect="always"
232+ xlink:href="#linearGradient4226"
233+ id="linearGradient4232"
234+ x1="255.99998"
235+ y1="-255.99998"
236+ x2="405.35773"
237+ y2="-255.99998"
238+ gradientUnits="userSpaceOnUse"
239+ spreadMethod="reflect" />
240+ <linearGradient
241+ inkscape:collect="always"
242+ id="linearGradient4226">
243+ <stop
244+ style="stop-color:#a73812;stop-opacity:1"
245+ offset="0"
246+ id="stop4228" />
247+ <stop
248+ style="stop-color:#973310;stop-opacity:0"
249+ offset="1"
250+ id="stop4230" />
251+ </linearGradient>
252+ <filter
253+ inkscape:collect="always"
254+ style="color-interpolation-filters:sRGB"
255+ id="filter4234"
256+ x="-0.096000001"
257+ width="1.192"
258+ y="-0.096000001"
259+ height="1.192">
260+ <feGaussianBlur
261+ inkscape:collect="always"
262+ stdDeviation="11.512321"
263+ id="feGaussianBlur4236" />
264+ </filter>
265+ </defs>
266+ <metadata
267+ id="metadata3341">
268+ <rdf:RDF>
269+ <cc:Work
270+ rdf:about="">
271+ <dc:format>image/svg+xml</dc:format>
272+ <dc:type
273+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
274+ <dc:title></dc:title>
275+ </cc:Work>
276+ </rdf:RDF>
277+ </metadata>
278+ <g
279+ inkscape:groupmode="layer"
280+ id="layer3"
281+ inkscape:label="Background">
282+ <path
283+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient4209);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate"
284+ d="M 0 0 L 0 183.89844 L 0 328.10156 L 0 512 L 512 512 L 512 328.10156 L 512 183.89844 L 512 0 L 0 0 z "
285+ id="rect4158" />
286+ <path
287+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
288+ d="M 0 256 L 0 328.10156 L 0 462.53516 C 0 479.69677 0.052846476 496.03174 0.13085938 512 L 511.86914 512 C 511.94715 496.03174 512 479.69677 512 462.53516 L 512 256 L 0 256 z "
289+ id="rect4286" />
290+ </g>
291+ <g
292+ inkscape:groupmode="layer"
293+ id="layer1"
294+ inkscape:label="Pictogram"
295+ style="display:inline"
296+ transform="translate(-32,-32)">
297+ <circle
298+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:#d04616;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.99999952;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter4220);enable-background:accumulate"
299+ id="circle4218"
300+ cx="258"
301+ cy="-256"
302+ r="143.90401"
303+ transform="rotate(90,-7.1132638e-7,31.999996)" />
304+ <circle
305+ transform="rotate(90,-7.1132638e-7,31.999996)"
306+ r="143.90401"
307+ cy="-256"
308+ cx="258"
309+ id="circle4224"
310+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient4232);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.99999952;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter4234);enable-background:accumulate" />
311+ <circle
312+ transform="rotate(90)"
313+ r="143.90401"
314+ cy="-288"
315+ cx="288"
316+ id="circle4206"
317+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.99999952;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
318+ <path
319+ style="display:inline;fill:#ea5420;fill-opacity:1;stroke-width:2.9398191;enable-background:new"
320+ id="path4258"
321+ d="m 193.9963,269.54024 c -10.19878,0 -18.46137,8.2634 -18.46137,18.46139 0,10.19309 8.26259,18.45568 18.46137,18.45568 10.19311,0 18.45569,-8.26259 18.45569,-18.45568 0,-10.19799 -8.26258,-18.46139 -18.45569,-18.46139 z m 131.78525,83.88906 c -8.82832,5.09898 -11.85536,16.38129 -6.75557,25.20475 5.0933,8.82834 16.37561,11.85455 25.20393,6.75556 8.82752,-5.0933 11.85457,-16.37561 6.75559,-25.20475 -5.0933,-8.82263 -16.38212,-11.84887 -25.20395,-6.75556 z m -91.69319,-65.42767 c 0,-18.24028 9.05999,-34.35498 22.92309,-44.11321 l -13.49406,-22.6012 c -16.14883,10.79461 -28.16435,27.28971 -33.15766,46.60863 5.82648,4.75434 9.55584,11.99194 9.55584,20.10497 0,8.10813 -3.72936,15.34572 -9.55584,20.10006 4.98681,19.32463 17.00232,35.82055 33.15766,46.61514 l 13.49406,-22.60689 c -13.8631,-9.75253 -22.92309,-25.86641 -22.92309,-44.1075 z m 53.91207,-53.91776 c 28.16514,0 51.27274,21.59491 53.69828,49.13495 l 26.30048,-0.38772 c -1.29405,-20.33173 -10.17604,-38.58421 -23.82372,-52.00594 -7.01814,2.65149 -15.12464,2.2459 -22.13139,-1.79314 -7.01894,-4.0504 -11.41969,-10.88319 -12.62271,-18.30044 -6.8214,-1.88254 -14.00046,-2.91323 -21.42257,-2.91323 -12.75925,0 -24.82271,2.99695 -35.53359,8.29836 l 12.82509,22.98243 c 6.89944,-3.21075 14.5963,-5.01526 22.71013,-5.01526 z m 0,107.82982 c -8.11383,0 -15.81069,-1.80533 -22.70931,-5.01528 l -12.82511,22.98163 c 10.71088,5.3079 22.77434,8.30568 35.53442,8.30568 7.42211,0 14.60118,-1.0315 21.42177,-2.91975 1.20301,-7.41724 5.60537,-14.24352 12.6227,-18.30125 7.01161,-4.04555 15.11326,-4.44382 22.13137,-1.79232 13.64769,-13.42174 22.52968,-31.67421 23.82372,-52.00595 l -26.30696,-0.38772 c -2.41986,27.54738 -25.52665,49.13496 -53.6926,49.13496 z m 37.77461,-119.35113 c 8.82834,5.09818 20.11145,2.07845 25.20475,-6.74987 5.099,-8.82833 2.07928,-20.11145 -6.74988,-25.21126 -8.82832,-5.0933 -20.11063,-2.06705 -25.21125,6.76127 -5.09247,8.82345 -2.06625,20.10657 6.75638,25.19986 z"
322+ inkscape:connector-curvature="0"
323+ inkscape:transform-center-x="16.232534"
324+ inkscape:transform-center-y="-0.0024900663" />
325+ </g>
326+</svg>
data/unity8-dash.url-dispatchernew file+6
@@ -0,0 +1,6 @@
1+[
2+ {
3+ "protocol": "scope"
4+ }
5+]
6+
data/unity8-filewatcher.conf−5
@@ -1,11 +1,6 @@
11description "File system watcher for unity8"
22author "Michael Zanetti <michael.zanetti@canonical.com>"
33
4−# This method of updating the launcher will not work in our new snappy world,
5−# neither for snaps installed in the system nor if we are running inside a snap.
6−# Plus it hardcodes the phablet user... To be replaced once bug 1630997 is
7−# fixed in ubuntu-app-launch.
8−
94# Workaround for bug 1360208. ~ and * in one expression doesn't work currently
105start on (file FILE=/home/phablet/.local/share/applications/*.desktop) or (file FILE=/usr/share/applications/*.desktop)
116
data/unity8-greeter-init.confdeleted−12
@@ -1,12 +0,0 @@
1−description "Unity 8 Greeter initialization"
2−author "Michael Terry <mterry@ubuntu.com>"
3−
4−start on unity8-greeter-started
5−task
6−emits indicator-services-start
7−
8−script
9− start --no-wait ofono-setup || true
10− initctl emit --no-wait indicator-services-start || true
11− start --no-wait maliit-server || true
12−end script
data/unity8-greeter-wrapperdeleted−109
@@ -1,109 +0,0 @@
1−#!/bin/sh
2−# -*- Mode: sh; indent-tabs-mode: nil; tab-width: 4 -*-
3−#
4−# Copyright (C) 2011,2013,2016 Canonical Ltd
5−#
6−# This program is free software: you can redistribute it and/or modify it under
7−# the terms of the GNU General Public License as published by the Free Software
8−# Foundation, version 3 of the License.
9−#
10−# See http://www.gnu.org/copyleft/gpl.html the full text of the license.
11−
12−# This wrapper merely ensures that init and friends live only as long as this
13−# script does. Otherwise, it's very easy for some processes to not notice that
14−# the session died. We could try to do this in-process, but we want to do this
15−# cleanup even if the greeter aborts.
16−
17−trap cleanup TERM EXIT
18−
19−cleanup()
20−{
21− trap - TERM EXIT
22− # Kill upstart and indicators
23− if [ -n "$INIT_PID" ]; then
24− kill "$INIT_PID"
25− fi
26− if [ -n "$CMD_PID" ]; then
27− kill "$CMD_PID"
28− fi
29− exit 0
30−}
31−
32−set_greeter_var()
33−{
34− export "$1=$2"
35− gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "{'$1': '$2'}"
36− if [ -n "$INIT_PID" ]; then
37− initctl set-env --global "$1=$2"
38− fi
39−}
40−
41−SUB_SOCKET=$XDG_RUNTIME_DIR/mir_socket
42−rm -f $SUB_SOCKET # clear socket in case we were hard shut down
43−
44−echo "DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS}" >"$XDG_RUNTIME_DIR/dbus-session"
45−
46−# If touch session script (which sets up grid units and mir variables) is available, use it
47−TOUCH_WRAPPER=
48−if which ubuntu-touch-session >/dev/null; then
49− TOUCH_WRAPPER=ubuntu-touch-session
50−fi
51−
52−# Advertise as a unity8 session, so that indicator-network will start.
53−export XDG_SESSION_DESKTOP=unity8
54−export DESKTOP_SESSION=$XDG_SESSION_DESKTOP
55−
56−set_greeter_var QT_IM_MODULE maliitphablet
57−set_greeter_var QT_QPA_PLATFORM ubuntumirclient
58−
59−# We disable ofono using pulse. It causes problems with racing with the user's
60−# pulse. We need to come up with a better long-term fix for this, because we
61−# eventually need the greeter to play ringtones for users that aren't logged in.
62−set_greeter_var PA_DISABLED 1
63−
64−# Normal unity8 sessions are entirely driven by Upstart. But greeters
65−# are special. They need access to the file descriptors that lightdm
66−# creates for them and don't want to start all the services that a normal
67−# session would. So it's inconvenient to live within an upstart session.
68−# But... we still want to use Upstart for some services. So launch here.
69−MIR_SOCKET=$SUB_SOCKET $TOUCH_WRAPPER upstart --user --no-startup-event &
70−INIT_PID=$!
71−while [ ! -e "$XDG_RUNTIME_DIR/upstart/sessions/$INIT_PID.session" ]; do sleep 0.1; done
72−. "$XDG_RUNTIME_DIR/upstart/sessions/$INIT_PID.session"
73−export UPSTART_SESSION
74−
75−# Connect upstart to system, but do first command in a loop to avoid any
76−# race condition between the session file above being written and upstart being
77−# ready to handle requests.
78−while ! initctl notify-dbus-address "$DBUS_SESSION_BUS_ADDRESS"; do sleep 0.1; done
79−initctl start notify-cgmanager
80−
81−# Start any pre-greeter tasks if needed (like wizard)
82−initctl emit unity8-greeter-starting
83−
84−# Define language here for phone if available. When phone user switches their
85−# language, they expect that to affect the greeter too. But the user doesn't
86−# have permission to switch system language, only their own. So we notice if
87−# the phablet user exists and use their language if so. TODO: talk to design
88−# about whether we should switch language on fly as users are selected (this
89−# is very hard to do technically).
90−#
91−# Do this after unity8-greeter-starting, in case a customization upstart job
92−# changes language.
93−if [ "$(id -u phablet 2>/dev/null)" = "32011" ]; then
94− USER_LANG=$(gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User32011 --method org.freedesktop.DBus.Properties.Get org.freedesktop.Accounts.User Language | cut -d\' -f2)
95− if [ -n "$USER_LANG" ]; then
96− set_greeter_var LANGUAGE "$USER_LANG"
97− fi
98− USER_LOCALE=$(gdbus call --system --dest org.freedesktop.Accounts --object-path /org/freedesktop/Accounts/User32011 --method org.freedesktop.DBus.Properties.Get org.freedesktop.Accounts.User FormatsLocale | cut -d\' -f2)
99− if [ -n "$USER_LOCALE" ]; then
100− set_greeter_var LANG "$USER_LOCALE"
101− set_greeter_var LC_ALL "$USER_LOCALE"
102− fi
103−fi
104−
105−# And finally actually start the greeter
106−exec env MIR_SERVER_FILE=$SUB_SOCKET $TOUCH_WRAPPER $@ &
107−CMD_PID=$!
108−wait $CMD_PID
109−CMD_PID=
data/unity8-greeter.desktop.indeleted−7
@@ -1,7 +0,0 @@
1−[Desktop Entry]
2−Type=Application
3−Name=Unity 8 Greeter
4−Comment=The converged Unity shell's Greeter
5−Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-greeter-wrapper @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8 --mode=greeter
6−X-LightDM-Session-Type=mir
7−X-Ubuntu-Touch=true
data/unity8-greeter.pkladeleted−44
@@ -1,44 +0,0 @@
1−# DO NOT EDIT THIS FILE, it will be overwritten on update
2−# Place your local configurations under /etc/polkit-1/localauthority/
3−
4−[Disable Controlling of Network Devices]
5−Identity=unix-user:lightdm
6−Action=org.freedesktop.NetworkManager.enable-disable-network;org.freedesktop.NetworkManager.enable-disable-wifi;org.freedesktop.NetworkManager.enable-disable-wwan;org.freedesktop.NetworkManager.enable-disable-wimax;
7−ResultActive=no
8−ResultInactive=no
9−ResultsAny=no
10−
11−[Disable Sleep and Wake]
12−Identity=unix-user:lightdm
13−Action=org.freedesktop.NetworkManager.sleep-wake
14−ResultActive=no
15−ResultInactive=no
16−ResultsAny=no
17−
18−[Disable WiFi Sharing]
19−Identity=unix-user:lightdm
20−Action=org.freedesktop.NetworkManager.wifi.share.protected;org.freedesktop.NetworkManager.wifi.share.open
21−ResultActive=no
22−ResultInactive=no
23−ResultsAny=no
24−
25−[Disable Settings Modifications]
26−Identity=unix-user:lightdm
27−Action=org.freedesktop.NetworkManager.settings.modify.own;org.freedesktop.NetworkManager.settings.modify.system;org.freedesktop.NetworkManager.settings.modify.hostname
28−ResultActive=no
29−ResultInactive=no
30−ResultsAny=no
31−
32−[Disable User Connections]
33−Identity=unix-user:lightdm
34−Action=org.freedesktop.NetworkManager.use-user-connections
35−ResultActive=no
36−ResultInactive=no
37−ResultsAny=no
38−
39−[Enable Controlling of Network Connections]
40−Identity=unix-user:lightdm
41−Action=org.freedesktop.NetworkManager.network-control
42−ResultActive=yes
43−ResultInactive=no
44−ResultsAny=no
data/unity8.conf+18−51
@@ -2,51 +2,37 @@ description "Unity Shell v8"
22author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
44emits indicator-services-start
5−emits indicator-services-end
65
7−start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=unity8-mir) or (xsession SESSION=unity8)) and started dbus
6+start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=unity8-mir)) and started dbus
87stop on desktop-end
98
109kill timeout 120
1110
12−#
13−# Ensure the shell always gets unthrottled touch events, so that applications
14−# who want full speed low-latency input can get it (LP: #1497105) and so that
15−# apps can use QML touch compression safely (the QML touch compression
16−# algorithm does not support nesting well - LP: #1486341, LP: #1556763 - so
17−# must be fed by the raw input event stream from Unity8).
18−#
19−env QML_NO_TOUCH_COMPRESSION=1
20−
2111respawn
2212expect stop
2313
24−# FIXME Create an autopilot test that makes sure start+stop and restart
25−# work fine at least 2 times
26−
2714pre-start script
2815 # Tell unity-mir to raise SIGSTOP after we start
2916 initctl set-env UNITY_MIR_EMITS_SIGSTOP=1
3017
31− # Save original value of MIR_SOCKET so that we can restore it when stopped,
32− # as we modify the variable for future jobs, including ourself.
33− initctl set-env UNITY_MIR_SOCKET=$MIR_SOCKET
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,
22+ # 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
3425
35− # Decide where we are going to put our own socket file
36− if [ -n "$SNAP" ]; then
37− # In snappy, we want to hard code our path because our apparmor profile
38− # only lets us put the socket in one place. And consumers expect it
39− # there.
40− MIR_SERVER_FILE=/run/user/$(id -u)/mir_socket
41− else
26+ # Point unity8 at unity-system-compositor
4227 MIR_SERVER_FILE=$XDG_RUNTIME_DIR/mir_socket
43− fi
44− initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
28+ initctl set-env MIR_SERVER_FILE=$MIR_SERVER_FILE
29+ initctl set-env MIR_SERVER_HOST_SOCKET=$UNITY_MIR_SOCKET
4530
46− # Point all future jobs in this session to our Mir socket instead of
47− # unity-system-compositor's socket.
48− initctl set-env --global MIR_SOCKET=$MIR_SERVER_FILE
49− gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
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
5036
5137 # Remove the normal and trusted sockets if still there
5238 if [ -S "$MIR_SERVER_FILE" ]; then
@@ -64,28 +50,9 @@ pre-start script
6450 # the lag seen in the indicator panel pull-down (LP: #1488327) and also
6551 # reduces lag seen in apps:
6652 initctl set-env --global QML_NO_TOUCH_COMPRESSION=1
67−
68− # Workaround for text not rendering correctly
69− initctl set-env --global QT_ENABLE_GLYPH_CACHE_WORKAROUND=1
70−
71− if [ "$XDG_SESSION_DESKTOP" = "ubuntu-touch" ]; then
72− # On Ubuntu Touch, we currently use a trick where we auto-login the
73− # user without a LightDM greeter at all. In this case, we want to
74− # start with the lockscreen visible. Once we switch to using a
75− # proper greeter for the first login, we can remove this code path.
76− initctl set-env MODE=full-greeter
77− else
78− initctl set-env MODE=full-shell
79− fi
80−
81− # HACK! WORKAROUND FOR HALIUM MISSING UBUNTU_PLATFORM_API
82− if [ ! -f /system/lib/libubuntu_application_api.so ]; then
83− initctl set-env --global UBUNTU_PLATFORM_API_BACKEND=test.so.3
84− initctl set-env --global UBUNTU_PLATFORM_API_SENSOR_TEST=/etc/ubuntusensors/test.sensors
85− fi
8653end script
8754
88−exec ${BINARY:-unity8} --mode=$MODE $ARGS
55+exec ${BINARY:-unity8} $ARGS
8956
9057post-start script
9158 initctl emit --no-wait indicator-services-start
@@ -93,7 +60,7 @@ end script
9360
9461post-stop script
9562 initctl set-env --global MIR_SOCKET=$UNITY_MIR_SOCKET
63+ initctl unset-env --global UNITY_MIR_SOCKET
9664 initctl unset-env --global MIR_SERVER_PROMPT_FILE
9765 initctl emit application-end
98− initctl emit indicator-services-end
9966end script
debian/changelog+20−1060
@@ -1,1038 +1,3 @@
1−unity8 (8.20+ubports) xenial; urgency=medium
2−
3− * Replace dependency on ubuntu-wallpapers with ubports-wallpapers
4−
5− -- Dalton Durst <dalton@ubports.com> Fri, 5 Oct 2018 13:28:20 -0500
6−
7−unity8 (8.17+ubports3) xenial; urgency=medium
8−
9− * Imported to UBports
10−
11− -- UBports auto importer <infra@ubports.com> Mon, 31 Jul 2017 03:12:43 +0200
12−
13−unity8 (8.15+17.04.20170404.7-0ubuntu2) zesty; urgency=medium
14−
15− [ Michael Zanetti ]
16− * Make the default store uri point to gnome software center
17−
18− -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Thu, 06 Apr 2017 10:49:29 +0300
19−
20−unity8 (8.15+17.04.20170404.7-0ubuntu1) zesty; urgency=medium
21−
22− [ Albert Astals Cid ]
23− * Tweak app drawer a bit (LP: #1667570)
24−
25− [ Josh Arenson ]
26− * Make some small changes to the greeter's session list
27− * Handle a user in the greeter having never selected a session better
28− (LP: #1673199)
29−
30− [ Lukáš Tinkl ]
31− * Do not occlude windows with an ongoing unmaximize transition (LP:
32− #1666363)
33− * Show and implement close buttons for child windows (LP: #1668053)
34− * Sanitize the logic for pointer vs. touch menus, fixes hiding the
35− window title in staged mode, when hovering the panel with mouse and
36− no menus available.
37−
38− [ Michael Zanetti ]
39− * Don't hide the launcher on super press if it's locked visible (LP:
40− #1675373)
41− * fix searchfield selection in drawer (LP: #1677259)
42− * make sure the stage has focus when going to spread (LP: #1672053,
43− #1672673, #1676995)
44− * don't autostart the dash app, but show its .desktop file instead
45−
46− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 04 Apr 2017 22:56:06 +0000
47−
48−unity8 (8.15+17.04.20170328.3-0ubuntu1) zesty; urgency=medium
49−
50− [ Albert Astals Cid ]
51− * mock: Remove empty property and move invokable
52− * Tune quicklist item selection
53− * Fix unminimizing going to the wrong position the second time (LP:
54− #1671458)
55− * Remove unclickable gaps on the menubar (LP: #1672722)
56− * indicators client is a tool
57− * Make sure we destroy the popups when the item goes away (LP:
58− #1670338)
59− * UnityApplicationMocks: Initialize m_state and m_requestedState
60− * Don't use appInfo after checking it if is null
61− * Initialize m_privateMode
62− * Hook up aboutToShow for overflow menus (LP: #1676016)
63−
64− [ Daniel d'Andrada ]
65− * Give active focus to child surface qml items (LP: #1671072)
66− * Satellite child windows (LP: #1673415)
67− * Tell qtmir/miral about the available desktop area
68−
69− [ Florian Boucault ]
70− * WindowStateStorage: use a private QThreadPool to ensure that
71− WindowStateStorage::saveValue always has a thread available to
72− execute the query in. (LP: #1675424)
73−
74− [ Lukáš Tinkl ]
75− * Protect against loading invalid window geometry (LP: #1674262)
76− * Remove usage of the deprecated (and non-functional) system-image-
77− dbus service.
78− * Implement Ctrl+Alt+T to launch the terminal app (LP: #1673500)
79− * Only take normal and dialog surface types into account for launcher
80− items (LP: #1669047)
81− * Fix the shutdown dialog after recent refactoring in
82− DBusUnitySessionService (LP: #1676426)
83−
84− [ Michael Zanetti ]
85− * drop the grey background behind icons in the drawer (LP: #1675688)
86−
87− [ Pete Woods ]
88− * Fix Unity/Platform::isPC, and add tests (LP: #1670657)
89−
90− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 28 Mar 2017 21:50:20 +0000
91−
92−unity8 (8.15+17.04.20170321-0ubuntu1) zesty; urgency=medium
93−
94− [ Albert Astals Cid ]
95− * Signal aboutToShow (LP: #1664578)
96− * Support Panel top level items to be disabled (LP: #1670694)
97− * Improve Launcher ←→ touch menu interaction (LP: #1667620, #1671069)
98− * Fix real world submenus (e.g. kate) not getting their first item
99− selected on open (LP: #1666859)
100−
101− [ Daniel d'Andrada ]
102− * Really disable the window decoration when in staged mode (LP:
103− #1670361)
104− * Don't let clients resize their surfaces while in staged
105− (phone/tablet) mode (LP: #1670390)
106− * TopLevelWindowModel: don't put hidden windows in the model (LP:
107− #1665286)
108−
109− [ Lukáš Tinkl ]
110− * Reset always-show-osk gsetting on startup to default value (false
111− atm)
112− * Fix the restored-to position with Miral due to the state changes
113− being async (LP: #1669819)
114− * Add a cursor name fallback mapping "grabbing" -> "closedhand" for
115− Breeze
116− * Fix unsnapping a maximized window from the panel (LP: #1671721)
117− * Disable altDrag feature outside windowed mode
118−
119− [ Michael Terry ]
120− * Don't lock the screen for guest users or users in the nopasswdlogin
121− group. (LP: #1644237)
122− * Support GNOME-style logout DBus API (making the Logout, Reboot, and
123− Shutdown launcher commands work) (LP: #1673229)
124−
125− [ Michael Zanetti ]
126− * Add support for closing apps from the spread with "Q" (LP: #1670327)
127− * hide "private" launcher quicklist entries when the greeter is locked
128− (LP: #1667649)
129− * add surface titles to launcher's quicklist (LP: #1661668)
130− * properly reset the drawer state when cancelling a horizontal drag
131− (LP: #1669536)
132− * fix the focus moving correctly between launcher and drawer (LP:
133− #1669880)
134− * unfocus the drawer's textfield when it is moved (LP: #1669839)
135−
136− [ Pete Woods ]
137− * Fix up indicators-client after refactoring (LP: #1672797)
138−
139− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 21 Mar 2017 10:58:13 +0000
140−
141−unity8 (8.15+17.04.20170308-0ubuntu1) zesty; urgency=medium
142−
143− [ Albert Astals Cid ]
144− * Let's follow the keyboard order
145− * Enable the license check (LP: #1590044)
146− * Show a barebones error message if loading the QML doesn't work
147− * Make sure cursor is back to normal when closing the window (LP:
148− #1666158)
149− * Fix small warning when sensitive is undefined
150− * Remove unused member variable
151− * Initialize m_msecsSinceReference
152− * Add warning if registerService fails
153− * Move menus Component {} out of the repeater
154− * Add tool to browse menus of a running app
155−
156− [ Daniel d'Andrada ]
157− * Drag child windows with Alt+LeftMouseButton (LP: #1664947)
158−
159− [ Gerry Boland ]
160− * TopLevelWindowModel: connect to the OSK surface to know when it goes
161− away so we can clean up after it. (LP: #1670681)
162−
163− [ Josh Arenson ]
164− * Initialize sessionMode to single when mock is reset (LP: #1667463)
165−
166− [ Lukáš Tinkl ]
167− * Make the menu string "Back" translatable
168− * Let the OSK be driven by a switch in indicator-keyboard (LP:
169− #1521518)
170− * Disable the tutorial when there's no touchscreen (LP: #1661557)
171− * Shell chrome fixes (LP: #1658117, #1665723, #1665724, #1669010)
172− * Cancel the drag as soon as we're entering the spread (LP: #1668642)
173− * Fix being unable to use window control buttons or menus with touch
174− (LP: #1667604, #1668387)
175−
176− [ Michael Terry ]
177− * Set QT_IM_MODULE in the greeter so that the OSK can come up. (LP:
178− #1670383)
179− * Simplify our startup handling of Mir environment variables and set
180− the right socket path in snappy.
181−
182− [ Michael Zanetti ]
183− * Cancel the home key activation if something else is pressed along
184− with Meta (LP: #1670678)
185− * close the drawer when something is launched from the launcher (LP:
186− #1660367)
187− * use a svg instead of a png for the Launcher's BFB (LP: #1668057)
188− * change the default setting for the launcher autohiding (LP:
189− #1670655)
190−
191− [ Nick Dedekind ]
192− * Split up Shell::test_spreadDisabled to ensure initial state for each
193− test.
194−
195− -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 08 Mar 2017 09:56:46 +0000
196−
197−unity8 (8.15+17.04.20170221-0ubuntu1) zesty; urgency=medium
198−
199− * Handle ubuntu-app-launch API/ABI break
200−
201− -- Ken VanDine <ken.vandine@canonical.com> Tue, 21 Feb 2017 13:23:23 +0000
202−
203−unity8 (8.15+17.04.20170216.1-0ubuntu1) zesty; urgency=medium
204−
205− [ Albert Astals Cid ]
206− * Make menus items close the menu when clicking on them (LP: #1657082,
207− #1657399)
208− * Clicking on an open menu closes it + test
209− * Make the menus and submenus do not go outside the screen when
210− popping out
211− * Auto open submenus on hover (LP: #1657085)
212− * Make the double click on a menu not be maximize the window below
213− (LP: #1657079)
214− * Make the MenuBar InverseMouseArea eat hover events when there's a
215− popup open (LP: #1657763)
216− * Make double click on the window decoration maximize (LP: #1657758)
217− * Eat hover events when the launcher quicklist is open (LP: #1640776)
218− * Remove TODO now that we require Qt > 5.5
219− * Serialize two make targets that want to cp to the same target file
220− (LP: #1660576)
221− * Remove variable that is always false (LP: #1585910)
222−
223− [ Daniel d'Andrada ]
224− * Consolidate launcher API checks
225−
226− [ Lukáš Tinkl ]
227− * Fixes for activating minimized windows and restoring fullscreen ones
228− (LP: #1656808, #1658937, #1658938)
229−
230− [ Michael Zanetti ]
231− * move right edge push area up some levels so it can be used on top of
232− the indicators
233− * fix minimizing/restoring transitions (LP: #1658936)
234− * fix some glitches with spread positioning
235− * fix jumpy animation when closing an item from the spread
236− * Show the wallpaper while the focused app is moving in staged mode
237− (LP: #1648251)
238− * Update the tutorial to mention the app drawer instead of the dash on
239− long left edge swipe (LP: #1658932)
240− * prevent hiding the launcher when the mouse hover event is eaten by
241− the EdgePushArea (LP: #1657045)
242− * properly invalidate the whole model (LP: #1658190)
243− * stabilize OrientedShell test (LP: #1658994)
244−
245− [ Nick Dedekind ]
246− * Added overflow support to application menus.
247− * Updated menu colors
248−
249− -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 16 Feb 2017 13:49:18 +0000
250−
251−unity8 (8.15+17.04.20170206-0ubuntu1) zesty; urgency=medium
252−
253− [ Daniel d'Andrada ]
254− * Initial support for child windows (menus, dialogs, tooltips) (LP:
255− #1543467, #1591384, #1656727)
256−
257− -- Albert Astals Cid <albert.astals@canonical.com> Mon, 06 Feb 2017 09:12:23 +0000
258−
259−unity8 (8.15+17.04.20170131.1-0ubuntu1) zesty; urgency=medium
260−
261− [ Rodney Dawes ]
262− * Remove dependencies on clickscope.
263−
264− -- Albert Astals Cid <albert.astals@canonical.com> Tue, 31 Jan 2017 14:40:33 +0000
265−
266−unity8 (8.15+17.04.20170124-0ubuntu1) zesty; urgency=medium
267−
268− [ Albert Astals Cid ]
269− * Limit tab-focus travelling on dialogs with a fence
270− * Restore focus to where it was when our ShellDialogs get unloaded
271− * Update current session after changing the user
272− * Add keyboard navigation for Indicators
273− * a window -> the current window
274− * There's no spreadDelegate_ anymore
275−
276− [ Daniel d'Andrada ]
277− * Simplify DecoratedWindow
278− * Remove unnecessary warning message
279−
280− [ Josh Arenson ]
281− * Add a test for the session chooser icon in the greeter's sessions
282− list
283−
284− [ Lukáš Tinkl ]
285− * Fix keymap not being applied on the shell itself (LP: #1626435)
286− * Shell dialog improvements (kbd focus, mouse eater)
287− * Start searching directly as you type, w/o having to first
288− focus/click the search field.
289− * Add a test for the real implementation of WindowStateStorage
290− * Use a four finger gesture to open the drawer, much like in u7
291−
292− [ Michael Terry ]
293− * Simplify the lightdm mock to make future greeter improvements easier
294− to test.
295− * Add support for guest sessions in unity8-greeter.
296− * Use a model for PAM prompts, supporting more possible interactions.
297− * Fix grouping of autopkg output and allow optionally passing
298− arguments to installed test scripts.
299− * Add support for LightDM hints for manual logins and hiding normal
300− users.
301−
302− [ Michael Zanetti ]
303− * hint the launcher to indicate a successful size change to the user
304− (LP: #1646457)
305− * Improvements for the appdrawer (LP: #1648173)
306− * Adjust home key to still focus the dash instead of messing with the
307− drawer
308− * allow 4 finger simulation with mousetouchadaptor
309−
310− [ Nick Dedekind ]
311− * Added Alt+F10 shortcut to open app menus. (LP: #1656896)
312− * Fixed menu layout width calculations. (LP: #1657050)
313− * Skip Panel::test_drag_indicator_item_down_shows_menu
314−
315− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 24 Jan 2017 07:46:58 +0000
316−
317−unity8 (8.15+17.04.20170110.4-0ubuntu1) zesty; urgency=medium
318−
319− [ Albert Astals Cid ]
320− * Give focus to one of the buttons of the dialog
321− * tst_WindowResizeArea: Use default values for mouseFlick speed and
322− iterations (LP: #1651580)
323− * Require Qt 5.6 & misc fixes
324−
325− [ Daniel van Vugt ]
326− * Deprecate usage of Mir's input resampling, instead opting for: (LP:
327− #1497105, #1591328)
328−
329− [ Josh Arenson ]
330− * Allow the scopes list to automatically scroll when a scope is being
331− dragged past the bounds of the screen. (LP: #1575319)
332−
333− [ Lukáš Tinkl ]
334− * Fix touch window controls being unreachable when the overlay is
335− being displayed (LP: #1648167)
336− * Fixup paths for window state storage in snappy environment
337− * Add Unity.Platform mock for our tests (LP: #1655336)
338−
339− [ Michael Zanetti ]
340− * PreviewRatingInput: Use displayText instead of text to
341− enable/disable the Send button (LP: #1595910)
342− * Add a D-Bus interface to control some debug facilities on the fly
343− * some launcher workarounds for the snapping
344−
345− [ Michał Sawicz ]
346− * Nuke leftover Platform in IndicatorsManager
347−
348− [ Nick Dedekind ]
349− * Added registry for application menus
350−
351− [ Michael Terry, Nick Dedekind ]
352− * Run the qmluitests.sh autopkg test against the installed package.
353−
354− [ Michał Sawicz, Nick Dedekind ]
355− * Application menus
356−
357− [ Rodney Dawes ]
358− * Remove the payments widget and dependency on libpay as no longer
359− needed.
360−
361− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 10 Jan 2017 14:48:42 +0000
362−
363−unity8 (8.15+17.04.20161215-0ubuntu2~1) zesty; urgency=medium
364−
365− * No change rebuild
366−
367− -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Wed, 04 Jan 2017 10:54:32 +0200
368−
369−unity8 (8.15+17.04.20161215-0ubuntu1) zesty; urgency=medium
370−
371− * Let the model deal with some window management decisions (LP:
372− #1346633)
373−
374− -- Daniel d'Andrada <daniel.dandrada@canonical.com> Thu, 15 Dec 2016 16:17:29 +0000
375−
376−unity8 (8.15+17.04.20161207.1-0ubuntu1) zesty; urgency=medium
377−
378− [ Albert Astals Cid ]
379− * Add the Wsuggest-override flag to gcc
380− * Add support for compiler sanitizers via ECM
381− * Use timeStep as delay time (LP: #1642919)
382− * Bring back fix for 1517830 (LP: #1517830)
383− * Fix compile warnings in mocks
384− * Do not hide panel when launching an application if the mouse is on
385− the panel (LP: #1591311)
386−
387− [ Daniel d'Andrada ]
388− * Fix "make tryApplicationWindow"
389− * Take save/restore functions out of WindowResizeArea
390−
391− [ Josh Arenson ]
392− * Enable the greeter to remember which session the user last logged
393− into (LP: #1631365)
394−
395− [ Lukáš Tinkl ]
396− * Fix the Super key not invoking the dash scope home (LP: #1607427)
397−
398− [ Michael Zanetti ]
399− * Add the ApplicationDrawer
400− * tune right edge push (LP: #1646094)
401− * improve close button visiblity when hovering with the mouse
402− * Update virtual touchpad visuals and add a tutorial. (LP: #1585220)
403−
404− [ Pete Woods ]
405− * MenuItemFactory: Add subtitle support to SwitchItem widget
406−
407− -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 07 Dec 2016 13:49:24 +0000
408−
409−unity8 (8.15+17.04.20161129-0ubuntu1) zesty; urgency=medium
410−
411− [ Albert Astals Cid ]
412− * Fix PreviewProgress implicitHeight (LP: #1641943)
413− * Adapt to dummy notification being gone
414− * Fix autopilot test_lock_screen tests
415− * Autopilot: Add more applications to the list for wider screens
416− * Fix autopilot DashHelperTestCase.test_search
417− * Also install the Screens mock
418− * Give default value to gu-px size
419−
420− [ Andrea Azzarone ]
421− * Set Mir.cursorName to "grabbing" on first mouse press on a window
422− decoration. Don't wait for press+motion. (LP: #1618078)
423− * Do not show a divider between each quicklist entry but just between
424− each section, similar to how unity7 does. (LP: #1637478)
425−
426− [ Andrea Cimitan ]
427− * Fix white text (LP: #1644468)
428− * Make MascotLoader in CardCreator flat
429− * Make the remaining UbuntuShape flat
430− * added dropshadow from panel indicators to dash page header extra
431− panel, so there is right shadow when the extra panel is narrow
432− * Look up for expandable template dash category flag
433−
434− [ Brian Douglass ]
435− * Added a setting to enable/disable the indicator dropdown menu.
436−
437− [ Daniel d'Andrada ]
438− * There's no need for WindowDecoration to access the appDelegate
439−
440− [ Lukáš Tinkl ]
441− * Enable brightness (laptop backlight) handling on desktop/laptop PCs
442− (LP: #1595947)
443−
444− [ Michael Zanetti ]
445− * disable spread interaction while locked (LP: #1641578)
446−
447− [ Andrea Azzarone, Michał Sawicz ]
448− * Implement launcher tooltips.
449−
450− [ Olivier Tilloy ]
451− * Remove dependency on transitional package. (LP: #1583079)
452−
453− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 29 Nov 2016 09:43:33 +0000
454−
455−unity8 (8.15+17.04.20161116.1-0ubuntu1) zesty; urgency=medium
456−
457− [ Marco Trevisan (Treviño) ]
458− * MenuItemFactory: bind calendar backend properties to calendarMenu item
459−
460− Adds support for showing the calendar at the requested date, marking days
461− with events properly and toggling the visibility of the week number.
462−
463− * MenuItemFactory: use Menus.RadioMenu and Menus.ButtonMenu
464−
465− * Bump version as USC breaks with unity8 << 8.14
466−
467− [ Albert Astals Cid ]
468− * [Hopefully] Fix infinite loop in some of the GSV tests (LP:
469− #1599301)
470−
471− [ Marco Trevisan (Treviño) ]
472− * testLauncher: use tryCompare to check launcher contentY
473−
474− [ Michael Zanetti ]
475− * Stabilize OrientedShell tests
476−
477− -- Marco Trevisan (Treviño) <mail@3v1n0.net> Wed, 16 Nov 2016 10:44:59 +0000
478−
479−unity8 (8.14+17.04.20161109-0ubuntu1) zesty; urgency=medium
480−
481− [ Albert Astals Cid ]
482− * Make more CardTool properties readonly
483− * Make the > in Dash Section Header be after text (LP: #1508905)
484− * Rework Dash Preview column margins
485− * Improve LVWPH <-> GenericScopeView interaction (LP: #1508905,
486− #1622423)
487− * Make the PreviewButtons be of the width of the button and not half
488− the total width
489− * Fix first column of the preview table to be 25%
490−
491− [ Andrea Cimitan ]
492− * Remove background under header pagination dots, update dots assets,
493− remove dash paper background, update bottom edge asset
494− * Few styling changes for cards
495− * various tweaks to fonts inside previews
496− * More visual tweaks
497−
498− [ Brian Douglass ]
499− * Add a new setting to enable/disable the launcher
500−
501− [ Lukáš Tinkl ]
502− * Stabilize test_doubleTapToMaximizeWindow()
503− * Enable loading the main Qt catalog which in turn allows for using
504− RTL languages
505− * Fix the pixelated notification icon by setting sourceSize (LP:
506− #1637712)
507−
508− [ Michael Terry ]
509− * More path lookup fixes for running inside of a snap. (LP: #1629009)
510−
511− [ Michael Zanetti ]
512− * Added blur and darkening to wallpaper while in spread
513− * Fixes in the spread after design review (LP: #1637502, #1638848)
514− * More fixes to the unified stages code (LP: #1637205, #1637249,
515− #1637258)
516− * Delay alt tab for tiny bit in order to avoid flickering on quick alt-
517− tabs
518−
519− [ Tomás Tormo ]
520− * Reload Infographics userdata when the day changes (LP: #1378814)
521−
522− -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 09 Nov 2016 15:10:32 +0000
523−
524−unity8 (8.14+17.04.20161027-0ubuntu1) zesty; urgency=medium
525−
526− * MenuItemFactory: activate item on calendar selection change (LP:
527− #1541125)
528−
529− -- Marco Trevisan (Treviño) <mail@3v1n0.net> Thu, 27 Oct 2016 12:32:25 +0000
530−
531−unity8 (8.14+17.04.20161024-0ubuntu1) zesty; urgency=medium
532−
533− [ Albert Astals Cid ]
534− * Make PreviewProgress be thicker again (LP: #1629382)
535− * tst_PreviewZoomableImage: Wait for LazyImage transitions on init()
536− (LP: #1630136)
537−
538− [ Andrea Azzarone ]
539− * Remove UbuntuShapeForItem and replace its use with the more standard
540− Ubuntu.Components.UbuntuShape.
541−
542− [ Lukáš Tinkl ]
543− * Restore the double tap decoration to maximize feature (LP: #1627281)
544− * Hide the cursor for fullscreen apps after 3 seconds of inactivity
545− * Implement moving windows by Alt + left mouse button
546−
547− [ Marco Trevisan (Treviño) ]
548− * MenuItemFactory: use more features from SlotsLayout based settings
549− components
550−
551− [ Michael Terry ]
552− * Grab launcher icon information from ubuntu-app-launch, not directly
553− from desktop files.
554− * Adjust root paths if we're running inside a snap. (LP: #1629009)
555−
556− [ Michael Zanetti ]
557− * Merge all Stages into one single codebase. Apply new spread visuals.
558− (LP: #1489517, #1603914, #1635800)
559−
560− -- Michael Zanetti <michael.zanetti@canonical.com> Mon, 24 Oct 2016 11:37:28 +0000
561−
562−unity8 (8.14+16.10.20160922-0ubuntu2) yakkety; urgency=medium
563−
564− * debian/control:
565− - Drop unity-scope-mediascanner2 to a Suggests rather than a Recommends,
566− to ease our transition to main. It's already seeded directly in
567− Touch, so this will only affect the Desktop variant of unity8.
568−
569− -- Michael Terry <mterry@ubuntu.com> Mon, 03 Oct 2016 10:43:25 -0400
570−
571−unity8 (8.14+16.10.20160922-0ubuntu1) yakkety; urgency=medium
572−
573− [ Albert Astals Cid ]
574− * LVWPH: update clipItem height when list height changes (LP:
575− #1606935)
576− * Put the touchdown shape inside a loader
577− * No need for the touchdown in the card for the cardtool
578− * Add bottom gradient to the Show Less floating button
579− * Remove artShapeSize from non cardtool cards
580− * LVWPH: Fix case in which header was shown incorrectly
581− * LVWPH: Fix items cut on top in the dash (or at least some instances
582− of it)
583− * Reduce calls to CardCreatorCache.getCardComponent while the
584− component is being created (LP: #1615675)
585− * Dash::test_cardIconStyle change compare into tryCompareFunction
586− * Make PreviewActionsTest::test_comboButton more stable
587− * Adapt onShiftedContentXChanged to work when the content changes very
588− abruptly
589− * Make tryGenericScopeView show the scope correctly
590− * Make sure the spinner does not get too close to the title text (LP:
591− #1597392)
592− * Show "Pull to refresh" in white when overlaid in low luminance
593− colors (LP: #1596849)
594− * Make test_Shell non ultra slow again (LP: #1597366)
595− * Improve findChild calls inside tryCompareFunction.
596−
597− [ Andrea Cimitan ]
598− * override some Qt Components definitions so we can have sane default
599− values for flick speeds
600− * Elide the label text inside recent searches panel (LP: #1611796)
601− * Add a PreviewSingleton module to store some data for previews (LP:
602− #1595235)
603− * Use PreviewSingleton for PreviewRatingInput and PreviewCommentInput
604− (LP: #1595235)
605− * rework GenericScopeView PullToRefresh test
606− * use mouseFlick instead touchFlick for manage_dash_move_current
607− * add a couple of waiting tricks for a flaky dash test
608−
609− [ Daniel d'Andrada ]
610− * Set progress bar indeterminate when processing signal received. (LP:
611− #1249349)
612− * Implement cursor confinement (LP: #1590099)
613−
614− [ Josh Arenson ]
615− * Add a frontend to the sessions model and enable a session chooser in
616− the greeter.
617−
618− [ Lukáš Tinkl ]
619− * Implement edge maximizing (aka window snapping) (LP: #1602628)
620− * On the PC platform (as opposed to running on $devices), use the
621− "mute" action instead of silent mode
622− * Respect Fitt's law wrt the window control buttons in panel (LP:
623− #1611959)
624− * Fix 2 failing color-related tests
625−
626− [ Marco Trevisan (Treviño) ]
627− * Indicators, mocks: add fake indicators menuitem to populate mocks
628− with different menu types
629− * IndicatorsClient: use PageHeader and ListItemLayout's
630−
631− [ Michael Terry ]
632− * Support launching apps inside a unity8 session from the greeter and
633− support emergency dialing inside the greeter.
634− * Fix tryShell to actually show appropriate backgrounds for each mock
635− user.
636− * Add an indicator to the greeter when a user is logged in (only shown
637− if we have more than one user)
638− * Hide the greeter OSK if indicators are open and don't show the edge
639− tutorial during an emergency call.
640− * Switch from lockscreen PIN pad to a passcode entry box that uses the
641− OSK.
642− * Use the default system wallpaper instead of our custom one.
643− * Update look of infographic a bit
644− * Make infographic bubbles white even on the default wallpaper.
645−
646− -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 22 Sep 2016 07:46:57 +0000
647−
648−unity8 (8.14+16.10.20160831.3-0ubuntu1) yakkety; urgency=medium
649−
650− [ Daniel d'Andrada ]
651− * Added implementation for MirSurfaceInterface::persistentId
652−
653− -- Ken VanDine <ken.vandine@canonical.com> Wed, 31 Aug 2016 11:56:09 +0000
654−
655−unity8 (8.14+16.10.20160826-0ubuntu1) yakkety; urgency=medium
656−
657− * Make sure we emit sounds when taking a screenshot even after media-
658− hub (LP: #1544477)
659−
660− -- Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com> Fri, 26 Aug 2016 08:14:14 +0000
661−
662−unity8 (8.14+16.10.20160819-0ubuntu1) yakkety; urgency=medium
663−
664− [ Lukáš Tinkl ]
665− * Reset topmostIsFullscreen to correctly rotate the shell when
666− dismissing SIM PIN screen (LP: #1614070)
667−
668− -- Michał Sawicz <michal.sawicz@canonical.com> Fri, 19 Aug 2016 14:16:54 +0000
669−
670−unity8 (8.14+16.10.20160811.1-0ubuntu1) yakkety; urgency=medium
671−
672− [ Albert Astals Cid ]
673− * Take into account carousel selectedItemScaleFactor when setting card
674− fixedArtShapeSize (LP: #1599238)
675− * Remove unused LimitProxyModel
676− * Do not calculate implicitHeight for Cards in a CardGrid
677− * Small clazy fixes
678−
679− [ Daniel d'Andrada ]
680− * Remove stage property from Application
681−
682− [ Larry Price ]
683− * Allow libertine-scope to show empty search result hint unmodified.
684− (LP: #1606693)
685−
686− [ Lukáš Tinkl ]
687− * Open the quicklist (context) menu also using the Menu key (LP:
688− #1608265)
689− * Fix incorrect SIM PIN dialog position when entering a wrong PIN (LP:
690− #1596076)
691− * Apply the correct keymap also on prompt surfaces (LP: #1610124)
692− * Implement an optional system update feature during OOBE wizard (LP:
693− #1580785)
694− * Implement a page for choosing HW keyboard layout in OOBE wizard
695−
696− [ Michael Zanetti ]
697− * Clean up some build script legacy
698− * Add a crossbuilder_post file to make crossbuilder restart unity8
699− after deploying
700− * fixes for the automatic switching between usage modes (LP: #1590944)
701−
702− [ Omer Akram ]
703− * Add object names for setup wizard
704−
705− -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 11 Aug 2016 06:28:20 +0000
706−
707−unity8 (8.14+16.10.20160803-0ubuntu1) yakkety; urgency=medium
708−
709− [ Albert Astals Cid ]
710− * Fix DisabledScreenNotice::test_rotation
711− * Make the delegate of DashNavigationList an async Loader
712− * unity-scope-tool: Use parse instead of process
713− * VerticalJournal improvements regarding model insertions and item
714− height changes (LP: #1599754)
715− * Add math.h includes for compilation in yakkety (LP: #1605502)
716−
717− [ Andrea Cimitan ]
718− * Unfocus the search text field in the dash page header when requested
719− (LP: #1590820)
720− * Use binding for filter popover contentWidth (LP: #1595116)
721− * Add few sourceSize for Image we forgot (LP: #1595113)
722− * Replace Flickable with an Item inside DashPageHeader for
723− headerContainer (LP: #1599235)
724−
725− [ Albert Astals Cid, Andrea Cimitan ]
726− * Unbox the artshapeLoader
727−
728− [ Daniel d'Andrada ]
729− * Fix splashscreen orientation when app rotates own contents (LP:
730− #1586050)
731− * tst_PreviewIconActions: Make test name match filename
732− * Cursor: make its size grid unit based (LP: #1604014)
733− * TouchEventSequenceWrapper: item might get deleted when touch
734− sequence is committed (LP: #1607686)
735−
736− [ Lukáš Tinkl ]
737− * Implement frontend support for running keyboard indicator
738− * Provide window/surface close shortcuts across all the stages (LP:
739− #1578392, #1606528)
740− * Restart the location trust prompt service when exiting the wizard
741− (LP: #1594430)
742− * Implement clearing the search and closing the panel on pressing
743− Escape key in the dash header
744− * Fix log timestamps (LP: #1602196)
745− * Don't display the mode switch warning dialog on tablets (LP:
746− #1600290)
747−
748− [ Michael Terry ]
749− * Fix indicator profile bug that caused sound indicator to say Mute
750− instead of Silent Mode. (LP: #1604205)
751− * Fix lockscreen appearing right after unlocking a locked session on
752− the desktop. (LP: #1604374)
753−
754− [ Michał Sawicz ]
755− * Add arm64 support, drop unnecessary B-D on web plugin
756−
757− -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 03 Aug 2016 15:56:27 +0000
758−
759−unity8 (8.14+16.10.20160728-0ubuntu1) yakkety; urgency=medium
760−
761− [ Zoltán Balogh ]
762− * Bump the version to secure UITK compatibility
763−
764− [ Albert Astals Cid ]
765− * Pass the correct number of arguments to mapToItem (LP: #1606835)
766−
767− -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 28 Jul 2016 08:17:13 +0000
768−
769−unity8 (8.13+16.10.20160714+fix1-0ubuntu2~1) yakkety; urgency=medium
770−
771− * Rebuild against Qt 5.6.
772− * Add https://code.launchpad.net/~aacid/unity8/floor_includes/+merge/300850
773−
774− -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Fri, 22 Jul 2016 09:03:54 +0300
775−
776−unity8 (8.13+16.10.20160714-0ubuntu1) yakkety; urgency=medium
777−
778− [ Daniel d'Andrada ]
779− * Make use of MirSurface::inputBounds and drop UbuntuKeyboardInfo hack
780−
781− -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 14 Jul 2016 07:09:29 +0000
782−
783−unity8 (8.12+16.10.20160711-0ubuntu1) yakkety; urgency=medium
784−
785− [ Josh Arenson ]
786− * Add a SessionsModel to lightdm to support the greeter's session
787− chooser
788− * Add unity8-greeter package which contains a basic, but usable
789− LightDM greeter. (LP: #1324602)
790−
791− [ Michael Terry ]
792− * Make sure indicators and launcher hide when power button is pressed
793− on greeter. (LP: #1595569)
794− * Fix tablet greeter focus to be always-on, no longer hiding the OSK
795− or forcing a mouse click to type a password. (LP: #1435923)
796−
797− -- Michael Terry <michael.terry@canonical.com> Mon, 11 Jul 2016 17:24:20 +0000
798−
799−unity8 (8.12+16.10.20160707-0ubuntu1) yakkety; urgency=medium
800−
801− [ Michael Zanetti ]
802− * emit the correct role changed signal on count visible changed (LP:
803− #1599925)
804−
805− -- Michał Sawicz <michal.sawicz@canonical.com> Thu, 07 Jul 2016 16:49:32 +0000
806−
807−unity8 (8.12+16.10.20160705-0ubuntu1) yakkety; urgency=medium
808−
809− [ Michael Zanetti ]
810− * don't displace windows if the OSK is on another screen (LP:
811− #1598917)
812−
813− -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 05 Jul 2016 10:00:57 +0000
814−
815−unity8 (8.12+16.10.20160627.5-0ubuntu1) yakkety; urgency=medium
816−
817− [ Albert Astals Cid ]
818− * Stop watching the old header item height once it's not our header
819− anymore
820− * LVWPH: cull the header item when not on view to save some painting
821− * Adapt test to new mock behaviour
822− * Don't let the mouse go outside the parentItem (LP: #1525350)
823− * Use non deprecated package names
824− * Mark system includes as such
825− * Fix initialization order warning
826− * Do not rely on deleteLater not crashing on null pointers
827− * Add more headers of classes we use for automoc to be run
828− * CardTool: Fix the fallback value to be a size and not an integer
829− * CardTool: Include Ubuntu Components since we're using units.gu
830− * Rework tst_PreviewRatingDisplayCreationRanges
831−
832− [ Daniel d'Andrada ]
833− * Cursor: Let AnimatedSprite run only on animated cursors and while
834− the display is on (LP: #1588873, #1594358)
835− * Fix missing screenshot when orientation changes while shell rotation
836− ongoing (LP: #1587796)
837−
838− [ Josh Arenson ]
839− * Make PreviewRatingSingleDisplay visible again after editing a
840− review. (LP: #1587097)
841− * Correct errors in all png images to prevent libpng warnings.
842−
843− [ Lukáš Tinkl ]
844− * Fix some smaller issues with OOBE wizard password pages (LP:
845− #1590467)
846− * Prevent mouse wheel events from going through shell elements (LP:
847− #1536268)
848− * Do not let mouse and wheel events pass thru the titlebar (LP:
849− #1588424)
850− * Hide the maximize window button based on size restrictions (LP:
851− #1541982)
852−
853− [ Marco Trevisan (Treviño) ]
854− * Unity8.conf: ensure MIR_SOCKET is set for future customers (such as
855− the dash)
856− * ClientIndicator: be more informative about loading failures for
857− dynamically created objects
858−
859− [ Michael Terry ]
860− * Stop unity8 from getting in a "switch-to-greeter" loop when locking
861− on a desktop. (LP: #1593718)
862−
863− [ Michael Zanetti ]
864− * set minimum window sizes on dash
865− * displace application windows when the OSK would cover them
866−
867− [ Nick Dedekind ]
868− * Force dash to always stay in the main stage. (lp:#1592404) (LP:
869− #1592404)
870− * Save the last surface stage on stage drop. (LP: #1579003)
871− * Default portrait only apps to the side stage. (LP: #1573153)
872−
873− [ Albert Astals Cid, Andrea Cimitan, Michał Sawicz, Nick Dedekind ]
874− * Added live video playback in dash previews
875−
876− -- Michael Zanetti <michael.zanetti@canonical.com> Mon, 27 Jun 2016 18:48:59 +0000
877−
878−unity8 (8.12+16.10.20160620.3-0ubuntu1) yakkety; urgency=medium
879−
880− [ Michael Terry, Michał Sawicz ]
881− * Support unlocking via fingerprint, if one is registered.
882−
883− -- Michael Terry <michael.terry@canonical.com> Mon, 20 Jun 2016 20:25:25 +0000
884−
885−unity8 (8.12+16.10.20160617-0ubuntu1) yakkety; urgency=medium
886−
887− [ Michael Terry ]
888− * Do not create Label/Icon if we don't need it
889− * Fix Z-ordering of prompt surfaces (LP: #1586219)
890− * Drop bottom edge tutorials completely and small fixes for other
891− edges. (LP: #1565103)
892− * Redo visuals for greeter prompt box. (LP: #1435923)
893− * Make tutorial qmltests more robust. (LP: #1590810)
894− * Stop showing an extra lockscreen in desktop unity8 sessions. (LP:
895− #1582987)
896−
897− [ Albert Astals Cid ]
898− * Improve dash plugin mock
899− * Stabilize PreviewExpandableTest::test_all_widgets_height
900− * Workaround QTBUG-53460
901− * Split artShape code for cardTool card and regular card
902− * Simplify the code since fixedArtSize code is mandatory for regular
903− cards
904− * Desktop stage: Support rotatesWindowContents (LP: #1547481)
905− * Turn if if else into if elseif else
906− * Fix leaks in QInputDeviceManagerPrivate::addDevice
907− * Do not call |= on uninitialized sigterm.sa_flags
908− * initialize udevMonitor
909− * Make notifier and notifierFd function local variables
910− * Fix crash if a component that is not an Item is given to
911− sectionDelegate
912− * Tests: Do not use dynamic_cast if we're not going to test it anyway
913− * Minor coverity fixes
914− * Fix warning about anchors.fill in ProportionalShape (LP: #1590963)
915− * Make wait in cleanup() wait for snapTo animation to have finished
916−
917− [ Alexandros Frantzis ]
918− * Improve the way notifications interact with power management (LP:
919− #1570922)
920−
921− [ Andrea Cimitan ]
922− * Correctly refresh cardcreator cache on artshapestyle changes (LP:
923− #1588335)
924− * Same tweaks we have for click scope now for libertine
925− * add a timer to pull to refresh to work on small windows (LP:
926− #1589060)
927−
928− [ Daniel d'Andrada ]
929− * Clean up debug leftovers
930− * Ensure mouse and window movement are pixel-aligned (LP: #1510382)
931− * Fix SpreadDelegate rotation animations
932− * No point in version-controlling files that are automatically
933− generated
934− * Center cursor on screen when it's first shown
935− * Custom cursor name just have to start with "custom"
936− * Work around AnimatedSprite infinite loop bug (LP: #1588929)
937−
938− [ Josh Arenson ]
939− * Disable showDash when it is already shown. (LP: #1506708)
940− * Add a timestamp to the dash log (LP: #1580074)
941− * Add timestamp to unity8 log (LP: #1498169)
942−
943− [ Lukáš Tinkl ]
944− * Implement keyboard shortcuts info panel
945− * Implement window controls overlay activatable with 3 fingers tap
946− (LP: #1489020)
947− * Select correct Chinese input method for OSK in the wizard (LP:
948− #1588633)
949−
950− [ Michael Zanetti ]
951− * Add support for the launcher surface pips displaying the correct
952− number of surfaces
953− * Add support for the persistent alert state. (LP: #1575147, #1584348,
954− #1586621)
955− * send a Alt-release event on alt+tab instead of delaying it
956− completely and invoking it later (LP: #1565236)
957−
958− [ Stephen M. Webb ]
959− * added a new upstart $SESSION for unity8-desktop-session (LP:
960− #1376715)
961−
962− -- Michael Terry <michael.terry@canonical.com> Fri, 17 Jun 2016 01:22:57 +0000
963−
964−unity8 (8.12+16.10.20160601.1-0ubuntu1) yakkety; urgency=medium
965−
966− [ Pawel Stolowski ]
967− * Added apparmor profile for unity8-dash.
968−
969− -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 01 Jun 2016 20:59:03 +0000
970−
971−unity8 (8.12+16.10.20160527-0ubuntu1) yakkety; urgency=medium
972−
973− [ Albert Astals Cid ]
974− * Activate on click for SimpleMessages (LP: #1421696)
975− * Add override
976− * Change the art back to the cardData value if it changes from broken
977− to valid image (LP: #1533577)
978− * Concierge mode generated code optimization
979− * Don't use context properties but properties of the delegates
980− * Listen to contentItem::widthChanged instead of
981− Flickable::contentWidthChanged (LP: #1565763)
982− * Make some AP code faster
983− * Make tests a bit more stable
984− * Make unity8 and unity8-dash handle termination signals
985− * Remove workaround not needed anymore (LP: #1475643)
986− * Resolve cardArtStyle on compile time
987− * Set the theme earlier (LP: #1574048)
988−
989− [ Albert Astals Cid, Daniel d'Andrada ]
990− * Remove DirectionalDragArea and libs/UbuntuGestures and port to SDK
991− equivalents
992−
993− [ Andrea Cimitan ]
994− * Hide the preview review input field when a rating is required (LP:
995− #1541971)
996−
997− [ CI Train Bot ]
998− * Resync trunk.
999−
1000− [ Daniel d'Andrada ]
1001− * Fix DragHandle so it works in all directions
1002− * Support animated cursors
1003− * WindowInputMonitor - also map Qt::Key_HomePage to our home key
1004− * plugins/Cursor: properly register to the screen's QPlatformCursor
1005− when screen changes (LP: #1579742)
1006−
1007− [ Josh Arenson ]
1008− * Close the PageHeaderExtraPanel when a filter option is selected (LP:
1009− #1569498)
1010− * Wrap primaryFilter in a flickable to make it behave nicely. (LP:
1011− #1569492)
1012−
1013− [ Lukáš Tinkl ]
1014− * First snap decision should always be expanded, unless user decides
1015− otherwise (LP: #1580090, #1575045)
1016− * Fullscreen notification bug fixes (LP: #1583944, #1581498, #1422711)
1017− * Implement maximizing windows horizontally/vertically
1018− * Lock the session when putting the laptop into sleep (LP: #1581063)
1019−
1020− [ Lukáš Tinkl, Michael Terry ]
1021− * With a maximized window, "dragging" the panel down should restore it
1022−
1023− [ Michael Terry ]
1024− * Change some dash button colors from orange to green. (LP: #1581047)
1025− * Use PageHeader instead Ambiance's PageHeadStyle
1026− * Use new setTimeZone method to set user-friendly timezone name in the
1027− wizard. (LP: #1566295)
1028−
1029− [ Michael Zanetti ]
1030− * Remove the background dimming when the launcher is revealed by a
1031− drag (LP: #1575137)
1032− * reenable or drop disabled tests
1033−
1034− -- Michael Terry <michael.terry@canonical.com> Fri, 27 May 2016 13:54:44 +0000
1035−
10361unity8 (8.12+16.10.20160520.1-0ubuntu1) yakkety; urgency=medium
10372
10383 [ Lukáš Tinkl ]
@@ -1224,7 +189,7 @@ unity8 (8.12+16.04.20160330-0ubuntu1) xenial; urgency=medium
1224189unity8 (8.12+16.04.20160323.2-0ubuntu1) xenial; urgency=medium
1225190
1226191 [ Michael Terry ]
1227− *
192+ *
1228193 * Fix setting OSK layout in OOBE wizard
1229194 * Stop the left edge tutorial from being shown when the bottom edge
1230195 tutorial wants to be shown after receiving a call.
@@ -3936,7 +2901,7 @@ unity8 (8.00+14.10.20140729-0ubuntu1) utopic; urgency=medium
39362901 * Re-architecture unity8 to use the QtMirCompositor library so that
39372902 the Qt scenegraph renderer is used as the Mir compositor, and
39382903 application surfaces are added to the QML scene as items.
3939−
2904+
39402905 [ Michael Zanetti ]
39412906 * Port phone right-edge spread code to use QtCompositor
39422907 * Add right-edge spread animation for tablet
@@ -4210,8 +3175,8 @@ unity8 (7.90+14.10.20140703.1-0ubuntu1) utopic; urgency=low
42103175
42113176unity8 (7.90+14.10.20140701.2-0ubuntu2) utopic; urgency=medium
42123177
4213− * debian/control:
4214− list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
3178+ * debian/control:
3179+ list qtdeclarative5-ubuntu-ui-toolkit-plugin-gles as an alternative
42153180 choice, since provides are not versionned, should restore installability
42163181 on amd64 and i386
42173182
@@ -7313,7 +6278,7 @@ unity8 (7.81.2) saucy; urgency=low
73136278 [ Michał Sawicz ]
73146279 * Fix icons in ApplicationsFilterGrid.qml.
73156280 * Support flipped image in run_on_device.
7316−
6281+
73176282 [ Michael Zanetti ]
73186283 * Don't clear lockscreen when it's fading out.
73196284 * Reworked Launcher folding.
@@ -7398,7 +6363,7 @@ qml-phone-shell (1.79) raring; urgency=low
73986363
73996364 [ Michael Terry ]
74006365 * Make greeter look like the desktop one
7401−
6366+
74026367 [ Gerry Boland ]
74036368 * Fix a bug where a minimized app gets focus after closing another app
74046369 * Applied a workaround to reduce flickering when launching apps
@@ -7414,7 +6379,7 @@ qml-phone-shell (1.79) raring; urgency=low
74146379qml-phone-shell (1.78) raring; urgency=low
74156380
74166381 [ Sergio Schvezov ]
7417− * Replacing the music and ski safari mock apps with calendar and weather in
6382+ * Replacing the music and ski safari mock apps with calendar and weather in
74186383 the launcher (LP: #1178262).
74196384
74206385 [ Daniel d'Andrada ]
@@ -7456,7 +6421,7 @@ qml-phone-shell (1.77) raring; urgency=low
74566421 [ Mathieu Trudel-Lapierre ]
74576422 * debian/control:
74586423 - Drop indicators-client-plugin* Depends for qml-phone-shell to Recommends.
7459− - Add/update Vcs-Browser, Vcs-Bzr and add a notice to uploaders.
6424+ - Add/update Vcs-Browser, Vcs-Bzr and add a notice to uploaders.
74606425 * debian/copyright: fix syntax.
74616426
74626427 [ Michał Sawicz ]
@@ -7466,7 +6431,7 @@ qml-phone-shell (1.77) raring; urgency=low
74666431 * Renamed Media player files to match with new application name.
74676432
74686433 [ Daniel d'Andrada ]
7469− * New: DirectionalDragArea component. An area that detects axis-aligned
6434+ * New: DirectionalDragArea component. An area that detects axis-aligned
74706435 single-finger drag gestures.
74716436 * Make it possible to send touch events from within QML test code.
74726437
@@ -7903,7 +6868,7 @@ qml-phone-shell (1.39) quantal; urgency=low
79036868
79046869qml-phone-shell (1.38) quantal; urgency=low
79056870
7906− * fix launching of notepad
6871+ * fix launching of notepad
79076872
79086873 -- Bill Filler <bill.filler@canonical.com> Fri, 01 Feb 2013 03:21:29 -0500
79096874
@@ -7916,14 +6881,14 @@ qml-phone-shell (1.37) quantal; urgency=low
79166881
79176882qml-phone-shell (1.36) quantal; urgency=low
79186883
7919− * launch real notepad app
6884+ * launch real notepad app
79206885 * fix launching of mock apps
79216886
79226887 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 21:36:05 -0500
79236888
79246889qml-phone-shell (1.35) quantal; urgency=low
79256890
7926− * integrate ubuntu-browser instead of snowshoe
6891+ * integrate ubuntu-browser instead of snowshoe
79276892
79286893 -- Bill Filler <bill.filler@canonical.com> Thu, 31 Jan 2013 17:33:37 -0500
79296894
@@ -8007,7 +6972,7 @@ qml-phone-shell (1.22) quantal; urgency=low
80076972
80086973qml-phone-shell (1.21) quantal; urgency=low
80096974
8010− * New release with fullscreen launcher fixes
6975+ * New release with fullscreen launcher fixes
80116976
80126977 -- Bill Filler <bill.filler@canonical.com> Fri, 07 Dec 2012 09:36:37 +0000
80136978
@@ -8019,7 +6984,7 @@ qml-phone-shell (1.20) quantal; urgency=low
80196984
80206985qml-phone-shell (1.19) quantal; urgency=low
80216986
8022− * enable multi-threaded render for apps
6987+ * enable multi-threaded render for apps
80236988
80246989 -- Bill Filler <bill.filler@canonical.com> Wed, 05 Dec 2012 17:34:09 +0000
80256990
@@ -8027,7 +6992,7 @@ qml-phone-shell (1.18) quantal; urgency=low
80276992
80286993 [ Bill Filler ]
80296994 * update launcher to use wk2-render (chromeless webkit) for facebook
8030− and twitter
6995+ and twitter
80316996
80326997 -- Florian Boucault <florian.boucault@canonical.com> Wed, 05 Dec 2012 12:20:50 +0000
80336998
@@ -8039,7 +7004,7 @@ qml-phone-shell (1.17) quantal; urgency=low
80397004
80407005qml-phone-shell (1.16) quantal; urgency=low
80417006
8042− * fix to launch new gallery with correct args
7007+ * fix to launch new gallery with correct args
80437008
80447009 -- Bill Filler <bill.filler@canonical.com> Thu, 29 Nov 2012 17:04:36 -0500
80457010
@@ -8101,7 +7066,7 @@ qml-phone-shell (1.2) quantal; urgency=low
81017066
81027067qml-phone-shell (1.1) quantal; urgency=low
81037068
8104− * comment out console.log() to prevent crash
7069+ * comment out console.log() to prevent crash
81057070
81067071 -- Bill Filler <bill.filler@canonical.com> Sun, 28 Oct 2012 22:18:36 +0100
81077072
@@ -8129,19 +7094,19 @@ qml-phone-shell (0.7) quantal; urgency=low
81297094 * qml-phone-shell.conf: better setup of env vars and launch
81307095 via dbus-luanch to properly setup session bus
81317096 * shellapplication.cpp: don't setup custom env before launching
8132− processes
7097+ processes
81337098
81347099 -- Bill Filler <bill.filler@canonical.com> Sun, 21 Oct 2012 11:32:42 +0200
81357100
81367101qml-phone-shell (0.6) quantal; urgency=low
81377102
8138− * added additional Android env vars to upstart script
7103+ * added additional Android env vars to upstart script
81397104
81407105 -- Bill Filler <bill.filler@canonical.com> Fri, 19 Oct 2012 09:35:25 -0400
81417106
81427107qml-phone-shell (0.5) quantal; urgency=low
81437108
8144− * added support to launch telephony-app
7109+ * added support to launch telephony-app
81457110
81467111 -- Bill Filler <bill.filler@canonical.com> Thu, 18 Oct 2012 13:45:25 -0400
81477112
@@ -8168,8 +7133,3 @@ qml-phone-shell (0.1) quantal; urgency=low
81687133 * Initial release
81697134
81707135 -- Bill Filler <bill.filler@canonical.com> Wed, 10 Oct 2012 10:19:53 -0400
8171−unity8 (8.15+17.04.20170404.7-0ubuntu2) zesty; urgency=medium
8172−
8173− [ Michael Zanetti ]
8174− * Make the default store uri point to gnome software center
8175−
debian/control+168−223
@@ -2,271 +2,216 @@ Source: unity8
22Section: x11
33Priority: optional
44Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5−Build-Depends:
6− android-headers,
7− cmake,
8− cmake-extras,
9− dbus-test-runner,
10− debhelper (>= 9),
11− dh-apparmor,
12− doxyqml,
13− g++:native,
14− gdb,
15− graphviz,
16− gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
17− libandroid-properties-dev,
18− libconnectivity-qt1-dev (>= 0.7.1),
19− libevdev-dev,
20− libgeonames-dev (>= 0.2),
21− libgl1-mesa-dev[!arm64 !armhf] | libgl-dev[!arm64 !armhf],
22− libgl1-mesa-dri,
23− libgles2-mesa-dev[arm64 armhf],
24− libglib2.0-dev,
25− libgnome-desktop-3-dev,
26− libgsettings-qt-dev,
27− libhardware-dev,
28− liblightdm-qt5-3-dev,
29− libpam0g-dev,
30− libpulse-dev,
31− libqmenumodel-dev (>= 0.2.12),
32− libqt5sql5-sqlite,
33− libqt5svg5-dev,
34− libqt5xmlpatterns5-dev,
35− libqtdbusmock1-dev (>= 0.7),
36− libqtdbustest1-dev,
37− libsystemsettings-dev,
38− libubuntu-app-launch2-dev,
39− libubuntu-download-manager-common-dev,
40− libubuntugestures5-dev (>= 1.3.2030),
41− libubuntugestures5-private-dev (>= 1.3.2030),
42− libudev-dev,
43− libudm-common-dev,
44− libunity-api-dev (>= 8.7),
45− libusermetricsoutput1-dev,
46− libx11-dev[!arm64 !armhf],
47− libxcb1-dev[!arm64 !armhf],
48− libxi-dev[!arm64 !armhf],
49− pkg-config,
50− python3-all:any,
51− python3-setuptools,
52− qml-module-qt-labs-folderlistmodel,
53− qml-module-qt-labs-settings,
54− qml-module-qtmultimedia (>= 5.6),
55− qml-module-qtqml-statemachine,
56− qml-module-qtquick-layouts,
57− qml-module-qtquick-xmllistmodel,
58− qml-module-qtquick2,
59− qml-module-qtsysteminfo,
60− qml-module-qttest,
61− qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
62− qml-module-ubuntu-layouts,
63− qml-module-ubuntu-settings-components,
64− qml-module-ubuntu-test,
65− qtbase5-dev (>= 5.6),
66− qtbase5-dev-tools,
67− qtbase5-private-dev (>= 5.6),
68− qtdbustest-runner,
69− qtdeclarative5-dev (>= 5.6),
70− qtdeclarative5-dev-tools,
71− qtdeclarative5-private-dev (>= 5.6),
72− qtdeclarative5-ubuntu-content1,
73− ttf-ubuntu-font-family,
74− ubports-wallpapers,
75− xvfb,
5+Build-Depends: cmake,
6+ dbus-test-runner,
7+ debhelper (>= 9),
8+ doxyqml,
9+# To allow cross-compiling to work, we also must append :native
10+# to g++ so we don't try to run armhf g++
11+# on an x86 CPU for example, when cross-compiling.
12+ g++:native,
13+ libandroid-properties-dev,
14+ graphviz,
15+ gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
16+ libconnectivity-qt1-dev (>= 0.7.1),
17+ libevdev-dev,
18+ libgeonames-dev (>= 0.2),
19+ libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
20+ libgl1-mesa-dri,
21+ libgles2-mesa-dev[armhf],
22+ libglib2.0-dev,
23+ libgsettings-qt-dev,
24+ libhardware-dev,
25+ libpam0g-dev,
26+ libpay2-dev,
27+ libpulse-dev,
28+ libqmenumodel-dev (>= 0.2.9),
29+ libqt5svg5-dev,
30+ libqt5xmlpatterns5-dev,
31+ libsystemsettings-dev,
32+ libubuntugestures5-dev,
33+ libubuntugestures5-private-dev,
34+ libudev-dev,
35+ libunity-api-dev (>= 7.112),
36+ libusermetricsoutput1-dev,
37+# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
38+ libx11-dev[!armhf],
39+ libxcb1-dev[!armhf],
40+ libxi-dev[!armhf],
41+# End of X11 libs
42+ pkg-config,
43+ python3-all:any,
44+ python3-setuptools,
45+ qml-module-qt-labs-folderlistmodel,
46+ qml-module-qtquick-layouts,
47+ qml-module-qtquick-xmllistmodel,
48+ qml-module-qtquick2,
49+ qml-module-qtsysteminfo,
50+ qml-module-qttest,
51+ qt5-default,
52+ qtbase5-dev (>= 5.4),
53+ qtbase5-dev-tools,
54+ qtbase5-private-dev (>= 5.4),
55+ qtdeclarative5-dev (>= 5.4),
56+ qtdeclarative5-dev-tools,
57+ qtdeclarative5-private-dev (>= 5.4),
58+ qtdeclarative5-qtmultimedia-plugin (>= 5.4.1-1ubuntu19~overlay2),
59+ qtdeclarative5-ubuntu-content1,
60+ qtdeclarative5-ubuntu-settings-components (>= 0.7),
61+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
62+ qtdeclarative5-ubuntu-web-plugin,
63+ ttf-ubuntu-font-family,
7664Standards-Version: 3.9.4
77−Homepage: https://github.com/ubports/unity8
78−Vcs-Git: https://github.com/ubports/unity8
65+Homepage: http://launchpad.net/unity
66+# If you aren't a member of ~unity-team but need to upload
67+# packaging changes, just go ahead. ~unity-team will notice
68+# and sync up the code again.
69+Vcs-Bzr: https://code.launchpad.net/unity8
70+Vcs-Browser: https://bazaar.launchpad.net/~unity-team/unity8/trunk
7971XS-Testsuite: autopkgtest
8072X-Ubuntu-Use-Langpack: yes
8173
8274Package: indicators-client
83−Architecture: any
84−Depends:
85− qmenumodel-qml (>= 0.2.11),
86− qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
87− unity8 (= ${binary:Version}),
88− ${misc:Depends},
89− ${shlibs:Depends},
75+Architecture: amd64 armhf i386
76+Depends: qmenumodel-qml (>= 0.2.9),
77+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
78+ unity8 (= ${binary:Version}),
79+ ${misc:Depends},
80+ ${shlibs:Depends},
9081Description: Indicators client test application
9182 This package contains the client application for indicators used by autopilot
9283
93−Package: unity8-greeter
84+Package: unity-scope-tool
9485Architecture: any
95−Depends:
96− unity-system-compositor,
97− unity8 (= ${binary:Version}),
98− ${misc:Depends},
99− ${shlibs:Depends},
100−Recommends:
101− lightdm,
102−Provides:
103− lightdm-greeter,
104−Description: The Unity8 Greeter
105− The Unity 8 greeter is the primary login greeter for Ubuntu devices.
86+Depends: unity8-common (= ${source:Version}),
87+ unity8-private (= ${binary:Version}),
88+ ${misc:Depends},
89+ ${shlibs:Depends},
90+# We do call pkg-config libunity-scopes from the code
91+ pkg-config,
92+ libunity-scopes-dev,
93+Description: Development tool for Unity scopes
94+ This package contains the development tool for new generation Unity scopes, based
95+ on Unity8.
10696
10797Package: unity8
10898Architecture: any
109−Provides:
110− indicator-renderer,
111−Depends:
112− dmz-cursor-theme,
113− gsettings-desktop-schemas,
114− libcap2-bin,
115− libglib2.0-bin,
116− qmenumodel-qml (>= 0.2.11),
117− qml-module-biometryd,
118− qml-module-qt-labs-folderlistmodel,
119− qml-module-qt-labs-settings,
120− qml-module-qtqml-statemachine,
121− qml-module-qtquick-xmllistmodel,
122− qml-module-qtsysteminfo,
123− qtdeclarative5-qtmir-plugin (>= 0.4.8),
124− qtdeclarative5-ubuntu-telephony0.1,
125− ubuntu-system-settings (>= 0.4),
126− unity-launcher-impl-13,
127− unity8-common (= ${source:Version}),
128− unity8-private (= ${binary:Version}),
129− unity8-private | unity-launcher-impl,
130− ${misc:Depends},
131− ${shlibs:Depends},
132−Recommends:
133− indicator-keyboard,
134− indicator-session,
135− unity-greeter-session-broadcast,
136−Breaks:
137− indicator-network (<< 0.5.1+14.10.20141014),
138− ubuntu-keyboard (<< 0.100),
139− ubuntu-touch-session (<< 0.107),
140− unity-scope-tool,
141− unity8-greeter (<< 7.89),
142−Replaces:
143− ubuntu-touch-session (<< 0.82~),
144− unity-scope-tool,
145− unity8-greeter (<< 7.89),
146−Conflicts:
147− ubuntu-system-settings-wizard,
99+Provides: indicator-renderer,
100+Depends: dmz-cursor-theme,
101+ gsettings-desktop-schemas,
102+ libcap2-bin,
103+ libglib2.0-bin,
104+ qmenumodel-qml (>= 0.2.9),
105+ qml-module-qt-labs-folderlistmodel,
106+ qml-module-qtquick-xmllistmodel,
107+ qml-module-qtsysteminfo,
108+ qtdeclarative5-qtmir-plugin (>= 0.4.8),
109+ qtdeclarative5-ubuntu-telephony0.1,
110+ qtdeclarative5-ubuntu-web-plugin,
111+ ubuntu-system-settings (>= 0.4),
112+ unity-launcher-impl-7,
113+ unity8-common (= ${source:Version}),
114+ unity8-private (= ${binary:Version}),
115+ unity8-private | unity-launcher-impl,
116+ ${misc:Depends},
117+ ${shlibs:Depends},
118+Recommends: indicator-session,
119+ unity-scope-click,
120+ unity-scope-mediascanner2,
121+Breaks: indicator-network (<< 0.5.1+14.10.20141014),
122+ ubuntu-touch-session (<< 0.107),
123+ unity8-greeter (<< 7.89),
124+Replaces: ubuntu-touch-session (<< 0.82~),
125+ unity8-greeter (<< 7.89),
126+Conflicts: ubuntu-system-settings-wizard,
148127Description: Unity 8 shell
149128 The Unity 8 shell is the primary user interface for Ubuntu devices.
150129
151130Package: unity8-common
152131Architecture: all
153−Depends:
154− qml-module-qtquick-layouts,
155− qml-module-ubuntu-components (>= 1.3.2030) | qml-module-ubuntu-components-gles (>= 1.3.2030),
156− qml-module-ubuntu-settings-components,
157− qml-module-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
158− qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
159− qttranslations5-l10n,
160− ubuntu-thumbnailer-impl-0,
161− unity-application-impl-27,
162− unity-notifications-impl-3,
163− unity8-schemas,
164− unity8-tests | unity-application-impl,
165− ${misc:Depends},
166−Breaks:
167− unity8 (<< 7.86),
168−Replaces:
169− unity8 (<< 7.86),
132+Depends: qml-module-qtquick-layouts,
133+ qtdeclarative5-ubuntu-settings-components (>= 0.7),
134+ qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
135+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3.1845) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3.1845),
136+ qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
137+ ubuntu-thumbnailer-impl-0,
138+ unity-application-impl-16,
139+ unity-notifications-impl-3,
140+ unity-plugin-scopes | unity-scopes-impl,
141+ unity-scopes-impl-12,
142+ unity8-fake-env | unity-application-impl,
143+ ${misc:Depends},
144+Breaks: unity8 (<< 7.86),
145+Replaces: unity8 (<< 7.86),
170146Description: Unity 8 shell (common files)
171147 The Unity 8 shell is the primary user interface for Ubuntu devices.
172148 .
173− This package contains the QML, graphics and locale files for unity8.
149+ This package contains the QML, graphics and locale files shared between
150+ unity8 and unity-scope-tool.
174151
175152Package: unity8-autopilot
176153Architecture: all
177−Depends:
178− autopilot-qt5 (>= 1.4),
179− gir1.2-glib-2.0,
180− gir1.2-notify-0.7,
181− libqt5test5,
182− libqt5widgets5,
183− ofono-phonesim,
184− python3-autopilot,
185− python3-evdev,
186− python3-fixtures,
187− python3-gi,
188− qttestability-autopilot (>= 1.4),
189− ubuntu-ui-toolkit-autopilot (>= 1.3.2030),
190− unity8 (= ${source:Version}),
191− unity8-tests (= ${source:Version}),
192− url-dispatcher-tools,
193− xvfb,
194− ${misc:Depends},
195− ${python3:Depends},
154+Depends: autopilot-qt5 (>= 1.4),
155+ gir1.2-glib-2.0,
156+ gir1.2-notify-0.7,
157+ libqt5test5,
158+ libqt5widgets5,
159+ ofono-phonesim,
160+ python3-autopilot,
161+ python3-evdev,
162+ python3-fixtures,
163+ python3-gi,
164+ qttestability-autopilot (>= 1.4),
165+ ubuntu-ui-toolkit-autopilot (>= 1.3.1845),
166+ unity-scope-click,
167+ unity8 (= ${source:Version}),
168+ unity8-fake-env (= ${source:Version}),
169+ url-dispatcher-tools,
170+ xvfb,
171+ ${misc:Depends},
172+ ${python3:Depends},
173+ ${shlibs:Depends},
196174Description: Test package for Unity 8 shell
197175 Autopilot tests for the unity8 package
198176
199−Package: unity8-tests
177+Package: unity8-fake-env
200178Architecture: any
201179Multi-Arch: same
202−Pre-Depends:
203− ${misc:Pre-Depends},
204−Depends:
205− dbus-test-runner,
206− parallel,
207− qt5-default,
208− qtdbustest-runner,
209− qtdeclarative5-dev-tools,
210− unity8 (= ${source:Version}),
211− xvfb,
212− ${misc:Depends},
213− ${shlibs:Depends},
214−Provides:
215− unity-application-impl,
216− unity-application-impl-27,
217− unity8-fake-env,
218−Replaces:
219− unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1),
220− unity8-fake-env,
221−Conflicts:
222− unity8-fake-env,
223−Description: Scripts and mocks for running Unity 8 shell tests
180+Pre-Depends: ${misc:Pre-Depends},
181+Depends: ${misc:Depends},
182+ ${shlibs:Depends},
183+Provides: unity-application-impl,
184+ unity-application-impl-16,
185+Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
186+Description: Fake environment for running Unity 8 shell
224187 Provides fake implementations of some QML modules used by Unity 8 shell
225− (e.g Ubuntu.Application) so that you can run it in a sandboxed environment
226− and scripts to run its test suite.
188+ (e.g Ubuntu.Application) so that you can run it in a sandboxed environment.
227189
228190Package: unity8-private
229191Architecture: any
230192Multi-Arch: same
231−Pre-Depends:
232− ${misc:Pre-Depends},
233−Depends:
234− accountsservice-ubuntu-schemas (>= 0.0.7),
235− gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
236− libhardware2,
237− qml-module-qtmultimedia,
238− qtdeclarative5-gsettings1.0,
239− unity8-schemas,
240− ${misc:Depends},
241− ${shlibs:Depends},
242−Provides:
243− unity-launcher-impl,
244− unity-launcher-impl-13,
193+Pre-Depends: ${misc:Pre-Depends},
194+Depends: accountsservice-ubuntu-schemas (>= 0.0.5),
195+ gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
196+ libhardware2,
197+ pay-service,
198+ unity-schemas (>= 7.3.1+14.10.20140915),
199+ qtdeclarative5-gsettings1.0,
200+ qml-module-qtmultimedia,
201+ ${misc:Depends},
202+ ${shlibs:Depends},
203+Provides: unity-launcher-impl,
204+ unity-launcher-impl-7,
245205Description: Unity 8 private libs
246206 The Unity 8 shell is the primary user interface for Ubuntu devices.
247207 .
248208 This package contains the private libraries for QML and other components
249209 only used by the shell.
250210
251−Package: unity8-schemas
252−Architecture: all
253−Multi-Arch: foreign
254−Depends:
255− ${misc:Depends},
256−Replaces:
257− unity-schemas (>= 7.3.1+14.10.20140915),
258−Breaks:
259− unity-schemas (>= 7.3.1+14.10.20140915),
260−Description: Unity 8 schemas
261− The Unity 8 shell is the primary user interface for Ubuntu devices.
262− .
263− This package contains the configuration schemas used by unity.
264−
265211Package: unity8-doc
266212Section: doc
267213Architecture: all
268214Multi-Arch: foreign
269−Depends:
270− ${misc:Depends},
215+Depends: ${misc:Depends},
271216Description: Documentation for Unity8
272217 The Unity 8 shell is the primary user interface for Ubuntu devices. (documentation)
debian/rules+4−23
@@ -7,12 +7,6 @@ include /usr/share/dpkg/default.mk
77#export DH_VERBOSE=1
88export DPKG_GENSYMBOLS_CHECK_LEVEL=4
99export NO_PNG_PKG_MANGLE=1
10−export QT_SELECT=qt5
11−
12−DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
13−
14−# Skip tests on the archs they are known to be flaky with current configuration
15−testskip_architectures := arm64 powerpc ppc64el s390x
1610
1711%:
1812 dh $@ --parallel --fail-missing --with python3
@@ -24,19 +18,7 @@ override_dh_auto_configure:
2418
2519override_dh_auto_build:
2620 # doc is not a default target
27− dh_auto_build -- -O all doc
28−
29−override_dh_auto_test:
30− # Run the entire test battery
31− # Parallel tests have a risk of starting xvfb on the same DISPLAY multiple times,
32− # causing the whole battery to fail.
33−ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
34−ifneq (,$(filter $(DEB_HOST_ARCH),$(testskip_architectures)))
35− -dh_auto_test --no-parallel -- -O -k xvfballtests
36−else
37− dh_auto_test --no-parallel -- -O -k xvfballtests
38−endif
39−endif
21+ dh_auto_build -- all doc
4022
4123override_dh_install:
4224 # install autopilot tests
@@ -49,9 +31,8 @@ override_dh_install:
4931
5032# use private lib directories
5133override_dh_makeshlibs:
52− dh_makeshlibs -Nunity8-private -Nunity8-tests
34+ dh_makeshlibs -Nunity8-private -Nunity8-fake-env
5335
36+# libMockLightDM-qml.so links against liblightdm-qt5-2.so which doesn't exist
5437override_dh_shlibdeps:
55− # Some mock libraries link against liblightdm-qt5-3.so which we want to
56− # avoid, since we only really link against our mock one, not the system one.
57− dh_shlibdeps -XlibMockAccountsService-qml.so -Lunity8-private
38+ dh_shlibdeps -XlibMockLightDM-qml.so
debian/shlibs.localdeleted−1
@@ -1 +0,0 @@
1−libunity8-private 0 unity8-private
debian/source/formatnew file+1
debian/tests/control+4−5
@@ -1,11 +1,10 @@
11Tests: qmluitests.sh
22Restrictions: allow-stderr
3−Depends:
4− dpkg-dev,
5− unity8-tests,
3+Depends: @,
4+ @builddeps@,
5+ xvfb,
66
77Tests: autopilot.sh
88Restrictions: allow-stderr,
99 isolation-machine,
10−Depends:
11− unity8-autopilot,
10+Depends: unity8-autopilot,
debian/tests/qmluitests.sh+14−4
@@ -1,11 +1,21 @@
11#!/bin/sh
2−# -*- Mode: sh; indent-tabs-mode: nil; tab-width: 4 -*-
32
43# log all commands and abort on error
54set -xe
65
7−DEB_HOST_MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH)
6+SHELL_QML_PATH=$(pkg-config --variable=plugindir unity-shell-api)
7+UNITY_SOURCE_DIR=$(readlink -f $(dirname $(readlink -f $0))/../..)
88
9−export ARTIFACTS_DIR="${ADT_ARTIFACTS}"
9+dh_auto_configure -- -DCMAKE_INSTALL_LOCALSTATEDIR="/var" \
10+ -DARTIFACTS_DIR=${ADT_ARTIFACTS} \
11+ -DUNITY_PLUGINPATH=${SHELL_QML_PATH} \
12+ -DUNITY_MOCKPATH=${SHELL_QML_PATH}/mocks
13+dh_auto_build --parallel -- -C tests/mocks
14+dh_auto_build --parallel -- -C tests/plugins
15+dh_auto_build --parallel -- -C tests/qmltests
16+dh_auto_build --parallel -- -C tests/uqmlscene
17+dh_auto_build --parallel -- -C tests/utils
1018
11−/usr/lib/$DEB_HOST_MULTIARCH/unity8/tests/scripts/xvfballtests.sh
19+export UNITY_SOURCE_DIR
20+
21+dh_auto_build --parallel -- -k xvfballtests
debian/unity-scope-tool.installnew file+2
@@ -0,0 +1,2 @@
1+usr/bin/unity-scope-tool
2+usr/share/unity8/ScopeTool.qml
debian/unity8-common.install+2
@@ -1,5 +1,7 @@
1+usr/share/glib-2.0/schemas
12usr/share/locale
23usr/share/unity8/Components
4+usr/share/unity8/Dash
35usr/share/unity8/Notifications
46usr/share/unity8/graphics
57var/lib/polkit-1/localauthority/10-vendor.d
debian/unity8-tests.install → debian/unity8-fake-env.installrenamed+1−4
@@ -2,8 +2,5 @@ data/unity-mock-indicator-service.conf usr/share/upstart/sessions/
22usr/bin/unity-mock-indicator-service
33usr/lib/*/unity8/qml/mocks
44usr/lib/*/unity8/qml/nonmirplugins
5−usr/lib/*/unity8/qml/utils
6−usr/lib/*/unity8/tests
7−usr/lib/*/unity8/uqmlscene
5+usr/lib/*/unity8/qml/scopefakes
86usr/share/unity8/mocks
9−usr/share/unity8/tests
debian/unity8-greeter.installdeleted−5
@@ -1,5 +0,0 @@
1−data/unity8-greeter-init.conf usr/share/upstart/sessions/
2−data/unity8-greeter-wrapper usr/bin/
3−data/unity8-greeter.pkla /var/lib/polkit-1/localauthority/10-vendor.d/
4−usr/share/lightdm/greeters/unity8-greeter.desktop
5−usr/share/lightdm/lightdm.conf.d/51-unity8-greeter.conf
debian/unity8-private.install+3−2
@@ -1,16 +1,17 @@
11usr/lib/*/libunity8-private.*
22usr/lib/*/unity8/qml/AccountsService
33usr/lib/*/unity8/qml/Cursor
4+usr/lib/*/unity8/qml/Dash
45usr/lib/*/unity8/qml/GlobalShortcut
56usr/lib/*/unity8/qml/Greeter
6−usr/lib/*/unity8/qml/LightDM
7+usr/lib/*/unity8/qml/IntegratedLightDM
78usr/lib/*/unity8/qml/Lights
89usr/lib/*/unity8/qml/Powerd
910usr/lib/*/unity8/qml/ScreenshotDirectory
1011usr/lib/*/unity8/qml/SessionBroadcast
11−usr/lib/*/unity8/qml/UInput
1212usr/lib/*/unity8/qml/Ubuntu
1313usr/lib/*/unity8/qml/Unity
14+usr/lib/*/unity8/qml/UInput
1415usr/lib/*/unity8/qml/Utils
1516usr/lib/*/unity8/qml/WindowManager
1617usr/lib/*/unity8/qml/Wizard
debian/unity8-schemas.installdeleted−1
@@ -1 +0,0 @@
1−usr/share/glib-2.0/schemas
debian/unity8-tests.lintian-overridesdeleted−1
@@ -1 +0,0 @@
1−unity8-tests: unusual-interpreter usr/lib/*/unity8/tests/scripts/*.sh #!/usr/bin/parallel
debian/unity8.install+10−8
@@ -1,19 +1,21 @@
1−data/devices.conf etc/ubuntu/
2−data/test.sensors etc/ubuntusensors/
1+var/lib/unity8/version
2+data/unity8-dash.conf usr/share/upstart/sessions/
33data/unity8-filewatcher.conf usr/share/upstart/sessions/
44data/unity8.conf usr/share/upstart/sessions/
5+data/devices.conf etc/ubuntu/
56usr/bin/unity8
7+usr/bin/unity8-dash
8+usr/share/applications/unity8-dash.desktop
69usr/share/applications/unity8.desktop
7−usr/share/unity8/ApplicationMenus
8−usr/share/unity8/DeviceConfiguration.qml
9−usr/share/unity8/DisabledScreenNotice.qml
1010usr/share/unity8/Greeter
1111usr/share/unity8/Launcher
12−usr/share/unity8/OrientedShell.qml
1312usr/share/unity8/Panel
1413usr/share/unity8/Rotation
14+usr/share/unity8/DeviceConfiguration.qml
15+usr/share/unity8/OrientedShell.qml
16+usr/share/unity8/DisabledScreenNotice.qml
1517usr/share/unity8/Shell.qml
16−usr/share/unity8/Stage
18+usr/share/unity8/Stages
1719usr/share/unity8/Tutorial
1820usr/share/unity8/Wizard
19−var/lib/unity8/version
21+usr/share/url-dispatcher/urls/unity8-dash.url-dispatcher
include/paths.h.in+25−59
@@ -1,5 +1,8 @@
11/*
2− * Copyright (C) 2012-2016 Canonical, Ltd.
2+ * Copyright (C) 2012 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Ugo Riboni <ugo.riboni@canonical.com>
36 *
47 * This program is free software; you can redistribute it and/or modify
58 * it under the terms of the GNU General Public License as published by
@@ -14,7 +17,8 @@
1417 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1518 */
1619
17−#pragma once
20+#ifndef PATHS_H
21+#define PATHS_H
1822
1923// Qt
2024#include <QtCore/QCoreApplication>
@@ -23,28 +27,10 @@
2327#include <QtQml/QQmlEngine>
2428#include <QStandardPaths>
2529
26−inline QString installRoot() {
27− static QString installRoot;
28− static bool installRootSet = false;
29− if (!installRootSet) {
30− QString snapRoot = QFile::decodeName(qgetenv("SNAP"));
31− if (!snapRoot.isEmpty() && QCoreApplication::applicationDirPath() ==
32− QDir(snapRoot + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@")).canonicalPath()) {
33− installRoot = snapRoot;
34− } else if (QCoreApplication::applicationDirPath() ==
35− QDir(QStringLiteral("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@")).canonicalPath()) {
36− installRoot = QStringLiteral("");
37− }
38− installRootSet = true;
39− }
40− return installRoot;
41−}
42−
4330inline bool isRunningInstalled() {
44− // Tests don't use the normal binary, so we want to check binary *and*
45− // the environment. Installed tests have UNITY_TESTING_DATADIR set.
46− static bool installed_test_env = !qgetenv("UNITY_TESTING_DATADIR").isEmpty();
47− return !installRoot().isNull() || installed_test_env;
31+ static bool installed = (QCoreApplication::applicationDirPath() ==
32+ QDir(QStringLiteral("@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@")).canonicalPath());
33+ return installed;
4834}
4935
5036inline QString buildDirectory() {
@@ -59,46 +45,24 @@ inline QString sourceDirectory() {
5945
6046inline QString translationDirectory() {
6147 if (isRunningInstalled()) {
62− return installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/share/locale");
63− } else {
64− return buildDirectory() + QStringLiteral("/po/locale");
65− }
66−}
67−
68−inline QString testDataDir() {
69− // Can't use isRunningInstalled, since tests don't use the normal unity8
70− // executable. $UNITY_TESTING_DATADIR is set by installed tests.
71− QString datadir(qgetenv("UNITY_TESTING_DATADIR"));
72− if (datadir.isEmpty()) {
73− return sourceDirectory() + "/tests";
74− } else {
75− return datadir + "/tests";
76− }
77−}
78−
79−inline QString testLibDir() {
80− // Can't use isRunningInstalled, since tests don't use the normal unity8
81− // executable. $UNITY_TESTING_DATADIR is set by installed tests.
82− QString libdir(qgetenv("UNITY_TESTING_LIBDIR"));
83− if (libdir.isEmpty()) {
84− return buildDirectory() + "/tests";
48+ return QStringLiteral("@CMAKE_INSTALL_PREFIX@/share/locale");
8549 } else {
86− return libdir + "/tests";
50+ return QString(buildDirectory() + "/po/locale");
8751 }
8852}
8953
9054inline QString qmlDirectory() {
9155 if (isRunningInstalled()) {
92− return installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/");
56+ return QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_APP_DIR@/");
9357 } else {
94− return sourceDirectory() + QStringLiteral("/qml");
58+ return QString(sourceDirectory() + "/qml");
9559 }
9660}
9761
9862inline QStringList overrideImportPaths() {
9963 QStringList paths;
10064 if (!isRunningInstalled()) {
101− paths << buildDirectory() + QStringLiteral("/plugins");
65+ paths << QString(buildDirectory() + "/plugins");
10266 }
10367 return paths;
10468}
@@ -106,9 +70,9 @@ inline QStringList overrideImportPaths() {
10670inline QStringList nonMirImportPaths() {
10771 QStringList paths;
10872 if (isRunningInstalled()) {
109− paths << installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/nonmirplugins");
73+ paths << QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/nonmirplugins");
11074 } else {
111− paths << buildDirectory() + QStringLiteral("/nonmirplugins");
75+ paths << QString(buildDirectory() + "/nonmirplugins");
11276 }
11377 return paths;
11478}
@@ -116,23 +80,23 @@ inline QStringList nonMirImportPaths() {
11680inline QStringList fallbackImportPaths() {
11781 QStringList paths;
11882 if (isRunningInstalled()) {
119− paths << installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@");
120− paths << installRoot() + QStringLiteral("@USS_PRIVATE_PLUGINDIR@");
121− paths << installRoot() + QStringLiteral("@SHELL_PLUGINDIR@");
122− paths << installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
83+ paths << QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@");
84+ paths << QStringLiteral("@USS_PRIVATE_PLUGINDIR@");
85+ paths << QStringLiteral("@SHELL_PLUGINDIR@");
86+ paths << QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
12387 } else {
12488 paths << QStringLiteral("@USS_PRIVATE_PLUGINDIR@");
12589 paths << QStringLiteral("@SHELL_PLUGINDIR@");
126− paths << buildDirectory() + QStringLiteral("/tests/mocks");
90+ paths << QString(buildDirectory() + "/tests/mocks");
12791 }
12892 return paths;
12993}
13094
13195inline QString mockPluginsDir() {
13296 if (isRunningInstalled()) {
133− return installRoot() + QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
97+ return QStringLiteral("@CMAKE_INSTALL_PREFIX@/@SHELL_INSTALL_QML@/mocks");
13498 } else {
135− return buildDirectory() + QStringLiteral("/tests/mocks");
99+ return QString(buildDirectory() + "/tests/mocks");
136100 }
137101}
138102
@@ -173,3 +137,5 @@ inline void appendImportPaths(QQmlEngine *engine, const QStringList &paths)
173137 }
174138 engine->setImportPathList(importPathList);
175139}
140+
141+#endif
plugins/AccountsService/AccountsService.cpp+33−42
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
2+ * Copyright (C) 2013, 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
2525#include <glib.h>
2626
2727#define IFACE_ACCOUNTS_USER QStringLiteral("org.freedesktop.Accounts.User")
28+#define IFACE_LOCATION_HERE QStringLiteral("com.ubuntu.location.providers.here.AccountsService")
2829#define IFACE_UBUNTU_INPUT QStringLiteral("com.ubuntu.AccountsService.Input")
2930#define IFACE_UBUNTU_SECURITY QStringLiteral("com.ubuntu.AccountsService.SecurityPrivacy")
3031#define IFACE_UBUNTU_SECURITY_OLD QStringLiteral("com.ubuntu.touch.AccountsService.SecurityPrivacy")
@@ -32,13 +33,11 @@
3233#define IFACE_UNITY_PRIVATE QStringLiteral("com.canonical.unity.AccountsService.Private")
3334
3435#define PROP_BACKGROUND_FILE QStringLiteral("BackgroundFile")
35−#define PROP_DEMO_EDGES QStringLiteral("DemoEdges2")
36+#define PROP_DEMO_EDGES QStringLiteral("demo-edges")
3637#define PROP_DEMO_EDGES_COMPLETED QStringLiteral("DemoEdgesCompleted")
3738#define PROP_EMAIL QStringLiteral("Email")
38−#define PROP_ENABLE_FINGERPRINT_IDENTIFICATION QStringLiteral("EnableFingerprintIdentification")
3939#define PROP_ENABLE_INDICATORS_WHILE_LOCKED QStringLiteral("EnableIndicatorsWhileLocked")
4040#define PROP_ENABLE_LAUNCHER_WHILE_LOCKED QStringLiteral("EnableLauncherWhileLocked")
41−#define PROP_FAILED_FINGERPRINT_LOGINS QStringLiteral("FailedFingerprintLogins")
4241#define PROP_FAILED_LOGINS QStringLiteral("FailedLogins")
4342#define PROP_INPUT_SOURCES QStringLiteral("InputSources")
4443#define PROP_LICENSE_ACCEPTED QStringLiteral("LicenseAccepted")
@@ -67,9 +66,9 @@ Q_DECLARE_METATYPE(StringMapList)
6766QVariant primaryButtonConverter(const QVariant &value)
6867{
6968 QString stringValue = value.toString();
70− if (stringValue == QLatin1String("left")) {
69+ if (stringValue == "left") {
7170 return QVariant::fromValue(0);
72− } else if (stringValue == QLatin1String("right")) {
71+ } else if (stringValue == "right") {
7372 return QVariant::fromValue(1); // Mir is less clear on this -- any non-zero value is the same
7473 } else {
7574 return QVariant::fromValue(0); // default to left
@@ -92,14 +91,14 @@ AccountsService::AccountsService(QObject* parent, const QString &user)
9291 registerProperty(IFACE_ACCOUNTS_USER, PROP_EMAIL, QStringLiteral("emailChanged"));
9392 registerProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME, QStringLiteral("realNameChanged"));
9493 registerProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QStringLiteral("keymapsChanged"));
95− registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION, QStringLiteral("enableFingerprintIdentificationChanged"));
94+ registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, QStringLiteral("hereEnabledChanged"));
95+ registerProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH, QStringLiteral("hereLicensePathChanged"));
9696 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED, QStringLiteral("enableLauncherWhileLockedChanged"));
9797 registerProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_INDICATORS_WHILE_LOCKED, QStringLiteral("enableIndicatorsWhileLockedChanged"));
9898 registerProperty(IFACE_UBUNTU_SECURITY, PROP_PASSWORD_DISPLAY_HINT, QStringLiteral("passwordDisplayHintChanged"));
9999 registerProperty(IFACE_UBUNTU_SECURITY_OLD, PROP_STATS_WELCOME_SCREEN, QStringLiteral("statsWelcomeScreenChanged"));
100100 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES, QStringLiteral("demoEdgesChanged"));
101101 registerProperty(IFACE_UNITY, PROP_DEMO_EDGES_COMPLETED, QStringLiteral("demoEdgesCompletedChanged"));
102− registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, QStringLiteral("failedFingerprintLoginsChanged"));
103102 registerProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS, QStringLiteral("failedLoginsChanged"));
104103
105104 registerProxy(IFACE_UBUNTU_INPUT, PROP_MOUSE_CURSOR_SPEED,
@@ -177,12 +176,6 @@ void AccountsService::markDemoEdgeCompleted(const QString &edge)
177176 }
178177}
179178
180−bool AccountsService::enableFingerprintIdentification() const
181−{
182− auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_FINGERPRINT_IDENTIFICATION);
183− return value.toBool();
184−}
185−
186179bool AccountsService::enableLauncherWhileLocked() const
187180{
188181 auto value = getProperty(IFACE_UBUNTU_SECURITY, PROP_ENABLE_LAUNCHER_WHILE_LOCKED);
@@ -213,6 +206,32 @@ AccountsService::PasswordDisplayHint AccountsService::passwordDisplayHint() cons
213206 return (PasswordDisplayHint)value.toInt();
214207}
215208
209+bool AccountsService::hereEnabled() const
210+{
211+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED);
212+ return value.toBool();
213+}
214+
215+void AccountsService::setHereEnabled(bool enabled)
216+{
217+ setProperty(IFACE_LOCATION_HERE, PROP_LICENSE_ACCEPTED, enabled);
218+}
219+
220+QString AccountsService::hereLicensePath() const
221+{
222+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
223+ QString hereLicensePath = value.toString();
224+ if (hereLicensePath.isEmpty() || !QFile::exists(hereLicensePath))
225+ hereLicensePath = QStringLiteral("");
226+ return hereLicensePath;
227+}
228+
229+bool AccountsService::hereLicensePathValid() const
230+{
231+ auto value = getProperty(IFACE_LOCATION_HERE, PROP_LICENSE_BASE_PATH);
232+ return !value.toString().isNull();
233+}
234+
216235QString AccountsService::realName() const
217236{
218237 auto value = getProperty(IFACE_ACCOUNTS_USER, PROP_REAL_NAME);
@@ -255,34 +274,6 @@ QStringList AccountsService::keymaps() const
255274 return {QStringLiteral("us")};
256275}
257276
258−void AccountsService::setKeymaps(const QStringList &keymaps)
259−{
260− if (keymaps.isEmpty()) {
261− qWarning() << "Setting empty keymaps is not supported";
262− return;
263− }
264−
265− StringMapList result;
266− Q_FOREACH(const QString &keymap, keymaps) {
267− StringMap map;
268− map.insert(QStringLiteral("xkb"), keymap);
269− result.append(map);
270− }
271−
272− setProperty(IFACE_ACCOUNTS_USER, PROP_INPUT_SOURCES, QVariant::fromValue(result));
273− Q_EMIT keymapsChanged();
274−}
275−
276−uint AccountsService::failedFingerprintLogins() const
277−{
278− return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS).toUInt();
279−}
280−
281−void AccountsService::setFailedFingerprintLogins(uint failedFingerprintLogins)
282−{
283− setProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_FINGERPRINT_LOGINS, failedFingerprintLogins);
284−}
285−
286277uint AccountsService::failedLogins() const
287278{
288279 return getProperty(IFACE_UNITY_PRIVATE, PROP_FAILED_LOGINS).toUInt();
plugins/AccountsService/AccountsService.h+21−16
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
2+ * Copyright (C) 2013, 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@ class QDBusInterface;
2929class AccountsService: public QObject
3030{
3131 Q_OBJECT
32+ Q_ENUMS(PasswordDisplayHint)
3233 Q_PROPERTY (QString user
3334 READ user
3435 WRITE setUser
@@ -40,9 +41,6 @@ class AccountsService: public QObject
4041 Q_PROPERTY (QStringList demoEdgesCompleted
4142 READ demoEdgesCompleted
4243 NOTIFY demoEdgesCompletedChanged)
43− Q_PROPERTY (bool enableFingerprintIdentification
44− READ enableFingerprintIdentification
45− NOTIFY enableFingerprintIdentificationChanged)
4644 Q_PROPERTY (bool enableLauncherWhileLocked
4745 READ enableLauncherWhileLocked
4846 NOTIFY enableLauncherWhileLockedChanged)
@@ -62,20 +60,27 @@ class AccountsService: public QObject
6260 READ failedLogins
6361 WRITE setFailedLogins
6462 NOTIFY failedLoginsChanged)
65− Q_PROPERTY (uint failedFingerprintLogins
66− READ failedFingerprintLogins
67− WRITE setFailedFingerprintLogins
68− NOTIFY failedFingerprintLoginsChanged)
63+ Q_PROPERTY(bool hereEnabled
64+ READ hereEnabled
65+ WRITE setHereEnabled
66+ NOTIFY hereEnabledChanged)
67+ Q_PROPERTY(QString hereLicensePath
68+ READ hereLicensePath
69+ NOTIFY hereLicensePathChanged)
70+ Q_PROPERTY(bool hereLicensePathValid // qml sees a null string as "", so we use proxy setting for that
71+ READ hereLicensePathValid
72+ NOTIFY hereLicensePathChanged)
6973 Q_PROPERTY(QString realName READ realName WRITE setRealName NOTIFY realNameChanged)
7074 Q_PROPERTY(QString email READ email WRITE setEmail NOTIFY emailChanged)
71− Q_PROPERTY(QStringList keymaps READ keymaps WRITE setKeymaps NOTIFY keymapsChanged)
75+ Q_PROPERTY(QStringList keymaps
76+ READ keymaps
77+ NOTIFY keymapsChanged)
7278
7379public:
7480 enum PasswordDisplayHint {
7581 Keyboard,
7682 Numeric,
7783 };
78− Q_ENUM(PasswordDisplayHint)
7984
8085 explicit AccountsService(QObject *parent = 0, const QString & user = QString());
8186 ~AccountsService() = default;
@@ -86,7 +91,6 @@ public:
8691 void setDemoEdges(bool demoEdges);
8792 QStringList demoEdgesCompleted() const;
8893 Q_INVOKABLE void markDemoEdgeCompleted(const QString &edge);
89− bool enableFingerprintIdentification() const;
9094 bool enableLauncherWhileLocked() const;
9195 bool enableIndicatorsWhileLocked() const;
9296 QString backgroundFile() const;
@@ -94,27 +98,28 @@ public:
9498 PasswordDisplayHint passwordDisplayHint() const;
9599 uint failedLogins() const;
96100 void setFailedLogins(uint failedLogins);
97− uint failedFingerprintLogins() const;
98− void setFailedFingerprintLogins(uint failedFingerprintLogins);
101+ bool hereEnabled() const;
102+ void setHereEnabled(bool enabled);
103+ QString hereLicensePath() const;
104+ bool hereLicensePathValid() const;
99105 QString realName() const;
100106 void setRealName(const QString &realName);
101107 QString email() const;
102108 void setEmail(const QString &email);
103109 QStringList keymaps() const;
104− void setKeymaps(const QStringList &keymaps);
105110
106111Q_SIGNALS:
107112 void userChanged();
108113 void demoEdgesChanged();
109114 void demoEdgesCompletedChanged();
110− void enableFingerprintIdentificationChanged();
111115 void enableLauncherWhileLockedChanged();
112116 void enableIndicatorsWhileLockedChanged();
113117 void backgroundFileChanged();
114118 void statsWelcomeScreenChanged();
115119 void passwordDisplayHintChanged();
116120 void failedLoginsChanged();
117− void failedFingerprintLoginsChanged();
121+ void hereEnabledChanged();
122+ void hereLicensePathChanged();
118123 void realNameChanged();
119124 void emailChanged();
120125 void keymapsChanged();
plugins/AccountsService/AccountsService.qmltypesnew file+41
@@ -0,0 +1,41 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable AccountsService 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "AccountsService"
12+ prototype: "QObject"
13+ exports: ["AccountsService/AccountsService 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Enum {
18+ name: "PasswordDisplayHint"
19+ values: {
20+ "Keyboard": 0,
21+ "Numeric": 1
22+ }
23+ }
24+ Property { name: "user"; type: "string" }
25+ Property { name: "demoEdges"; type: "bool" }
26+ Property { name: "demoEdgesCompleted"; type: "QStringList"; isReadonly: true }
27+ Property { name: "enableLauncherWhileLocked"; type: "bool"; isReadonly: true }
28+ Property { name: "enableIndicatorsWhileLocked"; type: "bool"; isReadonly: true }
29+ Property { name: "backgroundFile"; type: "string"; isReadonly: true }
30+ Property { name: "statsWelcomeScreen"; type: "bool"; isReadonly: true }
31+ Property { name: "passwordDisplayHint"; type: "PasswordDisplayHint"; isReadonly: true }
32+ Property { name: "failedLogins"; type: "uint" }
33+ Property { name: "hereEnabled"; type: "bool" }
34+ Property { name: "hereLicensePath"; type: "string"; isReadonly: true }
35+ Property { name: "hereLicensePathValid"; type: "bool"; isReadonly: true }
36+ Method {
37+ name: "markDemoEdgeCompleted"
38+ Parameter { name: "edge"; type: "string" }
39+ }
40+ }
41+}
plugins/AccountsService/CMakeLists.txt+2−1
@@ -7,8 +7,9 @@ add_library(AccountsService-qml MODULE
77 plugin.cpp
88 )
99
10+qt5_use_modules(AccountsService-qml DBus Qml)
11+
1012target_link_libraries(AccountsService-qml
11− Qt5::DBus Qt5::Qml
1213 ${GLIB_LIBRARIES}
1314 )
1415
plugins/AccountsService/com.canonical.unity.AccountsService.xml−10
@@ -9,17 +9,11 @@
99 <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
1010 value="com.ubuntu.AccountsService.GreeterChangeAny"/>
1111
12− <!-- Marks that V1 (pre-8.21) edge demos have been run. Legacy value. -->
1312 <!-- Should have been named DemoEdges, sorry folks. -mterry -->
1413 <property name="demo-edges" type="b" access="readwrite">
1514 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
1615 </property>
1716
18− <!-- Marks that V2 (post-8.21) edge demos have been run -->
19− <property name="DemoEdges2" type="b" access="readwrite">
20− <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
21− </property>
22−
2317 <!-- List of tutorial pages that have been completed by the user -->
2418 <property name="DemoEdgesCompleted" type="as" access="readwrite">
2519 <annotation name="org.freedesktop.Accounts.DefaultValue" value="[]"/>
@@ -53,9 +47,5 @@
5347 <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
5448 </property>
5549
56− <property name="FailedFingerprintLogins" type="u" access="readwrite">
57− <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
58− </property>
59−
6050 </interface>
6151</node>
plugins/CMakeLists.txt+3−2
@@ -1,4 +1,4 @@
1−find_package(QmlPlugins)
1+include(QmlPlugins)
22
33# Set up and install a plugin for unity8.
44#
@@ -15,8 +15,9 @@ add_subdirectory(AccountsService)
1515add_subdirectory(Cursor)
1616add_subdirectory(GlobalShortcut)
1717add_subdirectory(Greeter)
18−add_subdirectory(LightDM)
18+add_subdirectory(IntegratedLightDM)
1919add_subdirectory(Lights)
20+add_subdirectory(Dash)
2021add_subdirectory(Powerd)
2122add_subdirectory(ScreenshotDirectory)
2223add_subdirectory(SessionBroadcast)
plugins/Cursor/CMakeLists.txt+4−8
@@ -3,18 +3,13 @@ add_subdirectory(3rd_party)
33include_directories(
44 ${CMAKE_CURRENT_SOURCE_DIR}
55 ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/xcursor
6−)
7−
8−include_directories(
9− SYSTEM
106 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
117)
128
139set(QMLPLUGIN_SRC
1410 plugin.cpp
15− CursorImageInfo.cpp
16− CursorImageProvider.cpp
1711 MousePointer.cpp
12+ CursorImageProvider.cpp
1813 # We need to run moc on this header
1914 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirMousePointerInterface.h
2015 )
@@ -26,7 +21,8 @@ add_library(Cursor-qml SHARED
2621target_link_libraries(Cursor-qml
2722 xcursorloader-static
2823 ${QT5PLATFORM_SUPPORT_LDFLAGS}
29− Qt5::Qml Qt5::Quick Qt5::Svg
3024)
3125
32−add_unity8_plugin(Cursor 1.1 Cursor TARGETS Cursor-qml)
26+qt5_use_modules(Cursor-qml Qml Quick DBus Network Gui Sql Concurrent Svg)
27+
28+add_unity8_plugin(Cursor 1.0 Cursor TARGETS Cursor-qml)
plugins/Cursor/Cursor.qml+6−40
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
2+ * Copyright (C) 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,48 +15,14 @@
1515 */
1616
1717import QtQuick 2.4
18−import Cursor 1.1
19−import Powerd 0.1
18+import Cursor 1.0 // For MousePointer
2019
2120MousePointer {
2221 id: mousePointer
2322
24− CursorImageInfo {
25− id: imageInfo
26− themeName: mousePointer.themeName
27− cursorName: mousePointer.cursorName
28− cursorHeight: mousePointer.height
29− }
30−
31− Loader {
32− active: mousePointer.visible && imageInfo.frameCount > 1
33− sourceComponent: AnimatedSprite {
34− x: -imageInfo.hotspot.x
35− y: -imageInfo.hotspot.y
36− source: imageInfo.imageSource
37−
38− interpolate: false
39−
40− width: imageInfo.frameWidth
41− height: imageInfo.frameHeight
42−
43− frameCount: imageInfo.frameCount
44− frameDuration: imageInfo.frameDuration
45− frameWidth: imageInfo.frameWidth
46− frameHeight: imageInfo.frameHeight
47−
48− running: Powerd.status === Powerd.On
49− }
50− }
51−
52− Loader {
53− active: mousePointer.visible && imageInfo.frameCount === 1
54− sourceComponent: Image {
55− x: -imageInfo.hotspot.x
56− y: -imageInfo.hotspot.y
57− source: imageInfo.imageSource
58− width: sourceSize.width
59− height: sourceSize.height
60− }
23+ Image {
24+ x: -mousePointer.hotspotX
25+ y: -mousePointer.hotspotY
26+ source: "image://cursor/" + mousePointer.themeName + "/" + mousePointer.cursorName
6127 }
6228}
plugins/Cursor/Cursor.qmltypesnew file+78
@@ -0,0 +1,78 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Cursor 1.0 plugins'
8+
9+Module {
10+ Component {
11+ name: "MirMousePointerInterface"
12+ defaultProperty: "data"
13+ prototype: "QQuickItem"
14+ Property { name: "cursorName"; type: "string"; isReadonly: true }
15+ Property { name: "themeName"; type: "string"; isReadonly: true }
16+ Property { name: "hotspotX"; type: "double"; isReadonly: true }
17+ Property { name: "hotspotY"; type: "double"; isReadonly: true }
18+ Signal {
19+ name: "cursorNameChanged"
20+ Parameter { name: "name"; type: "string" }
21+ }
22+ Signal {
23+ name: "themeNameChanged"
24+ Parameter { name: "name"; type: "string" }
25+ }
26+ Signal {
27+ name: "hotspotXChanged"
28+ Parameter { name: "value"; type: "double" }
29+ }
30+ Signal {
31+ name: "hotspotYChanged"
32+ Parameter { name: "value"; type: "double" }
33+ }
34+ Method {
35+ name: "handleMouseEvent"
36+ Parameter { name: "timestamp"; type: "ulong" }
37+ Parameter { name: "movement"; type: "QPointF" }
38+ Parameter { name: "buttons"; type: "Qt::MouseButtons" }
39+ Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
40+ }
41+ Method {
42+ name: "handleWheelEvent"
43+ Parameter { name: "timestamp"; type: "ulong" }
44+ Parameter { name: "angleDelta"; type: "QPoint" }
45+ Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
46+ }
47+ }
48+ Component {
49+ name: "MousePointer"
50+ defaultProperty: "data"
51+ prototype: "MirMousePointerInterface"
52+ exports: ["Cursor/MousePointer 1.0"]
53+ exportMetaObjectRevisions: [0]
54+ Signal {
55+ name: "pushedLeftBoundary"
56+ Parameter { name: "amount"; type: "double" }
57+ Parameter { name: "buttons"; type: "Qt::MouseButtons" }
58+ }
59+ Signal {
60+ name: "pushedRightBoundary"
61+ Parameter { name: "amount"; type: "double" }
62+ Parameter { name: "buttons"; type: "Qt::MouseButtons" }
63+ }
64+ Method {
65+ name: "handleMouseEvent"
66+ Parameter { name: "timestamp"; type: "ulong" }
67+ Parameter { name: "movement"; type: "QPointF" }
68+ Parameter { name: "buttons"; type: "Qt::MouseButtons" }
69+ Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
70+ }
71+ Method {
72+ name: "handleWheelEvent"
73+ Parameter { name: "timestamp"; type: "ulong" }
74+ Parameter { name: "angleDelta"; type: "QPoint" }
75+ Parameter { name: "modifiers"; type: "Qt::KeyboardModifiers" }
76+ }
77+ }
78+}
plugins/Cursor/CursorImageInfo.cppdeleted−115
@@ -1,115 +0,0 @@
1−/*
2− * Copyright (C) 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−#include "CursorImageInfo.h"
18−
19−CursorImageInfo::CursorImageInfo(QObject *parent)
20− : QObject(parent)
21−{
22−}
23−
24−void CursorImageInfo::setCursorName(const QString &cursorName)
25−{
26− if (cursorName != m_cursorName) {
27− m_cursorName = cursorName;
28− update();
29− Q_EMIT cursorNameChanged();
30− }
31−
32−}
33−void CursorImageInfo::setCursorHeight(qreal cursorHeight)
34−{
35− if (cursorHeight != m_cursorHeight) {
36− m_cursorHeight = cursorHeight;
37− update();
38− Q_EMIT cursorHeightChanged();
39− }
40−}
41−
42−void CursorImageInfo::setThemeName(const QString &themeName)
43−{
44− if (m_themeName != themeName) {
45− m_themeName = themeName;
46− update();
47− Q_EMIT themeNameChanged();
48− }
49−}
50−
51−void CursorImageInfo::update()
52−{
53− m_cursorImage = CursorImageProvider::instance()->fetchCursor(m_themeName, m_cursorName, (int) m_cursorHeight);
54−
55− Q_EMIT hotspotChanged();
56− Q_EMIT frameWidthChanged();
57− Q_EMIT frameHeightChanged();
58− Q_EMIT frameCountChanged();
59− Q_EMIT frameDurationChanged();
60− Q_EMIT imageSourceChanged();
61−}
62−
63−QPoint CursorImageInfo::hotspot() const
64−{
65− if (m_cursorImage) {
66− return m_cursorImage->hotspot;
67− } else {
68− return QPoint();
69− }
70−}
71−
72−qreal CursorImageInfo::frameWidth() const
73−{
74− if (m_cursorImage) {
75− return m_cursorImage->frameWidth;
76− } else {
77− return 0;
78− }
79−}
80−
81−qreal CursorImageInfo::frameHeight() const
82−{
83− if (m_cursorImage) {
84− return m_cursorImage->frameHeight;
85− } else {
86− return 0;
87− }
88−}
89−
90−int CursorImageInfo::frameCount() const
91−{
92− if (m_cursorImage) {
93− return m_cursorImage->frameCount;
94− } else {
95− return 0;
96− }
97−}
98−
99−int CursorImageInfo::frameDuration() const
100−{
101− if (m_cursorImage) {
102− return m_cursorImage->frameDuration;
103− } else {
104− return 0;
105− }
106−}
107−
108−QUrl CursorImageInfo::imageSource() const
109−{
110− auto urlString = QString("image://cursor/%1/%2/%3")
111− .arg(m_themeName, m_cursorName)
112− .arg(m_cursorHeight);
113−
114− return QUrl(urlString);
115−}
plugins/Cursor/CursorImageInfo.hdeleted−82
@@ -1,82 +0,0 @@
1−/*
2− * Copyright (C) 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−#ifndef CURSOR_IMAGE_INFO_H
18−#define CURSOR_IMAGE_INFO_H
19−
20−#include "CursorImageProvider.h"
21−
22−#include <QObject>
23−#include <QString>
24−#include <QUrl>
25−
26−class CursorImageInfo : public QObject
27−{
28− Q_OBJECT
29−
30− Q_PROPERTY(QString themeName READ themeName WRITE setThemeName NOTIFY themeNameChanged)
31− Q_PROPERTY(QString cursorName READ cursorName WRITE setCursorName NOTIFY cursorNameChanged)
32− Q_PROPERTY(qreal cursorHeight READ cursorHeight WRITE setCursorHeight NOTIFY cursorHeightChanged)
33−
34− Q_PROPERTY(QPoint hotspot READ hotspot NOTIFY hotspotChanged)
35− Q_PROPERTY(qreal frameWidth READ frameWidth NOTIFY frameWidthChanged)
36− Q_PROPERTY(qreal frameHeight READ frameHeight NOTIFY frameHeightChanged)
37− Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged)
38− Q_PROPERTY(int frameDuration READ frameDuration NOTIFY frameDurationChanged)
39− Q_PROPERTY(QUrl imageSource READ imageSource NOTIFY imageSourceChanged)
40−
41−public:
42− CursorImageInfo(QObject *parent = nullptr);
43−
44− QString themeName() const { return m_themeName; }
45− void setThemeName(const QString &);
46−
47− QString cursorName() const { return m_cursorName; }
48− void setCursorName(const QString &);
49−
50− qreal cursorHeight() const { return m_cursorHeight; }
51− void setCursorHeight(qreal);
52−
53− QPoint hotspot() const;
54− qreal frameWidth() const;
55− qreal frameHeight() const;
56− int frameCount() const;
57− int frameDuration() const;
58− QUrl imageSource() const;
59−
60−Q_SIGNALS:
61− void themeNameChanged();
62− void cursorNameChanged();
63− void cursorHeightChanged();
64− void hotspotChanged();
65− void frameWidthChanged();
66− void frameHeightChanged();
67− void frameCountChanged();
68− void frameDurationChanged();
69− void imageSourceChanged();
70−
71−private Q_SLOTS:
72− void update();
73−
74−private:
75− QString m_themeName;
76− QString m_cursorName;
77− qreal m_cursorHeight{0};
78−
79− CursorImage *m_cursorImage{nullptr};
80−};
81−
82−#endif // CURSOR_IMAGE_INFO_H
plugins/Cursor/CursorImageProvider.cpp+42−85
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
2+ * Copyright (C) 2015 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -27,7 +27,7 @@ CursorImageProvider *CursorImageProvider::m_instance = nullptr;
2727/////
2828// BuiltInCursorImage
2929
30−BuiltInCursorImage::BuiltInCursorImage(int cursorHeight)
30+BuiltInCursorImage::BuiltInCursorImage()
3131{
3232 const char *svgString =
3333 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
@@ -42,15 +42,10 @@ BuiltInCursorImage::BuiltInCursorImage(int cursorHeight)
4242 " d=\"M 20.504,50.94931 460.42533,518.14486 266.47603,515.61948 366.48114,719.16522 274.05218,770.68296 172.53185,559.56112 20.504,716.13476 Z\" />"
4343 "</svg>";
4444
45− // NB: Original image dimension is 20x32. Ensure aspect ratio is kept
46− qimage = QImage((20./32.)*cursorHeight, cursorHeight, QImage::Format_ARGB32);
45+ qimage = QImage(20, 32, QImage::Format_ARGB32);
4746 qimage.fill(Qt::transparent);
4847 QPainter imagePainter(&qimage);
4948
50− frameWidth = qimage.width();
51− frameHeight = qimage.height();
52− requestedHeight = cursorHeight;
53−
5449 QSvgRenderer *svgRenderer = new QSvgRenderer(QByteArray(svgString));
5550 svgRenderer->render(&imagePainter);
5651 delete svgRenderer;
@@ -64,8 +59,6 @@ BlankCursorImage::BlankCursorImage()
6459{
6560 qimage = QImage(1, 1, QImage::Format_ARGB32);
6661 qimage.fill(Qt::transparent);
67− frameWidth = qimage.width();
68− frameHeight = qimage.height();
6962}
7063
7164/////
@@ -76,72 +69,40 @@ CustomCursorImage::CustomCursorImage(const QCursor &cursor)
7669{
7770 qimage = cursor.pixmap().toImage();
7871 hotspot = cursor.hotSpot();
79− frameWidth = qimage.width();
80− frameHeight = qimage.height();
8172}
8273
8374/////
8475// XCursorImage
8576
86−XCursorImage::XCursorImage(const QString &theme, const QString &file, int preferredCursorHeightPx)
77+XCursorImage::XCursorImage(const QString &theme, const QString &file)
78+ : xcursorImages(nullptr)
8779{
88− requestedHeight = preferredCursorHeightPx;
80+ // TODO: Consider grid unit value
81+ // Hardcoding to a medium size for now
82+ int preferredCursorHeightPx = 32;
8983
90− XcursorImages *xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme),
84+ xcursorImages = XcursorLibraryLoadImages(QFile::encodeName(file), QFile::encodeName(theme),
9185 preferredCursorHeightPx);
92− if (!xcursorImages || xcursorImages->nimage == 0) {
86+ if (!xcursorImages) {
9387 return;
9488 }
9589
96− frameCount = xcursorImages->nimage;
90+ // Just take the first one. It will have multiple images in case of an animated cursor.
91+ // TODO: Support animated cursors
92+ if ( xcursorImages->nimage > 0) {
93+ XcursorImage *xcursorImage = xcursorImages->images[0];
9794
98− for (int i = 0; i < xcursorImages->nimage; ++i) {
99− XcursorImage *xcursorImage = xcursorImages->images[i];
100− if (frameWidth < (int)xcursorImage->width) {
101− frameWidth = xcursorImage->width;
102− }
103− if (frameHeight < (int)xcursorImage->height) {
104− frameHeight = xcursorImage->height;
105− }
106− if (i == 0) {
107− frameDuration = (int)xcursorImage->delay;
108− } else {
109− if (frameDuration != (int)xcursorImage->delay) {
110− qWarning().nospace() << "CursorImageProvider: XCursorImage("<<theme<<","<<file<<") has"
111− " varying delays in its animation. Animation won't look right.";
112− }
113− }
114− }
95+ qimage = QImage((uchar*)xcursorImage->pixels,
96+ xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
11597
116− {
117− // Assume that the hotspot position does not animate
118− XcursorImage *xcursorImage = xcursorImages->images[0];
11998 hotspot.setX(xcursorImage->xhot);
12099 hotspot.setY(xcursorImage->yhot);
121100 }
122−
123− // Build the sprite as a single row of frames
124− qimage = QImage(frameWidth*frameCount, frameHeight, QImage::Format_ARGB32);
125− qimage.fill(Qt::transparent);
126−
127− {
128− QPainter painter(&qimage);
129−
130− for (int i = 0; i < xcursorImages->nimage; ++i) {
131− XcursorImage *xcursorImage = xcursorImages->images[i];
132−
133− auto frameImage = QImage((uchar*)xcursorImage->pixels,
134− xcursorImage->width, xcursorImage->height, QImage::Format_ARGB32);
135−
136− painter.drawImage(QPoint(i*frameWidth, 0), frameImage);
137− }
138− }
139−
140− XcursorImagesDestroy(xcursorImages);
141101}
142102
143103XCursorImage::~XCursorImage()
144104{
105+ XcursorImagesDestroy(xcursorImages);
145106}
146107
147108/////
@@ -174,8 +135,6 @@ CursorImageProvider::CursorImageProvider()
174135 m_fallbackNames[QStringLiteral("forbidden")].append(QStringLiteral("not-allowed"));
175136 m_fallbackNames[QStringLiteral("forbidden")].append(QStringLiteral("circle"));
176137
177− m_fallbackNames[QStringLiteral("grabbing")].append(QStringLiteral("closedhand")); // Breeze
178−
179138 m_fallbackNames[QStringLiteral("hand")].append(QStringLiteral("pointing_hand"));
180139 m_fallbackNames[QStringLiteral("hand")].append(QStringLiteral("pointer"));
181140
@@ -237,43 +196,44 @@ CursorImageProvider::~CursorImageProvider()
237196 m_instance = nullptr;
238197}
239198
240−QImage CursorImageProvider::requestImage(const QString &cursorThemeAndNameAndHeight, QSize *size, const QSize & /*requestedSize*/)
199+QImage CursorImageProvider::requestImage(const QString &cursorThemeAndName, QSize *size, const QSize & /*requestedSize*/)
241200{
242− CursorImage *cursorImage = fetchCursor(cursorThemeAndNameAndHeight);
201+ CursorImage *cursorImage = fetchCursor(cursorThemeAndName);
243202 size->setWidth(cursorImage->qimage.width());
244203 size->setHeight(cursorImage->qimage.height());
245204
246205 return cursorImage->qimage;
247206}
248207
249−CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndNameAndHeight)
208+QPoint CursorImageProvider::hotspot(const QString &themeName, const QString &cursorName)
209+{
210+ CursorImage *cursorImage = fetchCursor(themeName, cursorName);
211+ if (cursorImage) {
212+ return cursorImage->hotspot;
213+ } else {
214+ return QPoint(0,0);
215+ }
216+}
217+
218+CursorImage *CursorImageProvider::fetchCursor(const QString &cursorThemeAndName)
250219{
251220 QString themeName;
252221 QString cursorName;
253− int cursorHeight;
254222 {
255− QStringList themeAndNameList = cursorThemeAndNameAndHeight.split('/');
256− if (themeAndNameList.size() != 3) {
223+ QStringList themeAndNameList = cursorThemeAndName.split('/');
224+ if (themeAndNameList.size() != 2) {
257225 return nullptr;
258226 }
259227 themeName = themeAndNameList[0];
260228 cursorName = themeAndNameList[1];
261−
262− bool ok;
263− cursorHeight = themeAndNameList[2].toInt(&ok);
264− if (!ok) {
265− cursorHeight = 32;
266− qWarning().nospace() << "CursorImageProvider: invalid cursor height ("<<themeAndNameList[2]<<")."
267− " Falling back to "<<cursorHeight<<" pixels";
268− }
269229 }
270230
271− return fetchCursor(themeName, cursorName, cursorHeight);
231+ return fetchCursor(themeName, cursorName);
272232}
273233
274−CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QString &cursorName, int cursorHeight)
234+CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QString &cursorName)
275235{
276− CursorImage *cursorImage = fetchCursorHelper(themeName, cursorName, cursorHeight);
236+ CursorImage *cursorImage = fetchCursorHelper(themeName, cursorName);
277237
278238 // Try some fallbacks
279239 if (cursorImage->qimage.isNull()) {
@@ -282,7 +242,7 @@ CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QS
282242 int i = 0;
283243 while (cursorImage->qimage.isNull() && i < fallbackNames.count()) {
284244 qDebug().nospace() << "CursorImageProvider: "<< cursorName <<" not found, trying " << fallbackNames.at(i);
285− cursorImage = fetchCursorHelper(themeName, fallbackNames.at(i), cursorHeight);
245+ cursorImage = fetchCursorHelper(themeName, fallbackNames.at(i));
286246 ++i;
287247 }
288248 }
@@ -292,14 +252,14 @@ CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QS
292252 if (cursorImage->qimage.isNull() && cursorName != QLatin1String("left_ptr")) {
293253 qDebug() << "CursorImageProvider:" << cursorName
294254 << "not found (nor its fallbacks, if any). Going for \"left_ptr\" as a last resort.";
295− cursorImage = fetchCursorHelper(themeName, QStringLiteral("left_ptr"), cursorHeight);
255+ cursorImage = fetchCursorHelper(themeName, QStringLiteral("left_ptr"));
296256 }
297257
298258 if (cursorImage->qimage.isNull()) {
299259 // finally, go for the built-in cursor
300260 qWarning() << "CursorImageProvider: couldn't find any cursors. Using the built-in one";
301− if (!m_builtInCursorImage || m_builtInCursorImage->requestedHeight != cursorHeight) {
302− m_builtInCursorImage.reset(new BuiltInCursorImage(cursorHeight));
261+ if (!m_builtInCursorImage) {
262+ m_builtInCursorImage.reset(new BuiltInCursorImage);
303263 }
304264 cursorImage = m_builtInCursorImage.data();
305265 }
@@ -307,20 +267,17 @@ CursorImage *CursorImageProvider::fetchCursor(const QString &themeName, const QS
307267 return cursorImage;
308268}
309269
310−CursorImage *CursorImageProvider::fetchCursorHelper(const QString &themeName, const QString &cursorName, int cursorHeight)
270+CursorImage *CursorImageProvider::fetchCursorHelper(const QString &themeName, const QString &cursorName)
311271{
312272 if (cursorName == QLatin1String("blank")) {
313273 return &m_blankCursorImage;
314− } else if (cursorName.startsWith(QLatin1String("custom"))) {
274+ } else if (cursorName == QLatin1String("custom")) {
315275 return m_customCursorImage.data();
316276 } else {
317277 QMap<QString, CursorImage*> &themeCursors = m_cursors[themeName];
318278
319279 if (!themeCursors.contains(cursorName)) {
320− themeCursors[cursorName] = new XCursorImage(themeName, cursorName, cursorHeight);
321− } else if (themeCursors[cursorName]->requestedHeight != cursorHeight) {
322− delete themeCursors.take(cursorName);
323− themeCursors[cursorName] = new XCursorImage(themeName, cursorName, cursorHeight);
280+ themeCursors[cursorName] = new XCursorImage(themeName, cursorName);
324281 }
325282
326283 return themeCursors[cursorName];
plugins/Cursor/CursorImageProvider.h+9−20
@@ -31,31 +31,20 @@ public:
3131 virtual ~CursorImage() {}
3232
3333 QImage qimage;
34−
35− // TODO: consider if there's a need to animate the hotspot
36− // ie, if there's a need to make it an array of points, one for each frame.
37− // Maybe no single xcursor (or at least the ones we know of or use)
38− // vary its hotspot position through its animation.
3934 QPoint hotspot;
40−
41− int frameWidth{0};
42− int frameHeight{0};
43− int frameCount{1};
44− int frameDuration{40};
45−
46− // Requested height when creating this cursor.
47− int requestedHeight{0};
4835};
4936
5037class XCursorImage : public CursorImage {
5138public:
52− XCursorImage(const QString &theme, const QString &file, int preferredCursorHeightPx);
39+ XCursorImage(const QString &theme, const QString &file);
5340 virtual ~XCursorImage();
41+
42+ XcursorImages *xcursorImages;
5443};
5544
5645class BuiltInCursorImage : public CursorImage {
5746public:
58− BuiltInCursorImage(int cursorHeight);
47+ BuiltInCursorImage();
5948};
6049
6150class BlankCursorImage : public CursorImage {
@@ -77,18 +66,18 @@ public:
7766 static CursorImageProvider *instance() { return m_instance; }
7867
7968
80− QImage requestImage(const QString &cursorThemeAndNameAndHeight, QSize *size, const QSize &requestedSize) override;
69+ QImage requestImage(const QString &cursorName, QSize *size, const QSize &requestedSize) override;
8170
82− CursorImage *fetchCursor(const QString &themeName, const QString &cursorName, int cursorHeight);
71+ QPoint hotspot(const QString &themeName, const QString &cursorName);
8372
8473 void setCustomCursor(const QCursor &customCursor);
8574
8675private:
87− CursorImage *fetchCursor(const QString &cursorThemeAndNameAndHeight);
88− CursorImage *fetchCursorHelper(const QString &themeName, const QString &cursorName, int cursorHeight);
76+ CursorImage *fetchCursor(const QString &cursorThemeAndName);
77+ CursorImage *fetchCursor(const QString &themeName, const QString &cursorName);
78+ CursorImage *fetchCursorHelper(const QString &themeName, const QString &cursorName);
8979
9080 // themeName -> (cursorName -> cursorImage)
91− // TODO: discard old, unused, cursors
9281 QMap<QString, QMap<QString, CursorImage*> > m_cursors;
9382
9483 QScopedPointer<CursorImage> m_builtInCursorImage;
plugins/Cursor/MousePointer.cpp+39−126
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
2+ * Copyright (C) 2015 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -22,7 +22,6 @@
2222
2323#include <QQuickWindow>
2424#include <QGuiApplication>
25−#include <QtMath>
2625
2726#include <qpa/qwindowsysteminterface.h>
2827
@@ -30,7 +29,10 @@ MousePointer::MousePointer(QQuickItem *parent)
3029 : MirMousePointerInterface(parent)
3130 , m_cursorName(QStringLiteral("left_ptr"))
3231 , m_themeName(QStringLiteral("default"))
32+ , m_hotspotX(0)
33+ , m_hotspotY(0)
3334{
35+ updateHotspot();
3436}
3537
3638void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
@@ -44,83 +46,29 @@ void MousePointer::handleMouseEvent(ulong timestamp, QPointF movement, Qt::Mouse
4446 Q_EMIT mouseMoved();
4547 }
4648
47− m_accumulatedMovement += movement;
48− // don't apply the fractional part
49− QPointF appliedMovement(int(m_accumulatedMovement.x()), int(m_accumulatedMovement.y()));
50− m_accumulatedMovement -= appliedMovement;
51−
52− qreal newX = x() + appliedMovement.x();
53− qreal newY = y() + appliedMovement.y();
54− const qreal sceneWidth = parentItem()->width();
55− const qreal sceneHeight = parentItem()->height();
56−
57− if (newX <= 0 && newY < m_topBoundaryOffset) { // top left corner
58− const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-m_topBoundaryOffset, 2));
59− Q_EMIT pushedTopLeftCorner(qAbs(distance), buttons);
60− m_pushing = true;
61− } else if (newX >= sceneWidth-1 && newY < m_topBoundaryOffset) { // top right corner
62− const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-m_topBoundaryOffset, 2));
63− Q_EMIT pushedTopRightCorner(qAbs(distance), buttons);
64− m_pushing = true;
65− } else if (newX < 0 && newY >= sceneHeight-1) { // bottom left corner
66− const auto distance = qSqrt(qPow(newX, 2) + qPow(newY-sceneHeight, 2));
67− Q_EMIT pushedBottomLeftCorner(qAbs(distance), buttons);
68− m_pushing = true;
69− } else if (newX >= sceneWidth-1 && newY >= sceneHeight-1) { // bottom right corner
70− const auto distance = qSqrt(qPow(newX-sceneWidth, 2) + qPow(newY-sceneHeight, 2));
71− Q_EMIT pushedBottomRightCorner(qAbs(distance), buttons);
72− m_pushing = true;
73− } else if (newX < 0) { // left edge
49+ qreal newX = x() + movement.x();
50+ if (newX < 0) {
7451 Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
75− m_pushing = true;
76− } else if (newX >= sceneWidth) { // right edge
77− Q_EMIT pushedRightBoundary(newX - (sceneWidth - 1), buttons);
78− m_pushing = true;
79− } else if (newY < m_topBoundaryOffset) { // top edge
80− Q_EMIT pushedTopBoundary(qAbs(newY - m_topBoundaryOffset), buttons);
81− m_pushing = true;
82− } else if (Q_LIKELY(newX > 0 && newX < sceneWidth-1 && newY > 0 && newY < sceneHeight-1)) { // normal pos, not pushing
83− if (m_pushing) {
84− Q_EMIT pushStopped();
85− m_pushing = false;
86− }
52+ newX = 0;
53+ } else if (newX > parentItem()->width()) {
54+ Q_EMIT pushedRightBoundary(newX - parentItem()->width(), buttons);
55+ newX = parentItem()->width();
8756 }
57+ setX(newX);
8858
89− applyItemConfinement(newX, newY);
90−
91− setX(qBound(0.0, newX, sceneWidth - 1));
92− setY(qBound(0.0, newY, sceneHeight - 1));
59+ qreal newY = y() + movement.y();
60+ if (newY < 0) {
61+ newY = 0;
62+ } else if (newY > parentItem()->height()) {
63+ newY = parentItem()->height();
64+ }
65+ setY(newY);
9366
9467 QPointF scenePosition = mapToItem(nullptr, QPointF(0, 0));
9568 QWindowSystemInterface::handleMouseEvent(window(), timestamp, scenePosition /*local*/, scenePosition /*global*/,
9669 buttons, modifiers);
9770}
9871
99−void MousePointer::applyItemConfinement(qreal &newX, qreal &newY)
100−{
101− Q_ASSERT(parentItem() != nullptr);
102−
103− if (m_confiningItem.isNull()) {
104− return;
105− }
106−
107− QRectF confiningItemGeometry(0, 0, m_confiningItem->width(), m_confiningItem->height());
108−
109− QRectF confiningRect = m_confiningItem->mapRectToItem(parentItem(), confiningItemGeometry);
110−
111− if (newX < confiningRect.x()) {
112− newX = confiningRect.x();
113− } else if (newX > confiningRect.right()) {
114− newX = confiningRect.right();
115− }
116−
117− if (newY < confiningRect.y()) {
118− newY = confiningRect.y();
119− } else if (newY > confiningRect.bottom()) {
120− newY = confiningRect.bottom();
121− }
122−}
123−
12472void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers modifiers)
12573{
12674 if (!parentItem()) {
@@ -132,20 +80,6 @@ void MousePointer::handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::Keyb
13280 QPoint() /* pixelDelta */, angleDelta, modifiers, Qt::ScrollUpdate);
13381}
13482
135−int MousePointer::topBoundaryOffset() const
136−{
137− return m_topBoundaryOffset;
138−}
139−
140−void MousePointer::setTopBoundaryOffset(int topBoundaryOffset)
141−{
142− if (m_topBoundaryOffset == topBoundaryOffset)
143− return;
144−
145− m_topBoundaryOffset = topBoundaryOffset;
146− Q_EMIT topBoundaryOffsetChanged(topBoundaryOffset);
147−}
148−
14983void MousePointer::itemChange(ItemChange change, const ItemChangeData &value)
15084{
15185 if (change == ItemSceneChange) {
@@ -155,32 +89,8 @@ void MousePointer::itemChange(ItemChange change, const ItemChangeData &value)
15589
15690void MousePointer::registerWindow(QWindow *window)
15791{
158− if (window == m_registeredWindow) {
159− return;
160− }
161−
162− if (m_registeredWindow) {
163− m_registeredWindow->disconnect(this);
164− }
165−
166− m_registeredWindow = window;
167−
168− if (m_registeredWindow) {
169− connect(window, &QWindow::screenChanged, this, &MousePointer::registerScreen);
170− registerScreen(window->screen());
171− } else {
172− registerScreen(nullptr);
173− }
174−}
175−
176−void MousePointer::registerScreen(QScreen *screen)
177−{
178− if (m_registeredScreen == screen) {
179− return;
180− }
181−
182− if (m_registeredScreen) {
183− auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
92+ if (m_registeredWindow && window != m_registeredWindow) {
93+ auto previousCursor = dynamic_cast<MirPlatformCursor*>(m_registeredWindow->screen()->handle()->cursor());
18494 if (previousCursor) {
18595 previousCursor->setMousePointer(nullptr);
18696 } else {
@@ -188,10 +98,10 @@ void MousePointer::registerScreen(QScreen *screen)
18898 }
18999 }
190100
191− m_registeredScreen = screen;
101+ m_registeredWindow = window;
192102
193− if (m_registeredScreen) {
194− auto cursor = dynamic_cast<MirPlatformCursor*>(m_registeredScreen->handle()->cursor());
103+ if (m_registeredWindow) {
104+ auto cursor = dynamic_cast<MirPlatformCursor*>(window->screen()->handle()->cursor());
195105 if (cursor) {
196106 cursor->setMousePointer(this);
197107 } else {
@@ -205,6 +115,22 @@ void MousePointer::setCursorName(const QString &cursorName)
205115 if (cursorName != m_cursorName) {
206116 m_cursorName = cursorName;
207117 Q_EMIT cursorNameChanged(m_cursorName);
118+ updateHotspot();
119+ }
120+}
121+
122+void MousePointer::updateHotspot()
123+{
124+ QPoint newHotspot = CursorImageProvider::instance()->hotspot(m_themeName, m_cursorName);
125+
126+ if (m_hotspotX != newHotspot.x()) {
127+ m_hotspotX = newHotspot.x();
128+ Q_EMIT hotspotXChanged(m_hotspotX);
129+ }
130+
131+ if (m_hotspotY != newHotspot.y()) {
132+ m_hotspotY = newHotspot.y();
133+ Q_EMIT hotspotYChanged(m_hotspotY);
208134 }
209135}
210136
@@ -220,16 +146,3 @@ void MousePointer::setCustomCursor(const QCursor &customCursor)
220146{
221147 CursorImageProvider::instance()->setCustomCursor(customCursor);
222148}
223−
224−QQuickItem* MousePointer::confiningItem() const
225−{
226− return m_confiningItem.data();
227−}
228−
229−void MousePointer::setConfiningItem(QQuickItem *item)
230−{
231− if (item != m_confiningItem) {
232− m_confiningItem = item;
233− Q_EMIT confiningItemChanged();
234− }
235−}
plugins/Cursor/MousePointer.h+7−32
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
2+ * Copyright (C) 2015 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -20,15 +20,12 @@
2020// Qt
2121#include <QPointer>
2222#include <QWindow>
23−#include <QScreen>
2423
2524// Unity API
2625#include <unity/shell/application/MirMousePointerInterface.h>
2726
2827class MousePointer : public MirMousePointerInterface {
2928 Q_OBJECT
30− Q_PROPERTY(QQuickItem* confiningItem READ confiningItem WRITE setConfiningItem NOTIFY confiningItemChanged)
31− Q_PROPERTY(int topBoundaryOffset READ topBoundaryOffset WRITE setTopBoundaryOffset NOTIFY topBoundaryOffsetChanged)
3229public:
3330 MousePointer(QQuickItem *parent = nullptr);
3431
@@ -38,13 +35,10 @@ public:
3835 void setThemeName(const QString &themeName) override;
3936 QString themeName() const override { return m_themeName; }
4037
41− void setCustomCursor(const QCursor &) override;
42−
43− QQuickItem* confiningItem() const;
44− void setConfiningItem(QQuickItem*);
38+ qreal hotspotX() const override { return m_hotspotX; }
39+ qreal hotspotY() const override { return m_hotspotY; }
4540
46− int topBoundaryOffset() const;
47− void setTopBoundaryOffset(int topBoundaryOffset);
41+ void setCustomCursor(const QCursor &) override;
4842
4943public Q_SLOTS:
5044 void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
@@ -54,39 +48,20 @@ public Q_SLOTS:
5448Q_SIGNALS:
5549 void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);
5650 void pushedRightBoundary(qreal amount, Qt::MouseButtons buttons);
57− void pushedTopBoundary(qreal amount, Qt::MouseButtons buttons);
58− void pushedTopLeftCorner(qreal amount, Qt::MouseButtons buttons);
59− void pushedTopRightCorner(qreal amount, Qt::MouseButtons buttons);
60− void pushedBottomLeftCorner(qreal amount, Qt::MouseButtons buttons);
61− void pushedBottomRightCorner(qreal amount, Qt::MouseButtons buttons);
62− void pushStopped();
6351 void mouseMoved();
64− void confiningItemChanged();
65−
66− void topBoundaryOffsetChanged(int topBoundaryOffset);
6752
6853protected:
6954 void itemChange(ItemChange change, const ItemChangeData &value) override;
7055
71−private Q_SLOTS:
72− void registerScreen(QScreen *screen);
73−
7456private:
7557 void registerWindow(QWindow *window);
76− void applyItemConfinement(qreal &newX, qreal &newY);
58+ void updateHotspot();
7759
7860 QPointer<QWindow> m_registeredWindow;
79− QPointer<QScreen> m_registeredScreen;
8061 QString m_cursorName;
8162 QString m_themeName;
82−
83− // Accumulated, unapplied, mouse movement.
84− QPointF m_accumulatedMovement;
85−
86− QPointer<QQuickItem> m_confiningItem;
87−
88− int m_topBoundaryOffset{0};
89− bool m_pushing{false};
63+ int m_hotspotX;
64+ int m_hotspotY;
9065};
9166
9267#endif // MOUSEPOINTER_H
plugins/Cursor/plugin.cpp+2−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
2+ * Copyright (C) 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -22,15 +22,13 @@
2222#include "plugin.h"
2323
2424// local
25−#include "CursorImageInfo.h"
2625#include "CursorImageProvider.h"
2726#include "MousePointer.h"
2827
2928void CursorPlugin::registerTypes(const char *uri)
3029{
3130 Q_ASSERT(uri == QLatin1String("Cursor"));
32− qmlRegisterType<CursorImageInfo>(uri, 1, 1, "CursorImageInfo");
33− qmlRegisterType<MousePointer>(uri, 1, 1, "MousePointer");
31+ qmlRegisterType<MousePointer>(uri, 1, 0, "MousePointer");
3432}
3533
3634void CursorPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
plugins/Cursor/qmldir+1−1
@@ -1,3 +1,3 @@
11module Cursor
22plugin Cursor-qml
3−Cursor 1.1 Cursor.qml
3+Cursor 1.0 Cursor.qml
plugins/Dash/AudioProgressBar.qmlnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright 2015 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 Dash 0.1
20+
21+Item {
22+ id: root
23+
24+ implicitHeight: progressBarImage.height
25+
26+ property url source
27+ readonly property double progress: AudioUrlComparer.compare(source, DashAudioPlayer.currentSource) ? DashAudioPlayer.progress : 0
28+
29+ Image {
30+ id: progressBarImage
31+ anchors { left: parent.left; right: parent.right }
32+ height: units.dp(6)
33+ source: "graphics/music_progress_bg.png"
34+ asynchronous: true
35+ sourceSize.width: width
36+ sourceSize.height: height
37+ }
38+
39+ UbuntuShape {
40+ id: progressBarFill
41+ objectName: "progressBarFill"
42+
43+ readonly property int maxWidth: progressBarImage.width
44+
45+ anchors {
46+ left: progressBarImage.left
47+ right: progressBarImage.right
48+ verticalCenter: progressBarImage.verticalCenter
49+ rightMargin: maxWidth - (maxWidth * root.progress)
50+ }
51+ height: units.dp(2)
52+ backgroundColor: theme.palette.normal.activity
53+ }
54+}
plugins/Dash/CMakeLists.txtnew file+43
@@ -0,0 +1,43 @@
1+# There's no cmake var for v8 include path :-/
2+# so create one
3+LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
4+if(${Qt5Core_VERSION_STRING} VERSION_LESS "5.1.0")
5+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/../QtV8/${Qt5Core_VERSION_STRING}/QtV8)
6+else()
7+ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
8+endif()
9+
10+include_directories(
11+ ${CMAKE_CURRENT_SOURCE_DIR}
12+ ${CMAKE_CURRENT_BINARY_DIR}
13+ ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
14+ ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
15+ ${Qt5V8_PRIVATE_INCLUDE_DIR}
16+)
17+
18+remove_definitions(-DQT_NO_KEYWORDS)
19+
20+set(QMLPLUGIN_SRC
21+ plugin.cpp
22+ listviewwithpageheader.cpp
23+ abstractdashview.cpp
24+ verticaljournal.cpp
25+ horizontaljournal.cpp
26+ organicgrid.cpp
27+ )
28+
29+add_library(Dash-qml MODULE
30+ ${QMLPLUGIN_SRC}
31+ )
32+
33+target_link_libraries(Dash-qml
34+ ${Qt5Gui_LIBRARIES}
35+ ${Qt5Quick_LIBRARIES}
36+ )
37+
38+qt5_use_modules(Dash-qml Qml Quick Concurrent)
39+
40+add_unity8_plugin(Dash 0.1 Dash TARGETS Dash-qml)
41+
42+install(FILES graphics/music_progress_bg.png DESTINATION ${SHELL_INSTALL_QML}/Dash/graphics/)
43+file(COPY graphics/music_progress_bg.png DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/graphics/)
plugins/Dash/CardAttributes.qmlnew file+71
@@ -0,0 +1,71 @@
1+/*
2+ * Copyright 2014 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 QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.3
20+
21+GridLayout {
22+ id: grid
23+ anchors {
24+ left: parent.left;
25+ right: parent.right;
26+ }
27+ columns: 2 + repeater.count % 2
28+ rowSpacing: units.gu(.5)
29+ property alias model: repeater.model
30+ property color color: theme.palette.normal.baseText
31+ property real fontScale: 1.0
32+
33+ Repeater {
34+ id: repeater
35+ delegate: Row {
36+ spacing: units.gu(0.5)
37+ readonly property int column: index % grid.columns;
38+ Layout.alignment: {
39+ if (column == 0) return Qt.AlignLeft;
40+ if (column == grid.columns - 1 || index == repeater.count - 1) return Qt.AlignRight;
41+ if (column == 1) return Qt.AlignHCenter;
42+ }
43+ Layout.column: index % grid.columns
44+ Layout.row: index / grid.columns
45+ Layout.columnSpan: index == repeater.count - 1 && grid.columns == 3 && column == 1 ? 2 : 1
46+ Layout.maximumWidth: Math.max(icon.width, label.x + label.implicitWidth)
47+ Layout.fillWidth: true
48+ height: units.gu(2)
49+ Icon {
50+ id: icon
51+ height: units.gu(2)
52+ // FIXME Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
53+ width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth
54+ source: "icon" in modelData && modelData["icon"] || ""
55+ color: grid.color
56+ }
57+ Label {
58+ id: label
59+ width: parent.width - x
60+ anchors.verticalCenter: parent.verticalCenter
61+ text: "value" in modelData && modelData["value"] || "";
62+ elide: Text.ElideRight
63+ maximumLineCount: 1
64+ font.weight: "style" in modelData && modelData["style"] === "highlighted" ? Font.Bold : Font.Light
65+ fontSize: "small"
66+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
67+ color: grid.color
68+ }
69+ }
70+ }
71+}
plugins/Dash/CardAudioProgress.qmlnew file+59
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright 2015 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 Dash 0.1
20+
21+Item {
22+ id: root
23+
24+ implicitHeight: positionLabel.y + positionLabel.height
25+ visible: AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)
26+
27+ property int duration: 0
28+ property alias source: progress.source
29+ property color color: theme.palette.normal.baseText
30+ readonly property int position: root.visible ? DashAudioPlayer.position / 1000 : 0
31+
32+ AudioProgressBar {
33+ id: progress
34+ anchors { left: parent.left; right: parent.right }
35+ }
36+
37+ Label {
38+ id: positionLabel
39+ anchors {
40+ left: parent.left
41+ top: progress.bottom
42+ }
43+ verticalAlignment: Text.AlignBottom
44+ fontSize: "x-small"
45+ text: DashAudioPlayer.lengthToString(root.position)
46+ color: root.color
47+ }
48+
49+ Label {
50+ anchors {
51+ right: parent.right
52+ top: progress.bottom
53+ }
54+ verticalAlignment: Text.AlignBottom
55+ fontSize: "x-small"
56+ text: DashAudioPlayer.lengthToString(duration)
57+ color: root.color
58+ }
59+}
plugins/Dash/CardCreator.jsnew file+965
@@ -0,0 +1,965 @@
1+/*
2+ * Copyright (C) 2014 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+.pragma library
18+
19+// %1 is the template["card-background"]["elements"][0]
20+// %2 is the template["card-background"]["elements"][1]
21+// %3 is whether the loader should be asynchronous or not
22+// %4 is the template["card-background"] string
23+var kBackgroundLoaderCode = 'Loader {\n\
24+ id: backgroundLoader; \n\
25+ objectName: "backgroundLoader"; \n\
26+ anchors.fill: parent; \n\
27+ asynchronous: %3; \n\
28+ visible: status == Loader.Ready; \n\
29+ sourceComponent: UbuntuShape { \n\
30+ objectName: "background"; \n\
31+ radius: "medium"; \n\
32+ aspect: { \n\
33+ switch (root.backgroundShapeStyle) { \n\
34+ case "inset": return UbuntuShape.Inset; \n\
35+ case "shadow": return UbuntuShape.DropShadow; \n\
36+ default: \n\
37+ case "flat": return UbuntuShape.Flat; \n\
38+ } \n\
39+ } \n\
40+ backgroundColor: getColor(0) || "white"; \n\
41+ secondaryBackgroundColor: getColor(1) || backgroundColor; \n\
42+ backgroundMode: UbuntuShape.VerticalGradient; \n\
43+ anchors.fill: parent; \n\
44+ source: backgroundImage.source ? backgroundImage : null; \n\
45+ property real luminance: Style.luminance(backgroundColor); \n\
46+ property Image backgroundImage: Image { \n\
47+ objectName: "backgroundImage"; \n\
48+ source: { \n\
49+ if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
50+ else return %4; \n\
51+ } \n\
52+ } \n\
53+ function getColor(index) { \n\
54+ if (cardData && typeof cardData["background"] === "object" \n\
55+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) { \n\
56+ return cardData["background"]["elements"][index]; \n\
57+ } else return index === 0 ? %1 : %2; \n\
58+ } \n\
59+ } \n\
60+ }\n';
61+
62+// %1 is the aspect of the UbuntuShape
63+var kArtUbuntuShapeCode = 'UbuntuShape { \n\
64+ anchors.fill: parent; \n\
65+ source: artImage; \n\
66+ sourceFillMode: UbuntuShape.PreserveAspectCrop; \n\
67+ radius: "medium"; \n\
68+ aspect: %1; \n\
69+ }';
70+
71+var kArtProportionalShapeCode = 'ProportionalShape { \n\
72+ anchors.fill: parent; \n\
73+ source: artImage; \n\
74+ aspect: UbuntuShape.DropShadow; \n\
75+ }';
76+
77+// %1 is used as anchors of artShapeHolder
78+// %2 is used as image width
79+// %3 is used as image height
80+// %4 is whether the image should be visible
81+// %5 is used as aspect ratio fallback
82+// %6 is whether the loader should be asynchronous or not
83+// %7 is the shape code we want to use
84+// %8 is injected as code to artImage
85+// %9 is used as image fallback
86+var kArtShapeHolderCode = 'Item { \n\
87+ id: artShapeHolder; \n\
88+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
89+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width; \n\
90+ anchors { %1 } \n\
91+ Loader { \n\
92+ id: artShapeLoader; \n\
93+ objectName: "artShapeLoader"; \n\
94+ readonly property string cardArt: cardData && cardData["art"] || %9; \n\
95+ onCardArtChanged: { if (item) { item.image.source = cardArt; } } \n\
96+ active: cardArt != ""; \n\
97+ asynchronous: %6; \n\
98+ visible: status == Loader.Ready; \n\
99+ sourceComponent: Item { \n\
100+ id: artShape; \n\
101+ objectName: "artShape"; \n\
102+ visible: image.status == Image.Ready; \n\
103+ readonly property alias image: artImage; \n\
104+ %7 \n\
105+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1; \n\
106+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : %5; \n\
107+ Component.onCompleted: { updateWidthHeightBindings(); } \n\
108+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); } \n\
109+ function updateWidthHeightBindings() { \n\
110+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) { \n\
111+ width = root.fixedArtShapeSize.width; \n\
112+ height = root.fixedArtShapeSize.height; \n\
113+ } else { \n\
114+ width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width }); \n\
115+ height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height }); \n\
116+ } \n\
117+ } \n\
118+ CroppedImageMinimumSourceSize { \n\
119+ id: artImage; \n\
120+ objectName: "artImage"; \n\
121+ source: artShapeLoader.cardArt; \n\
122+ asynchronous: %6; \n\
123+ visible: %4; \n\
124+ width: %2; \n\
125+ height: %3; \n\
126+ %8 \n\
127+ } \n\
128+ } \n\
129+ } \n\
130+ }\n';
131+
132+// %1 is anchors.fill
133+// %2 is width
134+// %3 is height
135+// %4 is whether the icon should be asynchronous or not
136+var kAudioButtonCode = 'AbstractButton { \n\
137+ id: audioButton; \n\
138+ anchors.fill: %1; \n\
139+ width: %2; \n\
140+ height: %3; \n\
141+ readonly property url source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || ""; \n\
142+ UbuntuShape { \n\
143+ anchors.fill: parent; \n\
144+ visible: parent.pressed; \n\
145+ radius: "medium"; \n\
146+ } \n\
147+ Rectangle { \n\
148+ color: Qt.rgba(0, 0, 0, 0.5); \n\
149+ anchors.centerIn: parent; \n\
150+ width: parent.width * 0.5; \n\
151+ height: width; \n\
152+ radius: width / 2; \n\
153+ } \n\
154+ Icon { \n\
155+ anchors.centerIn: parent; \n\
156+ width: parent.width * 0.3; \n\
157+ height: width; \n\
158+ opacity: 0.9; \n\
159+ name: DashAudioPlayer.playing && AudioUrlComparer.compare(parent.source, DashAudioPlayer.currentSource) ? "media-playback-pause" : "media-playback-start"; \n\
160+ color: "white"; \n\
161+ asynchronous: %4; \n\
162+ } \n\
163+ onClicked: { \n\
164+ if (AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)) { \n\
165+ if (DashAudioPlayer.playing) { \n\
166+ DashAudioPlayer.pause(); \n\
167+ } else { \n\
168+ DashAudioPlayer.play(); \n\
169+ } \n\
170+ } else { \n\
171+ var playlist = (cardData["quickPreviewData"] && cardData["quickPreviewData"]["playlist"]) || null; \n\
172+ DashAudioPlayer.playSource(source, playlist); \n\
173+ } \n\
174+ } \n\
175+ onPressAndHold: { \n\
176+ root.pressAndHold(); \n\
177+ } \n\
178+ }';
179+
180+// %1 is whether the loader should be asynchronous or not
181+// %2 is the header height code
182+var kOverlayLoaderCode = 'Loader { \n\
183+ id: overlayLoader; \n\
184+ readonly property real overlayHeight: %2 + units.gu(2); \n\
185+ anchors.fill: artShapeHolder; \n\
186+ active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false; \n\
187+ asynchronous: %1; \n\
188+ visible: showHeader && status == Loader.Ready; \n\
189+ sourceComponent: UbuntuShapeOverlay { \n\
190+ id: overlay; \n\
191+ property real luminance: Style.luminance(overlayColor); \n\
192+ aspect: UbuntuShape.Flat; \n\
193+ radius: "medium"; \n\
194+ overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
195+ overlayRect: Qt.rect(0, 1 - overlayLoader.overlayHeight / height, 1, 1); \n\
196+ } \n\
197+ }\n';
198+
199+// multiple row version of HeaderRowCode
200+function kHeaderRowCodeGenerator() {
201+ var kHeaderRowCodeTemplate = 'Row { \n\
202+ id: row; \n\
203+ objectName: "outerRow"; \n\
204+ property real margins: units.gu(1); \n\
205+ spacing: margins; \n\
206+ %2\
207+ anchors { %1 } \n\
208+ anchors.right: parent.right; \n\
209+ anchors.margins: margins; \n\
210+ anchors.rightMargin: 0; \n\
211+ data: [ \n\
212+ %3 \n\
213+ ] \n\
214+ }\n';
215+ var args = Array.prototype.slice.call(arguments);
216+ var isCardTool = args.shift();
217+ var heightCode = isCardTool ? "" : "height: root.fixedHeaderHeight; \n";
218+ var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(heightCode).arg(args.join(',\n'));
219+ return code;
220+}
221+
222+// multiple item version of kHeaderContainerCode
223+function kHeaderContainerCodeGenerator() {
224+ var headerContainerCodeTemplate = 'Item { \n\
225+ id: headerTitleContainer; \n\
226+ anchors { %1 } \n\
227+ width: parent.width - x; \n\
228+ implicitHeight: %2; \n\
229+ data: [ \n\
230+ %3 \n\
231+ ]\n\
232+ }\n';
233+ var args = Array.prototype.slice.call(arguments);
234+ var code = headerContainerCodeTemplate.arg(args.shift()).arg(args.shift()).arg(args.join(',\n'));
235+ return code;
236+}
237+
238+// %1 is used as anchors of mascotShapeLoader
239+// %2 is whether the loader should be asynchronous or not
240+var kMascotShapeLoaderCode = 'Loader { \n\
241+ id: mascotShapeLoader; \n\
242+ objectName: "mascotShapeLoader"; \n\
243+ asynchronous: %2; \n\
244+ active: mascotImage.status === Image.Ready; \n\
245+ visible: showHeader && active && status == Loader.Ready; \n\
246+ width: units.gu(6); \n\
247+ height: units.gu(5.625); \n\
248+ sourceComponent: UbuntuShape { image: mascotImage } \n\
249+ anchors { %1 } \n\
250+ }\n';
251+
252+// %1 is used as anchors of mascotImage
253+// %2 is used as visible of mascotImage
254+// %3 is injected as code to mascotImage
255+// %4 is used as fallback image
256+var kMascotImageCode = 'CroppedImageMinimumSourceSize { \n\
257+ id: mascotImage; \n\
258+ objectName: "mascotImage"; \n\
259+ anchors { %1 } \n\
260+ source: cardData && cardData["mascot"] || %4; \n\
261+ width: units.gu(6); \n\
262+ height: units.gu(5.625); \n\
263+ horizontalAlignment: Image.AlignHCenter; \n\
264+ verticalAlignment: Image.AlignVCenter; \n\
265+ visible: %2; \n\
266+ %3 \n\
267+ }\n';
268+
269+// %1 is used as anchors of titleLabel
270+// %2 is used as color of titleLabel
271+// %3 is used as extra condition for visible of titleLabel
272+// %4 is used as title width
273+// %5 is used as horizontal alignment
274+var kTitleLabelCode = 'Label { \n\
275+ id: titleLabel; \n\
276+ objectName: "titleLabel"; \n\
277+ anchors { %1 } \n\
278+ elide: Text.ElideRight; \n\
279+ fontSize: "small"; \n\
280+ wrapMode: Text.Wrap; \n\
281+ maximumLineCount: 2; \n\
282+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
283+ color: %2; \n\
284+ visible: showHeader %3; \n\
285+ width: %4; \n\
286+ text: root.title; \n\
287+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal; \n\
288+ horizontalAlignment: %5; \n\
289+ }\n';
290+
291+// %1 is used as extra anchors of emblemIcon
292+// %2 is used as color of emblemIcon
293+// FIXME The width code is a
294+// Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
295+var kEmblemIconCode = 'Icon { \n\
296+ id: emblemIcon; \n\
297+ objectName: "emblemIcon"; \n\
298+ anchors { \n\
299+ bottom: titleLabel.baseline; \n\
300+ right: parent.right; \n\
301+ %1 \n\
302+ } \n\
303+ source: cardData && cardData["emblem"] || ""; \n\
304+ color: %2; \n\
305+ height: source != "" ? titleLabel.font.pixelSize : 0; \n\
306+ width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth; \n\
307+ }\n';
308+
309+// %1 is used as anchors of touchdown effect
310+var kTouchdownCode = 'UbuntuShape { \n\
311+ id: touchdown; \n\
312+ objectName: "touchdown"; \n\
313+ anchors { %1 } \n\
314+ visible: root.pressed; \n\
315+ radius: "medium"; \n\
316+ borderSource: "radius_pressed.sci" \n\
317+ }\n';
318+
319+// %1 is used as anchors of subtitleLabel
320+// %2 is used as color of subtitleLabel
321+var kSubtitleLabelCode = 'Label { \n\
322+ id: subtitleLabel; \n\
323+ objectName: "subtitleLabel"; \n\
324+ anchors { %1 } \n\
325+ anchors.topMargin: units.dp(2); \n\
326+ elide: Text.ElideRight; \n\
327+ maximumLineCount: 1; \n\
328+ fontSize: "x-small"; \n\
329+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale); \n\
330+ color: %2; \n\
331+ visible: titleLabel.visible && titleLabel.text; \n\
332+ text: cardData && cardData["subtitle"] || ""; \n\
333+ font.weight: Font.Light; \n\
334+ }\n';
335+
336+// %1 is used as anchors of attributesRow
337+// %2 is used as color of attributesRow
338+var kAttributesRowCode = 'CardAttributes { \n\
339+ id: attributesRow; \n\
340+ objectName: "attributesRow"; \n\
341+ anchors { %1 } \n\
342+ color: %2; \n\
343+ fontScale: root.fontScale; \n\
344+ model: cardData && cardData["attributes"]; \n\
345+ }\n';
346+
347+// %1 is used as anchors of socialActionsRow
348+// %2 is used as color of socialActionsRow
349+var kSocialActionsRowCode = 'CardSocialActions { \n\
350+ id: socialActionsRow; \n\
351+ objectName: "socialActionsRow"; \n\
352+ anchors { %1 } \n\
353+ color: %2; \n\
354+ model: cardData && cardData["socialActions"]; \n\
355+ onClicked: root.action(actionId); \n\
356+ }\n';
357+
358+// %1 is used as top anchor of summary
359+// %2 is used as topMargin anchor of summary
360+// %3 is used as color of summary
361+var kSummaryLabelCode = 'Label { \n\
362+ id: summary; \n\
363+ objectName: "summaryLabel"; \n\
364+ anchors { \n\
365+ top: %1; \n\
366+ left: parent.left; \n\
367+ right: parent.right; \n\
368+ margins: units.gu(1); \n\
369+ topMargin: %2; \n\
370+ } \n\
371+ wrapMode: Text.Wrap; \n\
372+ maximumLineCount: 5; \n\
373+ elide: Text.ElideRight; \n\
374+ text: cardData && cardData["summary"] || ""; \n\
375+ height: text ? implicitHeight : 0; \n\
376+ fontSize: "small"; \n\
377+ color: %3; \n\
378+ }\n';
379+
380+// %1 is used as bottom anchor of audio progress bar
381+// %2 is used as left anchor of audio progress bar
382+// %3 is used as text color
383+var kAudioProgressBarCode = 'CardAudioProgress { \n\
384+ id: audioProgressBar; \n\
385+ duration: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["duration"]) || 0; \n\
386+ source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || ""; \n\
387+ anchors { \n\
388+ bottom: %1; \n\
389+ left: %2; \n\
390+ right: parent.right; \n\
391+ margins: units.gu(1); \n\
392+ } \n\
393+ color: %3; \n\
394+ }';
395+
396+function sanitizeColor(colorString) {
397+ if (colorString !== undefined) {
398+ if (colorString.match(/^[#a-z0-9]*$/i) === null) {
399+ // This is not the perfect regexp for color
400+ // but what we're trying to do here is just protect
401+ // against injection so it's ok
402+ return "";
403+ }
404+ }
405+ return colorString;
406+}
407+
408+function cardString(template, components, isCardTool, artShapeStyle) {
409+ var code;
410+
411+ var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
412+
413+ code = 'AbstractButton { \n\
414+ id: root; \n\
415+ property var cardData; \n\
416+ property string backgroundShapeStyle: "inset"; \n\
417+ property real fontScale: 1.0; \n\
418+ property var scopeStyle: null; \n\
419+ %2\
420+ property size fixedArtShapeSize: Qt.size(-1, -1); \n\
421+ readonly property string title: cardData && cardData["title"] || ""; \n\
422+ property bool showHeader: true; \n\
423+ implicitWidth: childrenRect.width; \n\
424+ enabled: %1; \n\
425+ \n'.arg(templateInteractive);
426+
427+ code = code.arg(isCardTool ? "" : "property int fixedHeaderHeight: -1; \n");
428+
429+ var hasArt = components["art"] && components["art"]["field"] || false;
430+ var hasSummary = components["summary"] || false;
431+ var isConciergeMode = components["art"] && components["art"]["conciergeMode"] || false;
432+ var artAndSummary = hasArt && hasSummary && !isConciergeMode;
433+ var isHorizontal = template["card-layout"] === "horizontal";
434+ var hasBackground = (!isHorizontal && (template["card-background"] || components["background"] || artAndSummary)) ||
435+ (hasSummary && (template["card-background"] || components["background"]));
436+ var hasTitle = components["title"] || false;
437+ var hasMascot = components["mascot"] || false;
438+ var hasEmblem = components["emblem"] && !(hasMascot && template["card-size"] === "small") || false;
439+ var headerAsOverlay = hasArt && template && template["overlay"] === true && (hasTitle || hasMascot);
440+ var hasSubtitle = hasTitle && components["subtitle"] || false;
441+ var hasHeaderRow = hasMascot && hasTitle;
442+ var hasAttributes = hasTitle && components["attributes"] && components["attributes"]["field"] || false;
443+ var hasSocialActions = hasTitle && components["social-actions"] || false;
444+ var isAudio = template["quick-preview-type"] === "audio";
445+ var asynchronous = isCardTool ? "false" : "true";
446+
447+ code += 'signal action(var actionId);\n';
448+ if (isAudio) {
449+ // For now we only support audio cards with [optional] art, title, subtitle
450+ // in horizontal mode
451+ // Anything else makes it behave not like an audio card
452+ if (hasSummary) isAudio = false;
453+ if (!isHorizontal) isAudio = false;
454+ if (hasMascot) isAudio = false;
455+ if (hasEmblem) isAudio = false;
456+ if (headerAsOverlay) isAudio = false;
457+ if (hasAttributes) isAudio = false;
458+ }
459+
460+ if (hasBackground) {
461+ var templateCardBackground;
462+ if (template && typeof template["card-background"] === "string") {
463+ templateCardBackground = 'decodeURI("' + encodeURI(template["card-background"]) + '")';
464+ } else {
465+ templateCardBackground = '""';
466+ }
467+
468+ var backgroundElements0;
469+ var backgroundElements1;
470+ if (template && typeof template["card-background"] === "object" && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
471+ var element0 = sanitizeColor(template["card-background"]["elements"][0]);
472+ var element1 = sanitizeColor(template["card-background"]["elements"][1]);
473+ if (element0 !== undefined) {
474+ backgroundElements0 = '"%1"'.arg(element0);
475+ }
476+ if (element1 !== undefined) {
477+ backgroundElements1 = '"%1"'.arg(element1);
478+ }
479+ }
480+ code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(asynchronous).arg(templateCardBackground);
481+ }
482+
483+ if (hasArt) {
484+ code += 'readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);\n';
485+
486+ var widthCode, heightCode;
487+ var artAnchors;
488+ if (isHorizontal) {
489+ artAnchors = 'left: parent.left';
490+ if (hasMascot || hasTitle) {
491+ widthCode = 'height * artShape.aspect'
492+ heightCode = 'headerHeight + 2 * units.gu(1)';
493+ } else {
494+ // This side of the else is a bit silly, who wants an horizontal layout without mascot and title?
495+ // So we define a "random" height of the image height + 2 gu for the margins
496+ widthCode = 'height * artShape.aspect'
497+ heightCode = 'units.gu(7.625)';
498+ }
499+ } else {
500+ artAnchors = 'horizontalCenter: parent.horizontalCenter;';
501+ widthCode = 'root.width'
502+ heightCode = 'width / artShape.aspect';
503+ }
504+
505+ var aspectRatio = components["art"] && components["art"]["aspect-ratio"] || 1;
506+ if (isNaN(aspectRatio)) {
507+ aspectRatio = 1;
508+ }
509+ var fallback = !isCardTool && components["art"] && components["art"]["fallback"] || "";
510+ fallback = encodeURI(fallback);
511+ var fallbackStatusCode = "";
512+ var fallbackURICode = '""';
513+ if (fallback !== "") {
514+ // fallbackStatusCode has %9 in it because we want to substitute it for fallbackURICode
515+ // which in kArtShapeHolderCode is %9
516+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %9;';
517+ fallbackURICode = 'decodeURI("%1")'.arg(fallback);
518+ }
519+ var artShapeHolderShapeCode;
520+ if (!isConciergeMode) {
521+ if (artShapeStyle === "icon") {
522+ artShapeHolderShapeCode = kArtProportionalShapeCode;
523+ } else {
524+ var artShapeHolderShapeAspect;
525+ switch (artShapeStyle) {
526+ case "inset": artShapeHolderShapeAspect = "UbuntuShape.Inset"; break;
527+ case "shadow": artShapeHolderShapeAspect = "UbuntuShape.DropShadow"; break;
528+ default:
529+ case "flat": artShapeHolderShapeAspect = "UbuntuShape.Flat"; break;
530+ }
531+ artShapeHolderShapeCode = kArtUbuntuShapeCode.arg(artShapeHolderShapeAspect);
532+ }
533+ } else {
534+ artShapeHolderShapeCode = "";
535+ }
536+ code += kArtShapeHolderCode.arg(artAnchors)
537+ .arg(widthCode)
538+ .arg(heightCode)
539+ .arg(isConciergeMode ? "true" : "false")
540+ .arg(aspectRatio)
541+ .arg(asynchronous)
542+ .arg(artShapeHolderShapeCode)
543+ .arg(fallbackStatusCode)
544+ .arg(fallbackURICode);
545+ } else {
546+ code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
547+ }
548+
549+ if (headerAsOverlay) {
550+ var headerHeightCode = isCardTool ? "headerHeight" : "root.fixedHeaderHeight";
551+ code += kOverlayLoaderCode.arg(asynchronous).arg(headerHeightCode);
552+ }
553+
554+ var headerVerticalAnchors;
555+ if (headerAsOverlay) {
556+ headerVerticalAnchors = 'bottom: artShapeHolder.bottom; \n\
557+ bottomMargin: units.gu(1);\n';
558+ } else {
559+ if (hasArt) {
560+ if (isHorizontal) {
561+ headerVerticalAnchors = 'top: artShapeHolder.top; \n\
562+ topMargin: units.gu(1);\n';
563+ } else {
564+ headerVerticalAnchors = 'top: artShapeHolder.bottom; \n\
565+ topMargin: units.gu(1);\n';
566+ }
567+ } else {
568+ headerVerticalAnchors = 'top: parent.top; \n\
569+ topMargin: units.gu(1);\n';
570+ }
571+ }
572+
573+ var headerLeftAnchor;
574+ var headerLeftAnchorHasMargin = false;
575+ if (isHorizontal && hasArt) {
576+ headerLeftAnchor = 'left: artShapeHolder.right; \n\
577+ leftMargin: units.gu(1);\n';
578+ headerLeftAnchorHasMargin = true;
579+ } else if (isHorizontal && isAudio) {
580+ headerLeftAnchor = 'left: audioButton.right; \n\
581+ leftMargin: units.gu(1);\n';
582+ headerLeftAnchorHasMargin = true;
583+ } else {
584+ headerLeftAnchor = 'left: parent.left;\n';
585+ }
586+
587+ var touchdownOnArtShape = !hasBackground && hasArt && !hasMascot && !hasSummary && !isAudio;
588+
589+ if (hasHeaderRow) {
590+ code += 'readonly property int headerHeight: row.height;\n'
591+ } else if (hasMascot) {
592+ code += 'readonly property int headerHeight: mascotImage.height;\n'
593+ } else if (hasAttributes) {
594+ if (hasTitle && hasSubtitle) {
595+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + attributesRow.height + attributesRow.anchors.topMargin;\n'
596+ } else if (hasTitle) {
597+ code += 'readonly property int headerHeight: titleLabel.height + attributesRow.height + attributesRow.anchors.topMargin;\n'
598+ } else {
599+ code += 'readonly property int headerHeight: attributesRow.height;\n'
600+ }
601+ } else if (isAudio) {
602+ if (hasSubtitle) {
603+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + audioProgressBar.height + audioProgressBar.anchors.topMargin;\n'
604+ } else if (hasTitle) {
605+ code += 'readonly property int headerHeight: titleLabel.height + audioProgressBar.height + audioProgressBar.anchors.topMargin;\n'
606+ } else {
607+ code += 'readonly property int headerHeight: audioProgressBar.height;\n'
608+ }
609+ } else if (hasSubtitle) {
610+ code += 'readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;\n'
611+ } else if (hasTitle) {
612+ code += 'readonly property int headerHeight: titleLabel.height;\n'
613+ } else {
614+ code += 'readonly property int headerHeight: 0;\n'
615+ }
616+
617+ var mascotShapeCode = '';
618+ var mascotCode = '';
619+ if (hasMascot) {
620+ var useMascotShape = !hasBackground && !headerAsOverlay;
621+ var mascotAnchors = '';
622+ if (!hasHeaderRow) {
623+ mascotAnchors += headerLeftAnchor;
624+ mascotAnchors += headerVerticalAnchors;
625+ if (!headerLeftAnchorHasMargin) {
626+ mascotAnchors += 'leftMargin: units.gu(1);\n'
627+ }
628+ } else {
629+ mascotAnchors = 'verticalCenter: parent.verticalCenter;'
630+ }
631+
632+ if (useMascotShape) {
633+ mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors).arg(asynchronous);
634+ }
635+
636+ var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
637+ var fallback = !isCardTool && components["mascot"] && components["mascot"]["fallback"] || "";
638+ fallback = encodeURI(fallback);
639+ var fallbackStatusCode = "";
640+ var fallbackURICode = '""';
641+ if (fallback !== "") {
642+ // fallbackStatusCode has %4 in it because we want to substitute it for fallbackURICode
643+ // which in kMascotImageCode is %4
644+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %4;';
645+ fallbackURICode = 'decodeURI("%1")'.arg(fallback);
646+ }
647+ mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible).arg(fallbackStatusCode).arg(fallbackURICode);
648+ }
649+
650+ var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
651+
652+ var hasTitleContainer = hasTitle && (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes)));
653+ var titleSubtitleCode = '';
654+ if (hasTitle) {
655+ var titleColor;
656+ if (headerAsOverlay) {
657+ titleColor = 'root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
658+ } else if (hasSummary) {
659+ titleColor = 'summary.color';
660+ } else if (hasBackground) {
661+ titleColor = summaryColorWithBackground;
662+ } else {
663+ titleColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
664+ }
665+
666+ var titleAnchors;
667+ var subtitleAnchors;
668+ var attributesAnchors;
669+ var titleContainerAnchors;
670+ var titleRightAnchor;
671+ var titleWidth = "undefined";
672+
673+ var extraRightAnchor = '';
674+ var extraLeftAnchor = '';
675+ if (!touchdownOnArtShape) {
676+ extraRightAnchor = 'rightMargin: units.gu(1); \n';
677+ extraLeftAnchor = 'leftMargin: units.gu(1); \n';
678+ } else if (headerAsOverlay && !hasEmblem) {
679+ extraRightAnchor = 'rightMargin: units.gu(1); \n';
680+ }
681+
682+ if (hasMascot) {
683+ titleContainerAnchors = 'verticalCenter: parent.verticalCenter; ';
684+ } else {
685+ titleContainerAnchors = 'right: parent.right; ';
686+ titleContainerAnchors += headerLeftAnchor;
687+ titleContainerAnchors += headerVerticalAnchors;
688+ if (!headerLeftAnchorHasMargin) {
689+ titleContainerAnchors += extraLeftAnchor;
690+ }
691+ }
692+ if (hasEmblem) {
693+ titleRightAnchor = 'right: emblemIcon.left; \n\
694+ rightMargin: emblemIcon.width > 0 ? units.gu(0.5) : 0; \n';
695+ } else {
696+ titleRightAnchor = 'right: parent.right; \n'
697+ titleRightAnchor += extraRightAnchor;
698+ }
699+
700+ if (hasTitleContainer) {
701+ // Using headerTitleContainer
702+ titleAnchors = titleRightAnchor;
703+ titleAnchors += 'left: parent.left; \n\
704+ top: parent.top;';
705+ subtitleAnchors = 'right: parent.right; \n\
706+ left: parent.left; \n';
707+ subtitleAnchors += extraRightAnchor;
708+ if (hasSubtitle) {
709+ attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
710+ subtitleAnchors += 'top: titleLabel.bottom;\n';
711+ } else {
712+ attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
713+ }
714+ } else if (hasMascot) {
715+ // Using row without titleContainer
716+ titleAnchors = 'verticalCenter: parent.verticalCenter;\n';
717+ titleWidth = "parent.width - x";
718+ } else {
719+ if (headerAsOverlay) {
720+ // Using anchors to the overlay
721+ titleAnchors = titleRightAnchor;
722+ titleAnchors += 'left: parent.left; \n\
723+ leftMargin: units.gu(1); \n\
724+ top: overlayLoader.top; \n\
725+ topMargin: units.gu(1) + overlayLoader.height - overlayLoader.overlayHeight; \n';
726+ } else {
727+ // Using anchors to the mascot/parent
728+ titleAnchors = titleRightAnchor;
729+ titleAnchors += headerLeftAnchor;
730+ titleAnchors += headerVerticalAnchors;
731+ if (!headerLeftAnchorHasMargin) {
732+ titleAnchors += extraLeftAnchor;
733+ }
734+ }
735+ subtitleAnchors = 'left: titleLabel.left; \n\
736+ leftMargin: titleLabel.leftMargin; \n';
737+ subtitleAnchors += extraRightAnchor;
738+ if (hasEmblem) {
739+ // using container
740+ subtitleAnchors += 'right: parent.right; \n';
741+ } else {
742+ subtitleAnchors += 'right: titleLabel.right; \n';
743+ }
744+
745+ if (hasSubtitle) {
746+ attributesAnchors = subtitleAnchors + 'top: subtitleLabel.bottom;\n';
747+ subtitleAnchors += 'top: titleLabel.bottom;\n';
748+ } else {
749+ attributesAnchors = subtitleAnchors + 'top: titleLabel.bottom;\n';
750+ }
751+ }
752+
753+ var titleAlignment = "Text.AlignHCenter";
754+ if (template["card-layout"] === "horizontal"
755+ || typeof components["title"] !== "object"
756+ || components["title"]["align"] === "left") titleAlignment = "Text.AlignLeft";
757+ var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
758+ for (var key in keys) {
759+ key = keys[key];
760+ try {
761+ if (typeof components[key] === "string"
762+ || typeof components[key]["field"] === "string") titleAlignment = "Text.AlignLeft";
763+ } catch (e) {
764+ continue;
765+ }
766+ }
767+
768+ // code for different elements
769+ var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
770+ var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth).arg(titleAlignment);
771+ var subtitleCode;
772+ var attributesCode;
773+
774+ // code for the title container
775+ var containerCode = [];
776+ var containerHeight = 'titleLabel.height';
777+ containerCode.push(titleCode);
778+ if (hasSubtitle) {
779+ subtitleCode = kSubtitleLabelCode.arg(subtitleAnchors).arg(titleColor);
780+ containerCode.push(subtitleCode);
781+ containerHeight += ' + subtitleLabel.height';
782+ }
783+ if (hasEmblem) {
784+ containerCode.push(kEmblemIconCode.arg(extraRightAnchor).arg(titleColor));
785+ }
786+ if (hasAttributes) {
787+ attributesCode = kAttributesRowCode.arg(attributesAnchors).arg(titleColor);
788+ containerCode.push(attributesCode);
789+ containerHeight += ' + attributesRow.height';
790+ }
791+
792+ if (hasTitleContainer) {
793+ // use container
794+ titleSubtitleCode = kHeaderContainerCodeGenerator(titleContainerAnchors, containerHeight, containerCode);
795+ } else {
796+ // no container
797+ titleSubtitleCode = titleCode;
798+ if (hasSubtitle) {
799+ titleSubtitleCode += subtitleCode;
800+ }
801+ if (hasAttributes) {
802+ titleSubtitleCode += attributesCode;
803+ }
804+ }
805+ }
806+
807+ if (hasHeaderRow) {
808+ var rowCode = [mascotCode, titleSubtitleCode];
809+ if (mascotShapeCode != '') {
810+ rowCode.unshift(mascotShapeCode);
811+ }
812+ code += kHeaderRowCodeGenerator(isCardTool, headerVerticalAnchors + headerLeftAnchor, rowCode)
813+ } else {
814+ code += mascotShapeCode + mascotCode + titleSubtitleCode;
815+ }
816+
817+ if (isAudio) {
818+ var audioProgressBarLeftAnchor = 'audioButton.right';
819+ var audioProgressBarBottomAnchor = 'audioButton.bottom';
820+ var audioProgressBarTextColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
821+
822+ code += kAudioProgressBarCode.arg(audioProgressBarBottomAnchor)
823+ .arg(audioProgressBarLeftAnchor)
824+ .arg(audioProgressBarTextColor);
825+
826+ var audioButtonAnchorsFill;
827+ var audioButtonWidth;
828+ var audioButtonHeight;
829+ if (hasArt) {
830+ audioButtonAnchorsFill = 'artShapeHolder';
831+ audioButtonWidth = 'undefined';
832+ audioButtonHeight = 'undefined';
833+ } else {
834+ audioButtonAnchorsFill = 'undefined';
835+ audioButtonWidth = 'height';
836+ audioButtonHeight = isCardTool ? 'headerHeight + 2 * units.gu(1)'
837+ : 'root.fixedHeaderHeight + 2 * units.gu(1)';
838+ }
839+ code += kAudioButtonCode.arg(audioButtonAnchorsFill).arg(audioButtonWidth).arg(audioButtonHeight).arg(asynchronous);
840+ }
841+
842+ if (hasSummary) {
843+ var summaryTopAnchor;
844+ if (isHorizontal && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
845+ else if (headerAsOverlay && hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
846+ else if (hasHeaderRow) summaryTopAnchor = 'row.bottom';
847+ else if (hasTitleContainer) summaryTopAnchor = 'headerTitleContainer.bottom';
848+ else if (hasMascot) summaryTopAnchor = 'mascotImage.bottom';
849+ else if (hasAttributes) summaryTopAnchor = 'attributesRow.bottom';
850+ else if (hasSubtitle) summaryTopAnchor = 'subtitleLabel.bottom';
851+ else if (hasTitle) summaryTopAnchor = 'titleLabel.bottom';
852+ else if (hasArt) summaryTopAnchor = 'artShapeHolder.bottom';
853+ else summaryTopAnchor = 'parent.top';
854+
855+ var summaryColor;
856+ if (hasBackground) {
857+ summaryColor = summaryColorWithBackground;
858+ } else {
859+ summaryColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
860+ }
861+
862+ var summaryTopMargin = (hasMascot || hasSubtitle || hasAttributes ? 'anchors.margins' : '0');
863+
864+ code += kSummaryLabelCode.arg(summaryTopAnchor).arg(summaryTopMargin).arg(summaryColor);
865+ }
866+
867+// <<<<<<< TREE
868+// if (artShapeStyle != "shadow" && artShapeStyle != "icon") {
869+// var touchdownAnchors;
870+// =======
871+ if (hasSocialActions) {
872+ var socialAnchors;
873+ var socialTopAnchor;
874+
875+ if (hasSummary) socialTopAnchor = 'summary.bottom;';
876+ else if (isHorizontal && hasArt) socialTopAnchor = 'artShapeHolder.bottom;';
877+ else if (headerAsOverlay && hasArt) socialTopAnchor = 'artShapeHolder.bottom;';
878+ else if (hasHeaderRow) socialTopAnchor = 'row.bottom;';
879+ else if (hasTitleContainer) socialTopAnchor = 'headerTitleContainer.bottom;';
880+ else if (hasMascot) socialTopAnchor = 'mascotImage.bottom;';
881+ else if (hasAttributes) socialTopAnchor = 'attributesRow.bottom;';
882+ else if (hasSubtitle) socialTopAnchor = 'subtitleLabel.bottom;';
883+ else if (hasTitle) socialTopAnchor = 'titleLabel.bottom;';
884+ else if (hasArt) socialTopAnchor = 'artShapeHolder.bottom;';
885+ else socialTopAnchor = 'parent.top';
886+
887+ socialAnchors = 'top: ' + socialTopAnchor + ' left: parent.left; right: parent.right; topMargin: units.gu(1);'
888+
889+ var socialColor;
890+ if (hasBackground) {
891+ socialColor = summaryColorWithBackground;
892+ } else {
893+ socialColor = 'root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText';
894+ }
895+
896+ code += kSocialActionsRowCode.arg(socialAnchors).arg(socialColor);
897+ }
898+
899+ if (artShapeStyle != "shadow" && artShapeStyle != "icon") {
900+ var touchdownAnchors;
901+ if (hasBackground) {
902+ touchdownAnchors = 'fill: backgroundLoader';
903+ } else if (touchdownOnArtShape) {
904+ touchdownAnchors = 'fill: artShapeHolder';
905+ } else {
906+ touchdownAnchors = 'fill: root'
907+ }
908+ code += kTouchdownCode.arg(touchdownAnchors);
909+ }
910+
911+ var implicitHeight = 'implicitHeight: ';
912+ if (hasSocialActions) {
913+ implicitHeight += 'socialActionsRow.y + socialActionsRow.height + units.gu(1);\n';
914+ } else if (hasSummary) {
915+ implicitHeight += 'summary.y + summary.height + units.gu(1);\n';
916+ } else if (isAudio) {
917+ implicitHeight += 'audioButton.height;\n';
918+ } else if (headerAsOverlay) {
919+ implicitHeight += 'artShapeHolder.height;\n';
920+ } else if (hasHeaderRow) {
921+ implicitHeight += 'row.y + row.height + units.gu(1);\n';
922+ } else if (hasMascot) {
923+ implicitHeight += 'mascotImage.y + mascotImage.height;\n';
924+ } else if (hasTitleContainer) {
925+ implicitHeight += 'headerTitleContainer.y + headerTitleContainer.height + units.gu(1);\n';
926+ } else if (hasAttributes) {
927+ implicitHeight += 'attributesRow.y + attributesRow.height + units.gu(1);\n';
928+ } else if (hasSubtitle) {
929+ implicitHeight += 'subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
930+ } else if (hasTitle) {
931+ implicitHeight += 'titleLabel.y + titleLabel.height + units.gu(1);\n';
932+ } else if (hasArt) {
933+ implicitHeight += 'artShapeHolder.height;\n';
934+ } else {
935+ implicitHeight = '';
936+ }
937+
938+ // Close the AbstractButton
939+ code += implicitHeight + '}\n';
940+
941+ return code;
942+}
943+
944+function createCardComponent(parent, template, components, isCardTool, artShapeStyle, identifier) {
945+ var imports = 'import QtQuick 2.4; \n\
946+ import Ubuntu.Components 1.3; \n\
947+ import Ubuntu.Settings.Components 0.1; \n\
948+ import Dash 0.1;\n\
949+ import Utils 0.1;\n';
950+ var card = cardString(template, components, isCardTool, artShapeStyle);
951+ var code = imports + 'Component {\n' + card + '}\n';
952+
953+ try {
954+ return Qt.createQmlObject(code, parent, identifier);
955+ } catch (e) {
956+ console.error("ERROR: Invalid component created.");
957+ console.error("Template:");
958+ console.error(JSON.stringify(template));
959+ console.error("Components:");
960+ console.error(JSON.stringify(components));
961+ console.error("Code:");
962+ console.error(code);
963+ throw e;
964+ }
965+}
plugins/Dash/CardCreatorCache.qmlnew file+40
@@ -0,0 +1,40 @@
1+/*
2+ * Copyright (C) 2014 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+pragma Singleton
18+import QtQuick 2.4
19+import "CardCreator.js" as CardCreator
20+
21+QtObject {
22+ id: root
23+
24+ property var cache: new Object();
25+
26+ function getCardComponent(template, components, isCardTool, artShapeStyle) {
27+ if (template === undefined || components === undefined)
28+ return undefined;
29+
30+ var tString = JSON.stringify(template);
31+ var cString = JSON.stringify(components);
32+ var allString = tString + cString + isCardTool;
33+ var component = cache[allString];
34+ if (component === undefined) {
35+ component = CardCreator.createCardComponent(root, template, components, isCardTool, artShapeStyle, allString);
36+ cache[allString] = component;
37+ }
38+ return component;
39+ }
40+}
plugins/Dash/CardSocialActions.qmlnew file+94
@@ -0,0 +1,94 @@
1+/*
2+ * Copyright 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 QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.3
20+
21+Column {
22+ id: socialActions
23+ spacing: units.gu(0.5)
24+
25+ property alias model: repeater.model
26+ property color color: theme.palette.normal.baseText
27+
28+ signal clicked(var actionId)
29+
30+ Rectangle {
31+ id: divider
32+ visible: repeater.count > 0
33+ anchors {
34+ left: parent.left;
35+ right: parent.right;
36+ leftMargin:units.dp(1);
37+ rightMargin: units.dp(1);
38+ }
39+ color: Qt.darker(theme.palette.normal.background, 1.12)
40+ height: visible ? units.dp(1) : 0
41+ }
42+
43+ Row {
44+ id: row
45+ anchors {
46+ left: parent.left
47+ right: parent.right
48+ leftMargin: units.gu(1)
49+ rightMargin: units.gu(1)
50+ }
51+ spacing: units.gu(2)
52+ readonly property int visibleItems: {
53+ if (width <= units.gu(12)) // small card
54+ return 2;
55+ else if (width <= units.gu(21)) // medium card
56+ return 3;
57+ else // large or horizontal card
58+ return 4;
59+ }
60+
61+ Repeater {
62+ id: repeater
63+ delegate: Loader {
64+ height: units.gu(2)
65+ active: index < row.visibleItems
66+ sourceComponent: AbstractButton {
67+ objectName: "delegate" + index
68+ height: units.gu(2)
69+ width: icon.width
70+ Icon {
71+ id: icon
72+ objectName: "icon"
73+
74+ readonly property url urlIcon: modelData && modelData["icon"] || ""
75+ readonly property url urlTemporaryIcon: "temporaryIcon" in modelData && modelData["temporaryIcon"] || ""
76+
77+ height: units.gu(2)
78+ // FIXME Workaround for bug https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1421293
79+ width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth
80+ source: urlIcon
81+ color: socialActions.color
82+
83+ onUrlIconChanged: {
84+ if (urlIcon) source = urlIcon
85+ }
86+ }
87+
88+ onClicked: socialActions.clicked(modelData["id"]);
89+ onPressedChanged: if (pressed && icon.urlTemporaryIcon != "") icon.source = icon.urlTemporaryIcon
90+ }
91+ }
92+ }
93+ }
94+}
plugins/Dash/CroppedImageMinimumSourceSize.qmlnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright (C) 2014, 2015 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+
19+Image {
20+ id: root
21+
22+ fillMode: Image.PreserveAspectCrop
23+
24+ property bool useHeight: false
25+ function updateUseHeight()
26+ {
27+ // Do not turn into a binding since otherwise the qml
28+ // engine complains about binding loops
29+ useHeight = (implicitWidth / implicitHeight) > (width / height);
30+ }
31+
32+ onHeightChanged: updateUseHeight();
33+ onWidthChanged: updateUseHeight();
34+ onImplicitHeightChanged: updateUseHeight();
35+ onImplicitWidthChanged: updateUseHeight();
36+
37+ sourceSize: useHeight ? Qt.size(0, height) : Qt.size(width, 0)
38+}
plugins/Dash/Dash.qmltypesnew file+100
@@ -0,0 +1,100 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Dash 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "AbstractDashView"
12+ defaultProperty: "data"
13+ prototype: "QQuickItem"
14+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
15+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
16+ Property { name: "columnSpacing"; type: "double" }
17+ Property { name: "rowSpacing"; type: "double" }
18+ Property { name: "cacheBuffer"; type: "int" }
19+ Property { name: "displayMarginBeginning"; type: "double" }
20+ Property { name: "displayMarginEnd"; type: "double" }
21+ }
22+ Component {
23+ name: "HorizontalJournal"
24+ defaultProperty: "data"
25+ prototype: "AbstractDashView"
26+ exports: ["Dash/HorizontalJournal 0.1"]
27+ exportMetaObjectRevisions: [0]
28+ Property { name: "rowHeight"; type: "double" }
29+ }
30+ Component {
31+ name: "ListViewWithPageHeader"
32+ defaultProperty: "flickableData"
33+ prototype: "QQuickFlickable"
34+ exports: ["Dash/ListViewWithPageHeader 0.1"]
35+ exportMetaObjectRevisions: [0]
36+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
37+ Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
38+ Property { name: "pageHeader"; type: "QQuickItem"; isPointer: true }
39+ Property { name: "sectionDelegate"; type: "QQmlComponent"; isPointer: true }
40+ Property { name: "sectionProperty"; type: "string" }
41+ Property { name: "forceNoClip"; type: "bool" }
42+ Property { name: "stickyHeaderHeight"; type: "int"; isReadonly: true }
43+ Property { name: "headerItemShownHeight"; type: "double"; isReadonly: true }
44+ Property { name: "cacheBuffer"; type: "int" }
45+ Signal { name: "headerChanged" }
46+ Method { name: "positionAtBeginning" }
47+ Method { name: "showHeader" }
48+ Method { name: "firstCreatedIndex"; type: "int" }
49+ Method { name: "createdItemCount"; type: "int" }
50+ Method {
51+ name: "item"
52+ type: "QQuickItem*"
53+ Parameter { name: "modelIndex"; type: "int" }
54+ }
55+ Method {
56+ name: "maximizeVisibleArea"
57+ type: "bool"
58+ Parameter { name: "modelIndex"; type: "int" }
59+ }
60+ Method {
61+ name: "maximizeVisibleArea"
62+ type: "bool"
63+ Parameter { name: "modelIndex"; type: "int" }
64+ Parameter { name: "itemHeight"; type: "int" }
65+ }
66+ }
67+ Component {
68+ name: "OrganicGrid"
69+ defaultProperty: "data"
70+ prototype: "AbstractDashView"
71+ exports: ["Dash/OrganicGrid 0.1"]
72+ exportMetaObjectRevisions: [0]
73+ Property { name: "smallDelegateSize"; type: "QSizeF" }
74+ Property { name: "bigDelegateSize"; type: "QSizeF" }
75+ }
76+ Component {
77+ name: "VerticalJournal"
78+ defaultProperty: "data"
79+ prototype: "AbstractDashView"
80+ exports: ["Dash/VerticalJournal 0.1"]
81+ exportMetaObjectRevisions: [0]
82+ Property { name: "columnWidth"; type: "double" }
83+ }
84+ Component {
85+ prototype: "QObject"
86+ name: "CardCreatorCache"
87+ exports: ["CardCreatorCache -1.-1"]
88+ exportMetaObjectRevisions: [-1]
89+ isComposite: true
90+ isCreatable: false
91+ isSingleton: true
92+ Property { name: "cache"; type: "QVariant" }
93+ Method {
94+ name: "getCardComponent"
95+ type: "QVariant"
96+ Parameter { name: "template"; type: "QVariant" }
97+ Parameter { name: "components"; type: "QVariant" }
98+ }
99+ }
100+}
plugins/Dash/DashAudioPlayer.qmlnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2015 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+pragma Singleton
18+import QtQuick 2.4
19+import QtMultimedia 5.6
20+import Dash 0.1
21+
22+QtObject {
23+ readonly property real progress: audio.position / audio.duration
24+ readonly property bool playing: audio.playbackState === Audio.PlayingState
25+ readonly property bool paused: audio.playbackState === Audio.PausedState
26+ readonly property bool stopped: audio.playbackState === Audio.StoppedState
27+ readonly property alias position: audio.position
28+ readonly property url currentSource: audio.playlist.currentItemSource
29+
30+ function playSource(newSource, newPlaylist) {
31+ stop();
32+ audio.playlist.clear();
33+ if (newPlaylist) {
34+ // Look for newSource in newPlaylist
35+ var sourceIndex = -1;
36+ for (var i in newPlaylist) {
37+ if (AudioUrlComparer.compare(newSource, newPlaylist[i])) {
38+ sourceIndex = i;
39+ break;
40+ }
41+ }
42+ var urls = [];
43+ if (sourceIndex === -1 && newSource != "") {
44+ // If the playing song is not in the playlist, add it
45+ urls.push(newSource);
46+ sourceIndex = 0;
47+ }
48+ for (var i in newPlaylist) {
49+ urls.push(newPlaylist[i]);
50+ }
51+ audio.playlist.addItems(urls);
52+ audio.playlist.currentIndex = sourceIndex;
53+ } else {
54+ audio.playlist.addItem(newSource);
55+ audio.playlist.currentIndex = 0;
56+ }
57+ play();
58+ }
59+
60+ function stop() {
61+ audio.stop();
62+ }
63+
64+ function play() {
65+ audio.play();
66+ }
67+
68+ function pause() {
69+ audio.pause();
70+ }
71+
72+ property QtObject audio: Audio {
73+ id: audio
74+ objectName: "audio"
75+ playlist: Playlist {
76+ objectName: "playlist"
77+ }
78+
79+ onErrorStringChanged: console.warn("Dash Audio player error:", errorString)
80+ }
81+
82+ function lengthToString(s) {
83+ if (typeof(s) !== "number" || s < 0) return "";
84+
85+ var sec = "" + s % 60;
86+ if (sec.length == 1) sec = "0" + sec;
87+ var hour = Math.floor(s / 3600);
88+ if (hour < 1) {
89+ return Math.floor(s / 60) + ":" + sec;
90+ } else {
91+ var min = "" + Math.floor(s / 60) % 60;
92+ if (min.length == 1) min = "0" + min;
93+ return hour + ":" + min + ":" + sec;
94+ }
95+ }
96+}
plugins/Dash/ScopeStyle.qmlnew file+95
@@ -0,0 +1,95 @@
1+/*
2+ * Copyright 2014 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 Utils 0.1
19+import Ubuntu.Components 1.3
20+
21+/*! \brief Helper for processing scope customization options.
22+
23+ It will take the customizations object passed by the scope and
24+ process it to provide the scope UI with data such as colors or
25+ image paths.
26+ */
27+
28+QtObject {
29+ /// Style object passed from the scope
30+ property var style: Object()
31+
32+ /// Color used for text and symbolic icons
33+ readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
34+
35+ /// Luminance of the foreground color
36+ readonly property real foregroundLuminance: foreground ? Style.luminance(foreground) : Style.luminance(d.defaultDark)
37+
38+ /// Color used for the overall background
39+ readonly property color background: "background-color" in style ? style["background-color"] : "#00f5f5f5"
40+
41+ /// Luminance of the background color
42+ readonly property real backgroundLuminance: background ? Style.luminance(background) : Style.luminance(d.defaultLight)
43+
44+ /*! \brief Get the most contrasting available color based on luminance
45+ *
46+ * If background color is transparent, theme provided colors are taken into account
47+ */
48+ function getTextColor(luminance) {
49+ if (Math.abs(foregroundLuminance - luminance) >
50+ Math.abs(d.opaqueBackgroundLuminance - luminance)) {
51+ return foreground;
52+ } else {
53+ return d.opaqueBackground;
54+ }
55+ }
56+
57+ /// Source of the logo image for the header
58+ readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
59+
60+ /// Background style for the header
61+ readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : "color:///#ffffff"
62+
63+ /// Foreground color for the header
64+ readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
65+
66+ /// Color of the header divider
67+ readonly property color headerDividerColor: "divider-color" in d.headerStyle ? d.headerStyle["divider-color"] : "#e0e0e0"
68+
69+ /// Background style for the navigation
70+ readonly property url navigationBackground: "navigation-background" in d.headerStyle ? d.headerStyle["navigation-background"] : "color:///#f5f5f5"
71+
72+ /// Color of the primary preview button
73+ readonly property color previewButtonColor: "preview-button-color" in style ? style["preview-button-color"] : theme.palette.normal.positive
74+
75+ //! @cond
76+ property var d: QtObject {
77+ // FIXME: should be taken from the theme
78+ readonly property color defaultLight: "white"
79+ readonly property color defaultDark: UbuntuColors.darkGrey
80+ readonly property real defaultLightLuminance: Style.luminance(defaultLight)
81+ readonly property real defaultDarkLuminance: Style.luminance(defaultDark)
82+
83+ readonly property color opaqueBackground: {
84+ background.a > 0 ?
85+ background :
86+ (Math.abs(foregroundLuminance - defaultLightLuminance) >
87+ Math.abs(foregroundLuminance - defaultDarkLuminance)) ?
88+ defaultLight : defaultDark
89+ }
90+ readonly property real opaqueBackgroundLuminance: Style.luminance(opaqueBackground)
91+
92+ readonly property var headerStyle: "page-header" in style ? style["page-header"] : { }
93+ }
94+ //! @endcond
95+}
plugins/Dash/abstractdashview.cppnew file+346
@@ -0,0 +1,346 @@
1+/*
2+ * Copyright (C) 2013, 2014 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+#include "abstractdashview.h"
18+
19+AbstractDashView::AbstractDashView()
20+ : m_delegateModel(nullptr)
21+ , m_asyncRequestedIndex(-1)
22+ , m_columnSpacing(0)
23+ , m_rowSpacing(0)
24+ , m_buffer(320) // Same value used in qquickitemview.cpp in Qt 5.4
25+ , m_displayMarginBeginning(0)
26+ , m_displayMarginEnd(0)
27+ , m_needsRelayout(false)
28+ , m_delegateValidated(false)
29+ , m_implicitHeightDirty(false)
30+{
31+ connect(this, &AbstractDashView::widthChanged, this, &AbstractDashView::relayout);
32+ connect(this, &AbstractDashView::heightChanged, this, &AbstractDashView::onHeightChanged);
33+}
34+
35+QAbstractItemModel *AbstractDashView::model() const
36+{
37+ return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
38+}
39+
40+void AbstractDashView::setModel(QAbstractItemModel *model)
41+{
42+ if (model != this->model()) {
43+ if (!m_delegateModel) {
44+ createDelegateModel();
45+ } else {
46+ disconnect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &AbstractDashView::onModelUpdated);
47+ }
48+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
49+ connect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &AbstractDashView::onModelUpdated);
50+
51+ cleanupExistingItems();
52+
53+ Q_EMIT modelChanged();
54+ polish();
55+ }
56+}
57+
58+QQmlComponent *AbstractDashView::delegate() const
59+{
60+ return m_delegateModel ? m_delegateModel->delegate() : nullptr;
61+}
62+
63+void AbstractDashView::setDelegate(QQmlComponent *delegate)
64+{
65+ if (delegate != this->delegate()) {
66+ if (!m_delegateModel) {
67+ createDelegateModel();
68+ }
69+
70+ cleanupExistingItems();
71+
72+ m_delegateModel->setDelegate(delegate);
73+
74+ Q_EMIT delegateChanged();
75+ m_delegateValidated = false;
76+ polish();
77+ }
78+}
79+
80+qreal AbstractDashView::columnSpacing() const
81+{
82+ return m_columnSpacing;
83+}
84+
85+void AbstractDashView::setColumnSpacing(qreal columnSpacing)
86+{
87+ if (columnSpacing != m_columnSpacing) {
88+ m_columnSpacing = columnSpacing;
89+ Q_EMIT columnSpacingChanged();
90+
91+ if (isComponentComplete()) {
92+ relayout();
93+ }
94+ }
95+}
96+
97+qreal AbstractDashView::rowSpacing() const
98+{
99+ return m_rowSpacing;
100+}
101+
102+void AbstractDashView::setRowSpacing(qreal rowSpacing)
103+{
104+ if (rowSpacing != m_rowSpacing) {
105+ m_rowSpacing = rowSpacing;
106+ Q_EMIT rowSpacingChanged();
107+
108+ if (isComponentComplete()) {
109+ relayout();
110+ }
111+ }
112+}
113+
114+int AbstractDashView::cacheBuffer() const
115+{
116+ return m_buffer;
117+}
118+
119+void AbstractDashView::setCacheBuffer(int buffer)
120+{
121+ if (buffer < 0) {
122+ qmlInfo(this) << "Cannot set a negative cache buffer";
123+ return;
124+ }
125+
126+ if (m_buffer != buffer) {
127+ m_buffer = buffer;
128+ if (isComponentComplete()) {
129+ polish();
130+ }
131+ emit cacheBufferChanged();
132+ }
133+}
134+
135+qreal AbstractDashView::displayMarginBeginning() const
136+{
137+ return m_displayMarginBeginning;
138+}
139+
140+void AbstractDashView::setDisplayMarginBeginning(qreal begin)
141+{
142+ if (m_displayMarginBeginning == begin)
143+ return;
144+ m_displayMarginBeginning = begin;
145+ if (isComponentComplete()) {
146+ polish();
147+ }
148+ emit displayMarginBeginningChanged();
149+}
150+
151+qreal AbstractDashView::displayMarginEnd() const
152+{
153+ return m_displayMarginEnd;
154+}
155+
156+void AbstractDashView::setDisplayMarginEnd(qreal end)
157+{
158+ if (m_displayMarginEnd == end)
159+ return;
160+ m_displayMarginEnd = end;
161+ if (isComponentComplete()) {
162+ polish();
163+ }
164+ emit displayMarginEndChanged();
165+}
166+
167+void AbstractDashView::createDelegateModel()
168+{
169+ m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
170+ connect(m_delegateModel, &QQmlDelegateModel::createdItem, this, &AbstractDashView::itemCreated);
171+ if (isComponentComplete())
172+ m_delegateModel->componentComplete();
173+}
174+
175+void AbstractDashView::refill()
176+{
177+ if (!isComponentComplete() || height() < 0) {
178+ return;
179+ }
180+
181+ const qreal from = -m_displayMarginBeginning;
182+ const qreal to = height() + m_displayMarginEnd;
183+ const qreal bufferFrom = from - m_buffer;
184+ const qreal bufferTo = to + m_buffer;
185+
186+ bool added = addVisibleItems(from, to, false);
187+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
188+ added |= addVisibleItems(bufferFrom, bufferTo, true);
189+
190+ if (added || removed) {
191+ m_implicitHeightDirty = true;
192+ polish();
193+ }
194+}
195+
196+bool AbstractDashView::addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous)
197+{
198+ if (fillToY <= fillFromY)
199+ return false;
200+
201+ if (!delegate())
202+ return false;
203+
204+ if (m_delegateModel->count() == 0)
205+ return false;
206+
207+ int modelIndex;
208+ qreal yPos;
209+ findBottomModelIndexToAdd(&modelIndex, &yPos);
210+ bool changed = false;
211+ while (modelIndex < m_delegateModel->count() && yPos <= fillToY) {
212+ if (!createItem(modelIndex, asynchronous))
213+ break;
214+
215+ changed = true;
216+ findBottomModelIndexToAdd(&modelIndex, &yPos);
217+ }
218+
219+ findTopModelIndexToAdd(&modelIndex, &yPos);
220+ while (modelIndex >= 0 && yPos > fillFromY) {
221+ if (!createItem(modelIndex, asynchronous))
222+ break;
223+
224+ changed = true;
225+ findTopModelIndexToAdd(&modelIndex, &yPos);
226+ }
227+
228+ return changed;
229+}
230+
231+QQuickItem *AbstractDashView::createItem(int modelIndex, bool asynchronous)
232+{
233+ if (asynchronous && m_asyncRequestedIndex != -1)
234+ return nullptr;
235+
236+ m_asyncRequestedIndex = -1;
237+ QObject* object = m_delegateModel->object(modelIndex, asynchronous);
238+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
239+ if (!item) {
240+ if (object) {
241+ m_delegateModel->release(object);
242+ if (!m_delegateValidated) {
243+ m_delegateValidated = true;
244+ QObject* delegateObj = delegate();
245+ qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
246+ }
247+ } else {
248+ m_asyncRequestedIndex = modelIndex;
249+ }
250+ return nullptr;
251+ } else {
252+ addItemToView(modelIndex, item);
253+ return item;
254+ }
255+}
256+
257+void AbstractDashView::releaseItem(QQuickItem *item)
258+{
259+ QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
260+ if (flags & QQmlDelegateModel::Destroyed) {
261+ item->setParentItem(nullptr);
262+ }
263+}
264+
265+void AbstractDashView::setImplicitHeightDirty()
266+{
267+ m_implicitHeightDirty = true;
268+}
269+
270+void AbstractDashView::itemCreated(int modelIndex, QObject *object)
271+{
272+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
273+ if (!item) {
274+ qWarning() << "AbstractDashView::itemCreated got a non item for index" << modelIndex;
275+ return;
276+ }
277+ item->setParentItem(this);
278+
279+ // We only need to call createItem if we are here because of an asynchronous generation
280+ // otherwise we are in this slot because createItem is creating the item sync
281+ // and thus we don't need to call createItem again, nor need to set m_implicitHeightDirty
282+ // and call polish because the sync createItem was called from addVisibleItems that
283+ // is called from refill that will already do those if an item was added
284+ if (modelIndex == m_asyncRequestedIndex) {
285+ createItem(modelIndex, false);
286+ m_implicitHeightDirty = true;
287+ polish();
288+ }
289+}
290+
291+void AbstractDashView::onModelUpdated(const QQmlChangeSet &changeSet, bool reset)
292+{
293+ if (reset) {
294+ cleanupExistingItems();
295+ } else {
296+ processModelRemoves(changeSet.removes());
297+ }
298+ polish();
299+}
300+
301+
302+void AbstractDashView::relayout()
303+{
304+ m_needsRelayout = true;
305+ polish();
306+}
307+
308+void AbstractDashView::onHeightChanged()
309+{
310+ polish();
311+}
312+
313+void AbstractDashView::updatePolish()
314+{
315+ if (!model())
316+ return;
317+
318+ if (m_needsRelayout) {
319+ doRelayout();
320+ m_needsRelayout = false;
321+ m_implicitHeightDirty = true;
322+ }
323+
324+ refill();
325+
326+ const qreal from = -m_displayMarginBeginning;
327+ const qreal to = height() + m_displayMarginEnd;
328+ updateItemCulling(from, to);
329+
330+ if (m_implicitHeightDirty) {
331+ calculateImplicitHeight();
332+ m_implicitHeightDirty = false;
333+ }
334+}
335+
336+void AbstractDashView::componentComplete()
337+{
338+ if (m_delegateModel)
339+ m_delegateModel->componentComplete();
340+
341+ QQuickItem::componentComplete();
342+
343+ m_needsRelayout = true;
344+
345+ polish();
346+}
plugins/Dash/abstractdashview.hnew file+129
@@ -0,0 +1,129 @@
1+/*
2+ * Copyright (C) 2013, 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef ABSTRACTDASHVIEW_H
18+#define ABSTRACTDASHVIEW_H
19+
20+#include <QQuickItem>
21+
22+class QAbstractItemModel;
23+class QQmlComponent;
24+#pragma GCC diagnostic push
25+#pragma GCC diagnostic ignored "-pedantic"
26+#include <private/qqmldelegatemodel_p.h>
27+#include <qqmlinfo.h>
28+#pragma GCC diagnostic pop
29+
30+class AbstractDashView : public QQuickItem
31+{
32+ Q_OBJECT
33+
34+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
35+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
36+ Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
37+ Q_PROPERTY(qreal rowSpacing READ rowSpacing WRITE setRowSpacing NOTIFY rowSpacingChanged)
38+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
39+ Q_PROPERTY(qreal displayMarginBeginning READ displayMarginBeginning
40+ WRITE setDisplayMarginBeginning
41+ NOTIFY displayMarginBeginningChanged)
42+ Q_PROPERTY(qreal displayMarginEnd READ displayMarginEnd
43+ WRITE setDisplayMarginEnd
44+ NOTIFY displayMarginEndChanged)
45+
46+friend class VerticalJournalTest;
47+friend class HorizontalJournalTest;
48+friend class OrganicGridTest;
49+
50+public:
51+ AbstractDashView();
52+
53+ QAbstractItemModel *model() const;
54+ void setModel(QAbstractItemModel *model);
55+
56+ QQmlComponent *delegate() const;
57+ void setDelegate(QQmlComponent *delegate);
58+
59+ qreal columnSpacing() const;
60+ void setColumnSpacing(qreal columnSpacing);
61+
62+ qreal rowSpacing() const;
63+ void setRowSpacing(qreal rowSpacing);
64+
65+ int cacheBuffer() const;
66+ void setCacheBuffer(int);
67+
68+ qreal displayMarginBeginning() const;
69+ void setDisplayMarginBeginning(qreal);
70+
71+ qreal displayMarginEnd() const;
72+ void setDisplayMarginEnd(qreal);
73+
74+Q_SIGNALS:
75+ void modelChanged();
76+ void delegateChanged();
77+ void columnSpacingChanged();
78+ void rowSpacingChanged();
79+ void cacheBufferChanged();
80+ void displayMarginBeginningChanged();
81+ void displayMarginEndChanged();
82+
83+protected Q_SLOTS:
84+ void relayout();
85+
86+protected:
87+ void updatePolish() override;
88+ void componentComplete() override;
89+
90+ void releaseItem(QQuickItem *item);
91+ void setImplicitHeightDirty();
92+
93+private Q_SLOTS:
94+ void itemCreated(int modelIndex, QObject *object);
95+ void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
96+ void onHeightChanged();
97+
98+private:
99+ void createDelegateModel();
100+ void refill();
101+ bool addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous);
102+ QQuickItem *createItem(int modelIndex, bool asynchronous);
103+
104+ virtual void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) = 0;
105+ virtual void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) = 0;
106+ virtual void addItemToView(int modelIndex, QQuickItem *item) = 0;
107+ virtual bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) = 0;
108+ virtual void cleanupExistingItems() = 0;
109+ virtual void doRelayout() = 0;
110+ virtual void updateItemCulling(qreal visibleFromY, qreal visibleToY) = 0;
111+ virtual void calculateImplicitHeight() = 0;
112+ virtual void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) = 0;
113+
114+ QQmlDelegateModel *m_delegateModel;
115+
116+ // Index we are waiting because we requested it asynchronously
117+ int m_asyncRequestedIndex;
118+
119+ int m_columnSpacing;
120+ int m_rowSpacing;
121+ int m_buffer;
122+ qreal m_displayMarginBeginning;
123+ qreal m_displayMarginEnd;
124+ bool m_needsRelayout;
125+ bool m_delegateValidated;
126+ bool m_implicitHeightDirty;
127+};
128+
129+#endif
plugins/Dash/graphics/music_progress_bg.pngnew file
Binary file not shown.
plugins/Dash/horizontaljournal.cppnew file+242
@@ -0,0 +1,242 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+/*
18+ * The implementation is centered around m_visibleItems
19+ * that a list for each of the items in the view.
20+ * m_firstVisibleIndex is the index of the first item in m_visibleItems
21+ * m_lastInRowIndexPosition is a map that contains the x position
22+ * of items that are the last ones of a row so we can reconstruct the rows
23+ * when building back
24+ */
25+
26+#include "horizontaljournal.h"
27+
28+#include <qqmlengine.h>
29+#pragma GCC diagnostic push
30+#pragma GCC diagnostic ignored "-pedantic"
31+#include <private/qqmldelegatemodel_p.h>
32+#include <qqmlinfo.h>
33+#include <private/qquickitem_p.h>
34+#pragma GCC diagnostic pop
35+
36+HorizontalJournal::HorizontalJournal()
37+ : m_firstVisibleIndex(-1)
38+ , m_rowHeight(0)
39+{
40+}
41+
42+qreal HorizontalJournal::rowHeight() const
43+{
44+ return m_rowHeight;
45+}
46+
47+void HorizontalJournal::setRowHeight(qreal rowHeight)
48+{
49+ if (rowHeight != m_rowHeight) {
50+ m_rowHeight = rowHeight;
51+ Q_EMIT rowHeightChanged();
52+
53+ if (isComponentComplete()) {
54+ Q_FOREACH(QQuickItem *item, m_visibleItems) {
55+ item->setHeight(rowHeight);
56+ }
57+ relayout();
58+ }
59+ }
60+}
61+
62+void HorizontalJournal::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
63+{
64+ if (m_visibleItems.isEmpty()) {
65+ *modelIndex = 0;
66+ *yPos = 0;
67+ } else {
68+ *modelIndex = m_firstVisibleIndex + m_visibleItems.count();
69+ if (m_lastInRowIndexPosition.contains(*modelIndex - 1)) {
70+ *yPos = m_visibleItems.last()->y() + m_rowHeight + rowSpacing();
71+ } else {
72+ *yPos = m_visibleItems.last()->y();
73+ }
74+ }
75+}
76+
77+void HorizontalJournal::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
78+{
79+ if (m_visibleItems.isEmpty()) {
80+ *modelIndex = -1;
81+ *yPos = INT_MIN;
82+ } else {
83+ *modelIndex = m_firstVisibleIndex - 1;
84+ if (m_lastInRowIndexPosition.contains(*modelIndex)) {
85+ *yPos = m_visibleItems.first()->y() - rowSpacing() - m_rowHeight;
86+ } else {
87+ *yPos = m_visibleItems.first()->y();
88+ }
89+ }
90+}
91+
92+bool HorizontalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
93+{
94+ bool changed = false;
95+
96+ while (!m_visibleItems.isEmpty() && m_visibleItems.first()->y() + m_rowHeight < bufferFromY) {
97+ releaseItem(m_visibleItems.takeFirst());
98+ changed = true;
99+ m_firstVisibleIndex++;
100+ }
101+
102+ while (!m_visibleItems.isEmpty() && m_visibleItems.last()->y() > bufferToY) {
103+ releaseItem(m_visibleItems.takeLast());
104+ changed = true;
105+ m_lastInRowIndexPosition.remove(m_firstVisibleIndex + m_visibleItems.count());
106+ }
107+
108+ if (m_visibleItems.isEmpty()) {
109+ m_firstVisibleIndex = -1;
110+ }
111+
112+ return changed;
113+}
114+
115+void HorizontalJournal::addItemToView(int modelIndex, QQuickItem *item)
116+{
117+ if (item->height() != m_rowHeight) {
118+ qWarning() << "Item" << modelIndex << "height is not the one that the rowHeight mandates, resetting it";
119+ item->setHeight(m_rowHeight);
120+ }
121+
122+ if (m_visibleItems.isEmpty()) {
123+ Q_ASSERT(modelIndex == 0);
124+ item->setY(0);
125+ item->setX(0);
126+ m_visibleItems << item;
127+ m_firstVisibleIndex = 0;
128+ } else {
129+ // modelIndex has to be either m_firstVisibleIndex - 1 or m_firstVisibleIndex + m_visibleItems.count()
130+ if (modelIndex == m_firstVisibleIndex + m_visibleItems.count()) {
131+ QQuickItem *lastItem = m_visibleItems.last();
132+ if (lastItem->x() + lastItem->width() + columnSpacing() + item->width() <= width()) {
133+ // Fits in the row
134+ item->setY(lastItem->y());
135+ item->setX(lastItem->x() + lastItem->width() + columnSpacing());
136+ } else {
137+ // Starts a new row
138+ item->setY(lastItem->y() + m_rowHeight + rowSpacing());
139+ item->setX(0);
140+ m_lastInRowIndexPosition[modelIndex - 1] = lastItem->x();
141+ }
142+ m_visibleItems << item;
143+ } else if (modelIndex == m_firstVisibleIndex - 1) {
144+ QQuickItem *firstItem = m_visibleItems.first();
145+ if (m_lastInRowIndexPosition.contains(modelIndex)) {
146+ // It is the last item of its row, so start a new one since we're going back
147+ item->setY(firstItem->y() - rowSpacing() - m_rowHeight);
148+ item->setX(m_lastInRowIndexPosition[modelIndex]);
149+ } else {
150+ item->setY(firstItem->y());
151+ item->setX(firstItem->x() - columnSpacing() - item->width());
152+ }
153+ m_firstVisibleIndex = modelIndex;
154+ m_visibleItems.prepend(item);
155+ } else {
156+ qWarning() << "HorizontalJournal::addItemToView - Got unexpected modelIndex"
157+ << modelIndex << m_firstVisibleIndex << m_visibleItems.count();
158+ }
159+ }
160+}
161+
162+void HorizontalJournal::cleanupExistingItems()
163+{
164+ // Cleanup the existing items
165+ Q_FOREACH(QQuickItem *item, m_visibleItems)
166+ releaseItem(item);
167+ m_visibleItems.clear();
168+ m_lastInRowIndexPosition.clear();
169+ m_firstVisibleIndex = -1;
170+ setImplicitHeightDirty();
171+}
172+
173+void HorizontalJournal::calculateImplicitHeight()
174+{
175+ if (m_firstVisibleIndex >= 0) {
176+ const int nIndexes = m_firstVisibleIndex + m_visibleItems.count();
177+ const double bottomMostY = m_visibleItems.last()->y() + m_rowHeight;
178+ const double averageHeight = bottomMostY / nIndexes;
179+ setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - nIndexes));
180+ } else {
181+ setImplicitHeight(0);
182+ }
183+}
184+
185+void HorizontalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
186+{
187+ Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
188+ for (int i = remove.count - 1; i >= 0; --i) {
189+ const int indexToRemove = remove.index + i;
190+ // We only support removing from the end so
191+ // any of the last items of a column has to be indexToRemove
192+ const int lastIndex = m_firstVisibleIndex + m_visibleItems.count() - 1;
193+ if (indexToRemove == lastIndex) {
194+ releaseItem(m_visibleItems.takeLast());
195+ m_lastInRowIndexPosition.remove(indexToRemove);
196+ } else {
197+ if (indexToRemove < lastIndex) {
198+ qDebug() << "HorizontalJournal only supports removal from the end of the model, resetting instead";
199+ cleanupExistingItems();
200+ break;
201+ } else {
202+ setImplicitHeightDirty();
203+ }
204+ }
205+ }
206+ }
207+ if (m_visibleItems.isEmpty()) {
208+ m_firstVisibleIndex = -1;
209+ }
210+}
211+
212+
213+void HorizontalJournal::doRelayout()
214+{
215+ // If m_firstVisibleIndex is not 0 we need to drop all the delegates
216+ // since we can't consistently relayout without the first item being there
217+
218+ if (m_firstVisibleIndex == 0) {
219+ int i = 0;
220+ const QList<QQuickItem*> allItems = m_visibleItems;
221+ m_visibleItems.clear();
222+ m_lastInRowIndexPosition.clear();
223+ Q_FOREACH(QQuickItem *item, allItems) {
224+ addItemToView(i, item);
225+ ++i;
226+ }
227+ } else {
228+ Q_FOREACH(QQuickItem *item, m_visibleItems) {
229+ releaseItem(item);
230+ }
231+ m_visibleItems.clear();
232+ m_lastInRowIndexPosition.clear();
233+ m_firstVisibleIndex = -1;
234+ }
235+}
236+
237+void HorizontalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
238+{
239+ Q_FOREACH(QQuickItem *item, m_visibleItems) {
240+ QQuickItemPrivate::get(item)->setCulled(item->y() + m_rowHeight <= visibleFromY || item->y() >= visibleToY);
241+ }
242+}
plugins/Dash/horizontaljournal.hnew file+63
@@ -0,0 +1,63 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef HORIZONTALJOURNAL_H
18+#define HORIZONTALJOURNAL_H
19+
20+#include "abstractdashview.h"
21+
22+ /** A horizontal journal is a view that creates delegates
23+ * based on a model and layouts them one after the other
24+ * in the same row until there is no more free space for the next item
25+ * and so that item is layouted in the next row
26+ *
27+ * All delegates are forced to rowHeight if they don't have it.
28+ */
29+ class HorizontalJournal : public AbstractDashView
30+{
31+ Q_OBJECT
32+
33+ Q_PROPERTY(qreal rowHeight READ rowHeight WRITE setRowHeight NOTIFY rowHeightChanged)
34+
35+friend class HorizontalJournalTest;
36+
37+public:
38+ HorizontalJournal();
39+
40+ qreal rowHeight() const;
41+ void setRowHeight(qreal rowHeight);
42+
43+Q_SIGNALS:
44+ void rowHeightChanged();
45+
46+private:
47+ void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
48+ void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
49+ bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
50+ void addItemToView(int modelIndex, QQuickItem *item) override;
51+ void cleanupExistingItems() override;
52+ void calculateImplicitHeight() override;
53+ void doRelayout() override;
54+ void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
55+ void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
56+
57+ int m_firstVisibleIndex;
58+ QList<QQuickItem*> m_visibleItems;
59+ QMap<int, double> m_lastInRowIndexPosition;
60+ int m_rowHeight;
61+};
62+
63+#endif
plugins/Dash/listviewwithpageheader.cppnew file+1395
@@ -0,0 +1,1395 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+/*
18+ * Some documentation on how this thing works:
19+ *
20+ * A flickable has two very important concepts that define the top and
21+ * height of the flickable area.
22+ * The top is returned in minYExtent()
23+ * The height is set using setContentHeight()
24+ * By changing those two values we can make the list grow up or down
25+ * as needed. e.g. if we are in the middle of the list
26+ * and something that is above the viewport grows, since we do not
27+ * want to change the viewport because of that we just adjust the
28+ * minYExtent so that the list grows up.
29+ *
30+ * The implementation on the list relies on the delegateModel doing
31+ * most of the instantiation work. You call createItem() when you
32+ * need to create an item asking for it async or not. If returns null
33+ * it means the item will be created async and the model will call the
34+ * itemCreated slot with the item.
35+ *
36+ * updatePolish is the central point of dispatch for the work of the
37+ * class. It is called by the scene graph just before drawing the class.
38+ * In it we:
39+ * * Make sure all items are positioned correctly
40+ * * Add/Remove items if needed
41+ * * Update the content height if it was dirty
42+ *
43+ * m_visibleItems contains all the items we have created at the moment.
44+ * Actually not all of them are visible since it includes the ones
45+ * in the cache area we create asynchronously to help performance.
46+ * The first item in m_visibleItems has the m_firstVisibleIndex in
47+ * the model. If you actually want to know what is the first
48+ * item in the viewport you have to find the first non culled element
49+ * in m_visibleItems
50+ *
51+ * All the items (except the header) are childs of m_clipItem which
52+ * is a child of the contentItem() of the flickable (The contentItem()
53+ * is what actually 'moves' in a a flickable). This way
54+ * we can implement the clipping needed so we can have the header
55+ * shown in the middle of the list over the items without the items
56+ * leaking under the header in case it is transparent.
57+ *
58+ * The first item of m_visibleItems is the one that defines the
59+ * positions of all the rest of items (see updatePolish()) and
60+ * this is why sometimes we move it even if it's not the item
61+ * that has triggered the function (i.e. in itemGeometryChanged())
62+ *
63+ * m_visibleItems is a list of ListItem. Each ListItem
64+ * will contain a item and potentially a sectionItem. The sectionItem
65+ * is only there when the list is using sectionDelegate+sectionProperty
66+ * and this is the first item of the section. Each ListItem is vertically
67+ * layouted with the sectionItem first and then the item.
68+ *
69+ * For sectioning we also have a section item alone (m_topSectionItem)
70+ * that is used for the cases we need to show the sticky section item at
71+ * the top of the view.
72+ *
73+ * Each delegate item has a context property called heightToClip that is
74+ * used to communicate to the delegate implementation in case it has to
75+ * clip itself because of overlapping with the top sticky section item.
76+ * This is an implementation decision since it has been agreed it
77+ * is easier to implement the clipping in QML with this info than to
78+ * do it at the C++ level.
79+ *
80+ * Note that minYExtent and height are not always totally accurate, since
81+ * we don't have the items created we can't guess their heights
82+ * so we can only guarantee the values are correct when the first/last
83+ * items of the list are visible, otherwise we just live with good enough
84+ * values that make the list scrollable
85+ *
86+ * There are a few things that are not really implemented or tested properly
87+ * which we don't use at the moment like changing the model, changing
88+ * the section delegate, having a section delegate that changes its size, etc.
89+ * The known missing features are marked with TODOs along the code.
90+ */
91+
92+#include "listviewwithpageheader.h"
93+
94+#include <QCoreApplication>
95+#include <QDebug>
96+#include <qqmlinfo.h>
97+#include <qqmlengine.h>
98+#pragma GCC diagnostic push
99+#pragma GCC diagnostic ignored "-pedantic"
100+#include <private/qqmlcontext_p.h>
101+#include <private/qqmldelegatemodel_p.h>
102+#include <private/qqmlglobal_p.h>
103+#include <private/qquickitem_p.h>
104+#include <private/qquickanimation_p.h>
105+#pragma GCC diagnostic pop
106+// #include <private/qquickrectangle_p.h>
107+
108+qreal ListViewWithPageHeader::ListItem::height() const
109+{
110+ return m_item->height() + (m_sectionItem ? m_sectionItem->height() : 0);
111+}
112+
113+qreal ListViewWithPageHeader::ListItem::y() const
114+{
115+ return m_item->y() - (m_sectionItem ? m_sectionItem->height() : 0);
116+}
117+
118+void ListViewWithPageHeader::ListItem::setY(qreal newY)
119+{
120+ if (m_sectionItem) {
121+ m_sectionItem->setY(newY);
122+ m_item->setY(newY + m_sectionItem->height());
123+ } else {
124+ m_item->setY(newY);
125+ }
126+}
127+
128+bool ListViewWithPageHeader::ListItem::culled() const
129+{
130+ return QQuickItemPrivate::get(m_item)->culled;
131+}
132+
133+void ListViewWithPageHeader::ListItem::setCulled(bool culled)
134+{
135+ QQuickItemPrivate::get(m_item)->setCulled(culled);
136+ if (m_sectionItem)
137+ QQuickItemPrivate::get(m_sectionItem)->setCulled(culled);
138+}
139+
140+void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
141+{
142+ m_sectionItem = sectionItem;
143+}
144+
145+ListViewWithPageHeader::ListViewWithPageHeader()
146+ : m_delegateModel(nullptr)
147+ , m_asyncRequestedIndex(-1)
148+ , m_delegateValidated(false)
149+ , m_firstVisibleIndex(-1)
150+ , m_minYExtent(0)
151+ , m_contentHeightDirty(false)
152+ , m_headerItem(nullptr)
153+ , m_previousContentY(0)
154+ , m_headerItemShownHeight(0)
155+ , m_sectionDelegate(nullptr)
156+ , m_topSectionItem(nullptr)
157+ , m_forceNoClip(false)
158+ , m_inLayout(false)
159+ , m_inContentHeightKeepHeaderShown(false)
160+ , m_cacheBuffer(0)
161+{
162+ m_clipItem = new QQuickItem(contentItem());
163+// m_clipItem = new QQuickRectangle(contentItem());
164+// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
165+
166+ m_contentYAnimation = new QQuickNumberAnimation(this);
167+ m_contentYAnimation->setEasing(QEasingCurve::OutQuad);
168+ m_contentYAnimation->setProperty(QStringLiteral("contentY"));
169+ m_contentYAnimation->setDuration(200);
170+ m_contentYAnimation->setTargetObject(this);
171+
172+ connect(this, &ListViewWithPageHeader::contentWidthChanged, this, &ListViewWithPageHeader::onContentWidthChanged);
173+ connect(this, &ListViewWithPageHeader::contentHeightChanged, this, &ListViewWithPageHeader::onContentHeightChanged);
174+ connect(this, &ListViewWithPageHeader::heightChanged, this, &ListViewWithPageHeader::onHeightChanged);
175+ connect(m_contentYAnimation, &QQuickNumberAnimation::runningChanged, this, &ListViewWithPageHeader::contentYAnimationRunningChanged);
176+
177+ setFlickableDirection(VerticalFlick);
178+}
179+
180+ListViewWithPageHeader::~ListViewWithPageHeader()
181+{
182+}
183+
184+QAbstractItemModel *ListViewWithPageHeader::model() const
185+{
186+ return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
187+}
188+
189+void ListViewWithPageHeader::setModel(QAbstractItemModel *model)
190+{
191+ if (model != this->model()) {
192+ if (!m_delegateModel) {
193+ createDelegateModel();
194+ } else {
195+ disconnect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &ListViewWithPageHeader::onModelUpdated);
196+ }
197+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
198+ connect(m_delegateModel, &QQmlDelegateModel::modelUpdated, this, &ListViewWithPageHeader::onModelUpdated);
199+ Q_EMIT modelChanged();
200+ polish();
201+ // TODO?
202+// Q_EMIT contentHeightChanged();
203+// Q_EMIT contentYChanged();
204+ }
205+}
206+
207+QQmlComponent *ListViewWithPageHeader::delegate() const
208+{
209+ return m_delegateModel ? m_delegateModel->delegate() : nullptr;
210+}
211+
212+void ListViewWithPageHeader::setDelegate(QQmlComponent *delegate)
213+{
214+ if (delegate != this->delegate()) {
215+ if (!m_delegateModel) {
216+ createDelegateModel();
217+ }
218+
219+ // Cleanup the existing items
220+ Q_FOREACH(ListItem *item, m_visibleItems)
221+ releaseItem(item);
222+ m_visibleItems.clear();
223+ initializeValuesForEmptyList();
224+
225+ m_delegateModel->setDelegate(delegate);
226+
227+ Q_EMIT delegateChanged();
228+ m_delegateValidated = false;
229+ m_contentHeightDirty = true;
230+ polish();
231+ }
232+}
233+
234+void ListViewWithPageHeader::initializeValuesForEmptyList()
235+{
236+ m_firstVisibleIndex = -1;
237+ adjustMinYExtent();
238+ setContentY(0);
239+ m_clipItem->setY(0);
240+ if (m_topSectionItem) {
241+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
242+ }
243+}
244+
245+QQuickItem *ListViewWithPageHeader::header() const
246+{
247+ return m_headerItem;
248+}
249+
250+void ListViewWithPageHeader::setHeader(QQuickItem *headerItem)
251+{
252+ if (m_headerItem != headerItem) {
253+ qreal oldHeaderHeight = 0;
254+ qreal oldHeaderY = 0;
255+ if (m_headerItem) {
256+ oldHeaderHeight = m_headerItem->height();
257+ oldHeaderY = m_headerItem->y();
258+ m_headerItem->setParentItem(nullptr);
259+ }
260+ m_headerItem = headerItem;
261+ if (m_headerItem) {
262+ m_headerItem->setParentItem(contentItem());
263+ m_headerItem->setZ(1);
264+ m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
265+ QQuickItemPrivate::get(m_headerItem)->addItemChangeListener(this, QQuickItemPrivate::ImplicitHeight);
266+ }
267+ qreal newHeaderHeight = m_headerItem ? m_headerItem->height() : 0;
268+ if (!m_visibleItems.isEmpty() && newHeaderHeight != oldHeaderHeight) {
269+ headerHeightChanged(newHeaderHeight, oldHeaderHeight, oldHeaderY);
270+ polish();
271+ m_contentHeightDirty = true;
272+ }
273+ Q_EMIT headerChanged();
274+ }
275+}
276+
277+QQmlComponent *ListViewWithPageHeader::sectionDelegate() const
278+{
279+ return m_sectionDelegate;
280+}
281+
282+void ListViewWithPageHeader::setSectionDelegate(QQmlComponent *delegate)
283+{
284+ if (delegate != m_sectionDelegate) {
285+ // TODO clean existing sections
286+
287+ m_sectionDelegate = delegate;
288+
289+ m_topSectionItem = getSectionItem(QString(), false /*watchGeometry*/);
290+ m_topSectionItem->setZ(3);
291+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
292+ connect(m_topSectionItem, &QQuickItem::heightChanged, this, &ListViewWithPageHeader::stickyHeaderHeightChanged);
293+
294+ // TODO create sections for existing items
295+
296+ Q_EMIT sectionDelegateChanged();
297+ Q_EMIT stickyHeaderHeightChanged();
298+ }
299+}
300+
301+QString ListViewWithPageHeader::sectionProperty() const
302+{
303+ return m_sectionProperty;
304+}
305+
306+void ListViewWithPageHeader::setSectionProperty(const QString &property)
307+{
308+ if (property != m_sectionProperty) {
309+ m_sectionProperty = property;
310+
311+ updateWatchedRoles();
312+
313+ // TODO recreate sections
314+
315+ Q_EMIT sectionPropertyChanged();
316+ }
317+}
318+
319+bool ListViewWithPageHeader::forceNoClip() const
320+{
321+ return m_forceNoClip;
322+}
323+
324+void ListViewWithPageHeader::setForceNoClip(bool noClip)
325+{
326+ if (noClip != m_forceNoClip) {
327+ m_forceNoClip = noClip;
328+ updateClipItem();
329+ Q_EMIT forceNoClipChanged();
330+ }
331+}
332+
333+int ListViewWithPageHeader::stickyHeaderHeight() const
334+{
335+ return m_topSectionItem ? m_topSectionItem->height() : 0;
336+}
337+
338+qreal ListViewWithPageHeader::headerItemShownHeight() const
339+{
340+ return m_headerItemShownHeight;
341+}
342+
343+int ListViewWithPageHeader::cacheBuffer() const
344+{
345+ return m_cacheBuffer;
346+}
347+
348+void ListViewWithPageHeader::setCacheBuffer(int cacheBuffer)
349+{
350+ if (cacheBuffer < 0) {
351+ qmlInfo(this) << "Cannot set a negative cache buffer";
352+ return;
353+ }
354+
355+ if (cacheBuffer != m_cacheBuffer) {
356+ m_cacheBuffer = cacheBuffer;
357+ Q_EMIT cacheBufferChanged();
358+ polish();
359+ }
360+}
361+
362+void ListViewWithPageHeader::positionAtBeginning()
363+{
364+ if (m_delegateModel->count() <= 0)
365+ return;
366+
367+ qreal headerHeight = (m_headerItem ? m_headerItem->height() : 0);
368+ if (m_firstVisibleIndex != 0) {
369+ // TODO This could be optimized by trying to reuse the interesection
370+ // of items that may end up intersecting between the existing
371+ // m_visibleItems and the items we are creating in the next loop
372+ Q_FOREACH(ListItem *item, m_visibleItems)
373+ releaseItem(item);
374+ m_visibleItems.clear();
375+ m_firstVisibleIndex = -1;
376+
377+ // Create the item 0, it will be already correctly positioned at createItem()
378+ m_clipItem->setY(0);
379+ ListItem *item = createItem(0, false);
380+ // Create the subsequent items
381+ int modelIndex = 1;
382+ qreal pos = item->y() + item->height();
383+ const qreal bufferTo = height() + m_cacheBuffer;
384+ while (modelIndex < m_delegateModel->count() && pos <= bufferTo) {
385+ if (!(item = createItem(modelIndex, false)))
386+ break;
387+ pos += item->height();
388+ ++modelIndex;
389+ }
390+
391+ m_previousContentY = m_visibleItems.first()->y() - headerHeight;
392+ }
393+ setContentY(m_visibleItems.first()->y() + m_clipItem->y() - headerHeight);
394+ if (m_headerItem) {
395+ // TODO This should not be needed and the code that adjust the m_headerItem position
396+ // in viewportMoved() should be enough but in some cases we have not found a way to reproduce
397+ // yet the code of viewportMoved() fails so here we make sure that at least if we are calling
398+ // positionAtBeginning the header item will be correctly positioned
399+ m_headerItem->setY(-m_minYExtent);
400+ }
401+}
402+
403+static inline bool uFuzzyCompare(qreal r1, qreal r2)
404+{
405+ return qFuzzyCompare(r1, r2) || (qFuzzyIsNull(r1) && qFuzzyIsNull(r2));
406+}
407+
408+void ListViewWithPageHeader::showHeader()
409+{
410+ if (!m_headerItem)
411+ return;
412+
413+ const auto to = qMax(-minYExtent(), contentY() - m_headerItem->height() + m_headerItemShownHeight);
414+ if (!uFuzzyCompare(to, contentY())) {
415+ const bool headerShownByItsOwn = contentY() < m_headerItem->y() + m_headerItem->height();
416+ if (headerShownByItsOwn && m_headerItemShownHeight == 0) {
417+ // We are not clipping since we are just at the top of the viewport
418+ // but because of the showHeader animation we will need to, so
419+ // enable the clipping without logically moving the items
420+ m_headerItemShownHeight = m_headerItem->y() + m_headerItem->height() - contentY();
421+ if (!m_visibleItems.isEmpty()) {
422+ updateClipItem();
423+ ListItem *firstItem = m_visibleItems.first();
424+ firstItem->setY(firstItem->y() - m_headerItemShownHeight);
425+ layout();
426+ }
427+ Q_EMIT headerItemShownHeightChanged();
428+ }
429+ m_contentYAnimation->setTo(to);
430+ contentYAnimationType = ContentYAnimationShowHeader;
431+ m_contentYAnimation->start();
432+ }
433+}
434+
435+int ListViewWithPageHeader::firstCreatedIndex() const
436+{
437+ return m_firstVisibleIndex;
438+}
439+
440+int ListViewWithPageHeader::createdItemCount() const
441+{
442+ return m_visibleItems.count();
443+}
444+
445+QQuickItem *ListViewWithPageHeader::item(int modelIndex) const
446+{
447+ ListItem *item = itemAtIndex(modelIndex);
448+ if (item)
449+ return item->m_item;
450+ else
451+ return nullptr;
452+}
453+
454+bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex)
455+{
456+ ListItem *listItem = itemAtIndex(modelIndex);
457+ if (listItem) {
458+ return maximizeVisibleArea(listItem, listItem->height());
459+ }
460+
461+ return false;
462+}
463+
464+bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex, int itemHeight)
465+{
466+ if (itemHeight < 0)
467+ return false;
468+
469+ ListItem *listItem = itemAtIndex(modelIndex);
470+ if (listItem) {
471+ return maximizeVisibleArea(listItem, itemHeight + (listItem->sectionItem() ? listItem->sectionItem()->height() : 0));
472+ }
473+
474+ return false;
475+}
476+
477+bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listItemHeight)
478+{
479+ if (listItem) {
480+ layout();
481+ const auto listItemY = m_clipItem->y() + listItem->y();
482+ if (listItemY > contentY() && listItemY + listItemHeight > contentY() + height()) {
483+ // we can scroll the list up to show more stuff
484+ const auto to = qMin(listItemY, listItemY + listItemHeight - height());
485+ m_contentYAnimation->setTo(to);
486+ contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
487+ m_contentYAnimation->start();
488+ } else if ((listItemY < contentY() && listItemY + listItemHeight < contentY() + height()) ||
489+ (m_topSectionItem && !listItem->sectionItem() && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
490+ {
491+ // we can scroll the list down to show more stuff
492+ auto realVisibleListItemY = listItemY;
493+ if (m_topSectionItem) {
494+ // If we are showing the top section sticky item and this item doesn't have a section
495+ // item we have to make sure to scroll it a bit more so that it is not underlapping
496+ // the top section sticky item
497+ bool topSectionShown = !QQuickItemPrivate::get(m_topSectionItem)->culled;
498+ if (topSectionShown && !listItem->sectionItem()) {
499+ realVisibleListItemY -= m_topSectionItem->height();
500+ }
501+ }
502+ const auto to = qMax(realVisibleListItemY, listItemY + listItemHeight - height());
503+ m_contentYAnimation->setTo(to);
504+ contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
505+ m_contentYAnimation->start();
506+ }
507+ return true;
508+ }
509+ return false;
510+}
511+
512+qreal ListViewWithPageHeader::minYExtent() const
513+{
514+// qDebug() << "ListViewWithPageHeader::minYExtent" << m_minYExtent;
515+ return m_minYExtent;
516+}
517+
518+qreal ListViewWithPageHeader::maxYExtent() const
519+{
520+ return height() - contentHeight();
521+}
522+
523+void ListViewWithPageHeader::componentComplete()
524+{
525+ if (m_delegateModel)
526+ m_delegateModel->componentComplete();
527+
528+ QQuickFlickable::componentComplete();
529+
530+ polish();
531+}
532+
533+void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
534+{
535+ // Check we are not being taken down and don't paint anything
536+ // TODO Check if we still need this in 5.2
537+ // For reproduction just inifnite loop testDash or testDashContent
538+ if (!QQmlEngine::contextForObject(this)->parentContext())
539+ return;
540+
541+ QQuickFlickable::viewportMoved(orient);
542+// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
543+ const qreal diff = m_previousContentY - contentY();
544+ adjustHeader(diff);
545+ m_previousContentY = contentY();
546+ layout();
547+ polish();
548+}
549+
550+void ListViewWithPageHeader::adjustHeader(qreal diff)
551+{
552+ const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
553+ if (m_headerItem) {
554+ const auto oldHeaderItemShownHeight = m_headerItemShownHeight;
555+ if (uFuzzyCompare(contentY(), -m_minYExtent) || contentY() > -m_minYExtent) {
556+ m_headerItem->setHeight(m_headerItem->implicitHeight());
557+ // We are going down (but it's not because of the rebound at the end)
558+ // (but the header was not shown by it's own position)
559+ // or the header is partially shown and we are not doing a maximizeVisibleArea either
560+ const bool scrolledUp = m_previousContentY > contentY();
561+ const bool notRebounding = qRound(contentY() + height()) < qRound(contentHeight());
562+ const bool notShownByItsOwn = contentY() + diff >= m_headerItem->y() + m_headerItem->height();
563+ const bool maximizeVisibleAreaRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationMaximizeVisibleArea;
564+
565+ if (!scrolledUp && (contentY() == -m_minYExtent || (m_headerItemShownHeight == 0 && m_previousContentY == m_headerItem->y()))) {
566+ m_headerItemShownHeight = 0;
567+ m_headerItem->setY(-m_minYExtent);
568+ } else if ((scrolledUp && notRebounding && notShownByItsOwn && !maximizeVisibleAreaRunning) || (m_headerItemShownHeight > 0) || m_inContentHeightKeepHeaderShown) {
569+ if (maximizeVisibleAreaRunning && diff > 0) {
570+ // If we are maximizing and the header was shown, make sure we hide it
571+ m_headerItemShownHeight -= diff;
572+ } else {
573+ m_headerItemShownHeight += diff;
574+ }
575+ if (uFuzzyCompare(contentY(), -m_minYExtent)) {
576+ m_headerItemShownHeight = 0;
577+ } else {
578+ m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, m_headerItem->height());
579+ }
580+ if (m_headerItemShownHeight > 0) {
581+ if (uFuzzyCompare(m_headerItem->height(), m_headerItemShownHeight)) {
582+ m_headerItem->setY(contentY());
583+ m_headerItemShownHeight = m_headerItem->height();
584+ } else {
585+ m_headerItem->setY(contentY() - m_headerItem->height() + m_headerItemShownHeight);
586+ }
587+ } else {
588+ m_headerItem->setY(-m_minYExtent);
589+ }
590+ }
591+ Q_EMIT headerItemShownHeightChanged();
592+ } else {
593+ // Stick the header item to the top when dragging down
594+ m_headerItem->setY(contentY());
595+ m_headerItem->setHeight(m_headerItem->implicitHeight() + (-m_minYExtent - contentY()));
596+ }
597+ // We will be changing the clip item, need to accomadate for it
598+ // otherwise we move the firstItem down/up twice (unless the
599+ // show header animation is running, where we want to keep the viewport stable)
600+ if (!showHeaderAnimationRunning) {
601+ diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
602+ } else {
603+ diff = -diff;
604+ }
605+ }
606+ if (!m_visibleItems.isEmpty()) {
607+ updateClipItem();
608+ ListItem *firstItem = m_visibleItems.first();
609+ firstItem->setY(firstItem->y() + diff);
610+ if (showHeaderAnimationRunning) {
611+ adjustMinYExtent();
612+ }
613+ }
614+}
615+
616+void ListViewWithPageHeader::createDelegateModel()
617+{
618+ m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
619+ connect(m_delegateModel, &QQmlDelegateModel::createdItem, this, &ListViewWithPageHeader::itemCreated);
620+ if (isComponentComplete())
621+ m_delegateModel->componentComplete();
622+ updateWatchedRoles();
623+}
624+
625+void ListViewWithPageHeader::refill()
626+{
627+ if (m_inLayout) {
628+ return;
629+ }
630+ if (!isComponentComplete()) {
631+ return;
632+ }
633+
634+ const qreal from = contentY();
635+ const qreal to = from + height();
636+ const qreal bufferFrom = from - m_cacheBuffer;
637+ const qreal bufferTo = to + m_cacheBuffer;
638+
639+ bool added = addVisibleItems(from, to, false);
640+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
641+ added |= addVisibleItems(bufferFrom, bufferTo, true);
642+
643+ if (added || removed) {
644+ m_contentHeightDirty = true;
645+ }
646+}
647+
648+bool ListViewWithPageHeader::addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous)
649+{
650+ if (!delegate())
651+ return false;
652+
653+ if (m_delegateModel->count() == 0)
654+ return false;
655+
656+ ListItem *item;
657+// qDebug() << "ListViewWithPageHeader::addVisibleItems" << fillFrom << fillTo << asynchronous;
658+
659+ int modelIndex = 0;
660+ qreal pos = 0;
661+ if (!m_visibleItems.isEmpty()) {
662+ modelIndex = m_firstVisibleIndex + m_visibleItems.count();
663+ item = m_visibleItems.last();
664+ pos = item->y() + item->height() + m_clipItem->y();
665+ }
666+ bool changed = false;
667+// qDebug() << (modelIndex < m_delegateModel->count()) << pos << fillTo;
668+ while (modelIndex < m_delegateModel->count() && pos <= fillTo) {
669+// qDebug() << "refill: append item" << modelIndex << "pos" << pos << "asynchronous" << asynchronous;
670+ if (!(item = createItem(modelIndex, asynchronous)))
671+ break;
672+ pos += item->height();
673+ ++modelIndex;
674+ changed = true;
675+ }
676+
677+ modelIndex = 0;
678+ pos = 0;
679+ if (!m_visibleItems.isEmpty()) {
680+ modelIndex = m_firstVisibleIndex - 1;
681+ item = m_visibleItems.first();
682+ pos = item->y() + m_clipItem->y();
683+ }
684+ while (modelIndex >= 0 && pos > fillFrom) {
685+// qDebug() << "refill: prepend item" << modelIndex << "pos" << pos << "fillFrom" << fillFrom << "asynchronous" << asynchronous;
686+ if (!(item = createItem(modelIndex, asynchronous)))
687+ break;
688+ pos -= item->height();
689+ --modelIndex;
690+ changed = true;
691+ }
692+
693+ return changed;
694+}
695+
696+void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
697+{
698+ QQuickItem *item = listItem->m_item;
699+ QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
700+ if (flags & QQmlDelegateModel::Destroyed) {
701+ item->setParentItem(nullptr);
702+ }
703+ listItem->sectionItem()->deleteLater();
704+ delete listItem;
705+}
706+
707+void ListViewWithPageHeader::releaseItem(ListItem *listItem)
708+{
709+ QQuickItemPrivate::get(listItem->m_item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
710+ if (listItem->sectionItem()) {
711+ QQuickItemPrivate::get(listItem->sectionItem())->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
712+ }
713+ m_itemsToRelease << listItem;
714+}
715+
716+void ListViewWithPageHeader::updateWatchedRoles()
717+{
718+ if (m_delegateModel) {
719+ QList<QByteArray> roles;
720+ if (!m_sectionProperty.isEmpty())
721+ roles << m_sectionProperty.toUtf8();
722+ m_delegateModel->setWatchedRoles(roles);
723+ }
724+}
725+
726+QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyInserted)
727+{
728+ if (!m_sectionDelegate)
729+ return nullptr;
730+
731+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
732+
733+ if (modelIndex > 0) {
734+ const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
735+ if (section == prevSection)
736+ return nullptr;
737+ }
738+ if (modelIndex + 1 < model()->rowCount() && !alreadyInserted) {
739+ // Already inserted items can't steal next section header
740+ const QString nextSection = m_delegateModel->stringValue(modelIndex + 1, m_sectionProperty);
741+ if (section == nextSection) {
742+ // Steal the section header
743+ ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
744+ if (nextItem) {
745+ QQuickItem *sectionItem = nextItem->sectionItem();
746+ nextItem->setSectionItem(nullptr);
747+ return sectionItem;
748+ }
749+ }
750+ }
751+
752+ return getSectionItem(section);
753+}
754+
755+QQuickItem *ListViewWithPageHeader::getSectionItem(const QString §ionText, bool watchGeometry)
756+{
757+ QQuickItem *sectionItem = nullptr;
758+
759+ QQmlContext *creationContext = m_sectionDelegate->creationContext();
760+ QQmlContext *context = new QQmlContext(creationContext ? creationContext : qmlContext(this));
761+ QObject *nobj = m_sectionDelegate->beginCreate(context);
762+ if (nobj) {
763+ QQml_setParent_noEvent(context, nobj);
764+ sectionItem = qobject_cast<QQuickItem *>(nobj);
765+ if (!sectionItem) {
766+ delete nobj;
767+ } else {
768+ sectionItem->setProperty("text", sectionText);
769+ sectionItem->setProperty("delegateIndex", -1);
770+ sectionItem->setZ(2);
771+ QQml_setParent_noEvent(sectionItem, m_clipItem);
772+ sectionItem->setParentItem(m_clipItem);
773+ }
774+ } else {
775+ delete context;
776+ }
777+ m_sectionDelegate->completeCreate();
778+
779+ if (watchGeometry) {
780+ QQuickItemPrivate::get(sectionItem)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
781+ }
782+
783+ return sectionItem;
784+}
785+
786+void ListViewWithPageHeader::updateSectionItem(int modelIndex)
787+{
788+ ListItem *item = itemAtIndex(modelIndex);
789+ if (item) {
790+ const QString sectionText = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
791+
792+ bool needSectionHeader = true;
793+ // if it is the same section as the previous item need to drop the section
794+ if (modelIndex > 0) {
795+ const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
796+ if (sectionText == prevSection) {
797+ needSectionHeader = false;
798+ }
799+ }
800+
801+ if (needSectionHeader) {
802+ if (!item->sectionItem()) {
803+ item->setSectionItem(getSectionItem(sectionText));
804+ } else {
805+ item->sectionItem()->setProperty("text", sectionText);
806+ }
807+ } else {
808+ if (item->sectionItem()) {
809+ item->sectionItem()->deleteLater();
810+ item->setSectionItem(nullptr);
811+ }
812+ }
813+ }
814+}
815+
816+bool ListViewWithPageHeader::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
817+{
818+// qDebug() << "ListViewWithPageHeader::removeNonVisibleItems" << bufferFrom << bufferTo;
819+ // Do not remove items if we are overshooting up or down, since we'll come back
820+ // to the "stable" position and delete/create items without any reason
821+ if (contentY() < -m_minYExtent) {
822+ return false;
823+ } else if (contentY() + height() > contentHeight()) {
824+ return false;
825+ }
826+ bool changed = false;
827+
828+ bool foundVisible = false;
829+ int i = 0;
830+ int removedItems = 0;
831+ const auto oldFirstVisibleIndex = m_firstVisibleIndex;
832+ while (i < m_visibleItems.count()) {
833+ ListItem *item = m_visibleItems[i];
834+ const qreal pos = item->y() + m_clipItem->y();
835+// qDebug() << i << pos << (pos + item->height()) << bufferFrom << bufferTo;
836+ if (pos + item->height() < bufferFrom || pos > bufferTo) {
837+// qDebug() << "Releasing" << i << (pos + item->height() < bufferFrom) << pos + item->height() << bufferFrom << (pos > bufferTo) << pos << bufferTo;
838+ releaseItem(item);
839+ m_visibleItems.removeAt(i);
840+ changed = true;
841+ ++removedItems;
842+ } else {
843+ if (!foundVisible) {
844+ foundVisible = true;
845+ const int itemIndex = m_firstVisibleIndex + removedItems + i;
846+ m_firstVisibleIndex = itemIndex;
847+ }
848+ ++i;
849+ }
850+ }
851+ if (!foundVisible) {
852+ initializeValuesForEmptyList();
853+ }
854+ if (m_firstVisibleIndex != oldFirstVisibleIndex) {
855+ adjustMinYExtent();
856+ }
857+
858+ return changed;
859+}
860+
861+ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIndex, bool asynchronous)
862+{
863+// qDebug() << "CREATE ITEM" << modelIndex;
864+ if (asynchronous && m_asyncRequestedIndex != -1)
865+ return nullptr;
866+
867+ m_asyncRequestedIndex = -1;
868+ QObject* object = m_delegateModel->object(modelIndex, asynchronous);
869+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
870+ if (!item) {
871+ if (object) {
872+ m_delegateModel->release(object);
873+ if (!m_delegateValidated) {
874+ m_delegateValidated = true;
875+ QObject* delegateObj = delegate();
876+ qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
877+ }
878+ } else {
879+ m_asyncRequestedIndex = modelIndex;
880+ }
881+ return 0;
882+ } else {
883+// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
884+ ListItem *listItem = new ListItem;
885+ listItem->m_item = item;
886+ listItem->setSectionItem(getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/));
887+ QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
888+ ListItem *prevItem = itemAtIndex(modelIndex - 1);
889+ bool lostItem = false; // Is an item that we requested async but because of model changes
890+ // it is no longer attached to any of the existing items (has no prev nor next item)
891+ // nor is the first item
892+ if (prevItem) {
893+ listItem->setY(prevItem->y() + prevItem->height());
894+ } else {
895+ ListItem *currItem = itemAtIndex(modelIndex);
896+ if (currItem) {
897+ // There's something already in m_visibleItems at out index, meaning this is an insert, so attach to its top
898+ listItem->setY(currItem->y() - listItem->height());
899+ } else {
900+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
901+ if (nextItem) {
902+ listItem->setY(nextItem->y() - listItem->height());
903+ } else if (modelIndex == 0) {
904+ listItem->setY(-m_clipItem->y() + (m_headerItem ? m_headerItem->height() : 0));
905+ } else if (!m_visibleItems.isEmpty()) {
906+ lostItem = true;
907+ }
908+ }
909+ }
910+ if (lostItem) {
911+ listItem->setCulled(true);
912+ releaseItem(listItem);
913+ listItem = nullptr;
914+ } else {
915+ listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() <= contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
916+ if (m_visibleItems.isEmpty()) {
917+ m_visibleItems << listItem;
918+ } else {
919+ m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
920+ }
921+ if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
922+ m_firstVisibleIndex = modelIndex;
923+ polish();
924+ }
925+ if (listItem->sectionItem()) {
926+ listItem->sectionItem()->setProperty("delegateIndex", modelIndex);
927+ }
928+ adjustMinYExtent();
929+ m_contentHeightDirty = true;
930+ }
931+ return listItem;
932+ }
933+}
934+
935+void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
936+{
937+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
938+ if (!item) {
939+ qWarning() << "ListViewWithPageHeader::itemCreated got a non item for index" << modelIndex;
940+ return;
941+ }
942+// qDebug() << "ListViewWithPageHeader::itemCreated" << modelIndex << item;
943+ // Check we are not being taken down and don't paint anything
944+ // TODO Check if we still need this in 5.2
945+ // For reproduction just inifnite loop testDash or testDashContent
946+ if (!QQmlEngine::contextForObject(this)->parentContext())
947+ return;
948+
949+ item->setParentItem(m_clipItem);
950+ // FIXME Why do we need the refreshExpressions call?
951+ QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
952+ QQmlContextPrivate::get(context)->data->refreshExpressions();
953+ item->setProperty("heightToClip", QVariant::fromValue<int>(0));
954+ if (modelIndex == m_asyncRequestedIndex) {
955+ createItem(modelIndex, false);
956+ refill();
957+ }
958+}
959+
960+void ListViewWithPageHeader::updateClipItem()
961+{
962+ m_clipItem->setHeight(height() - m_headerItemShownHeight);
963+ m_clipItem->setY(contentY() + m_headerItemShownHeight);
964+ m_clipItem->setClip(!m_forceNoClip && m_headerItemShownHeight > 0);
965+}
966+
967+void ListViewWithPageHeader::onContentHeightChanged()
968+{
969+ updateClipItem();
970+}
971+
972+void ListViewWithPageHeader::onContentWidthChanged()
973+{
974+ m_clipItem->setWidth(contentItem()->width());
975+}
976+
977+void ListViewWithPageHeader::onHeightChanged()
978+{
979+ polish();
980+}
981+
982+
983+void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool /*reset*/)
984+{
985+ // TODO Do something with reset
986+// qDebug() << "ListViewWithPageHeader::onModelUpdated" << changeSet << reset;
987+ const auto oldFirstVisibleIndex = m_firstVisibleIndex;
988+
989+ Q_FOREACH(const QQmlChangeSet::Change remove, changeSet.removes()) {
990+// qDebug() << "ListViewWithPageHeader::onModelUpdated Remove" << remove.index << remove.count;
991+ if (remove.index + remove.count > m_firstVisibleIndex && remove.index < m_firstVisibleIndex + m_visibleItems.count()) {
992+ const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
993+ // If all the items we are removing are either not created or culled
994+ // we have to grow down to avoid viewport changing
995+ bool growDown = true;
996+ for (int i = 0; growDown && i < remove.count; ++i) {
997+ const int modelIndex = remove.index + i;
998+ ListItem *item = itemAtIndex(modelIndex);
999+ if (item && !item->culled()) {
1000+ growDown = false;
1001+ }
1002+ }
1003+ for (int i = remove.count - 1; i >= 0; --i) {
1004+ const int visibleIndex = remove.index + i - m_firstVisibleIndex;
1005+ if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
1006+ ListItem *item = m_visibleItems[visibleIndex];
1007+ // Pass the section item down if needed
1008+ if (item->sectionItem() && visibleIndex + 1 < m_visibleItems.count()) {
1009+ ListItem *nextItem = m_visibleItems[visibleIndex + 1];
1010+ if (!nextItem->sectionItem()) {
1011+ nextItem->setSectionItem(item->sectionItem());
1012+ item->setSectionItem(nullptr);
1013+ }
1014+ }
1015+ releaseItem(item);
1016+ m_visibleItems.removeAt(visibleIndex);
1017+ }
1018+ }
1019+ if (growDown) {
1020+ adjustMinYExtent();
1021+ } else if (remove.index <= m_firstVisibleIndex && !m_visibleItems.isEmpty()) {
1022+ m_visibleItems.first()->setY(oldFirstValidIndexPos);
1023+ }
1024+ if (m_visibleItems.isEmpty()) {
1025+ m_firstVisibleIndex = -1;
1026+ } else {
1027+ m_firstVisibleIndex -= qMax(0, m_firstVisibleIndex - remove.index);
1028+ }
1029+ } else if (remove.index + remove.count <= m_firstVisibleIndex) {
1030+ m_firstVisibleIndex -= remove.count;
1031+ }
1032+ for (int i = remove.count - 1; i >= 0; --i) {
1033+ const int modelIndex = remove.index + i;
1034+ if (modelIndex == m_asyncRequestedIndex) {
1035+ m_asyncRequestedIndex = -1;
1036+ } else if (modelIndex < m_asyncRequestedIndex) {
1037+ m_asyncRequestedIndex--;
1038+ }
1039+ }
1040+ }
1041+
1042+ Q_FOREACH(const QQmlChangeSet::Change insert, changeSet.inserts()) {
1043+// qDebug() << "ListViewWithPageHeader::onModelUpdated Insert" << insert.index << insert.count;
1044+ const bool insertingInValidIndexes = insert.index > m_firstVisibleIndex && insert.index < m_firstVisibleIndex + m_visibleItems.count();
1045+ const bool firstItemWithViewOnTop = insert.index == 0 && m_firstVisibleIndex == 0 && m_visibleItems.first()->y() + m_clipItem->y() > contentY();
1046+ if (insertingInValidIndexes || firstItemWithViewOnTop)
1047+ {
1048+ // If the items we are adding won't be really visible
1049+ // we grow up instead of down to not change the viewport
1050+ bool growUp = false;
1051+ if (!firstItemWithViewOnTop) {
1052+ for (int i = 0; i < m_visibleItems.count(); ++i) {
1053+ if (!m_visibleItems[i]->culled()) {
1054+ if (insert.index <= m_firstVisibleIndex + i) {
1055+ growUp = true;
1056+ }
1057+ break;
1058+ }
1059+ }
1060+ }
1061+
1062+ const qreal oldFirstValidIndexPos = m_visibleItems.first()->y();
1063+ for (int i = insert.count - 1; i >= 0; --i) {
1064+ const int modelIndex = insert.index + i;
1065+ ListItem *item = createItem(modelIndex, false);
1066+ if (growUp) {
1067+ ListItem *firstItem = m_visibleItems.first();
1068+ firstItem->setY(firstItem->y() - item->height());
1069+ }
1070+ // Adding an item may break a "same section" chain, so check
1071+ // if we need adding a new section item
1072+ if (m_sectionDelegate) {
1073+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
1074+ if (nextItem && !nextItem->sectionItem()) {
1075+ nextItem->setSectionItem(getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/));
1076+ if (growUp && nextItem->sectionItem()) {
1077+ ListItem *firstItem = m_visibleItems.first();
1078+ firstItem->setY(firstItem->y() - nextItem->sectionItem()->height());
1079+ }
1080+ }
1081+ }
1082+ }
1083+ if (firstItemWithViewOnTop) {
1084+ ListItem *firstItem = m_visibleItems.first();
1085+ firstItem->setY(oldFirstValidIndexPos);
1086+ }
1087+ adjustMinYExtent();
1088+ } else if (insert.index <= m_firstVisibleIndex) {
1089+ m_firstVisibleIndex += insert.count;
1090+ }
1091+
1092+ for (int i = insert.count - 1; i >= 0; --i) {
1093+ const int modelIndex = insert.index + i;
1094+ if (modelIndex <= m_asyncRequestedIndex) {
1095+ m_asyncRequestedIndex++;
1096+ }
1097+ }
1098+ }
1099+
1100+ Q_FOREACH(const QQmlChangeSet::Change change, changeSet.changes()) {
1101+ for (int i = change.start(); i < change.end(); ++i) {
1102+ updateSectionItem(i);
1103+ }
1104+ // Also update the section header for the next item after the change since it may be influenced
1105+ updateSectionItem(change.end());
1106+ }
1107+
1108+ if (m_firstVisibleIndex != oldFirstVisibleIndex) {
1109+ if (m_visibleItems.isEmpty()) {
1110+ initializeValuesForEmptyList();
1111+ } else {
1112+ adjustMinYExtent();
1113+ }
1114+ }
1115+
1116+ for (int i = 0; i < m_visibleItems.count(); ++i) {
1117+ ListItem *item = m_visibleItems[i];
1118+ if (item->sectionItem()) {
1119+ item->sectionItem()->setProperty("delegateIndex", m_firstVisibleIndex + i);
1120+ }
1121+ }
1122+
1123+ layout();
1124+ polish();
1125+ m_contentHeightDirty = true;
1126+}
1127+
1128+void ListViewWithPageHeader::contentYAnimationRunningChanged(bool running)
1129+{
1130+ setInteractive(!running);
1131+ if (!running) {
1132+ m_contentHeightDirty = true;
1133+ polish();
1134+ }
1135+}
1136+
1137+void ListViewWithPageHeader::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
1138+{
1139+ const qreal heightDiff = newGeometry.height() - oldGeometry.height();
1140+ if (heightDiff != 0) {
1141+ if (!m_visibleItems.isEmpty()) {
1142+ ListItem *firstItem = m_visibleItems.first();
1143+ const auto prevFirstItemY = firstItem->y();
1144+ if (!m_inContentHeightKeepHeaderShown && oldGeometry.y() + oldGeometry.height() + m_clipItem->y() <= contentY()) {
1145+ firstItem->setY(firstItem->y() - heightDiff);
1146+ } else if (item == firstItem->sectionItem()) {
1147+ firstItem->setY(firstItem->y() + heightDiff);
1148+ }
1149+
1150+ if (firstItem->y() != prevFirstItemY) {
1151+ adjustMinYExtent();
1152+ layout();
1153+ }
1154+ }
1155+ refill();
1156+ adjustMinYExtent();
1157+ polish();
1158+ m_contentHeightDirty = true;
1159+ }
1160+}
1161+
1162+void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item)
1163+{
1164+ if (item == m_headerItem) {
1165+ const qreal diff = m_headerItem->implicitHeight() - m_previousHeaderImplicitHeight;
1166+ if (diff != 0) {
1167+ adjustHeader(diff);
1168+ m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
1169+ layout();
1170+ polish();
1171+ m_contentHeightDirty = true;
1172+ }
1173+ }
1174+}
1175+
1176+void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY)
1177+{
1178+ const qreal heightDiff = newHeaderHeight - oldHeaderHeight;
1179+ if (m_headerItemShownHeight > 0) {
1180+ // If the header is shown because of the clip
1181+ // Change its size
1182+ m_headerItemShownHeight += heightDiff;
1183+ m_headerItemShownHeight = qBound(static_cast<qreal>(0.), m_headerItemShownHeight, newHeaderHeight);
1184+ updateClipItem();
1185+ adjustMinYExtent();
1186+ Q_EMIT headerItemShownHeightChanged();
1187+ } else {
1188+ if (oldHeaderY + oldHeaderHeight > contentY()) {
1189+ // If the header is shown because its position
1190+ // Change its size
1191+ ListItem *firstItem = m_visibleItems.first();
1192+ firstItem->setY(firstItem->y() + heightDiff);
1193+ layout();
1194+ } else {
1195+ // If the header is not on screen, just change the start of the list
1196+ // so the viewport is not changed
1197+ adjustMinYExtent();
1198+ }
1199+ }
1200+}
1201+
1202+
1203+void ListViewWithPageHeader::adjustMinYExtent()
1204+{
1205+ if (m_visibleItems.isEmpty() || (contentHeight() + m_minYExtent < height())) {
1206+ m_minYExtent = 0;
1207+ } else {
1208+ qreal nonCreatedHeight = 0;
1209+ if (m_firstVisibleIndex != 0) {
1210+ // Calculate the average height of items to estimate the position of the list start
1211+ const int visibleItems = m_visibleItems.count();
1212+ qreal visibleItemsHeight = 0;
1213+ Q_FOREACH(ListItem *item, m_visibleItems) {
1214+ visibleItemsHeight += item->height();
1215+ }
1216+ nonCreatedHeight = m_firstVisibleIndex * visibleItemsHeight / visibleItems;
1217+// qDebug() << m_firstVisibleIndex << visibleItemsHeight << visibleItems << nonCreatedHeight;
1218+ }
1219+ const qreal headerHeight = (m_headerItem ? m_headerItem->implicitHeight() : 0);
1220+ m_minYExtent = nonCreatedHeight - m_visibleItems.first()->y() - m_clipItem->y() + headerHeight;
1221+ if (m_minYExtent != 0 && qFuzzyIsNull(m_minYExtent)) {
1222+ m_minYExtent = 0;
1223+ m_visibleItems.first()->setY(nonCreatedHeight - m_clipItem->y() + headerHeight);
1224+ }
1225+ }
1226+}
1227+
1228+ListViewWithPageHeader::ListItem *ListViewWithPageHeader::itemAtIndex(int modelIndex) const
1229+{
1230+ const int visibleIndexedModelIndex = modelIndex - m_firstVisibleIndex;
1231+ if (visibleIndexedModelIndex >= 0 && visibleIndexedModelIndex < m_visibleItems.count())
1232+ return m_visibleItems[visibleIndexedModelIndex];
1233+
1234+ return nullptr;
1235+}
1236+
1237+void ListViewWithPageHeader::layout()
1238+{
1239+ if (m_inLayout)
1240+ return;
1241+
1242+ m_inLayout = true;
1243+ if (!m_visibleItems.isEmpty()) {
1244+ const qreal visibleFrom = contentY() - m_clipItem->y() + m_headerItemShownHeight;
1245+ const qreal visibleTo = contentY() + height() - m_clipItem->y();
1246+
1247+ qreal pos = m_visibleItems.first()->y();
1248+
1249+// qDebug() << "ListViewWithPageHeader::layout Updating positions and heights. contentY" << contentY() << "minYExtent" << minYExtent();
1250+ int firstReallyVisibleItem = -1;
1251+ int modelIndex = m_firstVisibleIndex;
1252+ Q_FOREACH(ListItem *item, m_visibleItems) {
1253+ const bool cull = pos + item->height() <= visibleFrom || pos >= visibleTo;
1254+ item->setCulled(cull);
1255+ item->setY(pos);
1256+ if (!cull && firstReallyVisibleItem == -1) {
1257+ firstReallyVisibleItem = modelIndex;
1258+ if (m_topSectionItem) {
1259+ // Positing the top section sticky item is a two step process
1260+ // First we set it either we cull it (because it doesn't need to be sticked to the top)
1261+ // or stick it to the top
1262+ // Then after the loop we'll make sure that if there's another section just below it
1263+ // pushed the sticky section up to make it disappear
1264+ const qreal topSectionStickPos = m_headerItemShownHeight + contentY() - m_clipItem->y();
1265+ bool showStickySectionItem;
1266+ // We need to show the "top section sticky item" when the position at the "top" of the
1267+ // viewport is bigger than the start of the position of the first visible item
1268+ // i.e. the first visible item starts before the viewport, or when the first
1269+ // visible item starts just at the viewport start and it does not have its own section item
1270+ if (topSectionStickPos > pos) {
1271+ showStickySectionItem = true;
1272+ } else if (topSectionStickPos == pos) {
1273+ showStickySectionItem = !item->sectionItem();
1274+ } else {
1275+ showStickySectionItem = false;
1276+ }
1277+ if (!showStickySectionItem) {
1278+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
1279+ if (item->sectionItem()) {
1280+ // This seems it should happen since why would we cull the top section
1281+ // if the first visible item has no section header? This only happens briefly
1282+ // when increasing the height of a list that is at the bottom, the m_topSectionItem
1283+ // gets shown shortly in the next polish call
1284+ QQuickItemPrivate::get(item->sectionItem())->setCulled(false);
1285+ }
1286+ } else {
1287+ // Update the top sticky section header
1288+ const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
1289+ m_topSectionItem->setProperty("text", section);
1290+
1291+ QQuickItemPrivate::get(m_topSectionItem)->setCulled(false);
1292+ m_topSectionItem->setY(topSectionStickPos);
1293+ int delegateIndex = modelIndex;
1294+ // Look for the first index with this section text
1295+ while (delegateIndex > 0) {
1296+ const QString prevSection = m_delegateModel->stringValue(delegateIndex - 1, m_sectionProperty);
1297+ if (prevSection != section)
1298+ break;
1299+ delegateIndex--;
1300+ }
1301+ m_topSectionItem->setProperty("delegateIndex", delegateIndex);
1302+ if (item->sectionItem()) {
1303+ QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
1304+ }
1305+ }
1306+ }
1307+ }
1308+ const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
1309+ if (!cull && pos < clipFrom) {
1310+ item->m_item->setProperty("heightToClip", clipFrom - pos);
1311+ } else {
1312+ item->m_item->setProperty("heightToClip", QVariant::fromValue<int>(0));
1313+ }
1314+// qDebug() << "ListViewWithPageHeader::layout" << item->m_item;
1315+ pos += item->height();
1316+ ++modelIndex;
1317+ }
1318+
1319+ // Second step of section sticky item positioning
1320+ // Look at the next section header, check if it's pushing up the sticky one
1321+ if (m_topSectionItem) {
1322+ if (firstReallyVisibleItem >= 0) {
1323+ for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
1324+ ListItem *item = m_visibleItems[i];
1325+ if (item->sectionItem()) {
1326+ if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
1327+ m_topSectionItem->setY(item->y() - m_topSectionItem->height());
1328+ }
1329+ break;
1330+ }
1331+ }
1332+ }
1333+ }
1334+ }
1335+ m_inLayout = false;
1336+}
1337+
1338+void ListViewWithPageHeader::updatePolish()
1339+{
1340+ // Check we are not being taken down and don't paint anything
1341+ // TODO Check if we still need this in 5.2
1342+ // For reproduction just inifnite loop testDash or testDashContent
1343+ if (!QQmlEngine::contextForObject(this)->parentContext())
1344+ return;
1345+
1346+ Q_FOREACH(ListItem *item, m_itemsToRelease)
1347+ reallyReleaseItem(item);
1348+ m_itemsToRelease.clear();
1349+
1350+ if (!model())
1351+ return;
1352+
1353+ layout();
1354+
1355+ refill();
1356+
1357+ if (m_contentHeightDirty) {
1358+ qreal contentHeight;
1359+ if (m_visibleItems.isEmpty()) {
1360+ contentHeight = m_headerItem ? m_headerItem->height() : 0;
1361+ } else {
1362+ const int modelCount = model()->rowCount();
1363+ const int visibleItems = m_visibleItems.count();
1364+ const int lastValidIndex = m_firstVisibleIndex + visibleItems - 1;
1365+ qreal nonCreatedHeight = 0;
1366+ if (lastValidIndex != modelCount - 1) {
1367+ const int visibleItems = m_visibleItems.count();
1368+ qreal visibleItemsHeight = 0;
1369+ Q_FOREACH(ListItem *item, m_visibleItems) {
1370+ visibleItemsHeight += item->height();
1371+ }
1372+ const int unknownSizes = modelCount - (m_firstVisibleIndex + visibleItems);
1373+ nonCreatedHeight = unknownSizes * visibleItemsHeight / visibleItems;
1374+ }
1375+ ListItem *item = m_visibleItems.last();
1376+ contentHeight = nonCreatedHeight + item->y() + item->height() + m_clipItem->y();
1377+ if (m_firstVisibleIndex != 0) {
1378+ // Make sure that if we are shrinking we tell the view we still fit
1379+ m_minYExtent = qMax(m_minYExtent, -(contentHeight - height()));
1380+ }
1381+ }
1382+
1383+ m_contentHeightDirty = false;
1384+ adjustMinYExtent();
1385+ if (contentHeight + m_minYExtent < height()) {
1386+ // need this since in the previous call to adjustMinYExtent contentHeight is not set yet
1387+ m_minYExtent = 0;
1388+ }
1389+ m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
1390+ setContentHeight(contentHeight);
1391+ m_inContentHeightKeepHeaderShown = false;
1392+ }
1393+}
1394+
1395+#include "moc_listviewwithpageheader.cpp"
plugins/Dash/listviewwithpageheader.hnew file+218
@@ -0,0 +1,218 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef LISTVIEWWITHPAGEHEADER_H
18+#define LISTVIEWWITHPAGEHEADER_H
19+
20+#include <private/qquickitemchangelistener_p.h>
21+#include <private/qquickflickable_p.h>
22+
23+class QAbstractItemModel;
24+class QQuickNumberAnimation;
25+class QQmlChangeSet;
26+class QQmlDelegateModel;
27+
28+
29+/**
30+ Note for users of this class
31+
32+ ListViewWithPageHeader already loads delegates async when appropiate so if
33+ your delegate uses a Loader you should not enable the asynchronous feature since
34+ that will need to introduce sizing problems
35+
36+ With the double async it may happen what while we are scrolling down
37+ we reach to a point where given the size of the just created delegate with loader not yet loaded (which will be very close to 0)
38+ we are already "at the end" of the list, but then a few milliseconds later the loader finishes loading and we could
39+ have kept scrolling. This is specially visible at the end of the list where you realize
40+ that scrolling ended a bit before the end of the list but the speed of the flicking was good
41+ to reach the end
42+
43+ By not having the second async we get a better sizing when the delegate is created and things work better
44+*/
45+
46+class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeListener
47+{
48+ Q_OBJECT
49+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
50+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
51+ Q_PROPERTY(QQuickItem *pageHeader READ header WRITE setHeader NOTIFY headerChanged)
52+ Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
53+ Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
54+ Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
55+ Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
56+ Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
57+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
58+
59+ friend class ListViewWithPageHeaderTest;
60+ friend class ListViewWithPageHeaderTestSection;
61+ friend class ListViewWithPageHeaderTestExternalModel;
62+
63+public:
64+ ListViewWithPageHeader();
65+ ~ListViewWithPageHeader();
66+
67+ QAbstractItemModel *model() const;
68+ void setModel(QAbstractItemModel *model);
69+
70+ QQmlComponent *delegate() const;
71+ void setDelegate(QQmlComponent *delegate);
72+
73+ QQuickItem *header() const;
74+ void setHeader(QQuickItem *header);
75+
76+ QQmlComponent *sectionDelegate() const;
77+ void setSectionDelegate(QQmlComponent *delegate);
78+
79+ QString sectionProperty() const;
80+ void setSectionProperty(const QString &property);
81+
82+ bool forceNoClip() const;
83+ void setForceNoClip(bool noClip);
84+
85+ int stickyHeaderHeight() const;
86+ qreal headerItemShownHeight() const;
87+
88+ int cacheBuffer() const;
89+ void setCacheBuffer(int cacheBuffer);
90+
91+ Q_INVOKABLE void positionAtBeginning();
92+ Q_INVOKABLE void showHeader();
93+ Q_INVOKABLE int firstCreatedIndex() const;
94+ Q_INVOKABLE int createdItemCount() const;
95+ Q_INVOKABLE QQuickItem *item(int modelIndex) const;
96+
97+ // The index has to be created for this to try to do something
98+ // Created items are those visible and the precached ones
99+ // Returns if the item existed or not
100+ Q_INVOKABLE bool maximizeVisibleArea(int modelIndex);
101+ Q_INVOKABLE bool maximizeVisibleArea(int modelIndex, int itemHeight);
102+
103+Q_SIGNALS:
104+ void modelChanged();
105+ void delegateChanged();
106+ void headerChanged();
107+ void sectionDelegateChanged();
108+ void sectionPropertyChanged();
109+ void forceNoClipChanged();
110+ void stickyHeaderHeightChanged();
111+ void headerItemShownHeightChanged();
112+ void cacheBufferChanged();
113+
114+protected:
115+ void componentComplete() override;
116+ void viewportMoved(Qt::Orientations orient) override;
117+ qreal minYExtent() const override;
118+ qreal maxYExtent() const override;
119+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
120+ void itemImplicitHeightChanged(QQuickItem *item) override;
121+ void updatePolish() override;
122+
123+private Q_SLOTS:
124+ void itemCreated(int modelIndex, QObject *object);
125+ void onContentHeightChanged();
126+ void onContentWidthChanged();
127+ void onHeightChanged();
128+ void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
129+ void contentYAnimationRunningChanged(bool running);
130+
131+private:
132+ class ListItem
133+ {
134+ public:
135+ qreal height() const;
136+
137+ qreal y() const;
138+ void setY(qreal newY);
139+
140+ bool culled() const;
141+ void setCulled(bool culled);
142+
143+ QQuickItem *sectionItem() const { return m_sectionItem; }
144+ void setSectionItem(QQuickItem *sectionItem);
145+
146+ QQuickItem *m_item;
147+ private:
148+ QQuickItem *m_sectionItem;
149+ };
150+
151+ bool maximizeVisibleArea(ListItem *listItem, int listItemHeight);
152+
153+ void createDelegateModel();
154+
155+ void layout();
156+ void refill();
157+ bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
158+ bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
159+ ListItem *createItem(int modelIndex, bool asynchronous);
160+
161+ void adjustHeader(qreal diff);
162+ void adjustMinYExtent();
163+ void updateClipItem();
164+ void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY);
165+ ListItem *itemAtIndex(int modelIndex) const; // Returns the item at modelIndex if has been created
166+ void releaseItem(ListItem *item);
167+ void reallyReleaseItem(ListItem *item);
168+ void updateWatchedRoles();
169+ QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
170+ QQuickItem *getSectionItem(const QString §ionText, bool watchGeometry = true);
171+ void updateSectionItem(int modelIndex);
172+ void initializeValuesForEmptyList();
173+
174+ QQmlDelegateModel *m_delegateModel;
175+
176+ // Index we are waiting because we requested it asynchronously
177+ int m_asyncRequestedIndex;
178+
179+ // Used to only give a warning once if the delegate does not return objects
180+ bool m_delegateValidated;
181+
182+ // Visible indexes, [0] is m_firstValidIndex, [0+1] is m_firstValidIndex +1, ...
183+ QList<ListItem *> m_visibleItems;
184+ int m_firstVisibleIndex;
185+
186+ qreal m_minYExtent;
187+
188+ QQuickItem *m_clipItem;
189+
190+ // If any of the heights has changed
191+ // or new items have been added/removed
192+ bool m_contentHeightDirty;
193+
194+ QQuickItem *m_headerItem;
195+ qreal m_previousContentY;
196+ qreal m_previousHeaderImplicitHeight;
197+ qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
198+ // i.e. it's being shown after dragging down in the middle of the list
199+ enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea };
200+ ContentYAnimationType contentYAnimationType;
201+ QQuickNumberAnimation *m_contentYAnimation;
202+
203+ QQmlComponent *m_sectionDelegate;
204+ QString m_sectionProperty;
205+ QQuickItem *m_topSectionItem;
206+
207+ bool m_forceNoClip;
208+ bool m_inLayout;
209+ bool m_inContentHeightKeepHeaderShown;
210+ int m_cacheBuffer;
211+
212+ // Qt 5.0 doesn't like releasing the items just after itemCreated
213+ // so we delay the releasing until the next updatePolish
214+ QList<ListItem *> m_itemsToRelease;
215+};
216+
217+
218+#endif
plugins/Dash/organicgrid.cppnew file+260
@@ -0,0 +1,260 @@
1+/*
2+ * Copyright (C) 2014 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+#include "organicgrid.h"
18+
19+#pragma GCC diagnostic push
20+#pragma GCC diagnostic ignored "-pedantic"
21+#include <private/qquickitem_p.h>
22+#pragma GCC diagnostic pop
23+
24+OrganicGrid::OrganicGrid()
25+ : m_firstVisibleIndex(-1)
26+ , m_numberOfModulesPerRow(-1)
27+{
28+}
29+
30+QSizeF OrganicGrid::smallDelegateSize() const
31+{
32+ return m_smallDelegateSize;
33+}
34+
35+void OrganicGrid::setSmallDelegateSize(const QSizeF size)
36+{
37+ if (m_smallDelegateSize != size) {
38+ m_smallDelegateSize = size;
39+ Q_EMIT smallDelegateSizeChanged();
40+
41+ if (isComponentComplete()) {
42+ relayout();
43+ }
44+ }
45+}
46+
47+QSizeF OrganicGrid::bigDelegateSize() const
48+{
49+ return m_bigDelegateSize;
50+}
51+
52+void OrganicGrid::setBigDelegateSize(const QSizeF size)
53+{
54+ if (m_bigDelegateSize != size) {
55+ m_bigDelegateSize = size;
56+ Q_EMIT bigDelegateSizeChanged();
57+
58+ if (isComponentComplete()) {
59+ relayout();
60+ }
61+ }
62+}
63+
64+QPointF OrganicGrid::positionForIndex(int modelIndex) const
65+{
66+ const qreal moduleHeight = m_smallDelegateSize.height() + rowSpacing() + m_bigDelegateSize.height();
67+ const qreal moduleWidth = m_smallDelegateSize.width() * 2 + columnSpacing() * 2 + m_bigDelegateSize.width();
68+ const int itemsPerRow = m_numberOfModulesPerRow * 6;
69+ const int rowIndex = floor(modelIndex / itemsPerRow);
70+ const int columnIndex = floor((modelIndex - rowIndex * itemsPerRow) / 6);
71+
72+ qreal yPos = (moduleHeight + rowSpacing()) * rowIndex;
73+ const int moduleIndex = modelIndex % 6;
74+ if (moduleIndex == 2) {
75+ yPos += m_smallDelegateSize.height() + rowSpacing();
76+ } else if (moduleIndex == 3 || moduleIndex == 5) {
77+ yPos += m_bigDelegateSize.height() + rowSpacing();
78+ }
79+
80+ qreal xPos = (moduleWidth + columnSpacing()) * columnIndex;
81+ if (moduleIndex == 1) {
82+ xPos += m_smallDelegateSize.width() + columnSpacing();
83+ } else if (moduleIndex == 3) {
84+ xPos += m_bigDelegateSize.width() + columnSpacing();
85+ } else if (moduleIndex == 4) {
86+ xPos += (m_smallDelegateSize.width() + columnSpacing()) * 2;
87+ } else if (moduleIndex == 5) {
88+ xPos += m_bigDelegateSize.width() + m_smallDelegateSize.width() + columnSpacing() * 2;
89+ }
90+
91+ return QPointF(xPos, yPos);
92+}
93+
94+QSizeF OrganicGrid::sizeForIndex(int modelIndex) const
95+{
96+ const int moduleIndex = modelIndex % 6;
97+ if (moduleIndex == 0 || moduleIndex == 1 || moduleIndex == 3 || moduleIndex == 5) {
98+ return m_smallDelegateSize;
99+ } else {
100+ return m_bigDelegateSize;
101+ }
102+}
103+
104+void OrganicGrid::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
105+{
106+ if (m_visibleItems.isEmpty()) {
107+ *modelIndex = 0;
108+ *yPos = 0;
109+ } else {
110+ *modelIndex = m_firstVisibleIndex + m_visibleItems.count();
111+ // We create stuff in a 6-module basis, so always return back
112+ // the y position of the first item
113+ const int firstModuleIndex = ((*modelIndex) / 6) * 6;
114+ *yPos = positionForIndex(firstModuleIndex).y();
115+ }
116+}
117+
118+void OrganicGrid::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
119+{
120+ if (m_visibleItems.isEmpty()) {
121+ *modelIndex = 0;
122+ *yPos = 0;
123+ } else {
124+ *modelIndex = m_firstVisibleIndex - 1;
125+ // We create stuff in a 6-module basis, so always return back
126+ // the y position of the last item bottom
127+ const int lastModuleIndex = ((*modelIndex) / 6) * 6 + 5;
128+ *yPos = positionForIndex(lastModuleIndex).y();
129+ *yPos += sizeForIndex(lastModuleIndex).height();
130+ }
131+}
132+
133+void OrganicGrid::addItemToView(int modelIndex, QQuickItem *item)
134+{
135+ // modelIndex has to be either m_firstVisibleIndex - 1 or m_firstVisibleIndex + m_visibleItems.count() or the first
136+ if (modelIndex == m_firstVisibleIndex + m_visibleItems.count()) {
137+ m_visibleItems << item;
138+ } else if (modelIndex == m_firstVisibleIndex - 1) {
139+ m_firstVisibleIndex = modelIndex;
140+ m_visibleItems.prepend(item);
141+ } else if (modelIndex == 0) {
142+ m_firstVisibleIndex = 0;
143+ m_visibleItems << item;
144+ } else {
145+ qWarning() << "OrganicGrid::addItemToView - Got unexpected modelIndex"
146+ << modelIndex << m_firstVisibleIndex << m_visibleItems.count();
147+ return;
148+ }
149+
150+ const QPointF pos = positionForIndex(modelIndex);
151+ item->setPosition(pos);
152+
153+ item->setSize(sizeForIndex(modelIndex));
154+}
155+
156+bool OrganicGrid::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
157+{
158+ bool changed = false;
159+
160+ // As adding, we also remove in a 6-module basis
161+ int lastModuleIndex = (m_firstVisibleIndex / 6) * 6 + 5;
162+ bool removeIndex = positionForIndex(lastModuleIndex).y() + sizeForIndex(lastModuleIndex).height() < bufferFromY;
163+ while (removeIndex && !m_visibleItems.isEmpty()) {
164+ releaseItem(m_visibleItems.takeFirst());
165+ changed = true;
166+ m_firstVisibleIndex++;
167+
168+ lastModuleIndex = (m_firstVisibleIndex / 6) * 6 + 5;
169+ removeIndex = positionForIndex(lastModuleIndex).y() + sizeForIndex(lastModuleIndex).height() < bufferFromY;
170+ }
171+
172+ int firstModuleIndex = ((m_firstVisibleIndex + m_visibleItems.count() - 1) / 6) * 6;
173+ removeIndex = positionForIndex(firstModuleIndex).y() > bufferToY;
174+ while (removeIndex && !m_visibleItems.isEmpty()) {
175+ releaseItem(m_visibleItems.takeLast());
176+ changed = true;
177+
178+ firstModuleIndex = ((m_firstVisibleIndex + m_visibleItems.count() - 1) / 6) * 6;
179+ removeIndex = positionForIndex(firstModuleIndex).y() > bufferToY;
180+ }
181+
182+ if (m_visibleItems.isEmpty()) {
183+ m_firstVisibleIndex = -1;
184+ }
185+
186+ return changed;
187+}
188+
189+void OrganicGrid::cleanupExistingItems()
190+{
191+ Q_FOREACH(QQuickItem *item, m_visibleItems)
192+ releaseItem(item);
193+ m_visibleItems.clear();
194+ m_firstVisibleIndex = -1;
195+ setImplicitHeightDirty();
196+}
197+
198+void OrganicGrid::doRelayout()
199+{
200+ const qreal moduleWidth = m_smallDelegateSize.width() * 2 + columnSpacing() * 2 + m_bigDelegateSize.width();
201+ m_numberOfModulesPerRow = floor((width() + columnSpacing()) / (moduleWidth + columnSpacing()));
202+ m_numberOfModulesPerRow = qMax(1, m_numberOfModulesPerRow);
203+
204+ int i = m_firstVisibleIndex;
205+ const QList<QQuickItem*> allItems = m_visibleItems;
206+ m_visibleItems.clear();
207+ Q_FOREACH(QQuickItem *item, allItems) {
208+ addItemToView(i, item);
209+ ++i;
210+ }
211+}
212+
213+void OrganicGrid::updateItemCulling(qreal visibleFromY, qreal visibleToY)
214+{
215+ Q_FOREACH(QQuickItem *item, m_visibleItems) {
216+ QQuickItemPrivate::get(item)->setCulled(item->y() + item->height() <= visibleFromY || item->y() >= visibleToY);
217+ }
218+}
219+
220+void OrganicGrid::calculateImplicitHeight()
221+{
222+ const qreal moduleHeight = m_smallDelegateSize.height() + rowSpacing() + m_bigDelegateSize.height();
223+ const int itemCount = !model() ? 0 : model()->rowCount();
224+ const int itemsPerRow = m_numberOfModulesPerRow * 6;
225+ const int fullRows = floor(itemCount / itemsPerRow);
226+ const qreal fullRowsHeight = fullRows == 0 ? 0 : fullRows * moduleHeight + rowSpacing() * (fullRows - 1);
227+
228+ const int remainingItems = itemCount - fullRows * itemsPerRow;
229+ if (remainingItems == 0) {
230+ setImplicitHeight(fullRowsHeight);
231+ } else if (remainingItems <= 2) {
232+ setImplicitHeight(fullRowsHeight + m_smallDelegateSize.height() + rowSpacing());
233+ } else {
234+ setImplicitHeight(fullRowsHeight + rowSpacing() + moduleHeight);
235+ }
236+}
237+
238+void OrganicGrid::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
239+{
240+ Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
241+ for (int i = remove.count - 1; i >= 0; --i) {
242+ const int indexToRemove = remove.index + i;
243+ // We only support removing from the end
244+ const int lastIndex = m_firstVisibleIndex + m_visibleItems.count() - 1;
245+ if (indexToRemove == lastIndex) {
246+ releaseItem(m_visibleItems.takeLast());
247+ } else {
248+ if (indexToRemove < lastIndex) {
249+ qDebug() << "OrganicGrid only supports removal from the end of the model, resetting instead";
250+ cleanupExistingItems();
251+ break;
252+ }
253+ }
254+ }
255+ }
256+ if (m_visibleItems.isEmpty()) {
257+ m_firstVisibleIndex = -1;
258+ }
259+ setImplicitHeightDirty();
260+}
plugins/Dash/organicgrid.hnew file+91
@@ -0,0 +1,91 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef ORGANICGRID_H
18+#define ORGANICGRID_H
19+
20+#include "abstractdashview.h"
21+
22+ /** An Organic Grid is is a view that creates delegates
23+ * based on a model and layouts them in groups of six items (called module).
24+ *
25+ * In each module there are 4 items that are forced to the small delegate size
26+ * and two that are forced to the big delegate size.
27+ *
28+ * Example:
29+ *
30+ * +---+ +---+ +-----+
31+ * | 1 | | 2 | | |
32+ * +---+ +---+ | 5 |
33+ * +-----+ | |
34+ * | | +-----+
35+ * | 3 | +---+ +---+
36+ * | | | 4 | | 6 |
37+ * +-----+ +---+ +---+
38+ *
39+ * Modules are positioned one after the other in a grid like fashion, i.e.
40+ *
41+ * +---+ +---+
42+ * | 1 | | 2 |
43+ * +---+ +---+
44+ * +---+ +---+
45+ * | 3 | | 4 |
46+ * +---+ +---+
47+ */
48+
49+class OrganicGrid : public AbstractDashView
50+{
51+ Q_OBJECT
52+
53+ Q_PROPERTY(QSizeF smallDelegateSize READ smallDelegateSize WRITE setSmallDelegateSize NOTIFY smallDelegateSizeChanged)
54+ Q_PROPERTY(QSizeF bigDelegateSize READ bigDelegateSize WRITE setBigDelegateSize NOTIFY bigDelegateSizeChanged)
55+
56+friend class OrganicGridTest;
57+
58+public:
59+ OrganicGrid();
60+
61+ QSizeF smallDelegateSize() const;
62+ void setSmallDelegateSize(const QSizeF size);
63+
64+ QSizeF bigDelegateSize() const;
65+ void setBigDelegateSize(const QSizeF size);
66+
67+Q_SIGNALS:
68+ void smallDelegateSizeChanged();
69+ void bigDelegateSizeChanged();
70+private:
71+ QPointF positionForIndex(int modelIndex) const;
72+ QSizeF sizeForIndex(int modelIndex) const;
73+
74+ void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
75+ void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
76+ void addItemToView(int modelIndex, QQuickItem *item) override;
77+ bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
78+ void cleanupExistingItems() override;
79+ void doRelayout() override;
80+ void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
81+ void calculateImplicitHeight() override;
82+ void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
83+
84+ QSizeF m_smallDelegateSize;
85+ QSizeF m_bigDelegateSize;
86+ int m_firstVisibleIndex;
87+ int m_numberOfModulesPerRow;
88+ QList<QQuickItem*> m_visibleItems;
89+};
90+
91+#endif
plugins/Dash/plugin.cppnew file+70
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include "plugin.h"
19+
20+#include "horizontaljournal.h"
21+#include "listviewwithpageheader.h"
22+#include "organicgrid.h"
23+#include "verticaljournal.h"
24+
25+#include <QAbstractItemModel>
26+#include <QUrlQuery>
27+
28+static QUrl oauthCleanedUrl(QUrl u)
29+{
30+ QUrlQuery q(u);
31+ q.removeQueryItem(QStringLiteral("oauth_nonce"));
32+ q.removeQueryItem(QStringLiteral("oauth_timestamp"));
33+ q.removeQueryItem(QStringLiteral("oauth_consumer_key"));
34+ q.removeQueryItem(QStringLiteral("oauth_signature_method"));
35+ q.removeQueryItem(QStringLiteral("oauth_version"));
36+ q.removeQueryItem(QStringLiteral("oauth_signature"));
37+ u.setQuery(q);
38+ return u;
39+}
40+
41+class AudioComparer : public QObject
42+{
43+ Q_OBJECT
44+public:
45+ Q_INVOKABLE bool compare(const QUrl &url1, const QUrl &url2)
46+ {
47+ return oauthCleanedUrl(url1) == oauthCleanedUrl(url2);
48+ }
49+};
50+
51+static QObject *audio_comparer_singleton_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
52+{
53+ Q_UNUSED(engine)
54+ Q_UNUSED(scriptEngine)
55+
56+ return new AudioComparer();
57+}
58+
59+void DashPlugin::registerTypes(const char *uri)
60+{
61+ Q_ASSERT(uri == QLatin1String("Dash"));
62+ qmlRegisterType<QAbstractItemModel>();
63+ qmlRegisterType<HorizontalJournal>(uri, 0, 1, "HorizontalJournal");
64+ qmlRegisterType<ListViewWithPageHeader>(uri, 0, 1, "ListViewWithPageHeader");
65+ qmlRegisterType<OrganicGrid>(uri, 0, 1, "OrganicGrid");
66+ qmlRegisterType<VerticalJournal>(uri, 0, 1, "VerticalJournal");
67+ qmlRegisterSingletonType<AudioComparer>(uri, 0, 1, "AudioUrlComparer", audio_comparer_singleton_provider);
68+}
69+
70+#include "plugin.moc"
tests/mocks/SessionBroadcast/plugin.h → plugins/Dash/plugin.hrenamed+5−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2012 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,15 +12,16 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
1516 */
1617
17−#ifndef MOCK_SESSIONBROADCAST_PLUGIN_H
18−#define MOCK_SESSIONBROADCAST_PLUGIN_H
18+#ifndef DASH_PLUGIN_H
19+#define DASH_PLUGIN_H
1920
2021#include <QtQml/QQmlEngine>
2122#include <QtQml/QQmlExtensionPlugin>
2223
23−class PowerdPlugin : public QQmlExtensionPlugin
24+class DashPlugin : public QQmlExtensionPlugin
2425{
2526 Q_OBJECT
2627 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
plugins/Dash/qmldirnew file+11
@@ -0,0 +1,11 @@
1+module Dash
2+plugin Dash-qml
3+typeinfo Dash.qmltypes
4+singleton CardCreatorCache 0.1 CardCreatorCache.qml
5+singleton DashAudioPlayer 0.1 DashAudioPlayer.qml
6+ScopeStyle 0.1 ScopeStyle.qml
7+CardAttributes 0.1 CardAttributes.qml
8+CardSocialActions 0.1 CardSocialActions.qml
9+CroppedImageMinimumSourceSize 0.1 CroppedImageMinimumSourceSize.qml
10+AudioProgressBar 0.1 AudioProgressBar.qml
11+CardAudioProgress 0.1 CardAudioProgress.qml
plugins/Dash/verticaljournal.cppnew file+273
@@ -0,0 +1,273 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+/*
18+ * The implementation is centered around m_columnVisibleItems
19+ * that holds a vector of lists. There's a list for each of the
20+ * columns the view has. In the list the items of the column are
21+ * ordered as they appear topdown in the view. m_indexColumnMap is
22+ * used when re-building the list up since given a position
23+ * in the middle of the list and the need to create the previous does
24+ * not give us enough information to know in which column we have
25+ * to position the item so that when we reach the item the view is
26+ * correctly layouted at 0 for all the columns
27+ */
28+#include "verticaljournal.h"
29+
30+#pragma GCC diagnostic push
31+#pragma GCC diagnostic ignored "-pedantic"
32+#include <private/qquickitem_p.h>
33+#pragma GCC diagnostic pop
34+
35+VerticalJournal::VerticalJournal()
36+ : m_columnWidth(0)
37+{
38+}
39+
40+qreal VerticalJournal::columnWidth() const
41+{
42+ return m_columnWidth;
43+}
44+
45+void VerticalJournal::setColumnWidth(qreal columnWidth)
46+{
47+ if (columnWidth != m_columnWidth) {
48+ m_columnWidth = columnWidth;
49+ Q_EMIT columnWidthChanged();
50+
51+ if (isComponentComplete()) {
52+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
53+ Q_FOREACH(const ViewItem item, column) {
54+ item.m_item->setWidth(columnWidth);
55+ }
56+ }
57+ relayout();
58+ }
59+ }
60+}
61+
62+void VerticalJournal::findBottomModelIndexToAdd(int *modelIndex, qreal *yPos)
63+{
64+ *modelIndex = 0;
65+ *yPos = std::numeric_limits<qreal>::max();
66+
67+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
68+ if (!column.isEmpty()) {
69+ const ViewItem &item = column.last();
70+ *yPos = qMin(*yPos, item.y() + item.height() + rowSpacing());
71+ *modelIndex = qMax(*modelIndex, item.m_modelIndex + 1);
72+ } else {
73+ *yPos = 0;
74+ }
75+ }
76+}
77+
78+void VerticalJournal::findTopModelIndexToAdd(int *modelIndex, qreal *yPos)
79+{
80+ *modelIndex = 0;
81+ *yPos = std::numeric_limits<qreal>::lowest();
82+ int columnToAddTo = -1;
83+
84+ // Find the topmost free column
85+ for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
86+ const auto &column = m_columnVisibleItems[i];
87+ if (!column.isEmpty()) {
88+ const ViewItem &item = column.first();
89+ const auto itemTopPos = item.y() - rowSpacing();
90+ if (itemTopPos > *yPos) {
91+ *yPos = itemTopPos;
92+ *modelIndex = item.m_modelIndex - 1;
93+ columnToAddTo = i;
94+ }
95+ }
96+ }
97+
98+ if (*modelIndex > 0) {
99+ Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
100+ while (m_indexColumnMap[*modelIndex] != columnToAddTo) {
101+ // We found out that we have to add to columnToAddTo
102+ // and thought that we had to add *modelIndex, but history tells
103+ // it is not correct, so find up from *modelIndex until we found the index
104+ // that has to end up in columnToAddTo
105+ *modelIndex = *modelIndex - 1;
106+ Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
107+ }
108+ }
109+}
110+
111+bool VerticalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
112+{
113+ bool changed = false;
114+
115+ for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
116+ QList<ViewItem> &column = m_columnVisibleItems[i];
117+ while (!column.isEmpty() && column.first().y() + column.first().height() < bufferFromY) {
118+ releaseItem(column.takeFirst().m_item);
119+ changed = true;
120+ }
121+
122+ while (!column.isEmpty() && column.last().y() > bufferToY) {
123+ releaseItem(column.takeLast().m_item);
124+ changed = true;
125+ }
126+ }
127+
128+ return changed;
129+}
130+
131+void VerticalJournal::addItemToView(int modelIndex, QQuickItem *item)
132+{
133+ if (item->width() != m_columnWidth) {
134+ qWarning() << "Item" << modelIndex << "width is not the one that the columnWidth mandates, resetting it";
135+ item->setWidth(m_columnWidth);
136+ }
137+
138+ // Check if we add it to the bottom of existing column items
139+ const QList<ViewItem> &firstColumn = m_columnVisibleItems[0];
140+ qreal columnToAddY = !firstColumn.isEmpty() ? firstColumn.last().y() + firstColumn.last().height() : -rowSpacing();
141+ int columnToAddTo = 0;
142+ for (int i = 1; i < m_columnVisibleItems.count(); ++i) {
143+ const QList<ViewItem> &column = m_columnVisibleItems[i];
144+ const qreal iY = !column.isEmpty() ? column.last().y() + column.last().height() : -rowSpacing();
145+ if (iY < columnToAddY) {
146+ columnToAddTo = i;
147+ columnToAddY = iY;
148+ }
149+ }
150+
151+ const QList<ViewItem> &columnToAdd = m_columnVisibleItems[columnToAddTo];
152+ if (columnToAdd.isEmpty() || columnToAdd.last().m_modelIndex < modelIndex) {
153+ item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
154+ item->setY(columnToAddY + rowSpacing());
155+
156+ m_columnVisibleItems[columnToAddTo] << ViewItem(item, modelIndex);
157+ m_indexColumnMap[modelIndex] = columnToAddTo;
158+ } else {
159+ Q_ASSERT(m_indexColumnMap.contains(modelIndex));
160+ columnToAddTo = m_indexColumnMap[modelIndex];
161+ columnToAddY = m_columnVisibleItems[columnToAddTo].first().y();
162+
163+ item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
164+ item->setY(columnToAddY - rowSpacing() - item->height());
165+
166+ m_columnVisibleItems[columnToAddTo].prepend(ViewItem(item, modelIndex));
167+ }
168+}
169+
170+void VerticalJournal::cleanupExistingItems()
171+{
172+ // Cleanup the existing items
173+ for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
174+ QList<ViewItem> &column = m_columnVisibleItems[i];
175+ Q_FOREACH(const ViewItem item, column)
176+ releaseItem(item.m_item);
177+ column.clear();
178+ }
179+ m_indexColumnMap.clear();
180+ setImplicitHeightDirty();
181+}
182+
183+void VerticalJournal::calculateImplicitHeight()
184+{
185+ int lastModelIndex = -1;
186+ qreal bottomMostY = 0;
187+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
188+ if (!column.isEmpty()) {
189+ const ViewItem &item = column.last();
190+ lastModelIndex = qMax(lastModelIndex, item.m_modelIndex);
191+ bottomMostY = qMax(bottomMostY, item.y() + item.height());
192+ }
193+ }
194+ if (lastModelIndex >= 0) {
195+ const double averageHeight = bottomMostY / (lastModelIndex + 1);
196+ setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - lastModelIndex - 1));
197+ } else {
198+ setImplicitHeight(0);
199+ }
200+}
201+
202+void VerticalJournal::doRelayout()
203+{
204+ QList<ViewItem> allItems;
205+ Q_FOREACH(const auto &column, m_columnVisibleItems)
206+ allItems << column;
207+
208+ qSort(allItems);
209+
210+ const int nColumns = qMax(1., floor((double)(width() + columnSpacing()) / (m_columnWidth + columnSpacing())));
211+ m_columnVisibleItems.resize(nColumns);
212+ m_indexColumnMap.clear();
213+ for (int i = 0; i < nColumns; ++i)
214+ m_columnVisibleItems[i].clear();
215+
216+ // If the first of allItems doesn't contain index 0 we need to drop them
217+ // all since we can't consistently relayout without the first item being there
218+
219+ if (!allItems.isEmpty()) {
220+ if (allItems.first().m_modelIndex == 0) {
221+ Q_FOREACH(const ViewItem item, allItems)
222+ addItemToView(item.m_modelIndex, item.m_item);
223+ } else {
224+ Q_FOREACH(const ViewItem item, allItems)
225+ releaseItem(item.m_item);
226+ }
227+ }
228+}
229+
230+void VerticalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
231+{
232+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
233+ Q_FOREACH(const ViewItem item, column) {
234+ const bool cull = item.y() + item.height() <= visibleFromY || item.y() >= visibleToY;
235+ QQuickItemPrivate::get(item.m_item)->setCulled(cull);
236+ }
237+ }
238+}
239+
240+void VerticalJournal::processModelRemoves(const QVector<QQmlChangeSet::Change> &removes)
241+{
242+ Q_FOREACH(const QQmlChangeSet::Change remove, removes) {
243+ for (int i = remove.count - 1; i >= 0; --i) {
244+ const int indexToRemove = remove.index + i;
245+ // Since we only support removing from the end, indexToRemove
246+ // must refer to the last item of one of the columns or
247+ // be bigger than them (because it's not in the viewport and
248+ // thus we have not created a delegate for it)
249+ bool found = false;
250+ int lastCreatedIndex = INT_MIN;
251+ for (int i = 0; !found && i < m_columnVisibleItems.count(); ++i) {
252+ QList<ViewItem> &column = m_columnVisibleItems[i];
253+ if (!column.isEmpty()) {
254+ const int lastColumnIndex = column.last().m_modelIndex;
255+ if (lastColumnIndex == indexToRemove) {
256+ releaseItem(column.takeLast().m_item);
257+ found = true;
258+ }
259+ lastCreatedIndex = qMax(lastCreatedIndex, lastColumnIndex);
260+ }
261+ }
262+ if (!found) {
263+ if (indexToRemove < lastCreatedIndex) {
264+ qDebug() << "VerticalJournal only supports removal from the end of the model, resetting instead";
265+ cleanupExistingItems();
266+ break;
267+ } else {
268+ setImplicitHeightDirty();
269+ }
270+ }
271+ }
272+ }
273+}
plugins/Dash/verticaljournal.hnew file+100
@@ -0,0 +1,100 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef VERTICALJOURNAL_H
18+#define VERTICALJOURNAL_H
19+
20+#include "abstractdashview.h"
21+
22+ /** A vertical journal is a view that creates delegates
23+ * based on a model and layouts them in columns following
24+ * a top-left most position rule.
25+ *
26+ * The number of columns is calculated using the width of
27+ * the view itself, the columnWidth (i.e. the width of each individual delegate)
28+ * and the columnSpacing between columns.
29+ *
30+ * All delegates are forced to columnWidth if they don't have it.
31+ *
32+ * The first nColumns items are layouted at row 0 from column 0
33+ * to column nColumns-1 in order. After that every new item
34+ * is positioned in the column which provides the free topmost
35+ * position as possible. If more than one column tie in providing
36+ * the topmost free position the leftmost column will be used.
37+ *
38+ * Example:
39+ *
40+ * +-----+ +-----+ +-----+
41+ * | | | 2 | | |
42+ * | | | | | |
43+ * | 1 | +-----+ | 3 |
44+ * | | +-----+ | |
45+ * | | | | +-----+
46+ * +-----+ | 4 | +-----+
47+ * +-----+ | | | 5 |
48+ * | 6 | +-----+ | |
49+ * | | +-----+
50+ * +-----+
51+ *
52+ */
53+
54+class VerticalJournal : public AbstractDashView
55+{
56+ Q_OBJECT
57+
58+ Q_PROPERTY(qreal columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged)
59+
60+friend class VerticalJournalTest;
61+
62+public:
63+ VerticalJournal();
64+
65+ qreal columnWidth() const;
66+ void setColumnWidth(qreal columnWidth);
67+
68+Q_SIGNALS:
69+ void columnWidthChanged();
70+
71+private:
72+ class ViewItem
73+ {
74+ public:
75+ ViewItem(QQuickItem *item, int modelIndex) : m_item(item), m_modelIndex(modelIndex) {}
76+ qreal x() const { return m_item->x(); }
77+ qreal y() const { return m_item->y(); }
78+ qreal height() const { return m_item->height(); }
79+ bool operator<(const ViewItem v) const { return m_modelIndex < v.m_modelIndex; }
80+
81+ QQuickItem *m_item;
82+ int m_modelIndex;
83+ };
84+
85+ void findBottomModelIndexToAdd(int *modelIndex, qreal *yPos) override;
86+ void findTopModelIndexToAdd(int *modelIndex, qreal *yPos) override;
87+ bool removeNonVisibleItems(qreal bufferFromY, qreal bufferToY) override;
88+ void addItemToView(int modelIndex, QQuickItem *item) override;
89+ void cleanupExistingItems() override;
90+ void calculateImplicitHeight() override;
91+ void doRelayout() override;
92+ void updateItemCulling(qreal visibleFromY, qreal visibleToY) override;
93+ void processModelRemoves(const QVector<QQmlChangeSet::Change> &removes) override;
94+
95+ QVector<QList<ViewItem>> m_columnVisibleItems;
96+ QHash<int, int> m_indexColumnMap;
97+ int m_columnWidth;
98+};
99+
100+#endif
plugins/GlobalShortcut/CMakeLists.txt+1−1
@@ -5,6 +5,6 @@ set(globalshortcutplugin_SRCS
55
66add_library(GlobalShortcut-qml SHARED ${globalshortcutplugin_SRCS})
77
8−target_link_libraries(GlobalShortcut-qml Qt5::Quick Qt5::Gui)
8+qt5_use_modules(GlobalShortcut-qml Quick Gui)
99
1010add_unity8_plugin(GlobalShortcut 1.0 GlobalShortcut TARGETS GlobalShortcut-qml)
plugins/GlobalShortcut/GlobalShortcut.qmltypesnew file+31
@@ -0,0 +1,31 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable GlobalShortcut 1.0 plugins'
8+
9+Module {
10+ Component {
11+ name: "GlobalShortcut"
12+ defaultProperty: "data"
13+ prototype: "QQuickItem"
14+ exports: ["GlobalShortcut/GlobalShortcut 1.0"]
15+ exportMetaObjectRevisions: [0]
16+ Property { name: "shortcut"; type: "QVariant" }
17+ Property { name: "active"; type: "bool" }
18+ Signal {
19+ name: "shortcutChanged"
20+ Parameter { name: "shortcut"; type: "QVariant" }
21+ }
22+ Signal {
23+ name: "triggered"
24+ Parameter { name: "shortcut"; type: "string" }
25+ }
26+ Signal {
27+ name: "activeChanged"
28+ Parameter { name: "active"; type: "bool" }
29+ }
30+ }
31+}
plugins/GlobalShortcut/globalshortcut.cpp+4−15
@@ -58,26 +58,15 @@ void GlobalShortcut::setActive(bool active)
5858
5959void GlobalShortcut::componentComplete()
6060{
61− if (this->window()) {
62− QMetaObject::invokeMethod(this, "setupFilterOnWindow", Q_ARG(QQuickWindow*, this->window()));
63− }
6461 connect(this, &QQuickItem::windowChanged, this, &GlobalShortcut::setupFilterOnWindow);
6562}
6663
6764void GlobalShortcut::keyPressEvent(QKeyEvent * event)
6865{
69− if (!m_active) return;
70−
71− event->accept();
72− Q_EMIT triggered(m_shortcut.toString());
73−}
74−
75−void GlobalShortcut::keyReleaseEvent(QKeyEvent * event)
76−{
77− if (!m_active) return;
78−
79− event->accept();
80− Q_EMIT released(m_shortcut.toString());
66+ Q_UNUSED(event)
67+ if (m_active) {
68+ Q_EMIT triggered(m_shortcut.toString());
69+ }
8170}
8271
8372void GlobalShortcut::setupFilterOnWindow(QQuickWindow *window)
plugins/GlobalShortcut/globalshortcut.h−5
@@ -55,7 +55,6 @@ public:
5555protected:
5656 void componentComplete() override;
5757 void keyPressEvent(QKeyEvent * event) override;
58− void keyReleaseEvent(QKeyEvent * event) override;
5958
6059Q_SIGNALS:
6160 void shortcutChanged(const QVariant &shortcut);
@@ -63,10 +62,6 @@ Q_SIGNALS:
6362 * Emitted when a global keypress of @p shortcut is detected
6463 */
6564 void triggered(const QString &shortcut);
66− /**
67− * Emitted when a global keypress of @p shortcut is released
68− */
69− void released(const QString &shortcut);
7065 void activeChanged(bool active);
7166
7267private Q_SLOTS:
plugins/GlobalShortcut/globalshortcutregistry.cpp+4−14
@@ -73,30 +73,20 @@ bool GlobalShortcutRegistry::eventFilter(QObject *obj, QEvent *event)
7373 Q_ASSERT(m_filteredWindow);
7474 Q_ASSERT(obj == static_cast<QObject*>(m_filteredWindow.data()));
7575
76− if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
77−
76+ if (event->type() == QEvent::KeyPress) {
7877 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
79−
80− // Make a copy of the event so we don't alter it for passing on.
81− QKeyEvent eCopy(keyEvent->type(),
82− keyEvent->key(),
83− keyEvent->modifiers(),
84− keyEvent->text(),
85− keyEvent->isAutoRepeat(),
86− keyEvent->count());
87− eCopy.ignore();
88−
8978 int seq = keyEvent->key() + keyEvent->modifiers();
9079 if (m_shortcuts.contains(seq)) {
9180 const auto shortcuts = m_shortcuts.value(seq);
9281 Q_FOREACH(const auto &shortcut, shortcuts) {
9382 if (shortcut) {
94− qApp->sendEvent(shortcut, &eCopy);
83+ qApp->sendEvent(shortcut, keyEvent);
84+ event->accept();
9585 }
9686 }
9787 }
9888
99− return eCopy.isAccepted();
89+ return event->isAccepted();
10090 }
10191
10292 return QObject::eventFilter(obj, event);
plugins/Greeter/Unity/Launcher/CMakeLists.txt+3−1
@@ -1,3 +1,4 @@
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
12pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
23
34add_definitions(-DSM_BUSNAME=systemBus)
@@ -29,7 +30,8 @@ add_library(UnityLauncherAS-qml MODULE
2930target_link_libraries(UnityLauncherAS-qml
3031 unity8-private
3132 ${GSETTINGS_QT_LDFLAGS}
32− Qt5::DBus Qt5::Qml Qt5::Gui
3333 )
3434
35+qt5_use_modules(UnityLauncherAS-qml DBus Qml Gui)
36+
3537add_unity8_greeter_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncherAS-qml)
plugins/Greeter/Unity/Launcher/Launcher.qmltypesnew file+182
@@ -0,0 +1,182 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.Launcher 0.1 plugins/Greeter'
8+
9+Module {
10+ Component {
11+ name: "LauncherItem"
12+ prototype: "unity::shell::launcher::LauncherItemInterface"
13+ exports: ["Unity.Launcher/LauncherItem 0.1"]
14+ isCreatable: false
15+ exportMetaObjectRevisions: [0]
16+ }
17+ Component {
18+ name: "LauncherModel"
19+ prototype: "unity::shell::launcher::LauncherModelInterface"
20+ exports: ["Unity.Launcher/LauncherModel 0.1"]
21+ isCreatable: false
22+ isSingleton: true
23+ exportMetaObjectRevisions: [0]
24+ Method {
25+ name: "requestRemove"
26+ Parameter { name: "appId"; type: "string" }
27+ }
28+ Method { name: "refresh" }
29+ Method {
30+ name: "get"
31+ type: "unity::shell::launcher::LauncherItemInterface*"
32+ Parameter { name: "index"; type: "int" }
33+ }
34+ Method {
35+ name: "move"
36+ Parameter { name: "oldIndex"; type: "int" }
37+ Parameter { name: "newIndex"; type: "int" }
38+ }
39+ Method {
40+ name: "pin"
41+ Parameter { name: "appId"; type: "string" }
42+ Parameter { name: "index"; type: "int" }
43+ }
44+ Method {
45+ name: "pin"
46+ Parameter { name: "appId"; type: "string" }
47+ }
48+ Method {
49+ name: "quickListActionInvoked"
50+ Parameter { name: "appId"; type: "string" }
51+ Parameter { name: "actionIndex"; type: "int" }
52+ }
53+ Method {
54+ name: "setUser"
55+ Parameter { name: "username"; type: "string" }
56+ }
57+ Method {
58+ name: "getUrlForAppId"
59+ type: "string"
60+ Parameter { name: "appId"; type: "string" }
61+ }
62+ }
63+ Component {
64+ name: "QuickListModel"
65+ prototype: "unity::shell::launcher::QuickListModelInterface"
66+ exports: ["Unity.Launcher/QuickListModel 0.1"]
67+ isCreatable: false
68+ exportMetaObjectRevisions: [0]
69+ }
70+ Component {
71+ name: "unity::shell::launcher::LauncherItemInterface"
72+ prototype: "QObject"
73+ exports: ["Unity.Launcher/LauncherItemInterface 0.1"]
74+ isCreatable: false
75+ exportMetaObjectRevisions: [0]
76+ Property { name: "appId"; type: "string"; isReadonly: true }
77+ Property { name: "name"; type: "string"; isReadonly: true }
78+ Property { name: "icon"; type: "string"; isReadonly: true }
79+ Property { name: "pinned"; type: "bool"; isReadonly: true }
80+ Property { name: "running"; type: "bool"; isReadonly: true }
81+ Property { name: "recent"; type: "bool"; isReadonly: true }
82+ Property { name: "progress"; type: "int"; isReadonly: true }
83+ Property { name: "count"; type: "int"; isReadonly: true }
84+ Property { name: "countVisible"; type: "bool"; isReadonly: true }
85+ Property { name: "focused"; type: "bool"; isReadonly: true }
86+ Property {
87+ name: "quickList"
88+ type: "unity::shell::launcher::QuickListModelInterface"
89+ isReadonly: true
90+ isPointer: true
91+ }
92+ Signal {
93+ name: "nameChanged"
94+ Parameter { name: "name"; type: "string" }
95+ }
96+ Signal {
97+ name: "iconChanged"
98+ Parameter { name: "icon"; type: "string" }
99+ }
100+ Signal {
101+ name: "pinnedChanged"
102+ Parameter { name: "pinned"; type: "bool" }
103+ }
104+ Signal {
105+ name: "runningChanged"
106+ Parameter { name: "running"; type: "bool" }
107+ }
108+ Signal {
109+ name: "recentChanged"
110+ Parameter { name: "running"; type: "bool" }
111+ }
112+ Signal {
113+ name: "progressChanged"
114+ Parameter { name: "progress"; type: "int" }
115+ }
116+ Signal {
117+ name: "countChanged"
118+ Parameter { name: "count"; type: "int" }
119+ }
120+ Signal {
121+ name: "countVisibleChanged"
122+ Parameter { name: "countVisible"; type: "bool" }
123+ }
124+ Signal {
125+ name: "focusedChanged"
126+ Parameter { name: "focused"; type: "bool" }
127+ }
128+ }
129+ Component {
130+ name: "unity::shell::launcher::LauncherModelInterface"
131+ prototype: "QAbstractListModel"
132+ exports: ["Unity.Launcher/LauncherModelInterface 0.1"]
133+ isCreatable: false
134+ exportMetaObjectRevisions: [0]
135+ Property {
136+ name: "applicationManager"
137+ type: "unity::shell::application::ApplicationManagerInterface"
138+ isPointer: true
139+ }
140+ Property { name: "onlyPinned"; type: "bool" }
141+ Signal { name: "hint" }
142+ Method {
143+ name: "move"
144+ Parameter { name: "oldIndex"; type: "int" }
145+ Parameter { name: "newIndex"; type: "int" }
146+ }
147+ Method {
148+ name: "get"
149+ type: "unity::shell::launcher::LauncherItemInterface*"
150+ Parameter { name: "index"; type: "int" }
151+ }
152+ Method {
153+ name: "pin"
154+ Parameter { name: "appId"; type: "string" }
155+ Parameter { name: "index"; type: "int" }
156+ }
157+ Method {
158+ name: "pin"
159+ Parameter { name: "appId"; type: "string" }
160+ }
161+ Method {
162+ name: "requestRemove"
163+ Parameter { name: "appId"; type: "string" }
164+ }
165+ Method {
166+ name: "quickListActionInvoked"
167+ Parameter { name: "appId"; type: "string" }
168+ Parameter { name: "actionIndex"; type: "int" }
169+ }
170+ Method {
171+ name: "setUser"
172+ Parameter { name: "username"; type: "string" }
173+ }
174+ }
175+ Component {
176+ name: "unity::shell::launcher::QuickListModelInterface"
177+ prototype: "QAbstractListModel"
178+ exports: ["Unity.Launcher/QuickListInterface 0.1"]
179+ isCreatable: false
180+ exportMetaObjectRevisions: [0]
181+ }
182+}
plugins/Greeter/Unity/Launcher/launcheritem.cpp−33
@@ -32,7 +32,6 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3232 m_countVisible(false),
3333 m_focused(false),
3434 m_alerting(false),
35− m_surfaceCount(0),
3635 m_quickList(new QuickListModel(this))
3736{
3837 QuickListEntry nameAction;
@@ -76,25 +75,6 @@ void LauncherItem::setIcon(const QString &icon)
7675 }
7776}
7877
79−QStringList LauncherItem::keywords() const
80−{
81− return m_keywords;
82−}
83−
84−void LauncherItem::setKeywords(const QStringList &keywords)
85−{
86− if (m_keywords != keywords) {
87− m_keywords = keywords;
88− Q_EMIT keywordsChanged(keywords);
89− }
90−}
91−
92−uint LauncherItem::popularity() const
93−{
94− // Not exposing usage order in greeter session at this point.
95− return 0;
96−}
97−
9878bool LauncherItem::pinned() const
9979{
10080 return m_pinned;
@@ -199,19 +179,6 @@ void LauncherItem::setAlerting(bool alerting)
199179 }
200180}
201181
202−int LauncherItem::surfaceCount() const
203−{
204− return m_surfaceCount;
205−}
206−
207−void LauncherItem::setSurfaceCount(int surfaceCount)
208−{
209− if (m_surfaceCount != surfaceCount) {
210− m_surfaceCount = surfaceCount;
211− Q_EMIT surfaceCountChanged(surfaceCount);
212− }
213−}
214−
215182unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
216183{
217184 return m_quickList;
plugins/Greeter/Unity/Launcher/launcheritem.h+1−7
@@ -34,8 +34,6 @@ public:
3434 QString appId() const override;
3535 QString name() const override;
3636 QString icon() const override;
37− QStringList keywords() const override;
38− uint popularity() const override;
3937 bool pinned() const override;
4038 bool running() const override;
4139 bool recent() const override;
@@ -44,14 +42,12 @@ public:
4442 bool countVisible() const override;
4543 bool focused() const override;
4644 bool alerting() const override;
47− int surfaceCount() const override;
4845
4946 unity::shell::launcher::QuickListModelInterface *quickList() const override;
5047
5148private:
5249 void setName(const QString &name);
5350 void setIcon(const QString &icon);
54− void setKeywords(const QStringList &keywords);
5551 void setPinned(bool pinned);
5652 void setRunning(bool running);
5753 void setRecent(bool recent);
@@ -60,13 +56,12 @@ private:
6056 void setCountVisible(bool countVisible);
6157 void setFocused(bool focused);
6258 void setAlerting(bool alerting);
63− void setSurfaceCount(int surfaceCount);
59+
6460
6561private:
6662 QString m_appId;
6763 QString m_name;
6864 QString m_icon;
69− QStringList m_keywords;
7065 bool m_pinned;
7166 bool m_running;
7267 bool m_recent;
@@ -75,7 +70,6 @@ private:
7570 bool m_countVisible;
7671 bool m_focused;
7772 bool m_alerting;
78− int m_surfaceCount;
7973 QuickListModel *m_quickList;
8074
8175 friend class LauncherModel;
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+7−2
@@ -69,13 +69,18 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
6969 return item->focused();
7070 case RoleRunning:
7171 return item->running();
72− case RoleSurfaceCount:
73− return item->surfaceCount();
7472 }
7573
7674 return QVariant();
7775}
7876
77+void LauncherModel::setAlerting(const QString &appId, bool alerting)
78+{
79+ Q_UNUSED(appId)
80+ Q_UNUSED(alerting)
81+ qWarning() << "This is a read only implementation. Cannot set alert-state of items.";
82+}
83+
7984unity::shell::launcher::LauncherItemInterface *LauncherModel::get(int index) const
8085{
8186 if (index < 0 || index >= m_list.count()) {
plugins/Greeter/Unity/Launcher/launchermodelas.h+1
@@ -41,6 +41,7 @@ public:
4141
4242 QVariant data(const QModelIndex &index, int role) const override;
4343
44+ Q_INVOKABLE void setAlerting(const QString &appId, bool alerting) override;
4445 Q_INVOKABLE unity::shell::launcher::LauncherItemInterface* get(int index) const override;
4546 Q_INVOKABLE void move(int oldIndex, int newIndex) override;
4647 Q_INVOKABLE void pin(const QString &appId, int index = -1) override;
plugins/Greeter/Unity/Launcher/quicklistmodel.cpp−2
@@ -65,8 +65,6 @@ QVariant QuickListModel::data(const QModelIndex &index, int role) const
6565 return m_list.at(index.row()).icon();
6666 case RoleClickable:
6767 return m_list.at(index.row()).clickable();
68− case RoleIsPrivate:
69− return false; // The greeter plugin would just not add any private entries
7068 }
7169 return QVariant();
7270}
plugins/IntegratedLightDM/CMakeLists.txtnew file+40
@@ -0,0 +1,40 @@
1+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2+# TODO: Once we split out a separate greeter process, uncomment these lines
3+#pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-2)
4+
5+add_subdirectory(liblightdm)
6+
7+include_directories(
8+ ${CMAKE_CURRENT_SOURCE_DIR}
9+ ${CMAKE_CURRENT_BINARY_DIR}
10+ ${CMAKE_SOURCE_DIR}/plugins/Utils
11+ ${CMAKE_SOURCE_DIR}/tests/mocks/IntegratedLightDM
12+ #${LIBLIGHTDM_INCLUDE_DIRS}
13+ ${libunity8-private_SOURCE_DIR}
14+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
15+)
16+
17+set(QMLPLUGIN_SRC
18+ ../Utils/unitysortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
19+ DBusGreeter.cpp
20+ DBusGreeterList.cpp
21+ Greeter.cpp
22+ plugin.cpp
23+ UsersModel.cpp
24+ )
25+
26+add_library(IntegratedLightDM-qml MODULE
27+ ${QMLPLUGIN_SRC}
28+ )
29+
30+target_link_libraries(IntegratedLightDM-qml
31+ integratedLightDM
32+ unity8-private
33+# TODO: Once we split out a separate greeter process, uncomment these lines
34+# ${LIBLIGHTDM_LDFLAGS}
35+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
36+ )
37+
38+qt5_use_modules(IntegratedLightDM-qml DBus Gui Qml)
39+
40+add_unity8_plugin(IntegratedLightDM 0.1 IntegratedLightDM TARGETS IntegratedLightDM-qml)
plugins/LightDM/DBusGreeter.cpp → plugins/IntegratedLightDM/DBusGreeter.cpprenamed+4−5
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014, 2015 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -24,8 +24,7 @@ DBusGreeter::DBusGreeter(Greeter *greeter, const QString &path)
2424 : UnityDBusObject(path, QStringLiteral("com.canonical.UnityGreeter"), true, greeter),
2525 m_greeter(greeter)
2626{
27− connect(m_greeter, &Greeter::isActiveChanged,
28− this, &DBusGreeter::isActiveChangedHandler);
27+ connect(m_greeter, &Greeter::isActiveChanged, this, &DBusGreeter::isActiveChangedHandler);
2928}
3029
3130bool DBusGreeter::isActive() const
@@ -35,12 +34,12 @@ bool DBusGreeter::isActive() const
3534
3635void DBusGreeter::ShowGreeter()
3736{
38− Q_EMIT m_greeter->showGreeter();
37+ return Q_EMIT m_greeter->showGreeter();
3938}
4039
4140void DBusGreeter::HideGreeter()
4241{
43− Q_EMIT m_greeter->hideGreeter();
42+ return Q_EMIT m_greeter->hideGreeter();
4443}
4544
4645void DBusGreeter::isActiveChangedHandler()
plugins/LightDM/DBusGreeter.h → plugins/IntegratedLightDM/DBusGreeter.hrenamed
The content is the same.
plugins/LightDM/DBusGreeterList.cpp → plugins/IntegratedLightDM/DBusGreeterList.cpprenamed+3−3
@@ -43,10 +43,10 @@ bool DBusGreeterList::entryIsLocked() const
4343 return !m_greeter->promptless();
4444}
4545
46−void DBusGreeterList::authenticationUserChangedHandler()
46+void DBusGreeterList::authenticationUserChangedHandler(const QString &user)
4747{
48− notifyPropertyChanged(QStringLiteral("ActiveEntry"), m_greeter->authenticationUser());
49− Q_EMIT EntrySelected(m_greeter->authenticationUser());
48+ notifyPropertyChanged(QStringLiteral("ActiveEntry"), user);
49+ Q_EMIT EntrySelected(user);
5050}
5151
5252void DBusGreeterList::promptlessChangedHandler()
plugins/LightDM/DBusGreeterList.h → plugins/IntegratedLightDM/DBusGreeterList.hrenamed+1−1
@@ -47,7 +47,7 @@ Q_SIGNALS:
4747 void entryIsLockedChanged();
4848
4949private Q_SLOTS:
50− void authenticationUserChangedHandler();
50+ void authenticationUserChangedHandler(const QString &user);
5151 void promptlessChangedHandler();
5252
5353private:
plugins/IntegratedLightDM/Greeter.cppnew file+138
@@ -0,0 +1,138 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "Greeter.h"
20+#include "GreeterPrivate.h"
21+#include <libintl.h>
22+
23+GreeterPrivate::GreeterPrivate(Greeter* parent)
24+ : m_greeter(new QLightDM::Greeter(parent)),
25+ m_active(false),
26+ wasPrompted(false),
27+ promptless(false),
28+ q_ptr(parent)
29+{
30+}
31+
32+Greeter::Greeter(QObject* parent)
33+ : QObject(parent),
34+ d_ptr(new GreeterPrivate(this))
35+{
36+ Q_D(Greeter);
37+
38+ connect(d->m_greeter, &QLightDM::Greeter::showMessage,
39+ this, &Greeter::showMessageFilter);
40+ connect(d->m_greeter, &QLightDM::Greeter::showPrompt,
41+ this, &Greeter::showPromptFilter);
42+ connect(d->m_greeter, &QLightDM::Greeter::authenticationComplete,
43+ this, &Greeter::authenticationCompleteFilter);
44+
45+ d->m_greeter->connectSync();
46+}
47+
48+bool Greeter::isActive() const
49+{
50+ Q_D(const Greeter);
51+ return d->m_active;
52+}
53+
54+void Greeter::setIsActive(bool active)
55+{
56+ Q_D(Greeter);
57+ if (d->m_active != active) {
58+ d->m_active = active;
59+ Q_EMIT isActiveChanged();
60+ }
61+}
62+
63+bool Greeter::isAuthenticated() const
64+{
65+ Q_D(const Greeter);
66+ return d->m_greeter->isAuthenticated();
67+}
68+
69+QString Greeter::authenticationUser() const
70+{
71+ Q_D(const Greeter);
72+ return d->m_greeter->authenticationUser();
73+}
74+
75+bool Greeter::promptless() const
76+{
77+ Q_D(const Greeter);
78+ return d->promptless;
79+}
80+
81+void Greeter::authenticate(const QString &username)
82+{
83+ Q_D(Greeter);
84+ d->wasPrompted = false;
85+ if (d->promptless) {
86+ d->promptless = false;
87+ Q_EMIT promptlessChanged();
88+ }
89+
90+ d->m_greeter->authenticate(username);
91+ Q_EMIT isAuthenticatedChanged();
92+ Q_EMIT authenticationUserChanged(username);
93+}
94+
95+void Greeter::respond(const QString &response)
96+{
97+ Q_D(Greeter);
98+ d->m_greeter->respond(response);
99+}
100+
101+bool Greeter::startSessionSync(const QString &session)
102+{
103+ Q_D(Greeter);
104+ return d->m_greeter->startSessionSync(session);
105+}
106+
107+void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
108+{
109+ Q_D(Greeter);
110+ d->wasPrompted = true;
111+
112+ bool isDefaultPrompt = (text == dgettext("Linux-PAM", "Password: "));
113+
114+ // Strip prompt of any colons at the end
115+ QString trimmedText = text.trimmed();
116+ if (trimmedText.endsWith(':') || trimmedText.endsWith(QStringLiteral(":"))) {
117+ trimmedText.chop(1);
118+ }
119+
120+ Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret, isDefaultPrompt);
121+}
122+
123+void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
124+{
125+ Q_EMIT showMessage(text, type == QLightDM::Greeter::MessageTypeError);
126+}
127+
128+void Greeter::authenticationCompleteFilter()
129+{
130+ Q_D(Greeter);
131+ if (!d->wasPrompted) {
132+ d->promptless = true;
133+ Q_EMIT promptlessChanged();
134+ }
135+
136+ Q_EMIT isAuthenticatedChanged();
137+ Q_EMIT authenticationComplete();
138+}
plugins/LightDM/Greeter.h → plugins/IntegratedLightDM/Greeter.hrenamed+11−21
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012-2016 Canonical, Ltd.
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -13,6 +13,7 @@
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
1617 */
1718
1819/* This class is a really tiny filter around QLightDM::Greeter. There are some
@@ -21,13 +22,13 @@
2122 such edits in the future, and by inserting ourselves here, we have more
2223 control. */
2324
24−#pragma once
25+#ifndef UNITY_GREETER_H
26+#define UNITY_GREETER_H
2527
2628#include <QLightDM/Greeter>
2729#include <QtCore/QObject>
2830
2931class GreeterPrivate;
30−class PromptsModel;
3132
3233class Greeter : public QObject
3334{
@@ -36,25 +37,15 @@ class Greeter : public QObject
3637 Q_PROPERTY(bool active READ isActive WRITE setIsActive NOTIFY isActiveChanged)
3738 Q_PROPERTY(bool authenticated READ isAuthenticated NOTIFY isAuthenticatedChanged)
3839 Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
39− Q_PROPERTY(QString defaultSession READ defaultSessionHint CONSTANT)
4040 Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
41− Q_PROPERTY(QString selectUser READ selectUser CONSTANT)
4241
4342public:
44− static Greeter *instance();
45− virtual ~Greeter();
43+ explicit Greeter(QObject* parent=0);
4644
4745 bool isActive() const;
4846 bool isAuthenticated() const;
4947 QString authenticationUser() const;
50− QString defaultSessionHint() const;
5148 bool promptless() const;
52− QString selectUser() const;
53− bool hasGuestAccount() const;
54− bool showManualLoginHint() const;
55− bool hideUsersHint() const;
56−
57− PromptsModel *promptsModel();
5849
5950public Q_SLOTS:
6051 void authenticate(const QString &username=QString());
@@ -63,23 +54,21 @@ public Q_SLOTS:
6354 void setIsActive(bool isActive);
6455
6556Q_SIGNALS:
66− void authenticationUserChanged();
57+ void showMessage(const QString &text, bool isError);
58+ void showPrompt(const QString &text, bool isSecret, bool isDefaultPrompt);
59+ void authenticationComplete();
60+ void authenticationUserChanged(const QString &user);
6761 void isActiveChanged();
6862 void isAuthenticatedChanged();
6963 void promptlessChanged();
7064 void showGreeter();
7165 void hideGreeter();
72− void loginError(bool automatic);
73− void loginSuccess(bool automatic);
74− void authenticationStarted(); // useful for testing
7566
7667 // This signal is emitted by external agents like indicators, and the UI
7768 // should switch to this user if possible.
7869 void requestAuthenticationUser(const QString &user);
7970
8071protected:
81− explicit Greeter(QObject* parent=0);
82−
8372 GreeterPrivate * const d_ptr;
8473
8574 Q_DECLARE_PRIVATE(Greeter)
@@ -88,5 +77,6 @@ private Q_SLOTS:
8877 void showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type);
8978 void showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type);
9079 void authenticationCompleteFilter();
91− void checkAuthenticationUser();
9280};
81+
82+#endif
plugins/LightDM/GreeterPrivate.h → plugins/IntegratedLightDM/GreeterPrivate.hrenamed+7−13
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2015-2017 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,14 +14,10 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#pragma once
17+#ifndef UNITY_GREETER_PRIVATE_H
18+#define UNITY_GREETER_PRIVATE_H
1819
19−#include "PromptsModel.h"
20−#include <QObject>
21−
22−namespace QLightDM {
23− class Greeter;
24−}
20+#include <QLightDM/Greeter>
2521
2622class GreeterPrivate
2723{
@@ -30,12 +26,8 @@ public:
3026
3127 QLightDM::Greeter *m_greeter;
3228 bool m_active;
33− PromptsModel prompts;
34− PromptsModel leftovers; // prompts to show during next auth for same user
35− bool responded;
36− bool everResponded;
29+ bool wasPrompted;
3730 bool promptless;
38− QString cachedAuthUser;
3931
4032protected:
4133 Greeter * const q_ptr;
@@ -43,3 +35,5 @@ protected:
4335private:
4436 Q_DECLARE_PUBLIC(Greeter)
4537};
38+
39+#endif // UNITY_GREETER_PRIVATE_H
plugins/IntegratedLightDM/IntegratedLightDM.qmltypesnew file+251
@@ -0,0 +1,251 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable LightDM 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "Greeter"
12+ prototype: "QObject"
13+ exports: ["LightDM/Greeter 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Property { name: "active"; type: "bool" }
18+ Property { name: "authenticated"; type: "bool"; isReadonly: true }
19+ Property { name: "authenticationUser"; type: "string"; isReadonly: true }
20+ Property { name: "promptless"; type: "bool"; isReadonly: true }
21+ Signal {
22+ name: "showMessage"
23+ Parameter { name: "text"; type: "string" }
24+ Parameter { name: "isError"; type: "bool" }
25+ }
26+ Signal {
27+ name: "showPrompt"
28+ Parameter { name: "text"; type: "string" }
29+ Parameter { name: "isSecret"; type: "bool" }
30+ Parameter { name: "isDefaultPrompt"; type: "bool" }
31+ }
32+ Signal { name: "authenticationComplete" }
33+ Signal {
34+ name: "authenticationUserChanged"
35+ Parameter { name: "user"; type: "string" }
36+ }
37+ Signal { name: "isActiveChanged" }
38+ Signal { name: "isAuthenticatedChanged" }
39+ Signal { name: "showGreeter" }
40+ Signal { name: "hideGreeter" }
41+ Signal {
42+ name: "requestAuthenticationUser"
43+ Parameter { name: "user"; type: "string" }
44+ }
45+ Method {
46+ name: "authenticate"
47+ Parameter { name: "username"; type: "string" }
48+ }
49+ Method { name: "authenticate" }
50+ Method {
51+ name: "respond"
52+ Parameter { name: "response"; type: "string" }
53+ }
54+ Method {
55+ name: "startSessionSync"
56+ type: "bool"
57+ Parameter { name: "session"; type: "string" }
58+ }
59+ Method { name: "startSessionSync"; type: "bool" }
60+ Method {
61+ name: "setIsActive"
62+ Parameter { name: "isActive"; type: "bool" }
63+ }
64+ }
65+ Component {
66+ name: "QAbstractProxyModel"
67+ prototype: "QAbstractItemModel"
68+ Property { name: "sourceModel"; type: "QAbstractItemModel"; isPointer: true }
69+ }
70+ Component {
71+ name: "QLightDM::UsersModel"
72+ prototype: "QAbstractListModel"
73+ exports: ["LightDM/UserRoles 0.1"]
74+ isCreatable: false
75+ exportMetaObjectRevisions: [0]
76+ Enum {
77+ name: "UserModelRoles"
78+ values: {
79+ "NameRole": 256,
80+ "RealNameRole": 257,
81+ "LoggedInRole": 258,
82+ "BackgroundRole": 259,
83+ "SessionRole": 260,
84+ "HasMessagesRole": 261,
85+ "ImagePathRole": 262,
86+ "BackgroundPathRole": 263
87+ }
88+ }
89+ }
90+ Component {
91+ name: "QSortFilterProxyModel"
92+ prototype: "QAbstractProxyModel"
93+ Property { name: "filterRegExp"; type: "QRegExp" }
94+ Property { name: "filterKeyColumn"; type: "int" }
95+ Property { name: "dynamicSortFilter"; type: "bool" }
96+ Property { name: "filterCaseSensitivity"; type: "Qt::CaseSensitivity" }
97+ Property { name: "sortCaseSensitivity"; type: "Qt::CaseSensitivity" }
98+ Property { name: "isSortLocaleAware"; type: "bool" }
99+ Property { name: "sortRole"; type: "int" }
100+ Property { name: "filterRole"; type: "int" }
101+ Method {
102+ name: "setFilterRegExp"
103+ Parameter { name: "pattern"; type: "string" }
104+ }
105+ Method {
106+ name: "setFilterWildcard"
107+ Parameter { name: "pattern"; type: "string" }
108+ }
109+ Method {
110+ name: "setFilterFixedString"
111+ Parameter { name: "pattern"; type: "string" }
112+ }
113+ Method { name: "clear" }
114+ Method { name: "invalidate" }
115+ }
116+ Component {
117+ name: "UnitySortFilterProxyModelQML"
118+ prototype: "QSortFilterProxyModel"
119+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
120+ Property { name: "totalCount"; type: "int"; isReadonly: true }
121+ Property { name: "count"; type: "int"; isReadonly: true }
122+ Property { name: "invertMatch"; type: "bool" }
123+ Signal {
124+ name: "invertMatchChanged"
125+ Parameter { type: "bool" }
126+ }
127+ Method {
128+ name: "get"
129+ type: "QVariantMap"
130+ Parameter { name: "row"; type: "int" }
131+ }
132+ Method {
133+ name: "data"
134+ type: "QVariant"
135+ Parameter { name: "row"; type: "int" }
136+ Parameter { name: "role"; type: "int" }
137+ }
138+ Method { name: "count"; type: "int" }
139+ Method {
140+ name: "findFirst"
141+ type: "int"
142+ Parameter { name: "role"; type: "int" }
143+ Parameter { name: "value"; type: "QVariant" }
144+ }
145+ Method {
146+ name: "mapRowToSource"
147+ type: "int"
148+ Parameter { name: "row"; type: "int" }
149+ }
150+ Method {
151+ name: "mapFromSource"
152+ type: "int"
153+ Parameter { name: "row"; type: "int" }
154+ }
155+ Method {
156+ name: "mapToSource"
157+ type: "int"
158+ Parameter { name: "row"; type: "int" }
159+ }
160+ }
161+ Component {
162+ name: "UserMetricsOutput::ColorTheme"
163+ prototype: "QObject"
164+ Property { name: "start"; type: "QColor"; isReadonly: true }
165+ Property { name: "main"; type: "QColor"; isReadonly: true }
166+ Property { name: "end"; type: "QColor"; isReadonly: true }
167+ Signal {
168+ name: "startChanged"
169+ Parameter { name: "color"; type: "QColor" }
170+ }
171+ Signal {
172+ name: "mainChanged"
173+ Parameter { name: "color"; type: "QColor" }
174+ }
175+ Signal {
176+ name: "endChanged"
177+ Parameter { name: "color"; type: "QColor" }
178+ }
179+ }
180+ Component {
181+ name: "UserMetricsOutput::UserMetrics"
182+ prototype: "QObject"
183+ exports: ["LightDM/Infographic 0.1"]
184+ isCreatable: false
185+ isSingleton: true
186+ exportMetaObjectRevisions: [0]
187+ Property { name: "label"; type: "string"; isReadonly: true }
188+ Property { name: "username"; type: "string" }
189+ Property {
190+ name: "firstColor"
191+ type: "UserMetricsOutput::ColorTheme"
192+ isReadonly: true
193+ isPointer: true
194+ }
195+ Property {
196+ name: "secondColor"
197+ type: "UserMetricsOutput::ColorTheme"
198+ isReadonly: true
199+ isPointer: true
200+ }
201+ Property { name: "firstMonth"; type: "QAbstractItemModel"; isReadonly: true; isPointer: true }
202+ Property { name: "secondMonth"; type: "QAbstractItemModel"; isReadonly: true; isPointer: true }
203+ Property { name: "currentDay"; type: "int"; isReadonly: true }
204+ Signal {
205+ name: "labelChanged"
206+ Parameter { name: "label"; type: "string" }
207+ }
208+ Signal {
209+ name: "usernameChanged"
210+ Parameter { name: "username"; type: "string" }
211+ }
212+ Signal {
213+ name: "firstColorChanged"
214+ Parameter { name: "color"; type: "ColorTheme"; isPointer: true }
215+ }
216+ Signal {
217+ name: "firstMonthChanged"
218+ Parameter { name: "firstMonth"; type: "QAbstractItemModel"; isPointer: true }
219+ }
220+ Signal {
221+ name: "currentDayChanged"
222+ Parameter { name: "currentDay"; type: "int" }
223+ }
224+ Signal {
225+ name: "secondColorChanged"
226+ Parameter { name: "color"; type: "ColorTheme"; isPointer: true }
227+ }
228+ Signal {
229+ name: "secondMonthChanged"
230+ Parameter { name: "secondMonth"; type: "QAbstractItemModel"; isPointer: true }
231+ }
232+ Signal { name: "nextDataSource" }
233+ Signal { name: "readyForDataChange" }
234+ Signal { name: "dataAboutToAppear" }
235+ Signal { name: "dataAppeared" }
236+ Signal { name: "dataAboutToChange" }
237+ Signal { name: "dataChanged" }
238+ Signal { name: "dataAboutToDisappear" }
239+ Signal { name: "dataDisappeared" }
240+ Method { name: "nextDataSourceSlot" }
241+ Method { name: "readyForDataChangeSlot" }
242+ }
243+ Component {
244+ name: "UsersModel"
245+ prototype: "UnitySortFilterProxyModelQML"
246+ exports: ["LightDM/Users 0.1"]
247+ isCreatable: false
248+ isSingleton: true
249+ exportMetaObjectRevisions: [0]
250+ }
251+}
plugins/IntegratedLightDM/UsersModel.cppnew file+71
@@ -0,0 +1,71 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "UsersModel.h"
20+#include <QLightDM/UsersModel>
21+#include <QtCore/QSortFilterProxyModel>
22+
23+// First, we define an internal class that wraps LightDM's UsersModel. This
24+// class will modify some of the data coming from LightDM. For example, we
25+// modify any empty Real Names into just normal Names.
26+// (We can't modify the data directly in UsersModel below because it won't sort
27+// using the modified data.)
28+class MangleModel : public QSortFilterProxyModel
29+{
30+ Q_OBJECT
31+
32+public:
33+ explicit MangleModel(QObject* parent=0);
34+
35+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
36+};
37+
38+MangleModel::MangleModel(QObject* parent)
39+ : QSortFilterProxyModel(parent)
40+{
41+ setSourceModel(new QLightDM::UsersModel(this));
42+}
43+
44+QVariant MangleModel::data(const QModelIndex &index, int role) const
45+{
46+ QVariant variantData = QSortFilterProxyModel::data(index, role);
47+
48+ // If user's real name is empty, switch to unix name
49+ if (role == QLightDM::UsersModel::RealNameRole && variantData.toString().isEmpty()) {
50+ variantData = QSortFilterProxyModel::data(index, QLightDM::UsersModel::NameRole);
51+ } else if (role == QLightDM::UsersModel::BackgroundPathRole && variantData.toString().startsWith('#')) {
52+ const QString stringData = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + variantData.toString() + "'/></svg>";
53+ variantData = stringData;
54+ }
55+
56+ return variantData;
57+}
58+
59+// **** Now we continue with actual UsersModel class ****
60+
61+UsersModel::UsersModel(QObject* parent)
62+ : UnitySortFilterProxyModelQML(parent)
63+{
64+ setModel(new MangleModel(this));
65+ setSortCaseSensitivity(Qt::CaseInsensitive);
66+ setSortLocaleAware(true);
67+ setSortRole(QLightDM::UsersModel::RealNameRole);
68+ sort(0);
69+}
70+
71+#include "UsersModel.moc"
plugins/LightDM/UsersModel.h → plugins/IntegratedLightDM/UsersModel.hrenamed+8−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012-2013,2015-2016 Canonical, Ltd.
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,16 +12,19 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
1517 */
1618
1719/* This class is a really tiny filter around QLightDM::UsersModel. There are
1820 some operations that we want to edit a bit for the benefit of Qml.
1921 Specifically, we want to sort users according to realName. */
2022
21−#pragma once
23+#ifndef UNITY_USERSMODEL_H
24+#define UNITY_USERSMODEL_H
2225
2326#include <unitysortfilterproxymodelqml.h>
24−#include <QObject>
27+#include <QtCore/QObject>
2528
2629class UsersModel : public UnitySortFilterProxyModelQML
2730{
@@ -29,7 +32,6 @@ class UsersModel : public UnitySortFilterProxyModelQML
2932
3033public:
3134 explicit UsersModel(QObject* parent=0);
32−
33−protected:
34− bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
3535};
36+
37+#endif
plugins/LightDM/IntegratedLightDM/liblightdm/CMakeLists.txt → plugins/IntegratedLightDM/liblightdm/CMakeLists.txtrenamed+6−7
@@ -2,10 +2,8 @@ pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
22
33set(LibLightDM_SOURCES
44 Greeter.cpp
5− SessionsModel.cpp
65 UsersModel.cpp
76 GreeterPrivate.cpp
8− SessionsModelPrivate.cpp
97 UsersModelPrivate.cpp
108 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
119 ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
@@ -26,29 +24,30 @@ target_link_libraries(integratedLightDM
2624 ${GLIB_LIBRARIES}
2725 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
2826 -lpam
29− Qt5::Concurrent Qt5::DBus Qt5::Gui
3027)
3128target_link_libraries(integratedLightDMSession
3229 ${GLIB_LIBRARIES}
3330 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
3431 -lpam
35− Qt5::Concurrent Qt5::DBus Qt5::Gui
3632)
3733target_link_libraries(MockLightDM-demo-shared
3834 ${GLIB_LIBRARIES}
3935 ${LIBUSERMETRICSOUTPUT_LDFLAGS}
4036 -lpam
41− Qt5::Concurrent Qt5::DBus Qt5::Gui
4237)
4338
39+qt5_use_modules(integratedLightDM Concurrent DBus Gui)
40+qt5_use_modules(integratedLightDMSession Concurrent DBus Gui)
41+qt5_use_modules(MockLightDM-demo-shared Concurrent DBus Gui)
42+
4443set_target_properties(integratedLightDM PROPERTIES
4544 COMPILE_FLAGS "-DSM_BUSNAME=systemBus -fPIC")
4645set_target_properties(integratedLightDMSession PROPERTIES
4746 COMPILE_FLAGS "-DSM_BUSNAME=sessionBus -fPIC")
4847set_target_properties(MockLightDM-demo-shared PROPERTIES
4948 COMPILE_FLAGS "-DSM_BUSNAME=systemBus"
50− OUTPUT_NAME lightdm-qt5-3)
49+ OUTPUT_NAME lightdm-qt5-2)
5150
5251install(TARGETS MockLightDM-demo-shared
53− DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/IntegratedLightDM/demo
52+ DESTINATION ${SHELL_INSTALL_QML}/mocks/IntegratedLightDM/demo
5453 )
plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.cpp → plugins/IntegratedLightDM/liblightdm/Greeter.cpprenamed+8−6
@@ -49,7 +49,7 @@ QString Greeter::authenticationUser() const
4949
5050bool Greeter::hasGuestAccountHint() const
5151{
52− return false;
52+ return true;
5353}
5454
5555QString Greeter::getHint(const QString &name) const
@@ -70,10 +70,15 @@ bool Greeter::hideUsersHint() const
7070
7171bool Greeter::showManualLoginHint() const
7272{
73− return false;
73+ return true;
7474}
7575
7676bool Greeter::showRemoteLoginHint() const
77+{
78+ return true;
79+}
80+
81+bool Greeter::lockHint () const
7782{
7883 return false;
7984}
@@ -146,10 +151,7 @@ void Greeter::authenticateRemote(const QString &session, const QString &username
146151}
147152
148153void Greeter::cancelAuthentication()
149−{
150− Q_D(Greeter);
151− d->cancelAuthentication();
152−}
154+{}
153155
154156void Greeter::setLanguage (const QString &language)
155157{
plugins/LightDM/IntegratedLightDM/liblightdm/Greeter.h → plugins/IntegratedLightDM/liblightdm/Greeter.hrenamed+4−2
@@ -45,19 +45,20 @@ class Q_DECL_EXPORT Greeter : public QObject
4545
4646 Q_PROPERTY(QString hostname READ hostname CONSTANT)
4747 Q_PROPERTY(bool hasGuestAccount READ hasGuestAccountHint CONSTANT)
48+ Q_PROPERTY(bool locked READ lockHint CONSTANT)
49+
50+ Q_ENUMS(PromptType MessageType)
4851
4952public:
5053 enum PromptType {
5154 PromptTypeQuestion,
5255 PromptTypeSecret
5356 };
54− Q_ENUM(PromptType)
5557
5658 enum MessageType {
5759 MessageTypeInfo,
5860 MessageTypeError
5961 };
60− Q_ENUM(MessageType)
6162
6263 explicit Greeter(QObject* parent=0);
6364 virtual ~Greeter();
@@ -67,6 +68,7 @@ public:
6768 bool hideUsersHint() const;
6869 bool showManualLoginHint() const;
6970 bool showRemoteLoginHint() const;
71+ bool lockHint () const;
7072 bool hasGuestAccountHint() const;
7173 QString selectUserHint() const;
7274 bool selectGuestHint() const;
plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.cpp → plugins/IntegratedLightDM/liblightdm/GreeterPrivate.cpprenamed+24−28
@@ -50,7 +50,8 @@ public:
5050 {
5151 qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture");
5252
53− connect(&futureWatcher, &QFutureWatcher<int>::finished, this, &GreeterImpl::finishPam);
53+ connect(&futureWatcher, &QFutureWatcher<int>::finished,
54+ this, &GreeterImpl::finishPam);
5455 connect(this, SIGNAL(showMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)),
5556 this, SLOT(handleMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)));
5657 // This next connect is how we pass ResponseFutures between threads
@@ -206,28 +207,6 @@ public Q_SLOTS:
206207 }
207208 }
208209
209− void cancelPam()
210− {
211− if (pamHandle != nullptr) {
212− QFuture<int> pamFuture = futureWatcher.future();
213− pam_handle *handle = pamHandle;
214− pamHandle = nullptr; // to disable normal finishPam() handling
215− pamFuture.cancel();
216−
217− // Note the empty loop, we just want to clear the futures queue.
218− // Any further prompts from the pam thread will be immediately
219− // responded to/dismissed in handlePrompt().
220− while (respond(QString()));
221−
222− // Now let signal/slot handling happen so the thread can finish
223− while (!pamFuture.isFinished()) {
224− QCoreApplication::processEvents();
225− }
226−
227− pam_end(handle, PAM_CONV_ERR);
228− }
229− }
230−
231210Q_SIGNALS:
232211 void showMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type);
233212 void showPrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
@@ -269,6 +248,28 @@ private Q_SLOTS:
269248 }
270249
271250private:
251+ void cancelPam()
252+ {
253+ if (pamHandle != nullptr) {
254+ QFuture<int> pamFuture = futureWatcher.future();
255+ pam_handle *handle = pamHandle;
256+ pamHandle = nullptr; // to disable normal finishPam() handling
257+ pamFuture.cancel();
258+
259+ // Note the empty loop, we just want to clear the futures queue.
260+ // Any further prompts from the pam thread will be immediately
261+ // responded to/dismissed in handlePrompt().
262+ while (respond(QString()));
263+
264+ // Now let signal/slot handling happen so the thread can finish
265+ while (!pamFuture.isFinished()) {
266+ QCoreApplication::processEvents();
267+ }
268+
269+ pam_end(handle, PAM_CONV_ERR);
270+ }
271+ }
272+
272273 Greeter *greeter;
273274 GreeterPrivate *greeterPrivate;
274275 pam_handle* pamHandle;
@@ -299,11 +300,6 @@ void GreeterPrivate::handleRespond(const QString &response)
299300 m_impl->respond(response);
300301}
301302
302−void GreeterPrivate::cancelAuthentication()
303−{
304− m_impl->cancelPam();
305−}
306−
307303}
308304
309305#include "GreeterPrivate.moc"
plugins/LightDM/IntegratedLightDM/liblightdm/GreeterPrivate.h → plugins/IntegratedLightDM/liblightdm/GreeterPrivate.hrenamed−1
@@ -38,7 +38,6 @@ public:
3838
3939 void handleAuthenticate();
4040 void handleRespond(const QString &response);
41− void cancelAuthentication();
4241
4342protected:
4443 GreeterImpl *m_impl; // if the backend needs more private data
plugins/LightDM/IntegratedLightDM/liblightdm/UsersModel.cpp → plugins/IntegratedLightDM/liblightdm/UsersModel.cpprenamed+3−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -40,6 +40,8 @@ UsersModel::UsersModel(QObject *parent) :
4040 QAbstractListModel(parent),
4141 d_ptr(new UsersModelPrivate(this))
4242{
43+ Q_D(UsersModel);
44+
4345 // Extend roleNames (we want to keep the "display" role)
4446 QHash<int, QByteArray> roles = roleNames();
4547 roles[NameRole] = "name";
@@ -50,7 +52,6 @@ UsersModel::UsersModel(QObject *parent) :
5052 roles[SessionRole] = "session";
5153 roles[HasMessagesRole] = "hasMessages";
5254 roles[ImagePathRole] = "imagePath";
53− roles[UidRole] = "uid";
5455 setRoleNames(roles);
5556
5657 connect(d_ptr, &UsersModelPrivate::dataChanged, this, [this](int i) {
@@ -100,8 +101,6 @@ QVariant UsersModel::data(const QModelIndex &index, int role) const
100101 return d->entries[row].has_messages;
101102 case UsersModel::ImagePathRole:
102103 return "";
103− case UsersModel::UidRole:
104− return d->entries[row].uid;
105104 default:
106105 return QVariant();
107106 }
plugins/LightDM/IntegratedLightDM/liblightdm/UsersModel.h → plugins/IntegratedLightDM/liblightdm/UsersModel.hrenamed+3−3
@@ -37,6 +37,8 @@ class Q_DECL_EXPORT UsersModel : public QAbstractListModel
3737{
3838 Q_OBJECT
3939
40+ Q_ENUMS(UserModelRoles)
41+
4042public:
4143 explicit UsersModel(QObject *parent = 0);
4244 virtual ~UsersModel() = default;
@@ -48,10 +50,8 @@ public:
4850 SessionRole,
4951 HasMessagesRole,
5052 ImagePathRole,
51− BackgroundPathRole,
52− UidRole
53+ BackgroundPathRole
5354 };
54− Q_ENUM(UserModelRoles)
5555
5656 int rowCount(const QModelIndex &parent) const override;
5757 QVariant data(const QModelIndex &index, int role) const override;
plugins/LightDM/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp → plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpprenamed+3−5
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -26,7 +26,6 @@
2626#include <QDir>
2727#include <QSettings>
2828#include <QStringList>
29−#include <unistd.h>
3029
3130namespace QLightDM
3231{
@@ -38,7 +37,6 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
3837{
3938 QFileInfo demoFile(QDir::homePath() + "/.unity8-greeter-demo");
4039 QString currentUser = g_get_user_name();
41− uid_t currentUid = getuid();
4240
4341 if (demoFile.exists()) {
4442 QSettings settings(demoFile.filePath(), QSettings::NativeFormat);
@@ -48,10 +46,10 @@ UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
4846 Q_FOREACH(const QString &user, users)
4947 {
5048 QString name = settings.value(user + "/name", user).toString();
51− entries.append({user, name, 0, 0, false, false, 0, 0, currentUid++});
49+ entries.append({user, name, 0, 0, false, false, 0, 0});
5250 }
5351 } else {
54− entries.append({currentUser, 0, 0, 0, false, false, 0, 0, currentUid});
52+ entries.append({currentUser, 0, 0, 0, false, false, 0, 0});
5553
5654 connect(m_service, &AccountsServiceDBusAdaptor::maybeChanged,
5755 this, [this](const QString &user) {
plugins/LightDM/IntegratedLightDM/liblightdm/UsersModelPrivate.h → plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.hrenamed+1−2
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -40,7 +40,6 @@ public:
4040 bool has_messages;
4141 QString session;
4242 QString infographic;
43− uid_t uid;
4443};
4544
4645class UsersModelPrivate : public QObject
plugins/LightDM/plugin.cpp → plugins/IntegratedLightDM/plugin.cpprenamed+7−37
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012,2013,2015 Canonical, Ltd.
2+ * Copyright (C) 2012,2013, 2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -19,12 +19,9 @@
1919#include "DBusGreeter.h"
2020#include "DBusGreeterList.h"
2121#include "Greeter.h"
22−#include "PromptsModel.h"
23−#include "SessionsModel.h"
2422#include "UsersModel.h"
2523#include <libusermetricsoutput/ColorTheme.h>
2624#include <libusermetricsoutput/UserMetrics.h>
27−#include <QLightDM/SessionsModel>
2825#include <QLightDM/UsersModel>
2926
3027#include <QAbstractItemModel>
@@ -33,31 +30,16 @@
3330
3431static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3532{
33+ Q_UNUSED(engine)
3634 Q_UNUSED(scriptEngine)
3735
38− Greeter *greeter = Greeter::instance();
36+ Greeter *greeter = new Greeter();
3937 new DBusGreeter(greeter, QStringLiteral("/"));
4038 new DBusGreeterList(greeter, QStringLiteral("/list"));
4139
42− engine->setObjectOwnership(greeter, QQmlEngine::CppOwnership);
43−
4440 return greeter;
4541}
4642
47−static QObject *prompts_provider(QQmlEngine *engine, QJSEngine *)
48−{
49− auto model = Greeter::instance()->promptsModel();
50− engine->setObjectOwnership(model, QQmlEngine::CppOwnership);
51− return model;
52−}
53−
54−static QObject *sessions_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
55−{
56− Q_UNUSED(engine)
57− Q_UNUSED(scriptEngine)
58− return new SessionsModel();
59−}
60−
6143static QObject *users_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
6244{
6345 Q_UNUSED(engine)
@@ -72,28 +54,16 @@ static QObject *infographic_provider(QQmlEngine *engine, QJSEngine *scriptEngine
7254 return UserMetricsOutput::UserMetrics::getInstance();
7355}
7456
75−void PLUGIN_CLASSNAME::registerTypes(const char *uri)
57+void IntegratedLightDMPlugin::registerTypes(const char *uri)
7658{
7759 qmlRegisterType<QAbstractItemModel>();
7860 qmlRegisterType<UserMetricsOutput::ColorTheme>();
7961
80−#if defined INTEGRATED_LIGHTDM
81− Q_ASSERT(uri == QLatin1String("LightDM.IntegratedLightDM"));
62+ Q_ASSERT(uri == QLatin1String("IntegratedLightDM"));
63+ qRegisterMetaType<QLightDM::Greeter::MessageType>("QLightDM::Greeter::MessageType");
64+ qRegisterMetaType<QLightDM::Greeter::PromptType>("QLightDM::Greeter::PromptType");
8265 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
83−#elif defined FULL_LIGHTDM
84− Q_ASSERT(uri == QLatin1String("LightDM.FullLightDM"));
85− qmlRegisterSingletonType<QLightDM::Greeter>(uri, 0, 1, "Greeter", greeter_provider);
86−#else
87− #error No library defined in LightDM plugin
88−#endif
89−
90− qmlRegisterSingletonType<PromptsModel>(uri, 0, 1, "Prompts", prompts_provider);
91−
92− qmlRegisterSingletonType<SessionsModel>(uri, 0, 1, "Sessions", sessions_provider);
93− qmlRegisterUncreatableType<QLightDM::SessionsModel>(uri, 0, 1, "SessionRoles", QStringLiteral("Type is not instantiable"));
94−
9566 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
9667 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", QStringLiteral("Type is not instantiable"));
97−
9868 qmlRegisterSingletonType<UserMetricsOutput::UserMetrics>(uri, 0, 1, "Infographic", infographic_provider);
9969}
plugins/IntegratedLightDM/plugin.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2012,2013, 2015 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+
18+#ifndef INTEGRATED_LIGHTDM_PLUGIN_H
19+#define INTEGRATED_LIGHTDM_PLUGIN_H
20+
21+#include <QtQml/QQmlEngine>
22+#include <QtQml/QQmlExtensionPlugin>
23+
24+class IntegratedLightDMPlugin : public QQmlExtensionPlugin
25+{
26+ Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28+
29+public:
30+ void registerTypes(const char *uri) override;
31+};
32+
33+#endif /* INTEGRATED_LIGHTDM_PLUGIN_H */
plugins/LightDM/qmldir → plugins/IntegratedLightDM/qmldirrenamed
The content is the same.
plugins/LightDM/CMakeLists.txtdeleted−26
@@ -1,26 +0,0 @@
1−pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2−
3−find_package(Qt5Core REQUIRED)
4−find_package(Qt5Quick REQUIRED)
5−
6−include_directories(
7− ${CMAKE_CURRENT_SOURCE_DIR}
8− ${CMAKE_CURRENT_BINARY_DIR}
9− ${CMAKE_SOURCE_DIR}/plugins/Utils
10− ${libunity8-private_SOURCE_DIR}
11− ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
12−)
13−
14−set(QMLPLUGIN_SRC
15− ../Utils/unitysortfilterproxymodelqml.cpp
16− DBusGreeter.cpp
17− DBusGreeterList.cpp
18− Greeter.cpp
19− plugin.cpp
20− PromptsModel.cpp
21− SessionsModel.cpp
22− UsersModel.cpp
23− )
24−
25−add_subdirectory(FullLightDM)
26−add_subdirectory(IntegratedLightDM)
plugins/LightDM/FullLightDM/CMakeLists.txtdeleted−32
@@ -1,32 +0,0 @@
1−pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-3)
2−
3−set(PLUGIN_CLASSNAME "FullLightDM")
4−
5−add_definitions(-DFULL_LIGHTDM)
6−
7−include_directories(
8− ../
9− ${CMAKE_CURRENT_BINARY_DIR}
10− )
11−
12−include_directories(
13− SYSTEM
14− ${LIBLIGHTDM_INCLUDE_DIRS}
15− )
16−
17−foreach(source_file ${QMLPLUGIN_SRC})
18− list(APPEND RELATIVE_QMLPLUGIN_SRC ../${source_file})
19−endforeach()
20−
21−add_library(FullLightDM-qml MODULE
22− ${RELATIVE_QMLPLUGIN_SRC}
23− )
24−
25−target_link_libraries(FullLightDM-qml
26− unity8-private
27− ${LIBLIGHTDM_LDFLAGS}
28− ${LIBUSERMETRICSOUTPUT_LDFLAGS}
29− Qt5::DBus Qt5::Gui Qt5::Qml
30− )
31−
32−add_unity8_plugin(FullLightDM 0.1 LightDM/FullLightDM TARGETS FullLightDM-qml)
plugins/LightDM/FullLightDM/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module LightDM.FullLightDM
2−plugin FullLightDM-qml
3−typeinfo FullLightDM.qmltypes
plugins/LightDM/Greeter.cppdeleted−279
@@ -1,279 +0,0 @@
1−/*
2− * Copyright (C) 2013-2017 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−
18−#include "Greeter.h"
19−#include "GreeterPrivate.h"
20−#include <QCoreApplication>
21−#include <libintl.h>
22−
23−static Greeter *singleton = nullptr;
24−
25−GreeterPrivate::GreeterPrivate(Greeter* parent)
26− : m_greeter(new QLightDM::Greeter(parent)),
27− m_active(false),
28− responded(false),
29− everResponded(false),
30− promptless(false),
31− q_ptr(parent)
32−{
33−}
34−
35−Greeter::Greeter(QObject* parent)
36− : QObject(parent),
37− d_ptr(new GreeterPrivate(this))
38−{
39− Q_D(Greeter);
40−
41− connect(d->m_greeter, &QLightDM::Greeter::showMessage,
42− this, &Greeter::showMessageFilter);
43− connect(d->m_greeter, &QLightDM::Greeter::showPrompt,
44− this, &Greeter::showPromptFilter);
45− connect(d->m_greeter, &QLightDM::Greeter::authenticationComplete,
46− this, &Greeter::authenticationCompleteFilter);
47−
48− // Don't get stuck waiting for PAM as we shut down.
49− connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
50− d->m_greeter, &QLightDM::Greeter::cancelAuthentication);
51−
52− d->m_greeter->connectSync();
53−}
54−
55−Greeter::~Greeter()
56−{
57− singleton = nullptr;
58−}
59−
60−Greeter *Greeter::instance()
61−{
62− if (!singleton) {
63− singleton = new Greeter;
64− }
65− return singleton;
66−}
67−
68−PromptsModel *Greeter::promptsModel()
69−{
70− Q_D(Greeter);
71− return &d->prompts;
72−}
73−
74−bool Greeter::isActive() const
75−{
76− Q_D(const Greeter);
77− return d->m_active;
78−}
79−
80−void Greeter::setIsActive(bool active)
81−{
82− Q_D(Greeter);
83− if (d->m_active != active) {
84− d->m_active = active;
85− Q_EMIT isActiveChanged();
86− }
87−}
88−
89−bool Greeter::isAuthenticated() const
90−{
91− Q_D(const Greeter);
92− return d->m_greeter->isAuthenticated();
93−}
94−
95−QString Greeter::authenticationUser() const
96−{
97− Q_D(const Greeter);
98− return d->cachedAuthUser;
99−}
100−
101−void Greeter::checkAuthenticationUser()
102−{
103− Q_D(Greeter);
104− if (d->cachedAuthUser != d->m_greeter->authenticationUser()) {
105− d->cachedAuthUser = d->m_greeter->authenticationUser();
106− Q_EMIT authenticationUserChanged();
107− }
108−}
109−
110−QString Greeter::defaultSessionHint() const
111−{
112− Q_D(const Greeter);
113− return d->m_greeter->defaultSessionHint();
114−}
115−
116−bool Greeter::promptless() const
117−{
118− Q_D(const Greeter);
119− return d->promptless;
120−}
121−
122−QString Greeter::selectUser() const
123−{
124− Q_D(const Greeter);
125− if (hasGuestAccount() && d->m_greeter->selectGuestHint()) {
126− return QStringLiteral("*guest");
127− } else {
128− return d->m_greeter->selectUserHint();
129− }
130−}
131−
132−bool Greeter::hasGuestAccount() const
133−{
134− Q_D(const Greeter);
135− return d->m_greeter->hasGuestAccountHint();
136−}
137−
138−bool Greeter::showManualLoginHint() const
139−{
140− Q_D(const Greeter);
141− return d->m_greeter->showManualLoginHint();
142−}
143−
144−bool Greeter::hideUsersHint() const
145−{
146− Q_D(const Greeter);
147− return d->m_greeter->hideUsersHint();
148−}
149−
150−void Greeter::authenticate(const QString &username)
151−{
152− Q_D(Greeter);
153− d->prompts.clear();
154− d->responded = false;
155− d->everResponded = false;
156− if (d->promptless) {
157− d->promptless = false;
158− Q_EMIT promptlessChanged();
159− }
160−
161− if (authenticationUser() == username) {
162− d->prompts = d->leftovers;
163− }
164− d->leftovers.clear();
165−
166− if (username == QStringLiteral("*guest")) {
167− d->m_greeter->authenticateAsGuest();
168− } else if (username == QStringLiteral("*other")) {
169− d->m_greeter->authenticate(nullptr);
170− } else {
171− d->m_greeter->authenticate(username);
172− }
173−
174− Q_EMIT authenticationStarted();
175− Q_EMIT isAuthenticatedChanged();
176− checkAuthenticationUser();
177−}
178−
179−void Greeter::respond(const QString &response)
180−{
181− Q_D(Greeter);
182− d->responded = true;
183− d->everResponded = true;
184− d->m_greeter->respond(response);
185−}
186−
187−bool Greeter::startSessionSync(const QString &session)
188−{
189− Q_D(Greeter);
190− return d->m_greeter->startSessionSync(session);
191−}
192−
193−void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
194−{
195− Q_D(Greeter);
196−
197− checkAuthenticationUser(); // may have changed in liblightdm
198−
199− bool isDefaultPrompt = (text == dgettext("Linux-PAM", "Password: "));
200− bool isSecret = type == QLightDM::Greeter::PromptTypeSecret;
201−
202− QString trimmedText;
203− if (!isDefaultPrompt)
204− trimmedText = text.trimmed();
205−
206− // Strip prompt of any colons at the end
207− if (trimmedText.endsWith(':') || trimmedText.endsWith(QStringLiteral(":"))) {
208− trimmedText.chop(1);
209− }
210−
211− if (trimmedText == "login") {
212− // 'login' is provided untranslated by LightDM when asking for a manual
213− // login username.
214− trimmedText = gettext("Username");
215− }
216−
217− if (d->responded) {
218− d->prompts.clear();
219− d->responded = false;
220− }
221−
222− d->prompts.append(trimmedText, isSecret ? PromptsModel::Secret : PromptsModel::Question);
223−}
224−
225−void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
226−{
227− Q_D(Greeter);
228−
229− checkAuthenticationUser(); // may have changed in liblightdm
230−
231− bool isError = type == QLightDM::Greeter::MessageTypeError;
232−
233− if (d->responded) {
234− d->prompts.clear();
235− d->responded = false;
236− }
237− d->prompts.append(text, isError? PromptsModel::Error : PromptsModel::Message);
238−}
239−
240−void Greeter::authenticationCompleteFilter()
241−{
242− Q_D(Greeter);
243−
244− Q_EMIT isAuthenticatedChanged();
245−
246− bool automatic = !d->everResponded;
247− bool pamHasLeftoverMessages = !d->prompts.hasPrompt() && d->prompts.rowCount() > 0;
248−
249− if (isAuthenticated() && automatic) {
250− d->promptless = true;
251− Q_EMIT promptlessChanged();
252− }
253−
254− if (!isAuthenticated()) {
255− if (pamHasLeftoverMessages) {
256− d->leftovers = d->prompts; // Prefer PAM's messages
257− } else if (automatic) {
258− d->leftovers.append(gettext("Failed to authenticate"), PromptsModel::Error);
259− } else {
260− d->leftovers.append(gettext("Invalid password, please try again"), PromptsModel::Error);
261− }
262− } else if (pamHasLeftoverMessages) {
263− automatic = true; // treat this successful login as automatic, so user sees message
264− d->leftovers = d->prompts;
265− }
266−
267− if (automatic) {
268− d->prompts = d->leftovers; // OK, we'll just use these now
269− d->leftovers.clear();
270− d->prompts.append(isAuthenticated() ? gettext("Log In") : gettext("Retry"),
271− PromptsModel::Button);
272− }
273−
274− if (isAuthenticated()) {
275− Q_EMIT loginSuccess(automatic);
276− } else {
277− Q_EMIT loginError(automatic);
278− }
279−}
plugins/LightDM/IntegratedLightDM/CMakeLists.txtdeleted−33
@@ -1,33 +0,0 @@
1−set(PLUGIN_CLASSNAME "IntegratedLightDM")
2−
3−add_definitions(-DINTEGRATED_LIGHTDM)
4−
5−foreach(include_directory ${QMLPLUGIN_INCLUDES})
6− list(APPEND RELATIVE_QMLPLUGIN_INCLUDES ../${include_directory})
7−endforeach()
8−
9−include_directories(
10− . #QLightDM
11− ${QMLPLUGIN_INCLUDES}
12− ${libunity8-private_SOURCE_DIR}
13− ${CMAKE_CURRENT_BINARY_DIR}
14−)
15−
16−foreach(source_file ${QMLPLUGIN_SRC})
17− list(APPEND RELATIVE_QMLPLUGIN_SRC ../${source_file})
18−endforeach()
19−
20−add_library(IntegratedLightDM-qml MODULE
21− ${RELATIVE_QMLPLUGIN_SRC}
22− )
23−
24−target_link_libraries(IntegratedLightDM-qml
25− integratedLightDM
26− unity8-private
27− ${LIBUSERMETRICSOUTPUT_LDFLAGS}
28− Qt5::DBus Qt5::Gui Qt5::Qml
29− )
30−
31−add_unity8_plugin(IntegratedLightDM 0.1 LightDM/IntegratedLightDM TARGETS IntegratedLightDM-qml)
32−
33−add_subdirectory(liblightdm)
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModel.cppdeleted−87
@@ -1,87 +0,0 @@
1−/*
2− * Copyright (C) 2015 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−
18−
19−/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20− * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
21− * COUNTERPART IN tests/mocks/LightDM/IntegratedLightDM/liblightdm
22− * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
23−
24−// LightDM currently is Qt4 compatible, and so doesn't define setRoleNames.
25−// To use the same method of setting role name that it does, we
26−// set our compatibility to Qt4 here too.
27−#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(4, 0, 0)
28−
29−#include "SessionsModel.h"
30−#include "SessionsModelPrivate.h"
31−#include <QtCore/QDir>
32−#include <QtCore/QString>
33−
34−namespace QLightDM
35−{
36−
37−SessionsModel::SessionsModel(QObject* parent) :
38− QAbstractListModel(parent),
39− d_ptr(new SessionsModelPrivate(this))
40−{
41− m_roleNames = QAbstractListModel::roleNames();
42− m_roleNames[KeyRole] = "key";
43− m_roleNames[TypeRole] = "type";
44−}
45−
46−SessionsModel::~SessionsModel()
47−{
48− delete d_ptr;
49−}
50−
51−QVariant SessionsModel::data(const QModelIndex& index, int role) const
52−{
53− Q_D(const SessionsModel);
54−
55− if(!index.isValid()) {
56− return QVariant();
57− }
58−
59− int row = index.row();
60−
61− switch (role) {
62− case QLightDM::SessionsModel::KeyRole:
63− return d->sessionItems[row].key;
64− case Qt::DisplayRole:
65− return d->sessionItems[row].name;
66− default:
67− return QVariant();
68− }
69−}
70−
71−QHash<int, QByteArray> SessionsModel::roleNames() const
72−{
73− return m_roleNames;
74−}
75−
76−int SessionsModel::rowCount(const QModelIndex& parent) const
77−{
78− Q_D(const SessionsModel);
79−
80− if (parent.isValid()) {
81− return 0;
82− } else { // parent is root
83− return d->sessionItems.size();
84− }
85−}
86−
87−} // namespace QLightDM
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModel.hdeleted−72
@@ -1,72 +0,0 @@
1−/*
2− * Copyright (C) 2015 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−
18−#ifndef UNITY_INTEGRATED_SESSIONSMODEL_H
19−#define UNITY_INTEGRATED_SESSIONSMODEL_H
20−
21−#include <QtCore/QAbstractListModel>
22−#include <QtCore/QString>
23−
24−/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
25− * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
26− * COUNTERPART IN tests/mocks/LightDM/IntegratedLightDM/liblightdm
27− * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
28−
29−// This is taken from liblightdm and modified to confirm to our syle conventions
30−namespace QLightDM
31−{
32−class SessionsModelPrivate;
33−
34−class Q_DECL_EXPORT SessionsModel : public QAbstractListModel
35− {
36− Q_OBJECT
37−
38− public:
39−
40− enum SessionModelRoles {
41− //name is exposed as Qt::DisplayRole
42− //comment is exposed as Qt::TooltipRole
43− KeyRole = Qt::UserRole,
44− IdRole = KeyRole, /** Deprecated */
45− TypeRole
46− };
47− Q_ENUM(SessionModelRoles)
48−
49− enum SessionType {
50− LocalSessions,
51− RemoteSessions
52− };
53− Q_ENUM(SessionType)
54−
55− explicit SessionsModel(QObject* parent=0); /** Deprecated. Loads local sessions*/
56− explicit SessionsModel(SessionsModel::SessionType, QObject* parent=0);
57− virtual ~SessionsModel();
58−
59− QHash<int, QByteArray> roleNames() const override;
60− int rowCount(const QModelIndex& parent) const override;
61− QVariant data(const QModelIndex& index, int role) const override;
62−
63− protected:
64− SessionsModelPrivate* const d_ptr;
65−
66− private:
67− QHash<int, QByteArray> m_roleNames;
68− Q_DECLARE_PRIVATE(SessionsModel)
69− };
70−}
71−
72−#endif // UNITY_INTEGRATED_SESSIONSMODEL_H
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModelPrivate.hdeleted−54
@@ -1,54 +0,0 @@
1−/*
2− * Copyright (C) 2015 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−
18−#ifndef UNITY_INTEGRATED_SESSIONSMODEL_PRIVATE_H
19−#define UNITY_INTEGRATED_SESSIONSMODEL_PRIVATE_H
20−
21−#include <QtCore/QList>
22−#include <QtCore/QString>
23−
24−namespace QLightDM
25−{
26−class SessionsModel;
27−
28−class SessionItem
29−{
30−public:
31− QString key;
32− QString type; // unused
33− QString name;
34− QString comment; // unused
35−};
36−
37−class SessionsModelPrivate
38−{
39−public:
40− explicit SessionsModelPrivate(SessionsModel* parent=0);
41− virtual ~SessionsModelPrivate() = default;
42−
43− QList<SessionItem> sessionItems;
44−
45−protected:
46− SessionsModel* const q_ptr;
47−
48−private:
49− Q_DECLARE_PUBLIC(SessionsModel)
50−};
51−
52−} // namespace QLightDM
53−
54−#endif // UNITY_INTEGRATED_SESSIONSMODEL_PRIVATE_H
plugins/LightDM/IntegratedLightDM/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module LightDM.IntegratedLightDM
2−plugin IntegratedLightDM-qml
3−typeinfo IntegratedLightDM.qmltypes
plugins/LightDM/PromptsModel.cppdeleted−97
@@ -1,97 +0,0 @@
1−/*
2− * Copyright (C) 2017 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−
18−#include "PromptsModel.h"
19−
20−PromptsModel::PromptsModel(QObject* parent)
21− : QAbstractListModel(parent)
22−{
23− m_roleNames[TypeRole] = "type";
24− m_roleNames[TextRole] = "text";
25−}
26−
27−PromptsModel& PromptsModel::operator=(const PromptsModel &other)
28−{
29− beginResetModel();
30− m_prompts = other.m_prompts;
31− endResetModel();
32− Q_EMIT countChanged();
33− return *this;
34−}
35−
36−int PromptsModel::rowCount(const QModelIndex &parent) const
37−{
38− if (parent.isValid())
39− return 0;
40−
41− return m_prompts.size();
42−}
43−
44−QVariant PromptsModel::data(const QModelIndex &index, int role) const
45−{
46− if (!index.isValid() || index.column() > 0 || index.row() >= m_prompts.size())
47− return QVariant();
48−
49− switch (role) {
50− case Qt::DisplayRole: // fallthrough
51− case TextRole: return m_prompts[index.row()].prompt;
52− case TypeRole: return m_prompts[index.row()].type;
53− default: return QVariant();
54− }
55−}
56−
57−QHash<int, QByteArray> PromptsModel::roleNames() const
58−{
59− return m_roleNames;
60−}
61−
62−void PromptsModel::prepend(const QString &text, PromptType type)
63−{
64− beginInsertRows(QModelIndex(), 0, 0);
65− m_prompts.prepend(PromptInfo{text, type});
66− endInsertRows();
67−
68− Q_EMIT countChanged();
69−}
70−
71−void PromptsModel::append(const QString &text, PromptType type)
72−{
73− beginInsertRows(QModelIndex(), m_prompts.size(), m_prompts.size());
74− m_prompts.append(PromptInfo{text, type});
75− endInsertRows();
76−
77− Q_EMIT countChanged();
78−}
79−
80−void PromptsModel::clear()
81−{
82− beginResetModel();
83− m_prompts.clear();
84− endResetModel();
85−
86− Q_EMIT countChanged();
87−}
88−
89−bool PromptsModel::hasPrompt() const
90−{
91− Q_FOREACH(const PromptInfo &info, m_prompts) {
92− if (info.type == PromptType::Secret || info.type == PromptType::Question) {
93− return true;
94− }
95− }
96− return false;
97−}
plugins/LightDM/PromptsModel.hdeleted−70
@@ -1,70 +0,0 @@
1−/*
2− * Copyright (C) 2017 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−
18−#pragma once
19−
20−#include <QAbstractListModel>
21−
22−class PromptsModel : public QAbstractListModel
23−{
24− Q_OBJECT
25−
26− Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
27−
28−public:
29− enum PromptsModelRoles {
30− TypeRole = Qt::UserRole,
31− TextRole,
32− };
33− Q_ENUM(PromptsModelRoles)
34−
35− enum PromptType {
36− Message,
37− Error,
38− Secret,
39− Question,
40− Button,
41− };
42− Q_ENUM(PromptType)
43−
44− explicit PromptsModel(QObject* parent=0);
45−
46− PromptsModel& operator=(const PromptsModel &other);
47−
48− int rowCount(const QModelIndex &parent = QModelIndex()) const override;
49− QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
50− QHash<int, QByteArray> roleNames() const override;
51−
52− Q_INVOKABLE void prepend(const QString &text, PromptType type);
53− Q_INVOKABLE void append(const QString &text, PromptType type);
54−
55− void clear();
56−
57− bool hasPrompt() const;
58−
59−Q_SIGNALS:
60− void countChanged();
61−
62−private:
63− struct PromptInfo {
64− QString prompt;
65− PromptType type;
66− };
67−
68− QList<PromptInfo> m_prompts;
69− QHash<int, QByteArray> m_roleNames;
70−};
plugins/LightDM/SessionsModel.cppdeleted−135
@@ -1,135 +0,0 @@
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−
18−#include "SessionsModel.h"
19−#include <QtCore/QFile>
20−#include <QtCore/QSortFilterProxyModel>
21−
22−QHash<int, QByteArray> SessionsModel::roleNames() const
23−{
24− return m_roleNames;
25−}
26−
27−int SessionsModel::rowCount(const QModelIndex& parent) const
28−{
29− return m_model->rowCount(parent);
30−}
31−
32−QList<QUrl> SessionsModel::iconSearchDirectories() const
33−{
34− return m_iconSearchDirectories;
35−}
36−
37−void SessionsModel::setIconSearchDirectories(const QList<QUrl> searchDirectories)
38−{
39− // QML gives us a url with file:// prepended which breaks QFile::exists()
40− // so convert the url to a local file
41− QList<QUrl> localList = {};
42− Q_FOREACH(const QUrl& searchDirectory, searchDirectories)
43− {
44− localList.append(searchDirectory.toLocalFile());
45− }
46− m_iconSearchDirectories = localList;
47− Q_EMIT iconSearchDirectoriesChanged();
48−}
49−
50−QUrl SessionsModel::iconUrl(const QString sessionKey) const
51−{
52− Q_FOREACH(const QUrl& searchDirectory, m_iconSearchDirectories)
53− {
54− // This is an established icon naming convention
55− QString customIconUrl = searchDirectory.toString(QUrl::StripTrailingSlash) +
56− "/custom_" + sessionKey + "_badge.png";
57− QString iconUrl = searchDirectory.toString(QUrl::StripTrailingSlash) +
58− "/" + sessionKey + "_badge.png";
59−
60− QFile customIconFile(customIconUrl);
61− QFile iconFile(iconUrl);
62− if (customIconFile.exists()) {
63− return QUrl(customIconUrl);
64− } else if (iconFile.exists()) {
65− return QUrl(iconUrl);
66− } else {
67− // Search the legacy way
68− QString path = searchDirectory.toString(QUrl::StripTrailingSlash) + "/";
69− bool iconFound = false;
70− if (sessionKey == "ubuntu" || sessionKey == "ubuntu-2d") {
71− path += "ubuntu_badge.png";
72− iconFound = true;
73− } else if(
74− sessionKey == "gnome-classic" ||
75− sessionKey == "gnome-flashback-compiz" ||
76− sessionKey == "gnome-flashback-metacity" ||
77− sessionKey == "gnome-shell" ||
78− sessionKey == "gnome-wayland" ||
79− sessionKey == "gnome"
80− ){
81− path += "gnome_badge.png";
82− iconFound = true;
83− } else if (sessionKey == "plasma") {
84− path += "kde_badge.png";
85− iconFound = true;
86− } else if (sessionKey == "xterm") {
87− path += "recovery_console_badge.png";
88− iconFound = true;
89− } else if (sessionKey == "remote-login") {
90− path += "remote_login_help.png";
91− iconFound = true;
92− }
93−
94− if (QFile(path).exists() && iconFound) {
95− return path;
96− }
97− }
98− }
99−
100− // FIXME make this smarter
101− return QUrl("./graphics/session_icons/unknown_badge.png");
102−}
103−
104−QVariant SessionsModel::data(const QModelIndex& index, int role) const
105−{
106− switch (role) {
107− case SessionsModel::IconRole:
108− return iconUrl(m_model->data(index, QLightDM::SessionsModel::KeyRole).toString());
109− default:
110− return m_model->data(index, role);
111− }
112−}
113−
114−SessionsModel::SessionsModel(QObject* parent)
115− : UnitySortFilterProxyModelQML(parent)
116−{
117− // Add a custom IconRole that isn't in either of the lightdm implementations
118− m_model = new QLightDM::SessionsModel(this);
119− m_roleNames = m_model->roleNames();
120− m_roleNames[IconRole] = "icon_url";
121−
122− // Update search locations to use $SNAP prefix if specified
123− auto snapRoot = QFile::decodeName(qgetenv("SNAP"));
124− if (!snapRoot.isEmpty()) {
125− for (int i = 0; i < m_iconSearchDirectories.size(); i++) {
126− m_iconSearchDirectories[i] = snapRoot + m_iconSearchDirectories[i].path();
127− }
128− }
129−
130− setModel(m_model);
131− setSortCaseSensitivity(Qt::CaseInsensitive);
132− setSortLocaleAware(true);
133− setSortRole(Qt::DisplayRole);
134− sort(0);
135−}
plugins/LightDM/SessionsModel.hdeleted−66
@@ -1,66 +0,0 @@
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−
18−#pragma once
19−
20−#include <unitysortfilterproxymodelqml.h>
21−#include <QLightDM/SessionsModel>
22−#include <QtCore/QHash>
23−#include <QtCore/QObject>
24−#include <QtCore/QUrl>
25−
26−class SessionsModel : public UnitySortFilterProxyModelQML
27−{
28− Q_OBJECT
29−
30− Q_PROPERTY(QList<QUrl> iconSearchDirectories READ iconSearchDirectories
31− WRITE setIconSearchDirectories NOTIFY iconSearchDirectoriesChanged)
32−
33−Q_SIGNALS:
34− void iconSearchDirectoriesChanged();
35−
36−public:
37− enum SessionModelRoles {
38− /* This is tricky / ugly. Since we are ultimately chaining 3 enums together,
39− * the _first_ value of this enum MUST be the _last_ value of
40− * QLightDM::SessionsModel::SessionModelRoles and consquently, this must
41− * also match the last value in the corresponding enum of the integrated lib
42− */
43− TypeRole = QLightDM::SessionsModel::SessionModelRoles::TypeRole,
44− IconRole
45− };
46− Q_ENUM(SessionModelRoles)
47−
48− explicit SessionsModel(QObject* parent=nullptr);
49−
50− QHash<int, QByteArray> roleNames() const override;
51− int rowCount(const QModelIndex& parent) const override;
52− QVariant data(const QModelIndex& index, int role) const override;
53− QList<QUrl> iconSearchDirectories() const;
54− Q_INVOKABLE QUrl iconUrl(const QString sessionName) const;
55−
56− void setIconSearchDirectories(const QList<QUrl> searchDirectories);
57−
58−private:
59− QLightDM::SessionsModel* m_model;
60− QHash<int, QByteArray> m_roleNames;
61− QList<QUrl> m_iconSearchDirectories{
62− QUrl("/usr/share/unity8/Greeter/graphics/session_icons"),
63− QUrl("/usr/local/share/unity-greeter"),
64− QUrl("/usr/share/unity-greeter/")};
65−
66−};
plugins/LightDM/UsersModel.cppdeleted−238
@@ -1,238 +0,0 @@
1−/*
2− * Copyright (C) 2013,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−#include "Greeter.h"
18−#include "UsersModel.h"
19−#include <QIdentityProxyModel>
20−#include <QLightDM/UsersModel>
21−
22−#include <libintl.h>
23−
24−// First, we define an internal class that wraps LightDM's UsersModel. This
25−// class will modify some of the data coming from LightDM. For example, we
26−// modify any empty Real Names into just normal Names. We also add optional
27−// rows, depending on configuration.
28−// (We can't modify the data directly in UsersModel below because it won't sort
29−// using the modified data.)
30−class MangleModel : public QIdentityProxyModel
31−{
32− Q_OBJECT
33−
34−public:
35− explicit MangleModel(QObject* parent=0);
36−
37− QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
38− int rowCount(const QModelIndex &parent = QModelIndex()) const override;
39− QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
40−
41−private:
42− struct CustomRow {
43− QString name;
44− QString realName;
45− };
46−
47− int sourceRowCount() const;
48−
49− void updateGuestRow();
50− void updateManualRow();
51− void updateCustomRows();
52−
53− void addCustomRow(const CustomRow &newRow);
54− void removeCustomRow(const QString &rowName);
55−
56− QList<CustomRow> m_customRows;
57− bool m_updatingCustomRows;
58−};
59−
60−MangleModel::MangleModel(QObject* parent)
61− : QIdentityProxyModel(parent)
62− , m_updatingCustomRows(false)
63−{
64− setSourceModel(new QLightDM::UsersModel(this));
65−
66− updateCustomRows();
67−
68− // Would be nice if there were a rowCountChanged signal in the base class.
69− // We redo all custom rows on any row count change, because (A) some of
70− // custom rows (manual login) use row count information and (B) when
71− // testing, we use a modelReset signal as a way to indicate that a custom
72− // row has been toggled off or on.
73− connect(this, &QIdentityProxyModel::modelReset,
74− this, &MangleModel::updateCustomRows);
75− connect(this, &QIdentityProxyModel::rowsInserted,
76− this, &MangleModel::updateCustomRows);
77− connect(this, &QIdentityProxyModel::rowsRemoved,
78− this, &MangleModel::updateCustomRows);
79−}
80−
81−QVariant MangleModel::data(const QModelIndex &index, int role) const
82−{
83− QVariant variantData;
84−
85− if (index.row() >= rowCount())
86− return QVariant();
87−
88− bool isCustomRow = index.row() >= sourceRowCount();
89− if (isCustomRow && index.column() == 0) {
90− int customIndex = index.row() - sourceRowCount();
91− if (role == QLightDM::UsersModel::NameRole) {
92− variantData = m_customRows[customIndex].name;
93− } else if (role == QLightDM::UsersModel::RealNameRole) {
94− variantData = m_customRows[customIndex].realName;
95− } else if (role == QLightDM::UsersModel::LoggedInRole) {
96− variantData = false;
97− } else if (role == QLightDM::UsersModel::SessionRole) {
98− variantData = Greeter::instance()->defaultSessionHint();
99− }
100− } else {
101− variantData = QIdentityProxyModel::data(index, role);
102− }
103−
104− // If user's real name is empty, switch to unix name
105− if (role == QLightDM::UsersModel::RealNameRole && variantData.toString().isEmpty()) {
106− variantData = data(index, QLightDM::UsersModel::NameRole);
107− } else if (role == QLightDM::UsersModel::BackgroundPathRole && variantData.toString().startsWith('#')) {
108− const QString stringData = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + variantData.toString() + "'/></svg>";
109− variantData = stringData;
110− }
111−
112− // Workaround for liblightdm returning "" when a user has no default session
113− if (Q_UNLIKELY(role == QLightDM::UsersModel::SessionRole && variantData.toString().isEmpty())) {
114− variantData = Greeter::instance()->defaultSessionHint();
115− }
116−
117− return variantData;
118−}
119−
120−void MangleModel::addCustomRow(const CustomRow &newRow)
121−{
122− for (int i = 0; i < m_customRows.size(); i++) {
123− if (m_customRows[i].name == newRow.name) {
124− return; // we don't have custom rows that change content yet
125− }
126− }
127−
128− beginInsertRows(QModelIndex(), rowCount(), rowCount());
129− m_customRows << newRow;
130− endInsertRows();
131−}
132−
133−void MangleModel::removeCustomRow(const QString &rowName)
134−{
135− for (int i = 0; i < m_customRows.size(); i++) {
136− if (m_customRows[i].name == rowName) {
137− int rowNum = sourceRowCount() + i;
138− beginRemoveRows(QModelIndex(), rowNum, rowNum);
139− m_customRows.removeAt(i);
140− endRemoveRows();
141− break;
142− }
143− }
144−}
145−
146−void MangleModel::updateManualRow()
147−{
148− bool hasAnotherEntry = sourceRowCount() > 0;
149− for (int i = 0; !hasAnotherEntry && i < m_customRows.size(); i++) {
150− if (m_customRows[i].name != QStringLiteral("*other")) {
151− hasAnotherEntry = true;
152− }
153− }
154−
155− // Show manual login if we are asked to OR if no other entry exists
156− if (Greeter::instance()->showManualLoginHint() || !hasAnotherEntry)
157− addCustomRow({QStringLiteral("*other"), gettext("Login")});
158− else
159− removeCustomRow(QStringLiteral("*other"));
160−}
161−
162−void MangleModel::updateGuestRow()
163−{
164− if (Greeter::instance()->hasGuestAccount())
165− addCustomRow({QStringLiteral("*guest"), gettext("Guest Session")});
166− else
167− removeCustomRow(QStringLiteral("*guest"));
168−}
169−
170−void MangleModel::updateCustomRows()
171−{
172− // We update when rowCount changes, but we also insert/remove rows here.
173− // So guard this function to avoid recursion.
174− if (m_updatingCustomRows)
175− return;
176−
177− m_updatingCustomRows = true;
178− updateGuestRow();
179− updateManualRow();
180− m_updatingCustomRows = false;
181−}
182−
183−int MangleModel::rowCount(const QModelIndex &parent) const
184−{
185− if (parent.isValid())
186− return 0;
187− else
188− return sourceRowCount() + m_customRows.size();
189−}
190−
191−int MangleModel::sourceRowCount() const
192−{
193− return Greeter::instance()->hideUsersHint() ? 0 : sourceModel()->rowCount();
194−}
195−
196−QModelIndex MangleModel::index(int row, int column, const QModelIndex &parent) const
197−{
198− if (row >= rowCount())
199− return QModelIndex();
200−
201− bool isCustomRow = row >= sourceRowCount();
202− if (isCustomRow && !parent.isValid()) {
203− return createIndex(row, column);
204− } else {
205− return QIdentityProxyModel::index(row, column, parent);
206− }
207−}
208−
209−// **** Now we continue with actual UsersModel class ****
210−
211−UsersModel::UsersModel(QObject* parent)
212− : UnitySortFilterProxyModelQML(parent)
213−{
214− setModel(new MangleModel(this));
215− setSortCaseSensitivity(Qt::CaseInsensitive);
216− setSortLocaleAware(true);
217− setSortRole(QLightDM::UsersModel::RealNameRole);
218− sort(0);
219−}
220−
221−bool UsersModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
222−{
223− auto leftName = source_left.data(QLightDM::UsersModel::NameRole);
224− auto rightName = source_right.data(QLightDM::UsersModel::NameRole);
225−
226− if (leftName == QStringLiteral("*guest"))
227− return false;
228− if (rightName == QStringLiteral("*guest"))
229− return true;
230− if (leftName == QStringLiteral("*other"))
231− return false;
232− if (rightName == QStringLiteral("*other"))
233− return true;
234−
235− return UnitySortFilterProxyModelQML::lessThan(source_left, source_right);
236−}
237−
238−#include "UsersModel.moc"
plugins/Lights/CMakeLists.txt+2−9
@@ -1,23 +1,16 @@
11pkg_check_modules(ANDROID_HEADERS REQUIRED android-headers)
22pkg_check_modules(ANDROID_HARDWARE REQUIRED libhardware)
3−pkg_check_modules(ANDROID_PROPERTIES REQUIRED libandroid-properties)
43
54include_directories(
6− SYSTEM
75 ${ANDROID_HEADERS_INCLUDE_DIRS}
86)
97
108add_library(Lights-qml MODULE
119 plugin.cpp
1210 Lights.cpp
13− LegacyLights.cpp
14− HfdLights.cpp
1511 )
1612
17−target_link_libraries(Lights-qml
18− Qt5::Qml Qt5::Gui Qt5::DBus
19− ${ANDROID_HARDWARE_LIBRARIES}
20− ${ANDROID_PROPERTIES_LIBRARIES}
21− )
13+qt5_use_modules(Lights-qml Qml Gui)
14+target_link_libraries(Lights-qml ${ANDROID_HARDWARE_LIBRARIES})
2215
2316add_unity8_plugin(Lights 0.1 Lights TARGETS Lights-qml)
plugins/Lights/HfdLights.cppdeleted−62
@@ -1,62 +0,0 @@
1−/*
2− * Copyright (C) 2021 UBports Foundation.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Author: Florian Leeber <florian@ubports.com>
17− */
18−
19−#include "HfdLights.h"
20−#include <QtCore/QDebug>
21−#include <QDBusArgument>
22−#include <QDBusConnection>
23−#include <iostream>
24−
25−#define HFD_SERVICE_NAME "com.lomiri.hfd"
26−#define HFD_SERVICE_PATH "/com/lomiri/hfd"
27−#define HFD_SERVICE_INTERFACE "com.lomiri.hfd.Leds"
28−
29−HfdLights::HfdLights(QObject* parent)
30− : Lights(parent)
31−{
32− m_hfdInterface = new QDBusInterface(
33− QStringLiteral(HFD_SERVICE_NAME),
34− QStringLiteral(HFD_SERVICE_PATH),
35− QStringLiteral(HFD_SERVICE_INTERFACE),
36− QDBusConnection::systemBus(),
37− this
38− );
39−}
40−
41−bool HfdLights::init()
42−{
43− // hfd does not need any initalization to be used
44− return true;
45−}
46−
47−void HfdLights::turnOn()
48−{
49− m_hfdInterface->call(QStringLiteral("setState"), 0);
50− m_hfdInterface->call(QStringLiteral("setColor"), (quint32)m_color.rgba());
51− m_hfdInterface->call(QStringLiteral("setOnMs"), m_onMs);
52− m_hfdInterface->call(QStringLiteral("setOffMs"), m_offMs);
53− m_hfdInterface->call(QStringLiteral("setState"), 1);
54−}
55−
56−void HfdLights::turnOff()
57−{
58− m_hfdInterface->call(QStringLiteral("setState"), 0);
59− m_hfdInterface->call(QStringLiteral("setColor"), (quint32)0);
60− m_hfdInterface->call(QStringLiteral("setOnMs"), 0);
61− m_hfdInterface->call(QStringLiteral("setOffMs"), 0);
62−}
plugins/Lights/LegacyLights.cppdeleted−91
@@ -1,91 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− * Copyright (C) 2021 UBports Foundation.
4− *
5− * This program is free software; you can redistribute it and/or modify
6− * it under the terms of the GNU General Public License as published by
7− * the Free Software Foundation; version 3.
8− *
9− * This program is distributed in the hope that it will be useful,
10− * but WITHOUT ANY WARRANTY; without even the implied warranty of
11− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12− * GNU General Public License for more details.
13− *
14− * You should have received a copy of the GNU General Public License
15− * along with this program. If not, see <http://www.gnu.org/licenses/>.
16− *
17− * Author: Renato Araujo Oliveira Filho <renato.filho@canonical.com>
18− */
19−
20−#include "LegacyLights.h"
21−#include <QtCore/QDebug>
22−
23−extern "C" {
24−#include "android-hardware.h"
25−#include <string.h>
26−}
27−
28−LegacyLights::~LegacyLights()
29−{
30− if (m_lightDevice) {
31− hw_device_t* device = (hw_device_t*) m_lightDevice;
32− device->close(device);
33− }
34−}
35−
36−bool LegacyLights::init()
37−{
38− if (m_lightDevice) {
39− return true;
40− }
41−
42− int err;
43− hw_module_t* module;
44−
45− err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
46− if (err == 0) {
47− hw_device_t* device;
48− err = module->methods->open(module, LIGHT_ID_NOTIFICATIONS, &device);
49− if (err == 0) {
50− m_lightDevice = (light_device_t*)device;
51− turnOff();
52− return true;
53− } else {
54− qWarning() << "Failed to access notification lights";
55− }
56− } else {
57− qWarning() << "Failed to initialize lights hardware.";
58− }
59− return false;
60−}
61−
62−void LegacyLights::turnOn()
63−{
64− // pulse
65− light_state_t state;
66− memset(&state, 0, sizeof(light_state_t));
67− state.color = m_color.rgba();
68− state.flashMode = LIGHT_FLASH_TIMED;
69− state.flashOnMS = m_onMs;
70− state.flashOffMS = m_offMs;
71− state.brightnessMode = BRIGHTNESS_MODE_USER;
72−
73− if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
74− qWarning() << "Failed to turn the light off";
75− }
76−}
77−
78−void LegacyLights::turnOff()
79−{
80− light_state_t state;
81− memset(&state, 0, sizeof(light_state_t));
82− state.color = 0x00000000;
83− state.flashMode = LIGHT_FLASH_NONE;
84− state.flashOnMS = 0;
85− state.flashOffMS = 0;
86− state.brightnessMode = 0;
87−
88− if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
89− qWarning() << "Failed to turn the light off";
90− }
91−}
plugins/Lights/Lights.cpp+65
@@ -26,12 +26,20 @@ extern "C" {
2626
2727Lights::Lights(QObject* parent)
2828 : QObject(parent),
29+ m_lightDevice(0),
2930 m_color("blue"),
3031 m_state(Lights::Off),
3132 m_onMs(1000),
3233 m_offMs(3000)
3334{
35+}
3436
37+Lights::~Lights()
38+{
39+ if (m_lightDevice) {
40+ hw_device_t* device = (hw_device_t*) m_lightDevice;
41+ device->close(device);
42+ }
3543}
3644
3745void Lights::setState(Lights::State newState)
@@ -99,3 +107,60 @@ void Lights::setOffMillisec(int offMs)
99107 // FIXME: update the property if the light is already on
100108 }
101109}
110+
111+bool Lights::init()
112+{
113+ if (m_lightDevice) {
114+ return true;
115+ }
116+
117+ int err;
118+ hw_module_t* module;
119+
120+ err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
121+ if (err == 0) {
122+ hw_device_t* device;
123+ err = module->methods->open(module, LIGHT_ID_NOTIFICATIONS, &device);
124+ if (err == 0) {
125+ m_lightDevice = (light_device_t*)device;
126+ turnOff();
127+ return true;
128+ } else {
129+ qWarning() << "Failed to access notification lights";
130+ }
131+ } else {
132+ qWarning() << "Failed to initialize lights hardware.";
133+ }
134+ return false;
135+}
136+
137+void Lights::turnOn()
138+{
139+ // pulse
140+ light_state_t state;
141+ memset(&state, 0, sizeof(light_state_t));
142+ state.color = m_color.rgba();
143+ state.flashMode = LIGHT_FLASH_TIMED;
144+ state.flashOnMS = m_onMs;
145+ state.flashOffMS = m_offMs;
146+ state.brightnessMode = BRIGHTNESS_MODE_USER;
147+
148+ if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
149+ qWarning() << "Failed to turn the light off";
150+ }
151+}
152+
153+void Lights::turnOff()
154+{
155+ light_state_t state;
156+ memset(&state, 0, sizeof(light_state_t));
157+ state.color = 0x00000000;
158+ state.flashMode = LIGHT_FLASH_NONE;
159+ state.flashOnMS = 0;
160+ state.flashOffMS = 0;
161+ state.brightnessMode = 0;
162+
163+ if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
164+ qWarning() << "Failed to turn the light off";
165+ }
166+}
plugins/Lights/Lights.h+9−5
@@ -22,9 +22,12 @@
2222#include <QtCore/QObject>
2323#include <QtGui/QColor>
2424
25+struct light_device_t;
26+
2527class Lights: public QObject
2628{
2729 Q_OBJECT
30+ Q_ENUMS(State)
2831 Q_PROPERTY(State state READ state WRITE setState NOTIFY stateChanged)
2932 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
3033 Q_PROPERTY(int onMillisec READ onMillisec WRITE setOnMillisec NOTIFY onMillisecChanged)
@@ -35,9 +38,9 @@ public:
3538 Off,
3639 On,
3740 };
38− Q_ENUM(State)
3941
4042 explicit Lights(QObject *parent = 0);
43+ ~Lights();
4144
4245 void setState(State newState);
4346 State state() const;
@@ -57,15 +60,16 @@ Q_SIGNALS:
5760 void onMillisecChanged(int onMs);
5861 void offMillisecChanged(int offMs);
5962
60−protected:
63+private:
64+ light_device_t* m_lightDevice;
6165 QColor m_color;
6266 State m_state;
6367 int m_onMs;
6468 int m_offMs;
6569
66− virtual bool init() = 0;
67− virtual void turnOff() = 0;
68− virtual void turnOn() = 0;
70+ bool init();
71+ void turnOff();
72+ void turnOn();
6973};
7074
7175#endif
plugins/Lights/Lights.qmltypesnew file+45
@@ -0,0 +1,45 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Lights 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "Lights"
12+ prototype: "QObject"
13+ exports: ["Lights/Lights 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Enum {
18+ name: "State"
19+ values: {
20+ "Off": 0,
21+ "On": 1
22+ }
23+ }
24+ Property { name: "state"; type: "State" }
25+ Property { name: "color"; type: "QColor" }
26+ Property { name: "onMillisec"; type: "int" }
27+ Property { name: "offMillisec"; type: "int" }
28+ Signal {
29+ name: "stateChanged"
30+ Parameter { name: "newState"; type: "State" }
31+ }
32+ Signal {
33+ name: "colorChanged"
34+ Parameter { name: "color"; type: "QColor" }
35+ }
36+ Signal {
37+ name: "onMillisecChanged"
38+ Parameter { name: "onMs"; type: "int" }
39+ }
40+ Signal {
41+ name: "offMillisecChanged"
42+ Parameter { name: "offMs"; type: "int" }
43+ }
44+ }
45+}
plugins/Lights/android-hardware.h+4
@@ -15,5 +15,9 @@
1515 *
1616 */
1717
18+// The purpose of this header wrapper is just to avoid having warnings being reported on
19+// code from external header files, as we can't do anything about them.
20+#pragma GCC system_header
21+
1822#include <hardware/hardware.h>
1923#include <hardware/lights.h>
plugins/Lights/plugin.cpp+1−20
@@ -18,11 +18,6 @@
1818
1919#include "plugin.h"
2020#include "Lights.h"
21−#include "HfdLights.h"
22−#include "LegacyLights.h"
23−
24−// libandroid-properties
25−#include <hybris/properties/properties.h>
2621
2722#include <QtQml/qqml.h>
2823
@@ -30,21 +25,7 @@ static QObject *lights_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3025{
3126 Q_UNUSED(engine)
3227 Q_UNUSED(scriptEngine)
33−
34− bool use_hfd = false;
35− char buffer[PROP_VALUE_MAX];
36− auto result = property_get("ro.build.version.sdk", buffer, "0");
37− if (result) {
38− auto sdkVersion = QString(buffer).toInt();
39− if (sdkVersion >= 27 || sdkVersion == 0) {
40− use_hfd = true;
41− }
42− }
43− if (use_hfd) {
44− return new HfdLights();
45− } else {
46− return new LegacyLights();
47− }
28+ return new Lights();
4829}
4930
5031void LightsPlugin::registerTypes(const char *uri)
plugins/Powerd/CMakeLists.txt+2−4
@@ -9,9 +9,7 @@ add_library(Powerd-qml MODULE
99 Powerd.cpp
1010 )
1111
12−target_link_libraries(Powerd-qml
13− Qt5::DBus Qt5::Qml
14− ${GIO_LDFLAGS}
15− )
12+qt5_use_modules(Powerd-qml DBus Qml)
13+target_link_libraries(Powerd-qml ${GIO_LDFLAGS})
1614
1715add_unity8_plugin(Powerd 0.1 Powerd TARGETS Powerd-qml)
plugins/Powerd/Powerd.h+2−2
@@ -27,6 +27,8 @@
2727class Powerd: public QObject
2828{
2929 Q_OBJECT
30+ Q_ENUMS(Status)
31+ Q_ENUMS(DisplayStateChangeReason)
3032 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
3133
3234public:
@@ -39,13 +41,11 @@ public:
3941 SnapDecision = 5, // Display changed state due to snap decision prompt
4042 CallDone = 6, // Display changed state due to voice call end
4143 };
42− Q_ENUM(DisplayStateChangeReason)
4344
4445 enum Status {
4546 Off,
4647 On,
4748 };
48− Q_ENUM(Status)
4949
5050 explicit Powerd(QObject *parent = 0);
5151 ~Powerd();
plugins/Powerd/Powerd.qmltypesnew file+39
@@ -0,0 +1,39 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Powerd 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "Powerd"
12+ prototype: "QObject"
13+ exports: ["Powerd/Powerd 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Enum {
18+ name: "DisplayStateChangeReason"
19+ values: {
20+ "Unknown": 0,
21+ "Inactivity": 1,
22+ "PowerKey": 2,
23+ "Proximity": 3
24+ }
25+ }
26+ Enum {
27+ name: "Status"
28+ values: {
29+ "Off": 0,
30+ "On": 1
31+ }
32+ }
33+ Property { name: "status"; type: "Status"; isReadonly: true }
34+ Signal {
35+ name: "statusChanged"
36+ Parameter { name: "reason"; type: "DisplayStateChangeReason" }
37+ }
38+ }
39+}
plugins/ScreenshotDirectory/CMakeLists.txt+1−1
@@ -4,6 +4,6 @@ set(PLUGIN_SOURCES
44)
55
66add_library(ScreenshotDirectory-qml MODULE ${PLUGIN_SOURCES})
7−target_link_libraries(ScreenshotDirectory-qml Qt5::Qml Qt5::Gui Qt5::Quick)
7+qt5_use_modules(ScreenshotDirectory-qml Qml Gui Quick)
88
99add_unity8_plugin(ScreenshotDirectory 0.1 ScreenshotDirectory TARGETS ScreenshotDirectory-qml)
plugins/SessionBroadcast/CMakeLists.txt+2−1
@@ -6,8 +6,9 @@ add_library(SessionBroadcast-qml MODULE
66 plugin.cpp
77 )
88
9+qt5_use_modules(SessionBroadcast-qml DBus Qml)
10+
911target_link_libraries(SessionBroadcast-qml
10− Qt5::DBus Qt5::Qml
1112 ${GLIB_LIBRARIES}
1213 )
1314
plugins/SessionBroadcast/SessionBroadcast.cpp+9−35
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013,2016 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,12 +12,12 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
1517 */
1618
1719#include "SessionBroadcast.h"
1820#include <QDBusConnection>
19−#include <QDBusConnectionInterface>
20−#include <QDBusInterface>
2121
2222#include <glib.h>
2323
@@ -27,39 +27,13 @@ SessionBroadcast::SessionBroadcast(QObject* parent)
2727 m_username = QString::fromUtf8(g_get_user_name());
2828
2929 auto connection = QDBusConnection::SM_BUSNAME();
30− auto interface = connection.interface();
31− interface->startService(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"));
32−
33− m_broadcaster = new QDBusInterface(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
34− QStringLiteral("/com/canonical/Unity/Greeter/Broadcast"),
35− QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
36− connection, this);
37−
38− connect(m_broadcaster, SIGNAL(StartUrl(const QString &, const QString &)),
39− this, SLOT(onStartUrl(const QString &, const QString &)));
40−
41− connect(m_broadcaster, SIGNAL(ShowHome(const QString &)),
42− this, SLOT(onShowHome(const QString &)));
43−}
44−
45−void SessionBroadcast::requestUrlStart(const QString &username, const QString &url)
46−{
47− m_broadcaster->asyncCall(QStringLiteral("RequestUrlStart"), username, url);
48−}
49−
50−void SessionBroadcast::requestHomeShown(const QString &username)
51−{
52− m_broadcaster->asyncCall(QStringLiteral("RequestHomeShown"), username);
53−}
5430
55−void SessionBroadcast::onStartUrl(const QString &username, const QString &url)
56−{
57− // Since this signal is just used for testing, we don't *really* care if
58− // username matches, but just in case we do eventually use the signal, we
59− // should only listen to our own requests.
60− if (username == m_username) {
61− Q_EMIT startUrl(url);
62− }
31+ connection.connect(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
32+ QStringLiteral("/com/canonical/Unity/Greeter/Broadcast"),
33+ QStringLiteral("com.canonical.Unity.Greeter.Broadcast"),
34+ QStringLiteral("ShowHome"),
35+ this,
36+ SLOT(onShowHome(const QString &)));
6337}
6438
6539void SessionBroadcast::onShowHome(const QString &username)
plugins/SessionBroadcast/SessionBroadcast.h+3−10
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013,2016 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,6 +12,8 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
1517 */
1618
1719#ifndef UNITY_SESSIONBROADCAST_H
@@ -29,23 +31,14 @@ class SessionBroadcast: public QObject
2931public:
3032 explicit SessionBroadcast(QObject *parent = 0);
3133
32− Q_INVOKABLE void requestUrlStart(const QString &username, const QString &url);
33− Q_INVOKABLE void requestHomeShown(const QString &username);
34−
3534Q_SIGNALS:
36− // This signal isn't actually used by the shell
37− // (unity-greeter-session-broadcast handles launching an app for us), but
38− // it's useful for testing the plugin.
39− void startUrl(const QString &url);
4035 void showHome();
4136
4237private Q_SLOTS:
43− void onStartUrl(const QString &username, const QString &url);
4438 void onShowHome(const QString &username);
4539
4640private:
4741 QString m_username;
48− QDBusInterface *m_broadcaster;
4942};
5043
5144#endif
plugins/SessionBroadcast/SessionBroadcast.qmltypesnew file+19
@@ -0,0 +1,19 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable SessionBroadcast 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "SessionBroadcast"
12+ prototype: "QObject"
13+ exports: ["SessionBroadcast/SessionBroadcast 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Signal { name: "showHome" }
18+ }
19+}
plugins/UInput/CMakeLists.txt+1−1
@@ -3,5 +3,5 @@ add_library(UInput-qml MODULE
33 uinput.cpp
44)
55
6−target_link_libraries(UInput-qml Qt5::Qml)
6+qt5_use_modules(UInput-qml Qml)
77add_unity8_plugin(UInput 0.1 UInput TARGETS UInput-qml)
plugins/UInput/UInput.qmltypesnew file+44
@@ -0,0 +1,44 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable UInput 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "UInput"
12+ prototype: "QObject"
13+ exports: ["UInput/UInput 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Enum {
16+ name: "Button"
17+ values: {
18+ "ButtonLeft": 0,
19+ "ButtonRight": 1,
20+ "ButtonMiddle": 2
21+ }
22+ }
23+ Method { name: "createMouse" }
24+ Method { name: "removeMouse" }
25+ Method {
26+ name: "moveMouse"
27+ Parameter { name: "dx"; type: "int" }
28+ Parameter { name: "dy"; type: "int" }
29+ }
30+ Method {
31+ name: "pressMouse"
32+ Parameter { name: "button"; type: "Button" }
33+ }
34+ Method {
35+ name: "releaseMouse"
36+ Parameter { name: "button"; type: "Button" }
37+ }
38+ Method {
39+ name: "scrollMouse"
40+ Parameter { name: "dh"; type: "int" }
41+ Parameter { name: "dv"; type: "int" }
42+ }
43+ }
44+}
plugins/UInput/uinput.h+1−1
@@ -27,6 +27,7 @@
2727class UInput : public QObject
2828{
2929 Q_OBJECT
30+ Q_ENUMS(Button)
3031
3132public:
3233 enum Button {
@@ -34,7 +35,6 @@ public:
3435 ButtonRight,
3536 ButtonMiddle
3637 };
37− Q_ENUM(Button)
3838
3939 explicit UInput(QObject *parent = nullptr);
4040 ~UInput();
plugins/Ubuntu/CMakeLists.txt+2
@@ -1,2 +1,4 @@
11add_subdirectory(Gestures)
22add_subdirectory(DownloadDaemonListener)
3+add_subdirectory(Payments)
4+add_subdirectory(SystemImage)
plugins/Ubuntu/DownloadDaemonListener/CMakeLists.txt+3−6
@@ -1,6 +1,7 @@
11include_directories(
22 ${CMAKE_CURRENT_SOURCE_DIR}
33 ${CMAKE_CURRENT_BINARY_DIR}
4+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
45)
56
67set(DOWNLOADDAEMONLISTENER_SOURCES
@@ -11,10 +12,6 @@ set(DOWNLOADDAEMONLISTENER_SOURCES
1112
1213add_library(DownloadDaemonListener MODULE ${DOWNLOADDAEMONLISTENER_SOURCES})
1314
14−pkg_check_modules(DDLADAPTER REQUIRED udm-common)
15−add_definitions(${DDLADAPTER_CFLAGS} ${DDLADAPTER_CFLAGS_OTHER})
16−target_link_libraries(DownloadDaemonListener
17− Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Core
18− ${DDLADAPTER_LIBRARIES}
19− )
15+qt5_use_modules(DownloadDaemonListener Qml Quick DBus Core)
16+
2017add_unity8_plugin(Ubuntu.DownloadDaemonListener 0.1 Ubuntu/DownloadDaemonListener TARGETS DownloadDaemonListener)
plugins/Ubuntu/DownloadDaemonListener/DownloadDaemonListener.qmltypesnew file+60
@@ -0,0 +1,60 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Ubuntu.DownloadDaemonListener 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "DownloadTracker"
12+ prototype: "QObject"
13+ exports: ["Ubuntu.DownloadDaemonListener/DownloadTracker 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "service"; type: "string" }
16+ Property { name: "dbusPath"; type: "string" }
17+ Property { name: "serviceReady"; type: "bool"; isReadonly: true }
18+ Signal {
19+ name: "serviceChanged"
20+ Parameter { name: "service"; type: "string" }
21+ }
22+ Signal {
23+ name: "dbusPathChanged"
24+ Parameter { name: "dbusPath"; type: "string" }
25+ }
26+ Signal {
27+ name: "serviceReadyChanged"
28+ Parameter { name: "serviceReady"; type: "bool" }
29+ }
30+ Signal {
31+ name: "canceled"
32+ Parameter { name: "success"; type: "bool" }
33+ }
34+ Signal {
35+ name: "error"
36+ Parameter { name: "error"; type: "string" }
37+ }
38+ Signal {
39+ name: "finished"
40+ Parameter { name: "path"; type: "string" }
41+ }
42+ Signal {
43+ name: "paused"
44+ Parameter { name: "success"; type: "bool" }
45+ }
46+ Signal {
47+ name: "progress"
48+ Parameter { name: "received"; type: "qulonglong" }
49+ Parameter { name: "total"; type: "qulonglong" }
50+ }
51+ Signal {
52+ name: "resumed"
53+ Parameter { name: "success"; type: "bool" }
54+ }
55+ Signal {
56+ name: "started"
57+ Parameter { name: "success"; type: "bool" }
58+ }
59+ }
60+}
plugins/Ubuntu/DownloadDaemonListener/DownloadTracker.cpp+1−2
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical Ltd.
2+ * Copyright (C) 2013 - Canonical Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it
55 * under the terms of the GNU Lesser General Public License, as
@@ -78,7 +78,6 @@ void DownloadTracker::startService()
7878 connect(m_adaptor, static_cast<void (DownloadTrackerAdaptor::*)(qulonglong, qulonglong)>(&DownloadTrackerAdaptor::progress), this, &DownloadTracker::progress);
7979 connect(m_adaptor, &DownloadTrackerAdaptor::resumed, this, &DownloadTracker::resumed);
8080 connect(m_adaptor, &DownloadTrackerAdaptor::started, this, &DownloadTracker::started);
81− connect(m_adaptor, &DownloadTrackerAdaptor::processing, this, &DownloadTracker::processing);
8281 }
8382 // FIXME find a better way of determining if the service is ready
8483 Q_EMIT serviceReadyChanged(m_adaptor && m_adaptor->isValid());
plugins/Ubuntu/DownloadDaemonListener/DownloadTracker.h+1−2
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013-2016 Canonical Ltd.
2+ * Copyright (C) 2013 - Canonical Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it
55 * under the terms of the GNU Lesser General Public License, as
@@ -54,7 +54,6 @@ Q_SIGNALS:
5454 void error(const QString &error);
5555 void finished(const QString &path);
5656 void paused(bool success);
57− void processing(const QString &path);
5857 void progress(qulonglong received, qulonglong total);
5958 void resumed(bool success);
6059 void started(bool success);
plugins/Ubuntu/DownloadDaemonListener/interface/downloadtrackeradaptor.cpp+2−2
@@ -1,8 +1,8 @@
11/*
22 * This file was generated by qdbusxml2cpp version 0.8
3− * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h ../../../../../../ubuntu-download-manager/trunk/docs/dbus/com.canonical.applications.download.xml
3+ * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h com.canonical.applications.download.xml
44 *
5− * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
5+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
66 *
77 * This is an auto-generated file.
88 * This file may have been hand-edited. Look for HAND-EDIT comments
plugins/Ubuntu/DownloadDaemonListener/interface/downloadtrackeradaptor.h+4−71
@@ -1,15 +1,15 @@
11/*
22 * This file was generated by qdbusxml2cpp version 0.8
3− * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h ../../../../../../ubuntu-download-manager/trunk/docs/dbus/com.canonical.applications.download.xml
3+ * Command line was: qdbusxml2cpp -v -c DownloadTrackerAdaptor -p downloadtrackeradaptor.h:downloadtrackeradaptor.cpp -i metatypes.h com.canonical.applications.download.xml
44 *
5− * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
5+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
66 *
77 * This is an auto-generated file.
88 * Do not edit! All changes made to it will be lost.
99 */
1010
11−#ifndef DOWNLOADTRACKERADAPTOR_H
12−#define DOWNLOADTRACKERADAPTOR_H
11+#ifndef DOWNLOADTRACKERADAPTOR_H_1374434371
12+#define DOWNLOADTRACKERADAPTOR_H_1374434371
1313
1414#include <QtCore/QObject>
1515#include <QtCore/QByteArray>
@@ -36,22 +36,6 @@ public:
3636
3737 ~DownloadTrackerAdaptor();
3838
39− Q_PROPERTY(QString ClickPackage READ clickPackage)
40− inline QString clickPackage() const
41− { return qvariant_cast< QString >(property("ClickPackage")); }
42−
43− Q_PROPERTY(QString DestinationApp READ destinationApp)
44− inline QString destinationApp() const
45− { return qvariant_cast< QString >(property("DestinationApp")); }
46−
47− Q_PROPERTY(bool ShowInIndicator READ showInIndicator)
48− inline bool showInIndicator() const
49− { return qvariant_cast< bool >(property("ShowInIndicator")); }
50−
51− Q_PROPERTY(QString Title READ title)
52− inline QString title() const
53− { return qvariant_cast< QString >(property("Title")); }
54−
5539public Q_SLOTS: // METHODS
5640 inline QDBusPendingReply<> allowGSMDownload(bool allowed)
5741 {
@@ -66,24 +50,6 @@ public Q_SLOTS: // METHODS
6650 return asyncCallWithArgumentList(QStringLiteral("cancel"), argumentList);
6751 }
6852
69− inline QDBusPendingReply<> collected()
70− {
71− QList<QVariant> argumentList;
72− return asyncCallWithArgumentList(QStringLiteral("collected"), argumentList);
73− }
74−
75− inline QDBusPendingReply<QString> filePath()
76− {
77− QList<QVariant> argumentList;
78− return asyncCallWithArgumentList(QStringLiteral("filePath"), argumentList);
79− }
80−
81− inline QDBusPendingReply<StringMap> headers()
82− {
83− QList<QVariant> argumentList;
84− return asyncCallWithArgumentList(QStringLiteral("headers"), argumentList);
85− }
86−
8753 inline QDBusPendingReply<bool> isGSMDownloadAllowed()
8854 {
8955 QList<QVariant> argumentList;
@@ -114,27 +80,6 @@ public Q_SLOTS: // METHODS
11480 return asyncCallWithArgumentList(QStringLiteral("resume"), argumentList);
11581 }
11682
117− inline QDBusPendingReply<> setDestinationDir(const QString &path)
118− {
119− QList<QVariant> argumentList;
120− argumentList << QVariant::fromValue(path);
121− return asyncCallWithArgumentList(QStringLiteral("setDestinationDir"), argumentList);
122− }
123−
124− inline QDBusPendingReply<> setHeaders(StringMap headers)
125− {
126− QList<QVariant> argumentList;
127− argumentList << QVariant::fromValue(headers);
128− return asyncCallWithArgumentList(QStringLiteral("setHeaders"), argumentList);
129− }
130−
131− inline QDBusPendingReply<> setMetadata(const QVariantMap &data)
132− {
133− QList<QVariant> argumentList;
134− argumentList << QVariant::fromValue(data);
135− return asyncCallWithArgumentList(QStringLiteral("setMetadata"), argumentList);
136− }
137−
13883 inline QDBusPendingReply<> setThrottle(qulonglong speed)
13984 {
14085 QList<QVariant> argumentList;
@@ -148,12 +93,6 @@ public Q_SLOTS: // METHODS
14893 return asyncCallWithArgumentList(QStringLiteral("start"), argumentList);
14994 }
15095
151− inline QDBusPendingReply<int> state()
152− {
153− QList<QVariant> argumentList;
154− return asyncCallWithArgumentList(QStringLiteral("state"), argumentList);
155− }
156−
15796 inline QDBusPendingReply<qulonglong> throttle()
15897 {
15998 QList<QVariant> argumentList;
@@ -167,16 +106,10 @@ public Q_SLOTS: // METHODS
167106 }
168107
169108Q_SIGNALS: // SIGNALS
170− void authError(AuthErrorStruct error);
171109 void canceled(bool success);
172110 void error(const QString &error);
173111 void finished(const QString &path);
174− void hashError(HashErrorStruct error);
175− void httpError(HttpErrorStruct error);
176− void networkError(NetworkErrorStruct error);
177112 void paused(bool success);
178− void processError(ProcessErrorStruct error);
179− void processing(const QString &path);
180113 void progress(qulonglong received, qulonglong total);
181114 void resumed(bool success);
182115 void started(bool success);
plugins/Ubuntu/DownloadDaemonListener/interface/metatypes.h+6−3
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2013-2016 Canonical Ltd.
2+ * Copyright 2013 2013 Canonical Ltd.
33 *
44 * This library is free software; you can redistribute it and/or
55 * modify it under the terms of version 3 of the GNU Lesser General Public
@@ -19,7 +19,10 @@
1919#ifndef DOWNLOADER_LIB_APP_METATYPES_H
2020#define DOWNLOADER_LIB_APP_METATYPES_H
2121
22−// Just include the system file so we're always up to date.
23−#include <ubuntu/download_manager/metatypes.h>
22+#include <QMap>
23+
24+typedef QMap<QString, QString> StringMap;
25+
26+Q_DECLARE_METATYPE(StringMap)
2427
2528#endif // METATYPES_H
plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp+1−1
@@ -21,7 +21,7 @@
2121#include "AxisVelocityCalculator.h"
2222#include <QtCore/QElapsedTimer>
2323
24−UG_USE_NAMESPACE
24+using namespace UbuntuGestures;
2525
2626AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
2727 : AxisVelocityCalculator(SharedTimeSource(new RealTimeSource), parent)
plugins/Ubuntu/Gestures/AxisVelocityCalculator.h+4−4
@@ -24,7 +24,7 @@
2424#include "UbuntuGesturesQmlGlobal.h"
2525#include <stdint.h>
2626#include <QtCore/QObject>
27−#include <UbuntuGestures/private/timesource_p.h>
27+#include <TimeSource>
2828
2929/*
3030 Estimates the current velocity of a finger based on recent movement along an axis
@@ -68,7 +68,7 @@ public:
6868 /*
6969 Constructor that takes a TimeSource
7070 */
71− AxisVelocityCalculator(const UG_PREPEND_NAMESPACE(SharedTimeSource) &timeSource, QObject *parent = 0);
71+ AxisVelocityCalculator(const UbuntuGestures::SharedTimeSource &timeSource, QObject *parent = 0);
7272
7373 virtual ~AxisVelocityCalculator();
7474
@@ -90,7 +90,7 @@ public:
9090 /*
9191 Replaces the TimeSource with the given one. Useful for testing purposes.
9292 */
93− void setTimeSource(const UG_PREPEND_NAMESPACE(SharedTimeSource) &timeSource);
93+ void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
9494
9595 /*
9696 The minimum amount of samples needed for a velocity calculation.
@@ -138,7 +138,7 @@ private:
138138 int m_samplesRead; /* index of the oldest sample available. -1 if buffer is empty */
139139 int m_samplesWrite; /* index where the next sample will be written */
140140
141− UG_PREPEND_NAMESPACE(SharedTimeSource) m_timeSource;
141+ UbuntuGestures::SharedTimeSource m_timeSource;
142142
143143 qreal m_trackedPosition;
144144};
plugins/Ubuntu/Gestures/CMakeLists.txt+5−8
@@ -16,17 +16,15 @@ pkg_check_modules(UBUNTUGESTURES REQUIRED UbuntuGestures)
1616
1717add_definitions(-DUBUNTUGESTURESQML_LIBRARY)
1818
19−add_library(UbuntuGesturesQml SHARED ${UbuntuGesturesQml_SOURCES})
20−target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES} Qt5::Core Qt5::Quick)
19+add_library(UbuntuGesturesQml MODULE ${UbuntuGesturesQml_SOURCES})
20+target_link_libraries(UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
21+
22+qt5_use_modules(UbuntuGesturesQml Core Quick)
2123
2224# So that Foo.cpp can #include "Foo.moc"
2325include_directories(${CMAKE_CURRENT_BINARY_DIR})
2426
25−include_directories(
26− SYSTEM
27− ${UBUNTUGESTURES_INCLUDE_DIRS}
28− ${UBUNTUGESTURES_INCLUDEDIR}/UbuntuGestures/${UBUNTUGESTURES_VERSION}
29−)
27+include_directories(${UBUNTUGESTURES_INCLUDE_DIRS})
3028
3129# There's no cmake var for v8 include path :-/ so create one
3230LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
@@ -34,7 +32,6 @@ SET(Qt5V8_PRIVATE_INCLUDE_DIR ${QtCoreDir0}/QtV8/${Qt5Core_VERSION_STRING}/QtV8)
3432
3533# DANGER! DANGER! Using Qt's private API!
3634include_directories(
37− SYSTEM
3835 ${Qt5Qml_PRIVATE_INCLUDE_DIRS}
3936 ${Qt5Quick_INCLUDE_DIRS}
4037 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
plugins/Ubuntu/Gestures/Direction.h+1−1
@@ -26,6 +26,7 @@
2626 */
2727class UBUNTUGESTURESQML_EXPORT Direction : public QObject {
2828 Q_OBJECT
29+ Q_ENUMS(Type)
2930
3031public:
3132 // Make sure it is kept synchronized with SDK UCSwipeArea::Direction
@@ -37,7 +38,6 @@ public:
3738 Horizontal, // Along the X axis, in any direction
3839 Vertical // Along the Y axis, in any direction
3940 };
40− Q_ENUM(Type)
4141
4242 Q_INVOKABLE static bool isHorizontal(Direction::Type type);
4343 Q_INVOKABLE static bool isVertical(Direction::Type type);
plugins/Ubuntu/Gestures/Gestures.qmltypesnew file+77
@@ -0,0 +1,77 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Ubuntu.Gestures 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "AxisVelocityCalculator"
12+ prototype: "QObject"
13+ exports: ["Ubuntu.Gestures/AxisVelocityCalculator 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "trackedPosition"; type: "double" }
16+ Signal {
17+ name: "trackedPositionChanged"
18+ Parameter { name: "value"; type: "double" }
19+ }
20+ Method { name: "calculate"; type: "double" }
21+ Method { name: "reset" }
22+ }
23+ Component {
24+ name: "Direction"
25+ prototype: "QObject"
26+ exports: ["Ubuntu.Gestures/Direction 0.1"]
27+ isCreatable: false
28+ isSingleton: true
29+ exportMetaObjectRevisions: [0]
30+ Enum {
31+ name: "Type"
32+ values: {
33+ "Rightwards": 0,
34+ "Leftwards": 1,
35+ "Downwards": 2,
36+ "Upwards": 3,
37+ "Horizontal": 4,
38+ "Vertical": 5
39+ }
40+ }
41+ Method {
42+ name: "isHorizontal"
43+ type: "bool"
44+ Parameter { name: "type"; type: "Direction::Type" }
45+ }
46+ Method {
47+ name: "isVertical"
48+ type: "bool"
49+ Parameter { name: "type"; type: "Direction::Type" }
50+ }
51+ Method {
52+ name: "isPositive"
53+ type: "bool"
54+ Parameter { name: "type"; type: "Direction::Type" }
55+ }
56+ }
57+ Component {
58+ name: "PressedOutsideNotifier"
59+ defaultProperty: "data"
60+ prototype: "QQuickItem"
61+ exports: ["Ubuntu.Gestures/PressedOutsideNotifier 0.1"]
62+ exportMetaObjectRevisions: [0]
63+ Signal { name: "pressedOutside" }
64+ }
65+ Component {
66+ name: "TouchGate"
67+ defaultProperty: "data"
68+ prototype: "QQuickItem"
69+ exports: ["Ubuntu.Gestures/TouchGate 0.1"]
70+ exportMetaObjectRevisions: [0]
71+ Property { name: "targetItem"; type: "QQuickItem"; isPointer: true }
72+ Signal {
73+ name: "targetItemChanged"
74+ Parameter { name: "item"; type: "QQuickItem"; isPointer: true }
75+ }
76+ }
77+}
plugins/Ubuntu/Gestures/TouchDispatcher.cpp+5−1
@@ -19,7 +19,11 @@
1919#include <QGuiApplication>
2020#include <QScopedPointer>
2121#include <QStyleHints>
22+
23+#pragma GCC diagnostic push
24+#pragma GCC diagnostic ignored "-pedantic"
2225#include <private/qquickitem_p.h>
26+#pragma GCC diagnostic pop
2327
2428#define TOUCHDISPATCHER_DEBUG 0
2529
@@ -221,7 +225,7 @@ void TouchDispatcher::dispatchAsMouse(
221225 QEvent::Type eventType;
222226 if (touchMouse->state() == Qt::TouchPointPressed) {
223227 eventType = QEvent::MouseButtonPress;
224− } else if (touchMouse->state() == Qt::TouchPointReleased) {
228+ } if (touchMouse->state() == Qt::TouchPointReleased) {
225229 eventType = QEvent::MouseButtonRelease;
226230 m_touchMouseId = -1;
227231 } else {
plugins/Ubuntu/Gestures/TouchGate.cpp+5−10
@@ -20,18 +20,16 @@
2020#include <QDebug>
2121#include <QQuickWindow>
2222
23−#include <UbuntuGestures/private/touchownershipevent_p.h>
24−#include <UbuntuGestures/private/touchregistry_p.h>
23+#include <TouchOwnershipEvent>
24+#include <TouchRegistry>
2525
2626#if TOUCHGATE_DEBUG
2727#define ugDebug(params) qDebug().nospace() << "[TouchGate(" << (void*)this << ")] " << params
28−#include <UbuntuGestures/private/debughelpers_p.h>
28+#include <DebugHelpers.h>
2929#else // TOUCHGATE_DEBUG
3030#define ugDebug(params) ((void)0)
3131#endif // TOUCHGATE_DEBUG
3232
33−UG_USE_NAMESPACE
34−
3533TouchGate::TouchGate(QQuickItem *parent)
3634 : QQuickItem(parent)
3735{
@@ -42,7 +40,7 @@ TouchGate::TouchGate(QQuickItem *parent)
4240bool TouchGate::event(QEvent *e)
4341{
4442 if (e->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
45− touchOwnershipEvent(static_cast<TouchOwnershipEvent*>(e));
43+ touchOwnershipEvent(static_cast<TouchOwnershipEvent *>(e));
4644 return true;
4745 } else {
4846 return QQuickItem::event(e);
@@ -61,10 +59,7 @@ void TouchGate::touchEvent(QTouchEvent *event)
6159 const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
6260
6361 if (touchPoint.state() == Qt::TouchPointPressed) {
64−// FIXME: This assert triggers frequently in make trySomething. We have verified
65−// that it's a bug in the mouse to touch conversion of the test environment
66−// and not in the actual product. Still, it probably should be cleaned up eventually.
67−// Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id()));
62+ Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id()));
6863 m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested;
6964 m_touchInfoMap[touchPoint.id()].ended = false;
7065 TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(), this);
plugins/Ubuntu/Gestures/TouchGate.h+2−3
@@ -19,7 +19,6 @@
1919
2020#include "UbuntuGesturesQmlGlobal.h"
2121#include "TouchDispatcher.h"
22−#include <UbuntuGestures/ubuntugesturesglobal.h>
2322
2423#include <QQuickItem>
2524#include <QList>
@@ -27,7 +26,7 @@
2726
2827#define TOUCHGATE_DEBUG 0
2928
30−UG_FORWARD_DECLARE_CLASS(TouchOwnershipEvent)
29+class TouchOwnershipEvent;
3130
3231/*
3332 Blocks the passage of events until ownership over the related touch points is granted.
@@ -83,7 +82,7 @@ private:
8382 ulong timestamp;
8483 };
8584
86− void touchOwnershipEvent(UG_PREPEND_NAMESPACE(TouchOwnershipEvent) *event);
85+ void touchOwnershipEvent(TouchOwnershipEvent *event);
8786 bool isTouchPointOwned(int touchId) const;
8887 void storeTouchEvent(QTouchDevice *device,
8988 Qt::KeyboardModifiers modifiers,
plugins/Ubuntu/Gestures/TouchGestureArea.cpp+21−22
@@ -16,9 +16,9 @@
1616
1717#include "TouchGestureArea.h"
1818
19−#include <UbuntuGestures/private/touchownershipevent_p.h>
20−#include <UbuntuGestures/private/touchregistry_p.h>
21−#include <UbuntuGestures/private/unownedtouchevent_p.h>
19+#include <UbuntuGestures/TouchOwnershipEvent>
20+#include <UbuntuGestures/TouchRegistry>
21+#include <UbuntuGestures/UnownedTouchEvent>
2222// #include "TouchRegistry.h"
2323// #include "UnownedTouchEvent.h"
2424
@@ -26,8 +26,6 @@
2626#include <QStyleHints>
2727#include <private/qquickwindow_p.h>
2828
29−UG_USE_NAMESPACE
30−
3129#define TOUCHGESTUREAREA_DEBUG 0
3230
3331// TODO - understand more about why we lose touch event releases.
@@ -137,7 +135,7 @@ TouchGestureArea::TouchGestureArea(QQuickItem* parent)
137135 , m_recognitionPeriod(50)
138136 , m_releaseRejectPeriod(100)
139137{
140− setRecognitionTimer(new Timer(this));
138+ setRecognitionTimer(new UbuntuGestures::Timer(this));
141139 m_recognitionTimer->setInterval(m_recognitionPeriod);
142140 m_recognitionTimer->setSingleShot(true);
143141}
@@ -155,10 +153,10 @@ bool TouchGestureArea::event(QEvent *event)
155153{
156154 // Process unowned touch events (handles update/release for incomplete gestures)
157155 if (event->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
158− touchOwnershipEvent(static_cast<TouchOwnershipEvent*>(event));
156+ touchOwnershipEvent(static_cast<TouchOwnershipEvent *>(event));
159157 return true;
160158 } else if (event->type() == UnownedTouchEvent::unownedTouchEventType()) {
161− unownedTouchEvent(static_cast<UnownedTouchEvent*>(event)->touchEvent());
159+ unownedTouchEvent(static_cast<UnownedTouchEvent *>(event)->touchEvent());
162160 return true;
163161 }
164162
@@ -328,12 +326,6 @@ void TouchGestureArea::touchEvent_rejected(QTouchEvent *event)
328326 }
329327 }
330328 }
331−
332− // If this event is a new touch, ignore it and let the item below have it.
333− // We won't recognize any new touch until the whole current gesture is done
334− // i.e. we're in WaitingForTouch state.
335− // And even if it isn't, just ignore it anyway; we don't care about it.
336− event->ignore();
337329}
338330
339331void TouchGestureArea::unownedTouchEvent(QTouchEvent *unownedTouchEvent)
@@ -383,7 +375,7 @@ void TouchGestureArea::unownedTouchEvent_waitingForMoreTouches(QTouchEvent *even
383375 }
384376 }
385377
386− if (m_candidateTouches.isEmpty()) {
378+ if (m_candidateTouches.count() == 0) {
387379 setInternalStatus(InternalStatus::WaitingForTouch);
388380 }
389381}
@@ -447,7 +439,7 @@ void TouchGestureArea::unownedTouchEvent_rejected(QTouchEvent *event)
447439 }
448440 }
449441
450− if (m_watchedTouches.isEmpty()) {
442+ if (m_watchedTouches.count() == 0) {
451443 setInternalStatus(InternalStatus::WaitingForTouch);
452444 }
453445}
@@ -535,7 +527,7 @@ void TouchGestureArea::updateTouchPoints(QTouchEvent *touchEvent)
535527 if (updateable) {
536528 if (!dragging() && m_status == InternalStatus::Recognized) {
537529 bool allWantDrag = !m_liveTouchPoints.isEmpty();
538− Q_FOREACH(const auto &point, m_liveTouchPoints) {
530+ Q_FOREACH(auto point, m_liveTouchPoints) {
539531 allWantDrag &= point->dragging();
540532 }
541533 // only dragging if all points are dragging.
@@ -616,7 +608,7 @@ void TouchGestureArea::setInternalStatus(uint newStatus)
616608 }
617609}
618610
619−void TouchGestureArea::setRecognitionTimer(AbstractTimer *timer)
611+void TouchGestureArea::setRecognitionTimer(UbuntuGestures::AbstractTimer *timer)
620612{
621613 int interval = 0;
622614 bool timerWasRunning = false;
@@ -654,9 +646,11 @@ bool TouchGestureArea::dragging() const
654646QQmlListProperty<GestureTouchPoint> TouchGestureArea::touchPoints()
655647{
656648 return QQmlListProperty<GestureTouchPoint>(this,
657− nullptr,
658− TouchGestureArea::touchPoint_count,
659− TouchGestureArea::touchPoint_at);
649+ 0,
650+ nullptr,
651+ TouchGestureArea::touchPoint_count,
652+ TouchGestureArea::touchPoint_at,
653+ 0);
660654}
661655
662656int TouchGestureArea::minimumTouchPoints() const
@@ -727,7 +721,7 @@ void TouchGestureArea::rejectGesture()
727721 }
728722 m_candidateTouches.clear();
729723
730− if (m_watchedTouches.isEmpty()) {
724+ if (m_watchedTouches.count() == 0) {
731725 setInternalStatus(InternalStatus::WaitingForTouch);
732726 } else {
733727 setInternalStatus(InternalStatus::Rejected);
@@ -741,6 +735,7 @@ void TouchGestureArea::resyncCachedTouchPoints()
741735 bool added = false;
742736 bool ended = false;
743737 bool moved = false;
738+ bool wantsDrag = false;
744739
745740 // list of deletes
746741 QMutableHashIterator<int, GestureTouchPoint*> removeIter(m_cachedTouchPoints);
@@ -770,6 +765,10 @@ void TouchGestureArea::resyncCachedTouchPoints()
770765 }
771766 }
772767
768+ if (wantsDrag && !dragging()) {
769+ setDragging(true);
770+ }
771+
773772 if (ended) {
774773 if (m_cachedTouchPoints.isEmpty()) {
775774 if (!dragging()) Q_EMIT clicked();
plugins/Ubuntu/Gestures/TouchGestureArea.h+16−17
@@ -21,11 +21,10 @@
2121
2222#include <QQuickItem>
2323
24−#include <UbuntuGestures/ubuntugesturesglobal.h>
25−#include <UbuntuGestures/private/timer_p.h>
24+#include <UbuntuGestures/Timer>
2625
27−UG_FORWARD_DECLARE_CLASS(TouchOwnershipEvent)
28−UG_FORWARD_DECLARE_CLASS(UnownedTouchEvent)
26+class TouchOwnershipEvent;
27+class UnownedTouchEvent;
2928
3029class GestureTouchPoint : public QObject
3130{
@@ -76,7 +75,7 @@ public:
7675 return *this;
7776 }
7877
79− bool operator==(const GestureTouchPoint& rhs) const {
78+ bool operator=(const GestureTouchPoint& rhs) const {
8079 if (&rhs == this) return true;
8180 return m_id == rhs.m_id &&
8281 m_pressed == rhs.m_pressed &&
@@ -84,7 +83,7 @@ public:
8483 m_y == rhs.m_y &&
8584 m_dragging == rhs.m_dragging;
8685 }
87− bool operator!=(const GestureTouchPoint& rhs) const { return !operator==(rhs); }
86+ bool operator!=(const GestureTouchPoint& rhs) const { return !operator=(rhs); }
8887
8988 void setPos(const QPointF &pos);
9089
@@ -106,14 +105,15 @@ private:
106105/*
107106 An area that detects multi-finger gestures.
108107
109− We can use this to detect gestures constrained by a minimum and/or maximum number of touch points.
110− This component uses the touch registry to apply for ownership of touch points.
108+ We can use this to detect gestures contstrained by a minimim and/or maximum number of touch points.
109+ This components uses the touch registry to apply for ownership of touch points.
111110 This way we can use the component in conjuntion with the directional drag area to compete for ownwership
112111 or gestures; unlike the MultiPointTouchArea.
113112 */
114113class UBUNTUGESTURESQML_EXPORT TouchGestureArea : public QQuickItem
115114{
116115 Q_OBJECT
116+ Q_ENUMS(Status)
117117
118118 Q_PROPERTY(int status READ status NOTIFY statusChanged)
119119 Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
@@ -136,13 +136,12 @@ public:
136136 Recognized,
137137 Rejected
138138 };
139− Q_ENUM(Status)
140− TouchGestureArea(QQuickItem* parent = nullptr);
139+ TouchGestureArea(QQuickItem* parent = NULL);
141140 ~TouchGestureArea();
142141
143142 bool event(QEvent *e) override;
144143
145− void setRecognitionTimer(UG_PREPEND_NAMESPACE(AbstractTimer) *timer);
144+ void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
146145
147146 int status() const;
148147 bool dragging() const;
@@ -165,10 +164,10 @@ Q_SIGNALS:
165164
166165 void touchPointsUpdated();
167166 void draggingChanged(bool dragging);
168− void minimumTouchPointsChanged(int value);
169− void maximumTouchPointsChanged(int value);
170− void recognitionPeriodChanged(int value);
171− void releaseRejectPeriodChanged(int value);
167+ void minimumTouchPointsChanged(bool value);
168+ void maximumTouchPointsChanged(bool value);
169+ void recognitionPeriodChanged(bool value);
170+ void releaseRejectPeriodChanged(bool value);
172171
173172 void pressed(const QList<QObject*>& points);
174173 void released(const QList<QObject*>& points);
@@ -195,7 +194,7 @@ private:
195194 void unownedTouchEvent_recognised(QTouchEvent *unownedTouchEvent);
196195 void unownedTouchEvent_rejected(QTouchEvent *unownedTouchEvent);
197196
198− void touchOwnershipEvent(UG_PREPEND_NAMESPACE(TouchOwnershipEvent) *event);
197+ void touchOwnershipEvent(TouchOwnershipEvent *event);
199198 void updateTouchPoints(QTouchEvent *event);
200199
201200 GestureTouchPoint* addTouchPoint(const QTouchEvent::TouchPoint *tp);
@@ -210,7 +209,7 @@ private:
210209 uint m_status;
211210 QSet<int> m_candidateTouches;
212211 QSet<int> m_watchedTouches;
213− UG_PREPEND_NAMESPACE(AbstractTimer) *m_recognitionTimer;
212+ UbuntuGestures::AbstractTimer *m_recognitionTimer;
214213
215214 bool m_dragging;
216215 QHash<int, GestureTouchPoint*> m_liveTouchPoints;
plugins/Ubuntu/Payments/CMakeLists.txtnew file+20
@@ -0,0 +1,20 @@
1+include_directories(
2+ ${CMAKE_CURRENT_SOURCE_DIR}
3+ ${CMAKE_CURRENT_BINARY_DIR}
4+)
5+
6+set(PAYMENTS_SOURCES
7+ plugin.cpp
8+ Payments.cpp
9+)
10+
11+add_library(Payments MODULE ${PAYMENTS_SOURCES})
12+
13+qt5_use_modules(Payments Qml Quick DBus Core)
14+
15+add_unity8_plugin(Ubuntu.Payments 0.1 Ubuntu/Payments TARGETS Payments)
16+
17+pkg_check_modules(LIBPAY REQUIRED pay-2)
18+add_definitions(${LIBPAY_CFLAGS} ${LIBPAY_CFLAGS_OTHER})
19+
20+target_link_libraries(Payments ${LIBPAY_LDFLAGS})
plugins/Ubuntu/Payments/Payments.cppnew file+136
@@ -0,0 +1,136 @@
1+/*
2+ * Copyright (C) 2014 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+#include "Payments.h"
18+
19+#include <QLocale>
20+
21+#include <libpay/pay-package.h>
22+
23+
24+// The observer callback for the package we are watching.
25+static void observer(PayPackage* /* package */, const char* itemid, PayPackageItemStatus status, void* user_data) {
26+ // This function is called in libpay's thread, so be careful what you call
27+ // Emitting signals should be fine as long as they use Queued or Auto
28+ // connections (the default)
29+ // http://qt-project.org/doc/qt-5/threads-qobject.html#signals-and-slots-across-threads
30+
31+ Payments *self = static_cast<Payments*>(user_data);
32+
33+ // If the item ID is different, ignore it.
34+ if (itemid != self->storeItemId()) {
35+ return;
36+ }
37+
38+ // FIXME: No error reporting from libpay, but we need to show some
39+ // types of errors to the user. https://launchpad.net/bugs/1333403
40+ switch (status) {
41+ case PAY_PACKAGE_ITEM_STATUS_PURCHASED:
42+ Q_EMIT self->purchaseCompleted();
43+ break;
44+ case PAY_PACKAGE_ITEM_STATUS_PURCHASING:
45+ self->setPurchasing(true);
46+ break;
47+ case PAY_PACKAGE_ITEM_STATUS_NOT_PURCHASED:
48+ if (self->purchasing()) {
49+ self->setPurchasing(false);
50+ Q_EMIT self->purchaseCancelled();
51+ }
52+ break;
53+ default:
54+ break;
55+ }
56+}
57+
58+Payments::Payments(QObject *parent)
59+ : QObject(parent),
60+ m_purchasing(false)
61+{
62+ m_package = pay_package_new("click-scope");
63+ pay_package_item_observer_install(m_package, observer, this);
64+}
65+
66+Payments::~Payments()
67+{
68+ pay_package_item_observer_uninstall(m_package, observer, this);
69+ pay_package_delete(m_package);
70+}
71+
72+QString Payments::currency() const
73+{
74+ return m_currency;
75+}
76+
77+double Payments::price() const
78+{
79+ return m_price;
80+}
81+
82+QString Payments::storeItemId() const
83+{
84+ return m_store_item_id;
85+}
86+
87+QString Payments::formattedPrice() const
88+{
89+ QLocale locale;
90+ return locale.toCurrencyString(m_price, m_currency);
91+}
92+
93+bool Payments::purchasing() const
94+{
95+ return m_purchasing;
96+}
97+
98+void Payments::setCurrency(const QString ¤cy)
99+{
100+ if(m_currency != currency) {
101+ m_currency = currency;
102+ Q_EMIT currencyChanged(currency);
103+ Q_EMIT formattedPriceChanged(formattedPrice());
104+ }
105+}
106+
107+void Payments::setPrice(const double price)
108+{
109+ if(m_price != price) {
110+ m_price = price;
111+ Q_EMIT priceChanged(price);
112+ Q_EMIT formattedPriceChanged(formattedPrice());
113+ }
114+}
115+
116+void Payments::setStoreItemId(const QString &store_item_id)
117+{
118+ if (m_store_item_id != store_item_id) {
119+ m_store_item_id = store_item_id;
120+ Q_EMIT storeItemIdChanged(m_store_item_id);
121+ }
122+
123+ if (m_store_item_id.isEmpty()) {
124+ return;
125+ }
126+}
127+
128+void Payments::setPurchasing(bool is_purchasing)
129+{
130+ m_purchasing = is_purchasing;
131+}
132+
133+void Payments::start()
134+{
135+ pay_package_item_start_purchase(m_package, m_store_item_id.toLocal8Bit().data());
136+}
plugins/Ubuntu/Payments/Payments.hnew file+69
@@ -0,0 +1,69 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef PAYMENTS_H
18+#define PAYMENTS_H
19+
20+#include <QObject>
21+
22+#include <libpay/pay-package.h>
23+
24+
25+class Payments : public QObject
26+{
27+ Q_OBJECT
28+ Q_DISABLE_COPY(Payments)
29+ Q_PROPERTY(QString currency READ currency WRITE setCurrency NOTIFY currencyChanged)
30+ Q_PROPERTY(double price READ price WRITE setPrice NOTIFY priceChanged)
31+ Q_PROPERTY(QString storeItemId READ storeItemId WRITE setStoreItemId NOTIFY storeItemIdChanged)
32+ Q_PROPERTY(QString formattedPrice READ formattedPrice NOTIFY formattedPriceChanged)
33+
34+public:
35+ explicit Payments(QObject *parent = 0);
36+ virtual ~Payments();
37+
38+ QString currency() const;
39+ double price() const;
40+ QString storeItemId() const;
41+ QString formattedPrice() const;
42+ bool purchasing() const;
43+
44+ void setCurrency(const QString& currency);
45+ void setPrice(const double price);
46+ void setStoreItemId(const QString& store_item_id);
47+ void setPurchasing(bool is_purchasing);
48+ Q_INVOKABLE void start();
49+
50+Q_SIGNALS:
51+ void currencyChanged(const QString& currency);
52+ void priceChanged(const double price);
53+ void storeItemIdChanged(const QString &store_item_id);
54+ void formattedPriceChanged(const QString &formatted_price);
55+
56+ void purchaseError(const QString &error);
57+ void purchaseCompleted();
58+ void purchaseCancelled();
59+
60+private:
61+ QString m_currency;
62+ double m_price;
63+ QString m_store_item_id;
64+ bool m_purchasing;
65+
66+ PayPackage *m_package;
67+};
68+
69+#endif // PAYMENTS_H
plugins/Ubuntu/Payments/Payments.qmltypesnew file+43
@@ -0,0 +1,43 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Ubuntu.Payments 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "Payments"
12+ prototype: "QObject"
13+ exports: ["Ubuntu.Payments/Payments 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "currency"; type: "string" }
16+ Property { name: "price"; type: "double" }
17+ Property { name: "storeItemId"; type: "string" }
18+ Property { name: "formattedPrice"; type: "string"; isReadonly: true }
19+ Signal {
20+ name: "currencyChanged"
21+ Parameter { name: "currency"; type: "string" }
22+ }
23+ Signal {
24+ name: "priceChanged"
25+ Parameter { name: "price"; type: "double" }
26+ }
27+ Signal {
28+ name: "storeItemIdChanged"
29+ Parameter { name: "store_item_id"; type: "string" }
30+ }
31+ Signal {
32+ name: "formattedPriceChanged"
33+ Parameter { name: "formatted_price"; type: "string" }
34+ }
35+ Signal {
36+ name: "purchaseError"
37+ Parameter { name: "error"; type: "string" }
38+ }
39+ Signal { name: "purchaseCompleted" }
40+ Signal { name: "purchaseCancelled" }
41+ Method { name: "start" }
42+ }
43+}
tests/mocks/Biometryd/MockIdentifier.cpp → plugins/Ubuntu/Payments/plugin.cpprenamed+9−9
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,15 +14,15 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#include "MockIdentifier.h"
18−#include "MockOperation.h"
17+#include "plugin.h"
18+#include "Payments.h"
1919
20−MockIdentifier::MockIdentifier(QObject *parent)
21− : QObject(parent)
22−{
23−}
20+#include <QtQml>
2421
25−MockOperation *MockIdentifier::identifyUser()
22+
23+void BackendPlugin::registerTypes(const char *uri)
2624{
27− return new MockOperation(this);
25+ Q_ASSERT(uri == QLatin1String("Ubuntu.Payments"));
26+
27+ qmlRegisterType<Payments>(uri, 0, 1, "Payments");
2828}
tests/mocks/Biometryd/plugin.h → plugins/Ubuntu/Payments/plugin.hrenamed+4−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef MOCK_BIOMETRYD_PLUGIN_H
18−#define MOCK_BIOMETRYD_PLUGIN_H
17+#ifndef PAYMENTS_PLUGIN_H
18+#define PAYMENTS_PLUGIN_H
1919
2020#include <QQmlExtensionPlugin>
2121
@@ -28,4 +28,4 @@ public:
2828 void registerTypes(const char *uri) override;
2929};
3030
31−#endif // MOCK_BIOMETRYD_PLUGIN_H
31+#endif // PAYMENTS_PLUGIN_H
plugins/Ubuntu/Payments/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Ubuntu.Payments
2+plugin Payments
3+typeinfo Payments.qmltypes
plugins/Ubuntu/SystemImage/CMakeLists.txtnew file+10
@@ -0,0 +1,10 @@
1+set(SYSTEMIMAGE_SOURCES
2+ plugin.cpp
3+ SystemImage.cpp
4+)
5+
6+add_library(SystemImage MODULE ${SYSTEMIMAGE_SOURCES})
7+
8+qt5_use_modules(SystemImage Qml DBus Core)
9+
10+add_unity8_plugin(Ubuntu.SystemImage 0.1 Ubuntu/SystemImage TARGETS SystemImage)
plugins/Ubuntu/SystemImage/SystemImage.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2014 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+#include "SystemImage.h"
18+#include <QDBusConnection>
19+#include <QDBusPendingCall>
20+
21+SystemImage::SystemImage(QObject *parent)
22+ : QObject(parent)
23+{
24+}
25+
26+void SystemImage::factoryReset()
27+{
28+ const QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("com.canonical.SystemImage"),
29+ QStringLiteral("/Service"),
30+ QStringLiteral("com.canonical.SystemImage"),
31+ QStringLiteral("FactoryReset"));
32+ QDBusConnection::systemBus().asyncCall(msg);
33+}
tests/mocks/Biometryd/MockIdentifier.h → plugins/Ubuntu/SystemImage/SystemImage.hrenamed+9−11
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -14,23 +14,21 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef MOCK_IDENTIFIER_H
18−#define MOCK_IDENTIFIER_H
17+#ifndef SYSTEMIMAGE_H
18+#define SYSTEMIMAGE_H
1919
2020#include <QObject>
2121
22−#include "MockOperation.h"
23−
24−class MockIdentifier : public QObject
22+class SystemImage : public QObject
2523{
2624 Q_OBJECT
25+ Q_DISABLE_COPY(SystemImage)
2726
2827public:
29− explicit MockIdentifier(QObject *parent = 0);
28+ explicit SystemImage(QObject *parent = 0);
29+ ~SystemImage() = default;
3030
31− Q_INVOKABLE MockOperation *identifyUser();
31+ Q_INVOKABLE void factoryReset();
3232};
3333
34−Q_DECLARE_METATYPE(MockIdentifier*)
35−
36−#endif // MOCK_IDENTIFIER_H
34+#endif // SYSTEMIMAGE_H
plugins/Ubuntu/SystemImage/SystemImage.qmltypesnew file+19
@@ -0,0 +1,19 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Ubuntu.SystemImage 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "SystemImage"
12+ prototype: "QObject"
13+ exports: ["Ubuntu.SystemImage/SystemImage 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Method { name: "factoryReset" }
18+ }
19+}
tests/mocks/SessionBroadcast/plugin.cpp → plugins/Ubuntu/SystemImage/plugin.cpprenamed+11−8
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,17 +15,20 @@
1515 */
1616
1717#include "plugin.h"
18−#include "SessionBroadcast.h"
18+#include "SystemImage.h"
1919
20−#include <QtQml/qqml.h>
20+#include <QtQml>
2121
22−static QObject *broadcast_provider(QQmlEngine *, QJSEngine *)
22+static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
2323{
24− return new SessionBroadcast();
24+ Q_UNUSED(engine)
25+ Q_UNUSED(scriptEngine)
26+ return new SystemImage();
2527}
2628
27−void PowerdPlugin::registerTypes(const char *uri)
29+void BackendPlugin::registerTypes(const char *uri)
2830{
29− Q_ASSERT(uri == QLatin1String("SessionBroadcast"));
30− qmlRegisterSingletonType<SessionBroadcast>(uri, 0, 1, "SessionBroadcast", broadcast_provider);
31+ Q_ASSERT(uri == QLatin1String("Ubuntu.SystemImage"));
32+
33+ qmlRegisterSingletonType<SystemImage>(uri, 0, 1, "SystemImage", service_provider);
3134}
plugins/Ubuntu/SystemImage/plugin.hnew file+31
@@ -0,0 +1,31 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef SYSTEMIMAGE_PLUGIN_H
18+#define SYSTEMIMAGE_PLUGIN_H
19+
20+#include <QQmlExtensionPlugin>
21+
22+class BackendPlugin : public QQmlExtensionPlugin
23+{
24+ Q_OBJECT
25+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26+
27+public:
28+ void registerTypes(const char *uri) override;
29+};
30+
31+#endif // SYSTEMIMAGE_PLUGIN_H
plugins/Ubuntu/SystemImage/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Ubuntu.SystemImage
2+plugin SystemImage
3+typeinfo SystemImage.qmltypes
plugins/Unity/ApplicationMenu/CMakeLists.txtdeleted−19
@@ -1,19 +0,0 @@
1−find_package(Qt5DBus REQUIRED)
2−
3−include_directories(
4− ${CMAKE_CURRENT_SOURCE_DIR}
5− ${CMAKE_CURRENT_BINARY_DIR}
6−)
7−
8−set(applicationMenu_SRCS
9− applicationmenuregistry.cpp
10− dbusapplicationmenuregistry.cpp
11− plugin.cpp)
12−
13−qt5_add_dbus_adaptor(applicationMenu_SRCS com.ubuntu.MenuRegistrar.xml dbusapplicationmenuregistry.h DBusApplicationMenuRegistry)
14−
15−add_library(ApplicationMenu-qml MODULE ${applicationMenu_SRCS})
16−
17−target_link_libraries(ApplicationMenu-qml Qt5::DBus Qt5::Qml)
18−
19−add_unity8_plugin(Unity.ApplicationMenu 0.1 Unity/ApplicationMenu TARGETS ApplicationMenu-qml)
plugins/Unity/ApplicationMenu/applicationmenuregistry.cppdeleted−141
@@ -1,141 +0,0 @@
1−/*
2− * Copyright (C) 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−#include "applicationmenuregistry.h"
18−
19−#include <QQmlEngine>
20−#include <QDebug>
21−
22−Q_LOGGING_CATEGORY(UNITY_APPMENU, "unity.appmenu", QtDebugMsg)
23−
24−#define DEBUG_MSG qCDebug(UNITY_APPMENU).nospace().noquote() << "ApplicationMenuRegistry::" << __func__
25−#define WARNING_MSG qCWarning(UNITY_APPMENU).nospace().noquote() << "ApplicationMenuRegistry::" << __func__
26−
27−ApplicationMenuRegistry::ApplicationMenuRegistry(QObject *parent)
28− : QObject(parent)
29−{
30−}
31−
32−ApplicationMenuRegistry::~ApplicationMenuRegistry()
33−{
34− qDeleteAll(m_appMenus);
35− m_appMenus.clear();
36−
37− qDeleteAll(m_surfaceMenus);
38− m_surfaceMenus.clear();
39−}
40−
41−void ApplicationMenuRegistry::RegisterAppMenu(pid_t processId,
42− const QDBusObjectPath &menuObjectPath,
43− const QDBusObjectPath &actionObjectPath,
44− const QString &service)
45−{
46− DEBUG_MSG << "(pid=" << processId
47− << ", menuPath=" << menuObjectPath.path()
48− << ", actionPath=" << actionObjectPath.path()
49− << ", service=" << service;
50−
51− auto i = m_appMenus.find(processId);
52− while (i != m_appMenus.end() && i.key() == processId) {
53− if (i.value()->m_menuPath == menuObjectPath.path().toUtf8()) {
54− WARNING_MSG << "Already have a menu for application (pid= " << processId
55− << ", service=" << service
56− << ", menuPath=" << menuObjectPath.path() << ")";
57− return;
58− }
59− ++i;
60− }
61−
62− auto menu = new MenuServicePath(service, menuObjectPath, actionObjectPath);
63− QQmlEngine::setObjectOwnership(menu, QQmlEngine::CppOwnership);
64−
65− m_appMenus.insert(processId, menu);
66− Q_EMIT appMenuRegistered(processId);
67−}
68−
69−void ApplicationMenuRegistry::UnregisterAppMenu(pid_t processId, const QDBusObjectPath &menuObjectPath)
70−{
71− DEBUG_MSG << "(pid=" << processId
72− << ", menuPath=" << menuObjectPath.path();
73−
74− auto i = m_appMenus.find(processId);
75− while (i != m_appMenus.end() && i.key() == processId) {
76− if (i.value()->m_menuPath == menuObjectPath.path().toUtf8()) {
77− i.value()->deleteLater();
78− m_appMenus.erase(i);
79− Q_EMIT appMenuUnregistered(processId);
80− break;
81− }
82− ++i;
83− }
84−}
85−
86−void ApplicationMenuRegistry::RegisterSurfaceMenu(const QString &surfaceId,
87− const QDBusObjectPath &menuObjectPath,
88− const QDBusObjectPath &actionObjectPath,
89− const QString &service)
90−{
91− DEBUG_MSG << "(surfaceId=" << surfaceId
92− << ", menuPath=" << menuObjectPath.path()
93− << ", actionPath=" << actionObjectPath.path()
94− << ", service=" << service;
95−
96− auto i = m_surfaceMenus.find(surfaceId);
97− while (i != m_surfaceMenus.end() && i.key() == surfaceId) {
98− if (i.value()->m_menuPath == menuObjectPath.path().toUtf8()) {
99− WARNING_MSG << "Already have a menu for surface (surfaceId= " << surfaceId
100− << ", service=" << service
101− << ", menuPath=" << menuObjectPath.path() << ")";
102− return;
103− }
104− ++i;
105− }
106−
107− auto menu = new MenuServicePath(service, menuObjectPath, actionObjectPath);
108− QQmlEngine::setObjectOwnership(menu, QQmlEngine::CppOwnership);
109−
110− m_surfaceMenus.insert(surfaceId, menu);
111− Q_EMIT surfaceMenuRegistered(surfaceId);
112−}
113−
114−void ApplicationMenuRegistry::UnregisterSurfaceMenu(const QString &surfaceId, const QDBusObjectPath &menuObjectPath)
115−{
116− DEBUG_MSG << "(surfaceId=" << surfaceId
117− << ", menuPath=" << menuObjectPath.path();
118−
119− auto i = m_surfaceMenus.find(surfaceId);
120− while (i != m_surfaceMenus.end() && i.key() == surfaceId) {
121− if (i.value()->m_menuPath == menuObjectPath.path().toUtf8()) {
122− i.value()->deleteLater();
123− m_surfaceMenus.erase(i);
124− Q_EMIT surfaceMenuUnregistered(surfaceId);
125− break;
126− }
127− ++i;
128− }
129−}
130−
131−QList<QObject*> ApplicationMenuRegistry::getMenusForSurface(const QString &surfaceId) const
132−{
133− QList<QObject*> list;
134−
135− auto i = m_surfaceMenus.find(surfaceId);
136− while (i != m_surfaceMenus.constEnd() && i.key() == surfaceId) {
137− list << i.value();
138− ++i;
139− }
140− return list;
141−}
plugins/Unity/ApplicationMenu/applicationmenuregistry.hdeleted−83
@@ -1,83 +0,0 @@
1−/*
2− * Copyright (C) 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−#ifndef APPLICATIONMENUREGISTRY_H
18−#define APPLICATIONMENUREGISTRY_H
19−
20−#include <QObject>
21−#include <QDBusContext>
22−#include <QDBusObjectPath>
23−#include <QtQml>
24−
25−Q_DECLARE_LOGGING_CATEGORY(UNITY_APPMENU)
26−
27−class MenuServicePath : public QObject
28−{
29− Q_OBJECT
30− Q_PROPERTY(QByteArray service MEMBER m_service CONSTANT)
31− Q_PROPERTY(QByteArray menuPath MEMBER m_menuPath CONSTANT)
32− Q_PROPERTY(QByteArray actionPath MEMBER m_actionPath CONSTANT)
33−public:
34− explicit MenuServicePath(const QString &service,
35− const QDBusObjectPath &menuPath,
36− const QDBusObjectPath &actionPath)
37− : m_service(service.toUtf8())
38− , m_menuPath(menuPath.path().toUtf8())
39− , m_actionPath(actionPath.path().toUtf8())
40− {}
41−
42− const QByteArray m_service;
43− const QByteArray m_menuPath;
44− const QByteArray m_actionPath;
45−};
46−
47−class ApplicationMenuRegistry : public QObject
48−{
49− Q_OBJECT
50−public:
51− virtual ~ApplicationMenuRegistry();
52−
53− // for qml
54− Q_INVOKABLE QList<QObject*> getMenusForSurface(const QString &surfaceId) const;
55−
56− // for dbus
57− void RegisterAppMenu(pid_t processId,
58− const QDBusObjectPath &menuObjectPath,
59− const QDBusObjectPath &actionObjectPath,
60− const QString &service);
61− void UnregisterAppMenu(pid_t processId, const QDBusObjectPath &menuObjectPath);
62−
63− void RegisterSurfaceMenu(const QString &surfaceId,
64− const QDBusObjectPath &menuObjectPath,
65− const QDBusObjectPath &actionObjectPath,
66− const QString &service);
67− void UnregisterSurfaceMenu(const QString &surfaceId, const QDBusObjectPath &menuObjectPath);
68−
69−Q_SIGNALS:
70− void appMenuRegistered(uint processId);
71− void appMenuUnregistered(uint processId);
72−
73− void surfaceMenuRegistered(const QString& surfaceId);
74− void surfaceMenuUnregistered(const QString& surfaceId);
75−
76−protected:
77− explicit ApplicationMenuRegistry(QObject *parent = 0);
78−
79− QMultiMap<pid_t, MenuServicePath*> m_appMenus;
80− QMultiMap<QString, MenuServicePath*> m_surfaceMenus;
81−};
82−
83−#endif // APPLICATIONMENUREGISTRY_H
plugins/Unity/ApplicationMenu/com.ubuntu.MenuRegistrar.xmldeleted−83
@@ -1,83 +0,0 @@
1−<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
2−<node xmlns:dox="http://www.ayatana.org/dbus/dox.dtd">
3− <dox:d><![CDATA[
4− @mainpage
5−
6− An interface to register menus that are associated with a window in an application. The
7− main interface is documented here: @ref com::ubuntu::MenuRegistrar.
8−
9− The actual menus are transported using the gmenumodel protocol
10− ]]></dox:d>
11− <interface name="com.ubuntu.MenuRegistrar" xmlns:dox="http://www.ayatana.org/dbus/dox.dtd">
12− <dox:d>
13− An interface to register a menu from an application to be displayed in another
14− window. This manages that association between processes and/or Mir surface IDs and the dbus
15− address and object that provides the menus using the org.gtk.Menus interface.
16− </dox:d>
17− <method name="RegisterAppMenu">
18− <dox:d><![CDATA[
19− Associates a gmenumodel with an application
20−
21− /note this method assumes that the connection from the caller is the DBus connection
22− to use for the object. Applications that use multiple DBus connections will need to
23− ensure this method is called with the same connection that implements the object.
24− ]]></dox:d>
25− <arg name="pid" type="u" direction="in">
26− <dox:d>The process ID of the application for which the menu is associated</dox:d>
27− </arg>
28− <arg name="menuObjectPath" type="o" direction="in">
29− <dox:d>The dbus path where the gmenumodel interface for the application menu has been exported</dox:d>
30− </arg>
31− <arg name="actionObjectPath" type="o" direction="in">
32− <dox:d>The dbus path where the gactionmenu interface for the application menu actions has been exported</dox:d>
33− </arg>
34− <arg name="service" type="s" direction="in">
35− <dox:d>The dbus conection name of the client application to be registered (e.g. :1.23 or org.example.service)</dox:d>
36− </arg>
37− </method>
38− <method name="UnregisterAppMenu">
39− <dox:d>
40− A method to allow removing an application menu from the database.
41− </dox:d>
42− <arg name="pid" type="u" direction="in">
43− <dox:d>The process id of the application</dox:d>
44− </arg>
45− <arg name="menuObjectPath" type="o" direction="in">
46− <dox:d>The dbus path for the registered application menu to be unregistered</dox:d>
47− </arg>
48− </method>
49−
50− <method name="RegisterSurfaceMenu">
51− <dox:d><![CDATA[
52− Associates a gmenumodel with a surface
53−
54− /note this method assumes that the connection from the caller is the DBus connection
55− to use for the object. Applications that use multiple DBus connections will need to
56− ensure this method is called with the same connection that implements the object.
57− ]]></dox:d>
58− <arg name="surface" type="s" direction="in">
59− <dox:d>The surface ID of the surface</dox:d>
60− </arg>
61− <arg name="menuObjectPath" type="o" direction="in">
62− <dox:d>The dbus path where the gmenumodel interface for the surface menu has been exported</dox:d>
63− </arg>
64− <arg name="actionObjectPath" type="o" direction="in">
65− <dox:d>The dbus path where the gactionmenu interface for the surface menu actions has been exported</dox:d>
66− </arg>
67− <arg name="service" type="s" direction="in">
68− <dox:d>The dbus conection name of the client application to be registered (e.g. :1.23 or org.example.service)</dox:d>
69− </arg>
70− </method>
71− <method name="UnregisterSurfaceMenu">
72− <dox:d>
73− A method to allow removing a surface menu from the database.
74− </dox:d>
75− <arg name="surfaceId" type="s" direction="in">
76− <dox:d>The surface id of the surface</dox:d>
77− </arg>
78− <arg name="menuObjectPath" type="o" direction="in">
79− <dox:d>The dbus path for the registered surface menu to be unregistered</dox:d>
80− </arg>
81− </method>
82− </interface>
83−</node>
plugins/Unity/ApplicationMenu/dbusapplicationmenuregistry.cppdeleted−44
@@ -1,44 +0,0 @@
1−/*
2− * Copyright (C) 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−#include "dbusapplicationmenuregistry.h"
18−#include "menuregistraradaptor.h"
19−
20−DBusApplicationMenuRegistry::DBusApplicationMenuRegistry(QObject *parent)
21− : ApplicationMenuRegistry(parent)
22−{
23− new MenuRegistrarAdaptor(this);
24−
25− QDBusConnection connection = QDBusConnection::sessionBus();
26− if (!connection.registerObject("/com/ubuntu/MenuRegistrar", this)) {
27− qCWarning(UNITY_APPMENU) << "Unable to register DBus object /com/ubuntu/MenuRegistrar";
28− }
29− if (!connection.registerService("com.ubuntu.MenuRegistrar")) {
30− qCWarning(UNITY_APPMENU) << "Unable to register DBus service com.ubuntu.MenuRegistrar";
31− }
32−}
33−
34−DBusApplicationMenuRegistry::~DBusApplicationMenuRegistry()
35−{
36− QDBusConnection connection = QDBusConnection::sessionBus();
37− connection.unregisterObject("/com/ubuntu/MenuRegistrar");
38−}
39−
40−ApplicationMenuRegistry *DBusApplicationMenuRegistry::instance()
41−{
42− static ApplicationMenuRegistry* reg(new DBusApplicationMenuRegistry());
43− return reg;
44−}
plugins/Unity/ApplicationMenu/dbusapplicationmenuregistry.hdeleted−34
@@ -1,34 +0,0 @@
1−/*
2− * Copyright (C) 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−#ifndef DBUSAPPLICATIONMENUREGISTRY_H
18−#define DBUSAPPLICATIONMENUREGISTRY_H
19−
20−#include "applicationmenuregistry.h"
21−
22−class DBusApplicationMenuRegistry : public ApplicationMenuRegistry,
23− protected QDBusContext
24−{
25− Q_OBJECT
26−public:
27− ~DBusApplicationMenuRegistry();
28− static ApplicationMenuRegistry* instance();
29−
30−protected:
31− explicit DBusApplicationMenuRegistry(QObject *parent = 0);
32−};
33−
34−#endif // DBUSAPPLICATIONMENUREGISTRY_H
plugins/Unity/ApplicationMenu/plugin.cppdeleted−42
@@ -1,42 +0,0 @@
1−/*
2− * Copyright (C) 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−#include "plugin.h"
18−#include "dbusapplicationmenuregistry.h"
19−
20−#include <QtQml>
21−
22−static QObject *menuRegistry(QQmlEngine *engine, QJSEngine *scriptEngine)
23−{
24− Q_UNUSED(engine)
25− Q_UNUSED(scriptEngine)
26− return DBusApplicationMenuRegistry::instance();
27−}
28−
29−void ApplicationMenuPlugin::registerTypes(const char *uri)
30−{
31− Q_ASSERT(uri == QLatin1String("Unity.ApplicationMenu"));
32−
33− qmlRegisterUncreatableType<MenuServicePath>(uri, 0, 1, "MenuServicePath", "You cannot create a MenuServicePath");
34− qmlRegisterSingletonType<DBusApplicationMenuRegistry>(uri, 0, 1, "ApplicationMenuRegistry", menuRegistry);
35−}
36−
37−void ApplicationMenuPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
38−{
39− QQmlExtensionPlugin::initializeEngine(engine, uri);
40−
41− menuRegistry(nullptr, nullptr);
42−}
plugins/Unity/ApplicationMenu/qmldirdeleted−3
@@ -1,3 +0,0 @@
1−module Unity.ApplicationMenu
2−plugin ApplicationMenu-qml
3−typeinfo ApplicationMenu.qmltypes
plugins/Unity/CMakeLists.txt+1−1
@@ -1,7 +1,7 @@
1−add_subdirectory(ApplicationMenu)
21add_subdirectory(Connectivity)
32add_subdirectory(Indicators)
43add_subdirectory(Launcher)
54add_subdirectory(Session)
5+add_subdirectory(DashCommunicator)
66add_subdirectory(InputInfo)
77add_subdirectory(Platform)
plugins/Unity/Connectivity/CMakeLists.txt+1−1
@@ -5,6 +5,6 @@ set(CONNECTIVITY_SOURCES
55
66add_library(Connectivity MODULE ${CONNECTIVITY_SOURCES})
77
8−target_link_libraries(Connectivity Qt5::Qml Qt5::DBus Qt5::Core)
8+qt5_use_modules(Connectivity Qml DBus Core)
99
1010add_unity8_plugin(Unity.Connectivity 0.1 Unity/Connectivity TARGETS Connectivity)
plugins/Unity/Connectivity/Connectivity.qmltypesnew file+19
@@ -0,0 +1,19 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.Connectivity 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "Connectivity"
12+ prototype: "QObject"
13+ exports: ["Unity.Connectivity/Connectivity 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Method { name: "unlockAllModems" }
18+ }
19+}
plugins/Unity/DashCommunicator/CMakeLists.txtnew file+25
@@ -0,0 +1,25 @@
1+include_directories(
2+ ${CMAKE_CURRENT_SOURCE_DIR}
3+ ${libunity8-private_SOURCE_DIR}
4+)
5+
6+set(QMLDASHCOMMUNICATORPLUGIN_SRC
7+ plugin.cpp
8+ dbusdashcommunicatorservice.cpp
9+ dashcommunicatorservice.cpp
10+ dashcommunicator.cpp
11+ dashconnection.cpp
12+)
13+
14+add_library(DashCommunicator-qml MODULE
15+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
16+)
17+
18+qt5_use_modules(DashCommunicator-qml DBus Qml)
19+
20+target_link_libraries(DashCommunicator-qml
21+ unity8-private
22+)
23+
24+# export the qmldir and qmltypes files
25+add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
plugins/Unity/DashCommunicator/DashCommunicator.qmltypesnew file+47
@@ -0,0 +1,47 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.DashCommunicator 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "DashCommunicator"
12+ prototype: "QThread"
13+ exports: ["Unity.DashCommunicator/DashCommunicator 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Method {
16+ name: "setCurrentScope"
17+ Parameter { name: "index"; type: "int" }
18+ Parameter { name: "animate"; type: "bool" }
19+ Parameter { name: "isSwipe"; type: "bool" }
20+ }
21+ }
22+ Component {
23+ name: "DashCommunicatorService"
24+ prototype: "QObject"
25+ exports: ["Unity.DashCommunicator/DashCommunicatorService 0.1"]
26+ exportMetaObjectRevisions: [0]
27+ Signal {
28+ name: "setCurrentScopeRequested"
29+ Parameter { name: "index"; type: "int" }
30+ Parameter { name: "animate"; type: "bool" }
31+ Parameter { name: "isSwipe"; type: "bool" }
32+ }
33+ }
34+ Component {
35+ name: "QThread"
36+ prototype: "QObject"
37+ Signal { name: "started" }
38+ Signal { name: "finished" }
39+ Method {
40+ name: "start"
41+ Parameter { type: "Priority" }
42+ }
43+ Method { name: "start" }
44+ Method { name: "terminate" }
45+ Method { name: "quit" }
46+ }
47+}
plugins/Unity/DashCommunicator/dashcommunicator.cppnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "dashcommunicator.h"
18+#include "dashconnection.h"
19+
20+#include <QObject>
21+
22+DashCommunicator::DashCommunicator(QObject *parent):
23+ QThread(parent),
24+ m_dashConnection(nullptr),
25+ m_created(false)
26+{
27+ start();
28+}
29+
30+DashCommunicator::~DashCommunicator()
31+{
32+ quit();
33+ wait();
34+}
35+
36+void DashCommunicator::setCurrentScope(int index, bool animate, bool isSwipe)
37+{
38+ m_mutex.lock();
39+ if (m_created) {
40+ QMetaObject::invokeMethod(m_dashConnection, "setCurrentScope",
41+ Q_ARG(int, index),
42+ Q_ARG(bool, animate),
43+ Q_ARG(bool, isSwipe));
44+ }
45+ m_mutex.unlock();
46+}
47+
48+void DashCommunicator::run()
49+{
50+ m_dashConnection = new DashConnection(QStringLiteral("com.canonical.UnityDash"),
51+ QStringLiteral("/com/canonical/UnityDash"),
52+ QLatin1String(""), this);
53+ m_mutex.lock();
54+ m_created = true;
55+ m_mutex.unlock();
56+
57+ exec();
58+}
plugins/WindowManager/AvailableDesktopArea.h → plugins/Unity/DashCommunicator/dashcommunicator.hrenamed+21−14
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2017 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -14,25 +14,32 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef AVAILABLEDESKTOPAREA_H
18−#define AVAILABLEDESKTOPAREA_H
17+#ifndef DASHCOMMUNICATOR_H
18+#define DASHCOMMUNICATOR_H
1919
20−#include <QQuickItem>
20+// Qt
21+#include <QThread>
22+#include <QMutex>
2123
22−/**
23− @brief Used to inform qtmir/miral about the available desktop area of shell
24+class DashConnection;
2425
25− So that qtmir/miral can take correct window management decisions.
26− */
27−class AvailableDesktopArea : public QQuickItem
26+class DashCommunicator: public QThread
2827{
2928 Q_OBJECT
3029public:
31− AvailableDesktopArea(QQuickItem *parent = nullptr);
30+ explicit DashCommunicator(QObject *parent = 0);
31+ ~DashCommunicator();
32+
33+public Q_SLOTS:
34+ void setCurrentScope(int index, bool animate, bool isSwipe);
35+
3236protected:
33− void itemChange(ItemChange change, const ItemChangeData &value) override;
34−private Q_SLOTS:
35− void updatePlatformWindowProperty();
37+ void run() override;
38+
39+private:
40+ DashConnection *m_dashConnection;
41+ bool m_created;
42+ QMutex m_mutex;
3643};
3744
38−#endif // AVAILABLEDESKTOPAREA_H
45+#endif
tests/plugins/Cursor/TextEntry.qml → plugins/Unity/DashCommunicator/dashcommunicatorservice.cpprenamed+13−17
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software: you can redistribute it and/or modify it under
55 * the terms of the GNU Lesser General Public License version 3, as published by
@@ -14,21 +14,17 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−import QtQuick 2.4
17+#include "dashcommunicatorservice.h"
18+
19+DashCommunicatorService::DashCommunicatorService(QObject *parent):
20+ QObject(parent),
21+ m_dbusService(new DBusDashCommunicatorService(this))
22+{
23+ connect(m_dbusService, &DBusDashCommunicatorService::setCurrentScopeRequested, this, &DashCommunicatorService::setCurrentScopeRequested);
24+}
25+
26+
27+DashCommunicatorService::~DashCommunicatorService()
28+{
1829
19−Column {
20− property alias name: entryText.text
21− property alias value: textInput.text
22− Text { id: entryText }
23− Rectangle {
24− color: "white"
25− width: parent.width - 20
26− height: 40
27− TextInput {
28− id: textInput
29− anchors.fill: parent
30− verticalAlignment: TextInput.AlignVCenter
31− selectByMouse: true
32− }
33− }
3430}
plugins/Unity/DashCommunicator/dashcommunicatorservice.hnew file+38
@@ -0,0 +1,38 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef DASHCOMMUNICATORSERVICE_H
18+#define DASHCOMMUNICATORSERVICE_H
19+
20+#include "dbusdashcommunicatorservice.h"
21+
22+#include <QObject>
23+
24+class DashCommunicatorService: public QObject
25+{
26+ Q_OBJECT
27+public:
28+ DashCommunicatorService(QObject *parent = 0);
29+ ~DashCommunicatorService();
30+
31+Q_SIGNALS:
32+ void setCurrentScopeRequested(int index, bool animate, bool isSwipe);
33+
34+private:
35+ DBusDashCommunicatorService *m_dbusService;
36+};
37+
38+#endif // DBUSUNITYSESSIONSERVICE_H
plugins/Unity/DashCommunicator/dashconnection.cppnew file+63
@@ -0,0 +1,63 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "dashconnection.h"
18+
19+#include <QDBusInterface>
20+#include <QDBusPendingCall>
21+
22+/* The default implementation of AbstractDBusServiceMonitor creates a QDBusInterface when the service
23+ * appears on the bus.
24+ *
25+ * On construction QDBusInterface synchronously introspects the service, which will block the GUI
26+ * thread of this process if the service is busy. QDBusAbstractInterface does not perform this
27+ * introspection, so let's subclass that and avoid the blocking scenario.
28+ *
29+ * However we lose Qt's wrapping of the DBus service with a MetaObject, with the result that we
30+ * cannot easily connect to DBus signals with the usual connect() calls. So this approach only
31+ * suited to push communication with the DBus service.
32+ */
33+class AsyncDBusInterface : public QDBusAbstractInterface
34+{
35+public:
36+ AsyncDBusInterface(const QString &service, const QString &path,
37+ const QString &interface, const QDBusConnection &connection,
38+ QObject *parent = 0)
39+ : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent)
40+ {}
41+ ~AsyncDBusInterface() = default;
42+};
43+
44+
45+DashConnection::DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent):
46+ AbstractDBusServiceMonitor(service, path, interface, SessionBus, parent)
47+{
48+
49+}
50+
51+/* Override the default implementation to create a non-blocking DBus interface (see note above). */
52+QDBusAbstractInterface* DashConnection::createInterface(const QString &service, const QString &path,
53+ const QString &interface, const QDBusConnection &connection)
54+{
55+ return new AsyncDBusInterface(service, path, interface, connection);
56+}
57+
58+void DashConnection::setCurrentScope(int index, bool animate, bool isSwipe)
59+{
60+ if (dbusInterface()) {
61+ dbusInterface()->asyncCall(QStringLiteral("SetCurrentScope"), index, animate, isSwipe);
62+ }
63+}
plugins/Unity/DashCommunicator/dashconnection.hnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef THREADEDDASHCONNECTION_H
18+#define THREADEDDASHCONNECTION_H
19+
20+// local
21+#include "abstractdbusservicemonitor.h"
22+
23+class DashConnection: public AbstractDBusServiceMonitor
24+{
25+ Q_OBJECT
26+public:
27+ DashConnection(const QString &service, const QString &path, const QString &interface, QObject *parent = 0);
28+
29+public Q_SLOTS:
30+ void setCurrentScope(int index, bool animate, bool isSwipe);
31+
32+private:
33+ QDBusAbstractInterface* createInterface(const QString &service, const QString &path,
34+ const QString &interface, const QDBusConnection &connection) override;
35+};
36+
37+#endif
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cppnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "dbusdashcommunicatorservice.h"
18+
19+#include <QDBusConnection>
20+#include <QDBusInterface>
21+#include <QDebug>
22+
23+DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
24+ UnityDBusObject(QStringLiteral("/com/canonical/UnityDash"), QStringLiteral("com.canonical.UnityDash"), false, parent)
25+{
26+}
27+
28+DBusDashCommunicatorService::~DBusDashCommunicatorService()
29+{
30+}
31+
32+void DBusDashCommunicatorService::SetCurrentScope(int index, bool animate, bool isSwipe)
33+{
34+ Q_EMIT setCurrentScopeRequested(index, animate, isSwipe);
35+}
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it under
5+ * the terms of the GNU Lesser General Public License version 3, as published by
6+ * the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+ * Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef DBUSDASHCOMMUNICATORSERVICE_H
18+#define DBUSDASHCOMMUNICATORSERVICE_H
19+
20+#include "unitydbusobject.h"
21+
22+class DBusDashCommunicatorService: public UnityDBusObject
23+{
24+ Q_OBJECT
25+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26+
27+public:
28+ DBusDashCommunicatorService(QObject *parent = 0);
29+ ~DBusDashCommunicatorService();
30+
31+Q_SIGNALS:
32+ void setCurrentScopeRequested(int index, bool animate, bool isSwipe);
33+
34+public Q_SLOTS:
35+ Q_SCRIPTABLE void SetCurrentScope(int index, bool animate, bool isSwipe);
36+
37+};
38+
39+#endif // DBUSDASHCOMMUNICATORSERVICE_H
tests/mocks/LightDMController/plugin.cpp → plugins/Unity/DashCommunicator/plugin.cpprenamed+11−14
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2017 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,24 +12,21 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1517 */
1618
1719#include "plugin.h"
20+#include "dashcommunicator.h"
21+#include "dashcommunicatorservice.h"
1822
19−#include "MockController.h"
20−
23+#include <QDBusConnection>
2124#include <QtQml/qqml.h>
2225
23−static QObject *mock_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
24−{
25− Q_UNUSED(scriptEngine)
26− auto controller = QLightDM::MockController::instance();
27− engine->setObjectOwnership(controller, QQmlEngine::CppOwnership);
28− return controller;
29−}
30−
31−void LightDMControllerPlugin::registerTypes(const char *uri)
26+void DashCommunicatorPlugin::registerTypes(const char *uri)
3227{
33− Q_ASSERT(uri == QLatin1String("LightDMController"));
34− qmlRegisterSingletonType<QLightDM::MockController>(uri, 0, 1, "LightDMController", mock_provider);
28+ // @uri Unity.DashCommunicator
29+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
30+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
31+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
3532}
plugins/Unity/ApplicationMenu/plugin.h → plugins/Unity/DashCommunicator/plugin.hrenamed+9−7
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2016 Canonical, Ltd.
2+ * Copyright (C) 2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -12,21 +12,23 @@
1212 *
1313 * You should have received a copy of the GNU General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1517 */
1618
17−#ifndef APPLICATIONMENU_PLUGIN_H
18−#define APPLICATIONMENU_PLUGIN_H
19+#ifndef DASHCOMMUNICATOR_PLUGIN_H
20+#define DASHCOMMUNICATOR_PLUGIN_H
1921
20−#include <QQmlExtensionPlugin>
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
2124
22−class ApplicationMenuPlugin : public QQmlExtensionPlugin
25+class DashCommunicatorPlugin : public QQmlExtensionPlugin
2326{
2427 Q_OBJECT
2528 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2629
2730public:
2831 void registerTypes(const char *uri) override;
29− void initializeEngine(QQmlEngine *engine, const char *uri) override;
3032};
3133
32−#endif // APPLICATIONMENU_PLUGIN_H
34+#endif
plugins/Unity/DashCommunicator/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Unity.DashCommunicator
2+plugin DashCommunicator-qml
3+typeinfo DashCommunicator.qmltypes
plugins/Unity/Indicators/CMakeLists.txt+2−8
@@ -6,14 +6,7 @@ find_package(Qt5Quick REQUIRED)
66include_directories(
77 ${CMAKE_CURRENT_SOURCE_DIR}
88 ${CMAKE_CURRENT_BINARY_DIR}
9−)
10−
11−include_directories(
12− SYSTEM
139 ${GLIB_INCLUDE_DIRS}
14−)
15−include_directories(
16− SYSTEM
1710 ${GIO_INCLUDE_DIRS}
1811 ${QMENUMODEL_INCLUDE_DIRS}
1912)
@@ -44,7 +37,8 @@ target_link_libraries(IndicatorsQml
4437 ${GLIB_LIBRARIES}
4538 ${GIO_LIBRARIES}
4639 ${QMENUMODEL_LDFLAGS}
47− Qt5::Core Qt5::Qml Qt5::Quick Qt5::DBus
4840)
4941
42+qt5_use_modules(IndicatorsQml Core Qml Quick DBus)
43+
5044add_unity8_plugin(Unity.Indicators 0.1 Unity/Indicators TARGETS IndicatorsQml)
plugins/Unity/Indicators/Indicators.qmltypesnew file+264
@@ -0,0 +1,264 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.Indicators 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "ActionRootState"
12+ prototype: "RootStateObject"
13+ exports: ["Unity.Indicators/ActionRootState 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "actionGroup"; type: "QDBusActionGroup"; isPointer: true }
16+ Property { name: "actionName"; type: "string" }
17+ }
18+ Component {
19+ name: "ActionState"
20+ prototype: "QObject"
21+ exports: ["Unity.Indicators/ActionState 0.1"]
22+ isCreatable: false
23+ exportMetaObjectRevisions: [0]
24+ Enum {
25+ name: "ActionStates"
26+ values: {
27+ "Label": 0,
28+ "IconSource": 1,
29+ "AccessableName": 2,
30+ "Visible": 3
31+ }
32+ }
33+ }
34+ Component {
35+ name: "FlatMenuProxyModelRole"
36+ prototype: "QObject"
37+ exports: ["Unity.Indicators/FlatMenuProxyModelRole 0.1"]
38+ isCreatable: false
39+ exportMetaObjectRevisions: [0]
40+ Enum {
41+ name: "Roles"
42+ values: {
43+ "Action": 1,
44+ "Label": 2,
45+ "Extra": 3,
46+ "Depth": 4,
47+ "hasSection": 5,
48+ "hasSubMenu": 6
49+ }
50+ }
51+ }
52+ Component {
53+ name: "IndicatorsManager"
54+ prototype: "QObject"
55+ exports: ["Unity.Indicators/IndicatorsManager 0.1"]
56+ exportMetaObjectRevisions: [0]
57+ Property { name: "loaded"; type: "bool"; isReadonly: true }
58+ Property { name: "profile"; type: "string" }
59+ Signal {
60+ name: "loadedChanged"
61+ Parameter { type: "bool" }
62+ }
63+ Signal {
64+ name: "profileChanged"
65+ Parameter { type: "string" }
66+ }
67+ Signal {
68+ name: "indicatorLoaded"
69+ Parameter { name: "indicator_name"; type: "string" }
70+ }
71+ Signal {
72+ name: "indicatorAboutToBeUnloaded"
73+ Parameter { name: "indicator_name"; type: "string" }
74+ }
75+ Method { name: "load" }
76+ Method { name: "unload" }
77+ }
78+ Component {
79+ name: "IndicatorsModel"
80+ prototype: "QAbstractListModel"
81+ exports: ["Unity.Indicators/IndicatorsModel 0.1"]
82+ exportMetaObjectRevisions: [0]
83+ Property { name: "count"; type: "int"; isReadonly: true }
84+ Property { name: "profile"; type: "string" }
85+ Signal {
86+ name: "indicatorDataChanged"
87+ Parameter { name: "data"; type: "QVariant" }
88+ }
89+ Method { name: "load" }
90+ Method { name: "unload" }
91+ Method {
92+ name: "data"
93+ type: "QVariant"
94+ Parameter { name: "row"; type: "int" }
95+ Parameter { name: "role"; type: "int" }
96+ }
97+ }
98+ Component {
99+ name: "IndicatorsModelRole"
100+ prototype: "QObject"
101+ exports: ["Unity.Indicators/IndicatorsModelRole 0.1"]
102+ isCreatable: false
103+ exportMetaObjectRevisions: [0]
104+ Enum {
105+ name: "Roles"
106+ values: {
107+ "Identifier": 0,
108+ "Position": 1,
109+ "IndicatorProperties": 2
110+ }
111+ }
112+ }
113+ Component {
114+ name: "MenuContentActivator"
115+ prototype: "QObject"
116+ exports: ["Unity.Indicators/MenuContentActivator 0.1"]
117+ exportMetaObjectRevisions: [0]
118+ Property { name: "baseIndex"; type: "int" }
119+ Property { name: "running"; type: "bool" }
120+ Property { name: "count"; type: "int" }
121+ Property { name: "content"; type: "MenuContentState"; isList: true; isReadonly: true }
122+ Signal {
123+ name: "baseIndexChanged"
124+ Parameter { name: "baseIndex"; type: "int" }
125+ }
126+ Signal {
127+ name: "deltaChanged"
128+ Parameter { name: "delta"; type: "int" }
129+ }
130+ Signal {
131+ name: "runningChanged"
132+ Parameter { name: "running"; type: "bool" }
133+ }
134+ Signal {
135+ name: "countChanged"
136+ Parameter { name: "count"; type: "int" }
137+ }
138+ Method { name: "restart" }
139+ Method { name: "stop" }
140+ Method { name: "clear" }
141+ Method {
142+ name: "isMenuContentActive"
143+ type: "bool"
144+ Parameter { name: "index"; type: "int" }
145+ }
146+ }
147+ Component {
148+ name: "MenuContentState"
149+ prototype: "QObject"
150+ exports: ["Unity.Indicators/MenuContentState 0.1"]
151+ isCreatable: false
152+ exportMetaObjectRevisions: [0]
153+ Property { name: "active"; type: "bool"; isReadonly: true }
154+ }
155+ Component {
156+ name: "ModelActionRootState"
157+ prototype: "RootStateObject"
158+ exports: ["Unity.Indicators/ModelActionRootState 0.1"]
159+ exportMetaObjectRevisions: [0]
160+ Property { name: "menu"; type: "UnityMenuModel"; isPointer: true }
161+ Signal { name: "indexChanged" }
162+ }
163+ Component {
164+ name: "ModelPrinter"
165+ prototype: "QObject"
166+ exports: ["Unity.Indicators/ModelPrinter 0.1"]
167+ exportMetaObjectRevisions: [0]
168+ Property { name: "model"; type: "UnityMenuModel"; isPointer: true }
169+ Property { name: "text"; type: "string"; isReadonly: true }
170+ Method { name: "text"; type: "string" }
171+ }
172+ Component {
173+ name: "NetworkActionState"
174+ prototype: "QObject"
175+ exports: ["Unity.Indicators/NetworkActionState 0.1"]
176+ isCreatable: false
177+ exportMetaObjectRevisions: [0]
178+ Enum {
179+ name: "NetworkActionStates"
180+ values: {
181+ "Connection": 1,
182+ "SignalStrength": 2
183+ }
184+ }
185+ }
186+ Component {
187+ name: "NetworkConnection"
188+ prototype: "QObject"
189+ exports: ["Unity.Indicators/NetworkConnection 0.1"]
190+ isCreatable: false
191+ exportMetaObjectRevisions: [0]
192+ Enum {
193+ name: "NetworkConnectionStates"
194+ values: {
195+ "Initial": 0,
196+ "Activating": 1,
197+ "Activated": 2,
198+ "Deactivating": 3
199+ }
200+ }
201+ }
202+ Component {
203+ name: "RootStateObject"
204+ prototype: "QObject"
205+ Property { name: "valid"; type: "bool"; isReadonly: true }
206+ Property { name: "title"; type: "string"; isReadonly: true }
207+ Property { name: "leftLabel"; type: "string"; isReadonly: true }
208+ Property { name: "rightLabel"; type: "string"; isReadonly: true }
209+ Property { name: "icons"; type: "QStringList"; isReadonly: true }
210+ Property { name: "accessibleName"; type: "string"; isReadonly: true }
211+ Property { name: "indicatorVisible"; type: "bool"; isReadonly: true }
212+ Signal { name: "updated" }
213+ }
214+ Component {
215+ name: "SharedUnityMenuModel"
216+ prototype: "QObject"
217+ exports: ["Unity.Indicators/SharedUnityMenuModel 0.1"]
218+ exportMetaObjectRevisions: [0]
219+ Property { name: "busName"; type: "QByteArray" }
220+ Property { name: "menuObjectPath"; type: "QByteArray" }
221+ Property { name: "actions"; type: "QVariantMap" }
222+ Property { name: "model"; type: "UnityMenuModel"; isReadonly: true; isPointer: true }
223+ }
224+ Component {
225+ name: "UnityMenuModelCache"
226+ prototype: "QObject"
227+ exports: ["Unity.Indicators/UnityMenuModelCache 0.1"]
228+ isCreatable: false
229+ isSingleton: true
230+ exportMetaObjectRevisions: [0]
231+ Method {
232+ name: "contains"
233+ type: "bool"
234+ Parameter { name: "path"; type: "QByteArray" }
235+ }
236+ }
237+ Component {
238+ name: "UnityMenuModelStack"
239+ prototype: "QObject"
240+ exports: ["Unity.Indicators/UnityMenuModelStack 0.1"]
241+ exportMetaObjectRevisions: [0]
242+ Property { name: "head"; type: "UnityMenuModel"; isPointer: true }
243+ Property { name: "tail"; type: "UnityMenuModel"; isReadonly: true; isPointer: true }
244+ Property { name: "count"; type: "int"; isReadonly: true }
245+ Signal {
246+ name: "headChanged"
247+ Parameter { name: "head"; type: "UnityMenuModel"; isPointer: true }
248+ }
249+ Signal {
250+ name: "tailChanged"
251+ Parameter { name: "tail"; type: "UnityMenuModel"; isPointer: true }
252+ }
253+ Signal {
254+ name: "countChanged"
255+ Parameter { name: "count"; type: "int" }
256+ }
257+ Method {
258+ name: "push"
259+ Parameter { name: "model"; type: "UnityMenuModel"; isPointer: true }
260+ Parameter { name: "menuIndex"; type: "int" }
261+ }
262+ Method { name: "pop"; type: "UnityMenuModel*" }
263+ }
264+}
plugins/Unity/Indicators/actionrootstate.cpp+1−1
@@ -44,7 +44,7 @@ void ActionRootState::setActionGroup(QDBusActionGroup *actionGroup)
4444 connect(m_actionGroup, &QDBusActionGroup::statusChanged, this, [&](bool) { updateActionState(); });
4545 connect(m_actionGroup, &QDBusActionGroup::actionAppear, this, [&](const QString&) { updateActionState(); });
4646 connect(m_actionGroup, &QDBusActionGroup::actionVanish, this, [&](const QString&) { updateActionState(); });
47− connect(m_actionGroup, &QDBusActionGroup::actionStateChanged, this, [&](const QVariant&) { updateActionState(); });
47+ connect(m_actionGroup, &QDBusActionGroup::actionStateChanged, this, [&](QVariant) { updateActionState(); });
4848
4949 connect(m_actionGroup, &QObject::destroyed, this, [&](QObject*) { updateActionState(); });
5050 }
plugins/Unity/Indicators/indicators.h+5−5
@@ -27,13 +27,13 @@ class UNITYINDICATORS_EXPORT ActionState : public QObject
2727{
2828 Q_OBJECT
2929public:
30+ Q_ENUMS(ActionStates)
3031 enum ActionStates {
3132 Label = 0x00,
3233 IconSource = 0x01,
3334 AccessableName = 0x02,
3435 Visible = 0x03,
3536 };
36− Q_ENUM(ActionStates)
3737
3838 ActionState(QObject*parent=0):QObject(parent) {}
3939};
@@ -42,11 +42,11 @@ class UNITYINDICATORS_EXPORT NetworkActionState : public QObject
4242{
4343 Q_OBJECT
4444public:
45+ Q_ENUMS(NetworkActionStates)
4546 enum NetworkActionStates {
4647 Connection = 0x01,
4748 SignalStrength = 0x02,
4849 };
49− Q_ENUM(NetworkActionStates)
5050
5151 NetworkActionState(QObject*parent=0):QObject(parent) {}
5252};
@@ -55,13 +55,13 @@ class UNITYINDICATORS_EXPORT NetworkConnection : public QObject
5555{
5656 Q_OBJECT
5757public:
58+ Q_ENUMS(NetworkConnectionStates)
5859 enum NetworkConnectionStates {
5960 Initial = 0x00,
6061 Activating = 0x01,
6162 Activated = 0x02,
6263 Deactivating = 0x03,
6364 };
64− Q_ENUM(NetworkConnectionStates)
6565
6666 NetworkConnection(QObject*parent=0):QObject(parent) {}
6767};
@@ -70,12 +70,12 @@ class UNITYINDICATORS_EXPORT IndicatorsModelRole : public QObject
7070{
7171 Q_OBJECT
7272public:
73+ Q_ENUMS(Roles)
7374 enum Roles {
7475 Identifier = 0,
7576 Position,
7677 IndicatorProperties
7778 };
78− Q_ENUM(Roles)
7979
8080 IndicatorsModelRole(QObject*parent=0):QObject(parent) {}
8181};
@@ -84,6 +84,7 @@ class UNITYINDICATORS_EXPORT FlatMenuProxyModelRole : public QObject
8484{
8585 Q_OBJECT
8686public:
87+ Q_ENUMS(Roles)
8788 enum Roles {
8889 Action = Qt::DisplayRole + 1,
8990 Label,
@@ -92,7 +93,6 @@ public:
9293 hasSection,
9394 hasSubMenu
9495 };
95− Q_ENUM(Roles)
9696
9797 FlatMenuProxyModelRole(QObject*parent=0):QObject(parent) {}
9898};
plugins/Unity/Indicators/indicatorsmanager.cpp+8−3
@@ -114,6 +114,10 @@ void IndicatorsManager::loadFile(const QFileInfo& file_info)
114114 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
115115 const QString name = indicator_settings.value(QStringLiteral("Indicator Service/Name")).toString();
116116
117+ if (m_platform.isPC() && name == QLatin1String("indicator-keyboard")) {
118+ return; // convergence: skip this indicator until it works in Mir
119+ }
120+
117121 auto iter = m_indicatorsData.constFind(name);
118122 if (iter != m_indicatorsData.constEnd())
119123 {
@@ -281,12 +285,13 @@ Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
281285
282286 // convergence:
283287 // 1) enable session indicator
284− // 2) enable keyboard indicator
288+ // 2) on a PC, switch the battery/power indicator to desktop mode,
289+ // can't control brightness for now and phone-on-desktop broken (FIXME)
285290 //
286291 // The rest of the indicators respect their default profile (which is "phone", even on desktop PCs)
287292 if ((new_indicator->identifier() == QStringLiteral("indicator-session"))
288− || new_indicator->identifier() == QStringLiteral("indicator-keyboard")) {
289− new_indicator->setProfile(QString(m_profile).replace(QStringLiteral("phone"), QStringLiteral("desktop")));
293+ || (new_indicator->identifier() == QStringLiteral("indicator-power") && m_platform.isPC())) {
294+ new_indicator->setProfile(QStringLiteral("desktop"));
290295 } else {
291296 new_indicator->setProfile(m_profile);
292297 }
plugins/Unity/Indicators/indicatorsmanager.h+2
@@ -76,6 +76,8 @@ private:
7676 QSharedPointer<QFileSystemWatcher> m_fsWatcher;
7777 bool m_loaded;
7878 QString m_profile;
79+
80+ Platform m_platform;
7981};
8082
8183#endif // INDICATORS_MANAGER_H
plugins/Unity/Indicators/indicatorsmodel.cpp−13
@@ -103,19 +103,6 @@ void IndicatorsModel::setProfile(const QString &profile)
103103 m_manager->setProfile(profile);
104104}
105105
106−bool IndicatorsModel::light() const
107−{
108− return m_light;
109−}
110−
111−void IndicatorsModel::setLight(const bool &light)
112−{
113− if (m_light != light) {
114− m_light = light;
115− Q_EMIT lightChanged();
116− }
117−}
118−
119106/*!
120107 \qmlmethod IndicatorsModel::unload()
121108
plugins/Unity/Indicators/indicatorsmodel.h+1−9
@@ -32,12 +32,10 @@ class IndicatorsManager;
3232class UNITYINDICATORS_EXPORT IndicatorsModel : public QAbstractListModel
3333{
3434 Q_OBJECT
35+ Q_ENUMS(Roles)
3536 Q_PROPERTY(int count READ count NOTIFY countChanged)
3637 Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
3738
38− // Used for tests
39− Q_PROPERTY(bool light READ light WRITE setLight NOTIFY lightChanged)
40−
4139public:
4240
4341 IndicatorsModel(QObject *parent=nullptr);
@@ -51,9 +49,6 @@ public:
5149 QString profile() const;
5250 void setProfile(const QString& profile);
5351
54− bool light() const;
55− void setLight(const bool &light);
56−
5752 /* QAbstractItemModel */
5853 QHash<int, QByteArray> roleNames() const override;
5954 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -66,7 +61,6 @@ Q_SIGNALS:
6661 void countChanged();
6762 void profileChanged();
6863 void indicatorDataChanged(const QVariant& data);
69− void lightChanged();
7064
7165private Q_SLOTS:
7266 void onIdentifierChanged();
@@ -81,8 +75,6 @@ private:
8175
8276 void notifyDataChanged(QObject *sender, int role);
8377 int count() const;
84−
85− bool m_light;
8678};
8779
8880#endif // INDICATORSMODEL_H
plugins/Unity/Indicators/modelprinter.cpp+4−19
@@ -105,25 +105,12 @@ QString ModelPrinter::getRowSring(UnityMenuModel* sourceModel, int row, int dept
105105
106106 Q_FOREACH(int role, roles) {
107107 const QByteArray& roleName = roleNames[role];
108− stream << getVariantString(roleName, sourceModel->get(row, roleName), depth);
108+ stream << tabify(depth) << getVariantString(roleName, sourceModel->get(row, roleName));
109109 }
110110 return str;
111111}
112112
113−QString ModelPrinter::getVariantString(const QVariant& vData) const
114−{
115− if (vData.type() == QVariant::List) {
116− QStringList strList;
117− for (const auto& v : vData.toList())
118− strList.append(getVariantString(v));
119−
120− return '[' + strList.join(", ") + ']';
121− }
122−
123− return vData.toString();
124−}
125−
126−QString ModelPrinter::getVariantString(const QString& roleName, const QVariant &vData, int depth) const
113+QString ModelPrinter::getVariantString(const QString& roleName, const QVariant &vData) const
127114{
128115 QString str;
129116 QTextStream stream(&str);
@@ -132,20 +119,18 @@ QString ModelPrinter::getVariantString(const QString& roleName, const QVariant &
132119 QMapIterator<QString, QVariant> iter(vData.toMap());
133120 while (iter.hasNext()) {
134121 iter.next();
135− stream << tabify(depth);
136122 stream << roleName
137123 << "."
138124 << iter.key()
139125 << ": "
140− << getVariantString(iter.value())
126+ << iter.value().toString()
141127 << endl;
142128 }
143129 }
144130 else {
145− stream << tabify(depth);
146131 stream << roleName
147132 << ": "
148− << getVariantString(vData)
133+ << vData.toString()
149134 << endl;
150135 }
151136 return str;
plugins/Unity/Indicators/modelprinter.h+1−2
@@ -46,8 +46,7 @@ Q_SIGNALS:
4646private:
4747 QString getModelDataString(UnityMenuModel* sourceModel, int level);
4848 QString getRowSring(UnityMenuModel* sourceModel, int index, int depth) const;
49− QString getVariantString(const QString& roleName, const QVariant &vData, int depth) const;
50− QString getVariantString(const QVariant&) const;
49+ QString getVariantString(const QString& roleName, const QVariant &vData) const;
5150
5251 UnityMenuModel* m_model;
5352 QList<UnityMenuModel*> m_children;
plugins/Unity/Indicators/sharedunitymenumodel.cpp−4
@@ -81,16 +81,12 @@ void SharedUnityMenuModel::initialize()
8181 }
8282 } else {
8383 QSharedPointer<UnityMenuModel> model = UnityMenuModelCache::singleton()->model(m_menuObjectPath);
84−
8584 if (model != m_model) {
8685 if (model->busName() != m_busName) model->setBusName(m_busName);
8786 if (model->actions() != m_actions) model->setActions(m_actions);
8887
8988 m_model = model;
9089 Q_EMIT modelChanged();
91− } else if (m_model) {
92− if (m_model->busName() != m_busName) m_model->setBusName(m_busName);
93− if (m_model->actions() != m_actions) m_model->setActions(m_actions);
9490 }
9591 }
9692}
plugins/Unity/InputInfo/CMakeLists.txt+2−1
@@ -32,7 +32,8 @@ add_library(InputInfo SHARED
3232target_link_libraries(InputInfo
3333 ${LIBUDEV_LDFLAGS}
3434 ${LIBEVDEV_LDFLAGS}
35− Qt5::Core Qt5::Qml Qt5::Quick
3635)
3736
37+qt5_use_modules(InputInfo Core Qml Quick)
38+
3839add_unity8_plugin(Unity.InputInfo 0.1 Unity/InputInfo TARGETS InputInfo)
plugins/Unity/InputInfo/InputInfo.qmltypesnew file+71
@@ -0,0 +1,71 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.InputInfo 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "QDeclarativeInputDeviceModel"
12+ prototype: "QAbstractListModel"
13+ exports: ["Unity.InputInfo/InputDeviceModel 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "deviceFilter"; type: "QInputDevice::InputType" }
16+ Property { name: "count"; type: "int"; isReadonly: true }
17+ Signal {
18+ name: "deviceAdded"
19+ Parameter { name: "devicePath"; type: "string" }
20+ }
21+ Signal {
22+ name: "deviceRemoved"
23+ Parameter { name: "devicePath"; type: "string" }
24+ }
25+ Signal {
26+ name: "deviceFilterChanged"
27+ Parameter { name: "filter"; type: "QInputDevice::InputType" }
28+ }
29+ Method { name: "updateDeviceList" }
30+ Method {
31+ name: "indexOf"
32+ type: "int"
33+ Parameter { name: "devicePath"; type: "string" }
34+ }
35+ Method {
36+ name: "get"
37+ type: "QInputDevice*"
38+ Parameter { name: "index"; type: "int" }
39+ }
40+ }
41+ Component {
42+ name: "QInputDevice"
43+ prototype: "QObject"
44+ exports: ["Unity.InputInfo/InputInfo 0.1"]
45+ exportMetaObjectRevisions: [0]
46+ Enum {
47+ name: "InputType"
48+ values: {
49+ "Unknown": 0,
50+ "Button": 1,
51+ "Mouse": 2,
52+ "TouchPad": 4,
53+ "TouchScreen": 8,
54+ "Keyboard": 16,
55+ "Switch": 32
56+ }
57+ }
58+ Enum {
59+ name: "InputTypeFlags"
60+ values: {
61+ "Unknown": 0,
62+ "Button": 1,
63+ "Mouse": 2,
64+ "TouchPad": 4,
65+ "TouchScreen": 8,
66+ "Keyboard": 16,
67+ "Switch": 32
68+ }
69+ }
70+ }
71+}
plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux.cpp+2−7
@@ -44,7 +44,6 @@
4444#include <libudev.h>
4545#include <libevdev/libevdev.h>
4646#include <fcntl.h>
47−#include <unistd.h>
4847#include <QDebug>
4948#include <QSocketNotifier>
5049#include <QTimer>
@@ -53,7 +52,6 @@
5352QInputDeviceManagerPrivate::QInputDeviceManagerPrivate(QObject *parent) :
5453 QObject(parent),
5554 currentFilter(QInputDevice::Unknown),
56− udevMonitor(0),
5755 udevice(0)
5856{
5957 QTimer::singleShot(250,this,SLOT(init()));
@@ -85,9 +83,9 @@ void QInputDeviceManagerPrivate::init()
8583 udev_enumerate_add_match_subsystem(enumerate, subsystem.toLatin1());
8684
8785 udev_monitor_enable_receiving(udevMonitor);
88− int notifierFd = udev_monitor_get_fd(udevMonitor);
86+ notifierFd = udev_monitor_get_fd(udevMonitor);
8987
90− QSocketNotifier *notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read, this);
88+ notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read, this);
9189 connect(notifier, SIGNAL(activated(int)), this, SLOT(onUDevChanges()));
9290
9391 udev_enumerate_scan_devices(enumerate);
@@ -170,7 +168,6 @@ QInputDevice *QInputDeviceManagerPrivate::addDevice(struct udev_device *udev)
170168 rc = libevdev_new_from_fd(fd, &dev);
171169 if (rc < 0) {
172170 qWarning() << "Failed to init libevdev ("<< strerror(-rc) << ")";
173− close(fd);
174171 return Q_NULLPTR;
175172 }
176173
@@ -198,8 +195,6 @@ QInputDevice *QInputDeviceManagerPrivate::addDevice(struct udev_device *udev)
198195 }
199196 }
200197
201− libevdev_free(dev);
202− close(fd);
203198 return inputDevice;
204199}
205200
plugins/Unity/InputInfo/linux/qinputdeviceinfo_linux_p.h+2
@@ -83,6 +83,8 @@ private:
8383
8484 QInputDevice *addDevice(const QString &path);
8585 void removeDevice(const QString &path);
86+ QSocketNotifier *notifier;
87+ int notifierFd;
8688 struct udev_monitor *udevMonitor;
8789 QInputDevice::InputTypeFlags getInputTypeFlags(struct udev_device *);
8890 struct udev *udevice;
plugins/Unity/InputInfo/qinputinfo.h+3−2
@@ -57,6 +57,8 @@ class QInputDeviceManager;
5757class QInputDevice : public QObject
5858{
5959 Q_OBJECT
60+ Q_ENUMS(InputType)
61+ Q_FLAGS(InputType InputTypeFlags)
6062 friend class QInputDeviceManagerPrivate;
6163
6264public:
@@ -70,9 +72,8 @@ public:
7072 Keyboard = 16,
7173 Switch = 32
7274 };
73− Q_FLAG(InputType)
75+ Q_ENUMS(InputType)
7476 Q_DECLARE_FLAGS(InputTypeFlags, InputType)
75− Q_FLAG(InputTypeFlags)
7677
7778 explicit QInputDevice(QObject *parent = 0);
7879 QString name() const;
plugins/Unity/Launcher/CMakeLists.txt+6−17
@@ -1,3 +1,4 @@
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
12pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
23
34add_definitions(-DSM_BUSNAME=systemBus)
@@ -5,15 +6,10 @@ add_definitions(-DSM_BUSNAME=systemBus)
56include_directories(
67 ${CMAKE_CURRENT_SOURCE_DIR}
78 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
8− ${libunity8-private_SOURCE_DIR}
9−)
10−
11−include_directories(
12− SYSTEM
139 ${GSETTINGS_QT_INCLUDE_DIRS}
1410 ${GLIB_INCLUDE_DIRS}
15− ${UAL_INCLUDE_DIRS}
16− )
11+ ${libunity8-private_SOURCE_DIR}
12+)
1713
1814set(QMLLAUNCHERPLUGIN_SRC
1915 plugin.cpp
@@ -23,20 +19,13 @@ set(QMLLAUNCHERPLUGIN_SRC
2319 quicklistentry.cpp
2420 dbusinterface.cpp
2521 gsettings.cpp
22+ desktopfilehandler.cpp
2623 asadapter.cpp
27− appdrawermodel.cpp
28− ualwrapper.cpp
29− xdgwatcher.cpp
3024 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
3125 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
32− ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
33− ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
34− ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
35− ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
3626 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
3727 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
3828 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
39− ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/AppDrawerModelInterface.h
4029 )
4130
4231add_library(UnityLauncher-qml MODULE
@@ -47,8 +36,8 @@ target_link_libraries(UnityLauncher-qml
4736 unity8-private
4837 ${GSETTINGS_QT_LDFLAGS}
4938 ${GLIB_LIBRARIES}
50− ${UAL_LIBRARIES}
51− Qt5::DBus Qt5::Qml Qt5::Gui Qt5::Concurrent
5239 )
5340
41+qt5_use_modules(UnityLauncher-qml DBus Qml Gui)
42+
5443add_unity8_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
plugins/Unity/Launcher/Launcher.qmltypesnew file+182
@@ -0,0 +1,182 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.Launcher 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "LauncherItem"
12+ prototype: "unity::shell::launcher::LauncherItemInterface"
13+ exports: ["Unity.Launcher/LauncherItem 0.1"]
14+ isCreatable: false
15+ exportMetaObjectRevisions: [0]
16+ }
17+ Component {
18+ name: "LauncherModel"
19+ prototype: "unity::shell::launcher::LauncherModelInterface"
20+ exports: ["Unity.Launcher/LauncherModel 0.1"]
21+ isCreatable: false
22+ isSingleton: true
23+ exportMetaObjectRevisions: [0]
24+ Method {
25+ name: "requestRemove"
26+ Parameter { name: "appId"; type: "string" }
27+ }
28+ Method { name: "refresh" }
29+ Method {
30+ name: "get"
31+ type: "unity::shell::launcher::LauncherItemInterface*"
32+ Parameter { name: "index"; type: "int" }
33+ }
34+ Method {
35+ name: "move"
36+ Parameter { name: "oldIndex"; type: "int" }
37+ Parameter { name: "newIndex"; type: "int" }
38+ }
39+ Method {
40+ name: "pin"
41+ Parameter { name: "appId"; type: "string" }
42+ Parameter { name: "index"; type: "int" }
43+ }
44+ Method {
45+ name: "pin"
46+ Parameter { name: "appId"; type: "string" }
47+ }
48+ Method {
49+ name: "quickListActionInvoked"
50+ Parameter { name: "appId"; type: "string" }
51+ Parameter { name: "actionIndex"; type: "int" }
52+ }
53+ Method {
54+ name: "setUser"
55+ Parameter { name: "username"; type: "string" }
56+ }
57+ Method {
58+ name: "getUrlForAppId"
59+ type: "string"
60+ Parameter { name: "appId"; type: "string" }
61+ }
62+ }
63+ Component {
64+ name: "QuickListModel"
65+ prototype: "unity::shell::launcher::QuickListModelInterface"
66+ exports: ["Unity.Launcher/QuickListModel 0.1"]
67+ isCreatable: false
68+ exportMetaObjectRevisions: [0]
69+ }
70+ Component {
71+ name: "unity::shell::launcher::LauncherItemInterface"
72+ prototype: "QObject"
73+ exports: ["Unity.Launcher/LauncherItemInterface 0.1"]
74+ isCreatable: false
75+ exportMetaObjectRevisions: [0]
76+ Property { name: "appId"; type: "string"; isReadonly: true }
77+ Property { name: "name"; type: "string"; isReadonly: true }
78+ Property { name: "icon"; type: "string"; isReadonly: true }
79+ Property { name: "pinned"; type: "bool"; isReadonly: true }
80+ Property { name: "running"; type: "bool"; isReadonly: true }
81+ Property { name: "recent"; type: "bool"; isReadonly: true }
82+ Property { name: "progress"; type: "int"; isReadonly: true }
83+ Property { name: "count"; type: "int"; isReadonly: true }
84+ Property { name: "countVisible"; type: "bool"; isReadonly: true }
85+ Property { name: "focused"; type: "bool"; isReadonly: true }
86+ Property {
87+ name: "quickList"
88+ type: "unity::shell::launcher::QuickListModelInterface"
89+ isReadonly: true
90+ isPointer: true
91+ }
92+ Signal {
93+ name: "nameChanged"
94+ Parameter { name: "name"; type: "string" }
95+ }
96+ Signal {
97+ name: "iconChanged"
98+ Parameter { name: "icon"; type: "string" }
99+ }
100+ Signal {
101+ name: "pinnedChanged"
102+ Parameter { name: "pinned"; type: "bool" }
103+ }
104+ Signal {
105+ name: "runningChanged"
106+ Parameter { name: "running"; type: "bool" }
107+ }
108+ Signal {
109+ name: "recentChanged"
110+ Parameter { name: "running"; type: "bool" }
111+ }
112+ Signal {
113+ name: "progressChanged"
114+ Parameter { name: "progress"; type: "int" }
115+ }
116+ Signal {
117+ name: "countChanged"
118+ Parameter { name: "count"; type: "int" }
119+ }
120+ Signal {
121+ name: "countVisibleChanged"
122+ Parameter { name: "countVisible"; type: "bool" }
123+ }
124+ Signal {
125+ name: "focusedChanged"
126+ Parameter { name: "focused"; type: "bool" }
127+ }
128+ }
129+ Component {
130+ name: "unity::shell::launcher::LauncherModelInterface"
131+ prototype: "QAbstractListModel"
132+ exports: ["Unity.Launcher/LauncherModelInterface 0.1"]
133+ isCreatable: false
134+ exportMetaObjectRevisions: [0]
135+ Property {
136+ name: "applicationManager"
137+ type: "unity::shell::application::ApplicationManagerInterface"
138+ isPointer: true
139+ }
140+ Property { name: "onlyPinned"; type: "bool" }
141+ Signal { name: "hint" }
142+ Method {
143+ name: "move"
144+ Parameter { name: "oldIndex"; type: "int" }
145+ Parameter { name: "newIndex"; type: "int" }
146+ }
147+ Method {
148+ name: "get"
149+ type: "unity::shell::launcher::LauncherItemInterface*"
150+ Parameter { name: "index"; type: "int" }
151+ }
152+ Method {
153+ name: "pin"
154+ Parameter { name: "appId"; type: "string" }
155+ Parameter { name: "index"; type: "int" }
156+ }
157+ Method {
158+ name: "pin"
159+ Parameter { name: "appId"; type: "string" }
160+ }
161+ Method {
162+ name: "requestRemove"
163+ Parameter { name: "appId"; type: "string" }
164+ }
165+ Method {
166+ name: "quickListActionInvoked"
167+ Parameter { name: "appId"; type: "string" }
168+ Parameter { name: "actionIndex"; type: "int" }
169+ }
170+ Method {
171+ name: "setUser"
172+ Parameter { name: "username"; type: "string" }
173+ }
174+ }
175+ Component {
176+ name: "unity::shell::launcher::QuickListModelInterface"
177+ prototype: "QAbstractListModel"
178+ exports: ["Unity.Launcher/QuickListInterface 0.1"]
179+ isCreatable: false
180+ exportMetaObjectRevisions: [0]
181+ }
182+}
plugins/Unity/Launcher/appdrawermodel.cppdeleted−192
@@ -1,192 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− * Copyright (C) 2020 UBports Foundation.
4− *
5− * This program is free software; you can redistribute it and/or modify
6− * it under the terms of the GNU General Public License as published by
7− * the Free Software Foundation; version 3.
8− *
9− * This program is distributed in the hope that it will be useful,
10− * but WITHOUT ANY WARRANTY; without even the implied warranty of
11− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12− * GNU General Public License for more details.
13− *
14− * You should have received a copy of the GNU General Public License
15− * along with this program. If not, see <http://www.gnu.org/licenses/>.
16− */
17−
18−#include "appdrawermodel.h"
19−#include "ualwrapper.h"
20−#include "xdgwatcher.h"
21−
22−#include <QDebug>
23−#include <QDateTime>
24−#include <QtConcurrentRun>
25−
26−static std::shared_ptr<LauncherItem> makeSharedLauncherItem(
27− const QString &appId, const QString &name, const QString &icon, QObject * parent)
28−{
29− return std::shared_ptr<LauncherItem>(
30− new LauncherItem(appId, name, icon, parent),
31− [] (LauncherItem *item) { item->deleteLater(); });
32−}
33−
34−AppDrawerModel::AppDrawerModel(QObject *parent):
35− AppDrawerModelInterface(parent),
36− m_ual(new UalWrapper(this)),
37− m_xdgWatcher(new XdgWatcher(this)),
38− m_refreshing(false)
39−{
40− connect(&m_refreshFutureWatcher, &QFutureWatcher<ItemList>::finished,
41− this, &AppDrawerModel::onRefreshFinished);
42−
43− // keep this a queued connection as it's coming from another thread.
44− connect(m_xdgWatcher, &XdgWatcher::appAdded, this, &AppDrawerModel::appAdded, Qt::QueuedConnection);
45− connect(m_xdgWatcher, &XdgWatcher::appRemoved, this, &AppDrawerModel::appRemoved, Qt::QueuedConnection);
46− connect(m_xdgWatcher, &XdgWatcher::appInfoChanged, this, &AppDrawerModel::appInfoChanged, Qt::QueuedConnection);
47−
48− refresh();
49−}
50−
51−int AppDrawerModel::rowCount(const QModelIndex &parent) const
52−{
53− Q_UNUSED(parent)
54− return m_list.count();
55−}
56−
57−QVariant AppDrawerModel::data(const QModelIndex &index, int role) const
58−{
59− switch (role) {
60− case RoleAppId:
61− return m_list.at(index.row())->appId();
62− case RoleName:
63− return m_list.at(index.row())->name();
64− case RoleIcon:
65− return m_list.at(index.row())->icon();
66− case RoleKeywords:
67− return m_list.at(index.row())->keywords();
68− case RoleUsage:
69− return m_list.at(index.row())->popularity();
70− }
71−
72− return QVariant();
73−}
74−
75−void AppDrawerModel::appAdded(const QString &appId)
76−{
77− if (m_refreshing)
78− // Will be replaced by the refresh result anyway.
79− return;
80−
81− UalWrapper::AppInfo info = UalWrapper::getApplicationInfo(appId);
82− if (!info.valid) {
83− qWarning() << "App added signal received but failed to get app info for app" << appId;
84− return;
85− }
86−
87− beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
88− auto item = makeSharedLauncherItem(appId, info.name, info.icon, /* parent */ nullptr);
89− item->setKeywords(info.keywords);
90− item->setPopularity(info.popularity);
91− m_list.append(std::move(item));
92− endInsertRows();
93−}
94−
95−void AppDrawerModel::appRemoved(const QString &appId)
96−{
97− if (m_refreshing)
98− // Will be replaced by the refresh result anyway.
99− return;
100−
101− int idx = -1;
102− for (int i = 0; i < m_list.count(); i++) {
103− if (m_list.at(i)->appId() == appId) {
104− idx = i;
105− break;
106− }
107− }
108− if (idx < 0) {
109− qWarning() << "App removed signal received but app doesn't seem to be in the drawer model";
110− return;
111− }
112− beginRemoveRows(QModelIndex(), idx, idx);
113− m_list.removeAt(idx);
114− endRemoveRows();
115−}
116−
117−void AppDrawerModel::appInfoChanged(const QString &appId)
118−{
119− if (m_refreshing)
120− // Will be replaced by the refresh result anyway.
121− return;
122−
123− std::shared_ptr<LauncherItem> item;
124− int idx = -1;
125−
126− for(int i = 0; i < m_list.count(); i++) {
127− if (m_list.at(i)->appId() == appId) {
128− item = m_list.at(i);
129− idx = i;
130− break;
131− }
132− }
133−
134− if (!item) {
135− return;
136− }
137−
138− UalWrapper::AppInfo info = m_ual->getApplicationInfo(appId);
139− item->setPopularity(info.popularity);
140− Q_EMIT dataChanged(index(idx), index(idx), {AppDrawerModelInterface::RoleUsage});
141−}
142−
143−bool AppDrawerModel::refreshing() {
144− return m_refreshing;
145−}
146−
147−void AppDrawerModel::refresh() {
148− if (m_refreshing)
149− return;
150−
151− m_refreshFutureWatcher.setFuture(QtConcurrent::run([](QThread *thread) {
152− ItemList list;
153−
154− Q_FOREACH (const QString &appId, UalWrapper::installedApps()) {
155− UalWrapper::AppInfo info = UalWrapper::getApplicationInfo(appId);
156− if (!info.valid) {
157− qWarning() << "Failed to get app info for app" << appId;
158− continue;
159− }
160− // We don't pass parent in because this may run after the model is destroyed.
161− // (And, in fact, we can't, because the model is in a diferent thread.)
162− auto item = makeSharedLauncherItem(appId, info.name, info.icon, /* parent */ nullptr);
163− item->setKeywords(info.keywords);
164− item->setPopularity(info.popularity);
165− item->moveToThread(thread);
166− list.append(std::move(item));
167− }
168−
169− return list;
170− }, this->thread()));
171−
172− m_refreshing = true;
173− Q_EMIT refreshingChanged();
174−}
175−
176−void AppDrawerModel::onRefreshFinished() {
177− if (m_refreshFutureWatcher.isCanceled())
178− // This is the result of setting canceled future below.
179− return;
180−
181− beginResetModel();
182−
183− m_list = m_refreshFutureWatcher.result();
184− // Remove the future & its result, so that future modifications won't
185− // create a copy.
186− m_refreshFutureWatcher.setFuture(QFuture<ItemList>());
187−
188− endResetModel();
189−
190− m_refreshing = false;
191− Q_EMIT refreshingChanged();
192−}
plugins/Unity/Launcher/appdrawermodel.hdeleted−64
@@ -1,64 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− * Copyright (C) 2020 UBports Foundation.
4− *
5− * This program is free software; you can redistribute it and/or modify
6− * it under the terms of the GNU General Public License as published by
7− * the Free Software Foundation; version 3.
8− *
9− * This program is distributed in the hope that it will be useful,
10− * but WITHOUT ANY WARRANTY; without even the implied warranty of
11− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12− * GNU General Public License for more details.
13− *
14− * You should have received a copy of the GNU General Public License
15− * along with this program. If not, see <http://www.gnu.org/licenses/>.
16− */
17−
18−#include <memory>
19−#include <QFutureWatcher>
20−#include <unity/shell/launcher/AppDrawerModelInterface.h>
21−
22−#include "launcheritem.h"
23−
24−class UalWrapper;
25−class XdgWatcher;
26−
27−class AppDrawerModel: public AppDrawerModelInterface
28−{
29− Q_OBJECT
30− // TODO: Add this to AppDrawerModelInterface in unity-api.
31− // Or, better yet, remove AppDrawerModelInterface from unity-api.
32− Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
33−public:
34− AppDrawerModel(QObject* parent = nullptr);
35−
36− int rowCount(const QModelIndex &parent) const override;
37− QVariant data(const QModelIndex &index, int role) const override;
38−
39− // TODO: add these to AppDrawerModelInterface too.
40− bool refreshing();
41− Q_INVOKABLE void refresh();
42−
43−Q_SIGNALS:
44− void refreshingChanged();
45−
46−private Q_SLOTS:
47− void appAdded(const QString &appId);
48− void appRemoved(const QString &appId);
49− void appInfoChanged(const QString &appId);
50−
51− void onRefreshFinished();
52−
53−private:
54− // Using shared_ptr is unavoidable in order to share the refresh result
55− // from the worker thread safely without a memory leak, in case the model
56− // is destructed before the worker finishes.
57− typedef QList<std::shared_ptr<LauncherItem>> ItemList;
58−
59− ItemList m_list;
60− UalWrapper *m_ual;
61− XdgWatcher *m_xdgWatcher;
62− QFutureWatcher<ItemList> m_refreshFutureWatcher;
63− bool m_refreshing;
64−};
plugins/Unity/Launcher/desktopfilehandler.cppnew file+155
@@ -0,0 +1,155 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#include "desktopfilehandler.h"
21+
22+#include <QStringList>
23+#include <QStandardPaths>
24+#include <QDir>
25+#include <QSettings>
26+#include <QLocale>
27+
28+#include <libintl.h>
29+
30+DesktopFileHandler::DesktopFileHandler(const QString &appId, QObject *parent):
31+ QObject(parent),
32+ m_appId(appId)
33+{
34+ load();
35+}
36+
37+QString DesktopFileHandler::appId() const
38+{
39+ return m_appId;
40+}
41+
42+void DesktopFileHandler::setAppId(const QString &appId)
43+{
44+ if (m_appId != appId) {
45+ m_appId = appId;
46+ load();
47+ }
48+}
49+
50+QString DesktopFileHandler::filename() const
51+{
52+ return m_filename;
53+}
54+
55+bool DesktopFileHandler::isValid() const
56+{
57+ return !m_filename.isEmpty();
58+}
59+
60+void DesktopFileHandler::load()
61+{
62+ m_filename.clear();
63+
64+ if (m_appId.isEmpty()) {
65+ return;
66+ }
67+
68+ int dashPos = -1;
69+ QString helper = m_appId;
70+
71+ QStringList searchDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
72+#ifdef LAUNCHER_TESTING
73+ searchDirs << QStringLiteral(".");
74+#endif
75+
76+ QString path;
77+ do {
78+ if (dashPos != -1) {
79+ helper.replace(dashPos, 1, '/');
80+ }
81+
82+ if (helper.contains('/')) {
83+ path += helper.split('/').at(0) + '/';
84+ helper.remove(QRegExp("^" + path));
85+ }
86+
87+ Q_FOREACH(const QString &searchDirName, searchDirs) {
88+ QDir searchDir(searchDirName + "/" + path);
89+ const QString desktop = QStringLiteral("*.desktop");
90+ Q_FOREACH(const QString &desktopFile, searchDir.entryList(QStringList() << desktop)) {
91+ if (desktopFile.startsWith(helper)) {
92+ QFileInfo fileInfo(searchDir, desktopFile);
93+ m_filename = fileInfo.absoluteFilePath();
94+ return;
95+ }
96+ }
97+ }
98+
99+ dashPos = helper.indexOf('-');
100+ } while (dashPos != -1);
101+}
102+
103+QString DesktopFileHandler::displayName() const
104+{
105+ if (!isValid()) {
106+ return QString();
107+ }
108+
109+ QSettings settings(m_filename, QSettings::IniFormat);
110+ settings.setIniCodec("UTF-8");
111+ settings.beginGroup(QStringLiteral("Desktop Entry"));
112+
113+ // First try to find Name[xx_YY] and Name[xx] in .desktop file
114+ const QString locale = QLocale().name();
115+ const QStringList splitLocale = locale.split(QLatin1Char('_'));
116+ const QString shortLocale = splitLocale.first();
117+
118+ if (locale != shortLocale && settings.contains(QStringLiteral("Name[%1]").arg(locale))) {
119+ return settings.value(QStringLiteral("Name[%1]").arg(locale)).toString();
120+ }
121+
122+ if (settings.contains(QStringLiteral("Name[%1]").arg(shortLocale))) {
123+ return settings.value(QStringLiteral("Name[%1]").arg(shortLocale)).toString();
124+ }
125+
126+ // No translation found in desktop file. Get the untranslated one and have a go with gettext.
127+ QString displayName = settings.value(QStringLiteral("Name")).toString();
128+
129+ if (settings.contains(QStringLiteral("X-Ubuntu-Gettext-Domain"))) {
130+ const QString domain = settings.value(QStringLiteral("X-Ubuntu-Gettext-Domain")).toString();
131+ return dgettext(domain.toUtf8().constData(), displayName.toUtf8().constData());
132+ }
133+
134+ return displayName;
135+}
136+
137+QString DesktopFileHandler::icon() const
138+{
139+ if (!isValid()) {
140+ return QString();
141+ }
142+
143+ QSettings settings(m_filename, QSettings::IniFormat);
144+ settings.setIniCodec("UTF-8");
145+ settings.beginGroup(QStringLiteral("Desktop Entry"));
146+ QString iconString = settings.value(QStringLiteral("Icon")).toString();
147+ QString pathString = settings.value(QStringLiteral("Path")).toString();
148+
149+ if (QFileInfo::exists(iconString)) {
150+ return QFileInfo(iconString).absoluteFilePath();
151+ } else if (QFileInfo::exists(pathString + '/' + iconString)) {
152+ return pathString + '/' + iconString;
153+ }
154+ return "image://theme/" + iconString;
155+}
plugins/Unity/Launcher/desktopfilehandler.hnew file+56
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+#ifndef DESKTOPFILEHANDLER_H
21+#define DESKTOPFILEHANDLER_H
22+
23+#include <QObject>
24+
25+/**
26+ * When an object of this class is created or whenever setAppId(appId) is called,
27+ * this will search for a .desktop file matching the give appId. If a file is
28+ * found, isValid() will return true and the other methods return the contents
29+ * of the .desktop file.
30+ *
31+ * Note that this class will consider the user's locale and do a best effort
32+ * to return localized values.
33+ */
34+
35+class DesktopFileHandler: public QObject
36+{
37+ Q_OBJECT
38+public:
39+ DesktopFileHandler(const QString &appId = QString(), QObject *parent = nullptr);
40+
41+ QString appId() const;
42+ void setAppId(const QString &appId);
43+
44+ bool isValid() const;
45+ QString filename() const;
46+ QString displayName() const;
47+ QString icon() const;
48+
49+private:
50+ void load();
51+
52+ QString m_appId;
53+ QString m_filename;
54+};
55+
56+#endif
plugins/Unity/Launcher/launcheritem.cpp+10−65
@@ -37,22 +37,20 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3737 m_alerting(false),
3838 m_quickList(new QuickListModel(this))
3939{
40+ Q_ASSERT(parent != nullptr);
4041 QuickListEntry nameAction;
4142 nameAction.setActionId(QStringLiteral("launch_item"));
4243 nameAction.setText(m_name);
43− nameAction.setHasSeparator(true);
4444 m_quickList->appendAction(nameAction);
4545
4646 QuickListEntry pinningAction;
4747 pinningAction.setActionId(QStringLiteral("pin_item"));
4848 pinningAction.setText(gettext("Pin shortcut"));
49− pinningAction.setIsPrivate(true);
5049 m_quickList->appendAction(pinningAction);
5150
5251 m_quitAction.setActionId(QStringLiteral("stop_item"));
5352 m_quitAction.setIcon(QStringLiteral("application-exit"));
5453 m_quitAction.setText(gettext("Quit"));
55− m_quitAction.setIsPrivate(true);
5654}
5755
5856QString LauncherItem::appId() const
@@ -90,19 +88,6 @@ void LauncherItem::setIcon(const QString &icon)
9088 }
9189}
9290
93−QStringList LauncherItem::keywords() const
94−{
95− return m_keywords;
96−}
97−
98−void LauncherItem::setKeywords(const QStringList &keywords)
99−{
100− if (m_keywords != keywords) {
101− m_keywords = keywords;
102− Q_EMIT keywordsChanged(keywords);
103− }
104−}
105−
10691bool LauncherItem::pinned() const
10792{
10893 return m_pinned;
@@ -120,7 +105,6 @@ void LauncherItem::setPinned(bool pinned)
120105 QuickListEntry entry;
121106 entry.setActionId(QStringLiteral("pin_item"));
122107 entry.setText(pinned ? gettext("Unpin shortcut") : gettext("Pin shortcut"));
123− entry.setIsPrivate(true);
124108 m_quickList->updateAction(entry);
125109}
126110
@@ -178,6 +162,9 @@ void LauncherItem::setCount(int count)
178162 if (m_count != count) {
179163 m_count = count;
180164 Q_EMIT countChanged(count);
165+ if (m_countVisible) {
166+ setAlerting(true);
167+ }
181168 }
182169}
183170
@@ -191,6 +178,9 @@ void LauncherItem::setCountVisible(bool countVisible)
191178 if (m_countVisible != countVisible) {
192179 m_countVisible = countVisible;
193180 Q_EMIT countVisibleChanged(countVisible);
181+ if (countVisible) {
182+ setAlerting(true);
183+ }
194184 }
195185}
196186
@@ -203,6 +193,9 @@ void LauncherItem::setFocused(bool focused)
203193{
204194 if (m_focused != focused) {
205195 m_focused = focused;
196+ if (focused) {
197+ setAlerting(false);
198+ }
206199 Q_EMIT focusedChanged(focused);
207200 }
208201}
@@ -220,54 +213,6 @@ void LauncherItem::setAlerting(bool alerting)
220213 }
221214}
222215
223−int LauncherItem::surfaceCount() const
224−{
225− return m_surfaces.count();
226−}
227−
228−void LauncherItem::setSurfaces(const QList<QPair<QString, QString> > &surfaces)
229−{
230− if (m_surfaces != surfaces) {
231− m_surfaces = surfaces;
232−
233− QList<QuickListEntry> removedEntries;
234− for (int i = 0; i < m_quickList->rowCount(); ++i) {
235− QuickListEntry entry = m_quickList->get(i);
236− if (entry.actionId().startsWith(QStringLiteral("surface_"))) {
237− removedEntries.append(entry);
238− }
239− }
240− Q_FOREACH (const QuickListEntry &entry, removedEntries) {
241− m_quickList->removeAction(entry);
242− }
243− for (int i = 0; i < surfaces.count(); ++i) {
244− QuickListEntry entry;
245− entry.setActionId(QStringLiteral("surface_") + surfaces.at(i).first);
246− entry.setText(surfaces.at(i).second);
247− entry.setIsPrivate(true);
248− if (i == surfaces.count() - 1) {
249− entry.setHasSeparator(true);
250− }
251− m_quickList->insertAction(entry, i + 1);
252− }
253−
254− Q_EMIT surfaceCountChanged(m_surfaces.count());
255− }
256−}
257−
258−uint LauncherItem::popularity() const
259−{
260− return m_popularity;
261−}
262−
263−void LauncherItem::setPopularity(uint popularity)
264−{
265− if (m_popularity != popularity) {
266− m_popularity = popularity;
267− Q_EMIT popularityChanged(popularity);
268− }
269−}
270−
271216unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
272217{
273218 return m_quickList;
plugins/Unity/Launcher/launcheritem.h−11
@@ -23,7 +23,6 @@
2323#include "quicklistmodel.h"
2424
2525#include <unity/shell/launcher/LauncherItemInterface.h>
26−#include <unity/shell/application/MirSurfaceInterface.h>
2726
2827class QuickListModel;
2928
@@ -38,8 +37,6 @@ public:
3837 QString appId() const override;
3938 QString name() const override;
4039 QString icon() const override;
41− QStringList keywords() const override;
42− uint popularity() const override;
4340 bool pinned() const override;
4441 bool running() const override;
4542 bool recent() const override;
@@ -48,15 +45,12 @@ public:
4845 bool countVisible() const override;
4946 bool focused() const override;
5047 bool alerting() const override;
51− int surfaceCount() const override;
5248
5349 unity::shell::launcher::QuickListModelInterface *quickList() const override;
5450
5551private:
5652 void setName(const QString &name);
5753 void setIcon(const QString &icon);
58− void setKeywords(const QStringList &keywords);
59− void setPopularity(uint popularity);
6054 void setPinned(bool pinned);
6155 void setRunning(bool running);
6256 void setRecent(bool recent);
@@ -65,14 +59,11 @@ private:
6559 void setCountVisible(bool countVisible);
6660 void setFocused(bool focused);
6761 void setAlerting(bool alerting);
68− void setSurfaces(const QList<QPair<QString, QString >> &surfaces);
6962
7063private:
7164 QString m_appId;
7265 QString m_name;
7366 QString m_icon;
74− QStringList m_keywords;
75− uint m_popularity;
7667 bool m_pinned;
7768 bool m_running;
7869 bool m_recent;
@@ -81,12 +72,10 @@ private:
8172 bool m_countVisible;
8273 bool m_focused;
8374 bool m_alerting;
84− QList<QPair<QString, QString> > m_surfaces;
8575 QuickListModel *m_quickList;
8676 QuickListEntry m_quitAction;
8777
8878 friend class LauncherModel;
89− friend class AppDrawerModel;
9079};
9180
9281#endif // LAUNCHERITEM_H
plugins/Unity/Launcher/launchermodel.cpp+59−118
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2013-2016 Canonical Ltd.
2+ * Copyright 2013-2014 Canonical Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU Lesser General Public License as published by
@@ -12,18 +12,19 @@
1212 *
1313 * You should have received a copy of the GNU Lesser General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
1518 */
1619
1720#include "launchermodel.h"
1821#include "launcheritem.h"
1922#include "gsettings.h"
23+#include "desktopfilehandler.h"
2024#include "dbusinterface.h"
2125#include "asadapter.h"
22−#include "ualwrapper.h"
2326
2427#include <unity/shell/application/ApplicationInfoInterface.h>
25−#include <unity/shell/application/MirSurfaceListInterface.h>
26−#include <unity/shell/application/MirSurfaceInterface.h>
2728
2829#include <QDesktopServices>
2930#include <QDebug>
@@ -87,8 +88,6 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
8788 return item->alerting();
8889 case RoleRunning:
8990 return item->running();
90− case RoleSurfaceCount:
91− return item->surfaceCount();
9291 default:
9392 qWarning() << Q_FUNC_INFO << "missing role, implement me";
9493 return QVariant();
@@ -97,6 +96,18 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
9796 return QVariant();
9897}
9998
99+void LauncherModel::setAlerting(const QString &appId, bool alerting) {
100+ int index = findApplication(appId);
101+ if (index >= 0) {
102+ QModelIndex modelIndex = this->index(index);
103+ LauncherItem *item = m_list.at(index);
104+ if (!item->focused()) {
105+ item->setAlerting(alerting);
106+ Q_EMIT dataChanged(modelIndex, modelIndex, {RoleAlerting});
107+ }
108+ }
109+}
110+
100111unity::shell::launcher::LauncherItemInterface *LauncherModel::get(int index) const
101112{
102113 if (index < 0 || index >= m_list.count()) {
@@ -155,19 +166,18 @@ void LauncherModel::pin(const QString &appId, int index)
155166 index = m_list.count();
156167 }
157168
158− UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(appId);
159− if (!appInfo.valid) {
160− qWarning() << "Can't pin application, appId not found:" << appId;
169+ DesktopFileHandler desktopFile(appId);
170+ if (!desktopFile.isValid()) {
171+ qWarning() << "Can't pin this application, there is no .desktop file available.";
161172 return;
162173 }
163174
164175 beginInsertRows(QModelIndex(), index, index);
165176 LauncherItem *item = new LauncherItem(appId,
166− appInfo.name,
167− appInfo.icon,
177+ desktopFile.displayName(),
178+ desktopFile.icon(),
168179 this);
169180 item->setPinned(true);
170− item->setPopularity(appInfo.popularity);
171181 m_list.insert(index, item);
172182 endInsertRows();
173183 }
@@ -200,26 +210,12 @@ void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex
200210 } else {
201211 pin(appId);
202212 }
203− } else if (actionId == QStringLiteral("launch_item")) {
213+ } else if (actionId == QLatin1String("launch_item")) {
204214 QDesktopServices::openUrl(getUrlForAppId(appId));
205− } else if (actionId == QStringLiteral("stop_item")) { // Quit
215+ } else if (actionId == QLatin1String("stop_item")) { // Quit
206216 if (m_appManager) {
207217 m_appManager->stopApplication(appId);
208218 }
209− } else if (actionId.startsWith(QStringLiteral("surface_"))){
210− ApplicationInfoInterface *appInfo = m_appManager->findApplication(appId);
211− if (appInfo) {
212− for (int i = 0; i < appInfo->surfaceList()->count(); ++i) {
213− MirSurfaceInterface *iface = appInfo->surfaceList()->get(i);
214− QString id = actionId;
215− id.remove(QRegExp("^surface_"));
216− if (id == iface->persistentId()) {
217− iface->activate();
218− }
219− }
220− } else {
221− qWarning() << "App for" << appId << "not found in launcher. Cannot invoke quicklist action";
222− }
223219 // Nope, we don't know this action, let the backend forward it to the application
224220 } else {
225221 // TODO: forward quicklist action to app, possibly via m_dbusIface
@@ -230,6 +226,7 @@ void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex
230226void LauncherModel::setUser(const QString &username)
231227{
232228 Q_UNUSED(username)
229+ qWarning() << "This backend doesn't support multiple users";
233230}
234231
235232QString LauncherModel::getUrlForAppId(const QString &appId) const
@@ -361,13 +358,11 @@ void LauncherModel::countChanged(const QString &appId, int count)
361358 if (idx >= 0) {
362359 LauncherItem *item = m_list.at(idx);
363360 item->setCount(count);
364− QVector<int> changedRoles = {RoleCount};
365− if (item->countVisible() && !item->alerting() && !item->focused()) {
366− changedRoles << RoleAlerting;
367− item->setAlerting(true);
361+ if (item->countVisible()) {
362+ setAlerting(item->appId(), true);
368363 }
369364 m_asAdapter->syncItems(m_list);
370− Q_EMIT dataChanged(index(idx), index(idx), changedRoles);
365+ Q_EMIT dataChanged(index(idx), index(idx), {RoleCount});
371366 }
372367}
373368
@@ -377,12 +372,10 @@ void LauncherModel::countVisibleChanged(const QString &appId, bool countVisible)
377372 if (idx >= 0) {
378373 LauncherItem *item = m_list.at(idx);
379374 item->setCountVisible(countVisible);
380− QVector<int> changedRoles = {RoleCountVisible};
381− if (countVisible && !item->alerting() && !item->focused()) {
382− changedRoles << RoleAlerting;
383− item->setAlerting(true);
375+ if (countVisible) {
376+ setAlerting(item->appId(), true);
384377 }
385− Q_EMIT dataChanged(index(idx), index(idx), changedRoles);
378+ Q_EMIT dataChanged(index(idx), index(idx), {RoleCountVisible});
386379
387380 // If countVisible goes to false, and the item is neither pinned nor recent we can drop it
388381 if (!countVisible && !item->pinned() && !item->recent()) {
@@ -392,11 +385,11 @@ void LauncherModel::countVisibleChanged(const QString &appId, bool countVisible)
392385 }
393386 } else {
394387 // Need to create a new LauncherItem and show the highlight
395− UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(appId);
396− if (countVisible && appInfo.valid) {
388+ DesktopFileHandler desktopFile(appId);
389+ if (countVisible && desktopFile.isValid()) {
397390 LauncherItem *item = new LauncherItem(appId,
398− appInfo.name,
399− appInfo.icon,
391+ desktopFile.displayName(),
392+ desktopFile.icon(),
400393 this);
401394 item->setCountVisible(true);
402395 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
@@ -412,28 +405,28 @@ void LauncherModel::refresh()
412405 // First walk through all the existing items and see if we need to remove something
413406 QList<LauncherItem*> toBeRemoved;
414407 Q_FOREACH (LauncherItem* item, m_list) {
415− UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(item->appId());
416− if (!appInfo.valid) {
417− // Application no longer available => drop it!
408+ DesktopFileHandler desktopFile(item->appId());
409+ if (!desktopFile.isValid()) {
410+ // Desktop file not available for this app => drop it!
418411 toBeRemoved << item;
419412 } else if (!m_settings->storedApplications().contains(item->appId())) {
420413 // Item not in settings any more => drop it!
421414 toBeRemoved << item;
422415 } else {
423416 int idx = m_list.indexOf(item);
424− item->setName(appInfo.name);
417+ item->setName(desktopFile.displayName());
425418 item->setPinned(item->pinned()); // update pinned text if needed
426419 item->setRunning(item->running());
427420 Q_EMIT dataChanged(index(idx), index(idx), {RoleName, RoleRunning});
428421
429422 const QString oldIcon = item->icon();
430− if (oldIcon == appInfo.icon) { // same icon file, perhaps different contents, simulate changing the icon name to force reload
423+ if (oldIcon == desktopFile.icon()) { // same icon file, perhaps different contents, simulate changing the icon name to force reload
431424 item->setIcon(QString());
432425 Q_EMIT dataChanged(index(idx), index(idx), {RoleIcon});
433426 }
434427
435428 // now set the icon for real
436− item->setIcon(appInfo.icon);
429+ item->setIcon(desktopFile.icon());
437430 Q_EMIT dataChanged(index(idx), index(idx), {RoleIcon});
438431 }
439432 }
@@ -464,14 +457,15 @@ void LauncherModel::refresh()
464457 if (itemIndex == -1) {
465458 // Need to add it. Just add it into the addedIndex to keep same ordering as the list
466459 // in the settings.
467− UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(entry);
468− if (!appInfo.valid) {
460+ DesktopFileHandler desktopFile(entry);
461+ if (!desktopFile.isValid()) {
462+ qWarning() << "Couldn't find a .desktop file for" << entry << ". Skipping...";
469463 continue;
470464 }
471465
472466 LauncherItem *item = new LauncherItem(entry,
473− appInfo.name,
474− appInfo.icon,
467+ desktopFile.displayName(),
468+ desktopFile.icon(),
475469 this);
476470 item->setPinned(true);
477471 beginInsertRows(QModelIndex(), addedIndex, addedIndex);
@@ -504,10 +498,8 @@ void LauncherModel::alert(const QString &appId)
504498 int idx = findApplication(appId);
505499 if (idx >= 0) {
506500 LauncherItem *item = m_list.at(idx);
507− if (!item->focused() && !item->alerting()) {
508− item->setAlerting(true);
509− Q_EMIT dataChanged(index(idx), index(idx), {RoleAlerting});
510− }
501+ setAlerting(item->appId(), true);
502+ Q_EMIT dataChanged(index(idx), index(idx), {RoleAlerting});
511503 }
512504}
513505
@@ -521,6 +513,11 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
521513 return;
522514 }
523515
516+ if (app->appId() == QLatin1String("unity8-dash")) {
517+ // Not adding the dash app
518+ return;
519+ }
520+
524521 const int itemIndex = findApplication(app->appId());
525522 if (itemIndex != -1) {
526523 LauncherItem *item = m_list.at(itemIndex);
@@ -534,65 +531,22 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
534531 item->setRecent(true);
535532 item->setRunning(true);
536533 item->setFocused(app->focused());
534+
537535 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
538536 m_list.append(item);
539537 endInsertRows();
540538 }
541− connect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::updateSurfaceList);
542539 m_asAdapter->syncItems(m_list);
543540 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRunning});
544541}
545542
546−void LauncherModel::updateSurfaceList()
547−{
548− ApplicationInfoInterface *app = static_cast<ApplicationInfoInterface*>(sender());
549− updateSurfaceListForApp(app);
550−}
551−
552−void LauncherModel::updateSurfaceListForSurface()
553−{
554− MirSurfaceInterface *iface = static_cast<MirSurfaceInterface*>(sender());
555− ApplicationInfoInterface* app = m_appManager->findApplication(iface->appId());
556− if (!app) {
557− return;
558− }
559− updateSurfaceListForApp(app);
560−}
561−
562−void LauncherModel::updateSurfaceListForApp(ApplicationInfoInterface* app)
563−{
564− int idx = findApplication(app->appId());
565− if (idx < 0) {
566− qWarning() << "Received a surface count changed event from an app that's not in the Launcher model";
567− return;
568− }
569− LauncherItem *item = m_list.at(idx);
570− QList<QPair<QString, QString> > surfaces;
571− for (int i = 0; i < app->surfaceList()->count(); ++i) {
572− MirSurfaceInterface* iface = app->surfaceList()->get(i);
573− if (iface->type() == Mir::NormalType || iface->type() == Mir::DialogType) {
574− // Avoid duplicate connections, so let's just disconnect first to be sure
575− disconnect(iface, &MirSurfaceInterface::nameChanged, this, &LauncherModel::updateSurfaceListForSurface);
576− connect(iface, &MirSurfaceInterface::nameChanged, this, &LauncherModel::updateSurfaceListForSurface);
577− QString name = iface->name();
578− if (name.isEmpty()) {
579− name = app->name();
580− }
581− surfaces.append({iface->persistentId(), name});
582− }
583− }
584− item->setSurfaces(surfaces);
585− Q_EMIT dataChanged(index(idx), index(idx), {RoleSurfaceCount});
586−}
587−
588543void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
589544{
590545 Q_UNUSED(parent)
591546
592− ApplicationInfoInterface *app = m_appManager->get(row);
593547 int appIndex = -1;
594548 for (int i = 0; i < m_list.count(); ++i) {
595− if (m_list.at(i)->appId() == app->appId()) {
549+ if (m_list.at(i)->appId() == m_appManager->get(row)->appId()) {
596550 appIndex = i;
597551 break;
598552 }
@@ -603,24 +557,17 @@ void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
603557 return;
604558 }
605559
606− disconnect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::updateSurfaceList);
607−
608560 LauncherItem * item = m_list.at(appIndex);
561+ item->setRunning(false);
609562
610563 if (!item->pinned()) {
611564 beginRemoveRows(QModelIndex(), appIndex, appIndex);
612565 m_list.takeAt(appIndex)->deleteLater();
613566 endRemoveRows();
614567 m_asAdapter->syncItems(m_list);
615− } else {
616− QVector<int> changedRoles = {RoleRunning};
617− item->setRunning(false);
618− if (item->focused()) {
619− changedRoles << RoleFocused;
620− item->setFocused(false);
621− }
622− Q_EMIT dataChanged(index(appIndex), index(appIndex), changedRoles);
568+ Q_EMIT dataChanged(index(appIndex), index(appIndex), {RolePinned});
623569 }
570+ Q_EMIT dataChanged(index(appIndex), index(appIndex), {RoleRunning});
624571}
625572
626573void LauncherModel::focusedAppIdChanged()
@@ -629,14 +576,8 @@ void LauncherModel::focusedAppIdChanged()
629576 for (int i = 0; i < m_list.count(); ++i) {
630577 LauncherItem *item = m_list.at(i);
631578 if (!item->focused() && item->appId() == appId) {
632− QVector<int> changedRoles;
633− changedRoles << RoleFocused;
634579 item->setFocused(true);
635− if (item->alerting()) {
636− changedRoles << RoleAlerting;
637− item->setAlerting(false);
638− }
639− Q_EMIT dataChanged(index(i), index(i), changedRoles);
580+ Q_EMIT dataChanged(index(i), index(i), {RoleFocused});
640581 } else if (item->focused() && item->appId() != appId) {
641582 item->setFocused(false);
642583 Q_EMIT dataChanged(index(i), index(i), {RoleFocused});
plugins/Unity/Launcher/launchermodel.h+9−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2013-2016 Canonical Ltd.
2+ * Copyright 2013-2014 Canonical Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU Lesser General Public License as published by
@@ -12,11 +12,14 @@
1212 *
1313 * You should have received a copy of the GNU Lesser General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
1518 */
1619
17−#pragma once
20+#ifndef LAUNCHERMODEL_H
21+#define LAUNCHERMODEL_H
1822
19−#include <memory>
2023#include <unity/shell/launcher/LauncherModelInterface.h>
2124#include <unity/shell/application/ApplicationManagerInterface.h>
2225
@@ -42,6 +45,7 @@ public:
4245
4346 QVariant data(const QModelIndex &index, int role) const override;
4447
48+ Q_INVOKABLE void setAlerting(const QString &appId, bool alerting) override;
4549 Q_INVOKABLE unity::shell::launcher::LauncherItemInterface* get(int index) const override;
4650 Q_INVOKABLE void move(int oldIndex, int newIndex) override;
4751 Q_INVOKABLE void pin(const QString &appId, int index = -1) override;
@@ -75,9 +79,6 @@ private Q_SLOTS:
7579 void applicationAdded(const QModelIndex &parent, int row);
7680 void applicationRemoved(const QModelIndex &parent, int row);
7781 void focusedAppIdChanged();
78− void updateSurfaceList();
79− void updateSurfaceListForApp(ApplicationInfoInterface *app);
80− void updateSurfaceListForSurface();
8182
8283private:
8384 QList<LauncherItem*> m_list;
@@ -90,3 +91,5 @@ private:
9091
9192 friend class LauncherModelTest;
9293};
94+
95+#endif // LAUNCHERMODEL_H
plugins/Unity/Launcher/plugin.cpp+1−2
@@ -26,7 +26,7 @@
2626// local
2727#include "launchermodel.h"
2828#include "launcheritem.h"
29−#include "appdrawermodel.h"
29+
3030
3131using namespace unity::shell::launcher;
3232
@@ -46,5 +46,4 @@ void UnityLauncherPlugin::registerTypes(const char *uri)
4646 qmlRegisterSingletonType<LauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
4747 qmlRegisterUncreatableType<LauncherItem>(uri, 0, 1, "LauncherItem", QStringLiteral("Can't create new Launcher Items in QML. Get them from the LauncherModel."));
4848 qmlRegisterUncreatableType<QuickListModel>(uri, 0, 1, "QuickListModel", QStringLiteral("Can't create a QuickListModel in QML. Get them from the LauncherItems."));
49− qmlRegisterType<AppDrawerModel>(uri, 0, 1, "AppDrawerModel");
5049}
plugins/Unity/Launcher/quicklistentry.cpp−22
@@ -19,8 +19,6 @@
1919#include "quicklistentry.h"
2020
2121QuickListEntry::QuickListEntry()
22− : m_hasSeparator(false)
23− , m_isPrivate(false)
2422{
2523}
2624
@@ -59,27 +57,7 @@ bool QuickListEntry::clickable() const
5957 return !m_actionId.isEmpty();
6058}
6159
62−void QuickListEntry::setHasSeparator(bool hasSeparator)
63−{
64− m_hasSeparator = hasSeparator;
65−}
66−
67−bool QuickListEntry::hasSeparator() const
68−{
69− return m_hasSeparator;
70−}
71−
7260bool QuickListEntry::operator==(const QuickListEntry &other)
7361{
7462 return !other.actionId().isEmpty() && other.actionId() == m_actionId;
7563}
76−
77−bool QuickListEntry::isPrivate() const
78−{
79− return m_isPrivate;
80−}
81−
82−void QuickListEntry::setIsPrivate(bool isPrivate)
83−{
84− m_isPrivate = isPrivate;
85−}
plugins/Unity/Launcher/quicklistentry.h−8
@@ -37,20 +37,12 @@ public:
3737
3838 bool clickable() const;
3939
40− void setHasSeparator(bool hasSeparator);
41− bool hasSeparator() const;
42−
4340 bool operator==(const QuickListEntry & other);
4441
45− bool isPrivate() const;
46− void setIsPrivate(bool isPrivate);
47−
4842private:
4943 QString m_actionId;
5044 QString m_text;
5145 QString m_icon;
52− bool m_hasSeparator;
53− bool m_isPrivate;
5446};
5547
5648#endif // QUICKLISTENTRY
plugins/Unity/Launcher/quicklistmodel.cpp−11
@@ -37,13 +37,6 @@ void QuickListModel::appendAction(const QuickListEntry &entry)
3737 endInsertRows();
3838}
3939
40−void QuickListModel::insertAction(const QuickListEntry &entry, int index)
41−{
42− beginInsertRows(QModelIndex(), index, index);
43− m_list.insert(index, entry);
44− endInsertRows();
45−}
46−
4740void QuickListModel::updateAction(const QuickListEntry &entry)
4841{
4942 for (int i = 0; i < m_list.count(); ++i) {
@@ -86,10 +79,6 @@ QVariant QuickListModel::data(const QModelIndex &index, int role) const
8679 return m_list.at(index.row()).icon();
8780 case RoleClickable:
8881 return m_list.at(index.row()).clickable();
89− case RoleHasSeparator:
90− return m_list.at(index.row()).hasSeparator();
91− case RoleIsPrivate:
92− return m_list.at(index.row()).isPrivate();
9382 }
9483 return QVariant();
9584}
plugins/Unity/Launcher/quicklistmodel.h−1
@@ -36,7 +36,6 @@ public:
3636 ~QuickListModel();
3737
3838 void appendAction(const QuickListEntry &entry);
39− void insertAction(const QuickListEntry &entry, int index);
4039
4140 /**
4241 * @brief Update an existing action
plugins/Unity/Launcher/ualwrapper.cppdeleted−74
@@ -1,74 +0,0 @@
1−/*
2− * Copyright (C) 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−#include <QDebug>
18−
19−#include "ualwrapper.h"
20−
21−#include <ubuntu-app-launch/registry.h>
22−using namespace ubuntu::app_launch;
23−
24−UalWrapper::UalWrapper(QObject *parent):
25− QObject(parent)
26−{
27−}
28−
29−QStringList UalWrapper::installedApps()
30−{
31− QStringList appIds;
32− try {
33− for (const std::shared_ptr<Application> &app : Registry::installedApps()) {
34− if (!app->appId().package.value().empty()) {
35− appIds << QString::fromStdString(app->appId().package.value() + "_" + app->appId().appname.value());
36− } else {
37− appIds << QString::fromStdString(app->appId().appname);
38− }
39− }
40− } catch (const std::runtime_error &e) {
41− qWarning() << "ubuntu-app-launch threw an exception listing apps:" << e.what();
42− }
43−
44− return appIds;
45−}
46−
47−UalWrapper::AppInfo UalWrapper::getApplicationInfo(const QString &appId)
48−{
49− AppInfo info;
50−
51− try {
52− AppID ualAppId = AppID::find(appId.toStdString());
53− if (ualAppId.empty()) {
54− qWarning() << "Empty ualAppId result for" << appId;
55− return info;
56− }
57−
58− std::shared_ptr<Application> ualApp;
59− ualApp = Application::create(ualAppId, Registry::getDefault());
60−
61− info.appId = appId;
62− info.name = QString::fromStdString(ualApp->info()->name());
63− info.icon = QString::fromStdString(ualApp->info()->iconPath());
64− for (const std::string &keyword : ualApp->info()->keywords().value()) {
65− info.keywords << QString::fromStdString(keyword);
66− }
67− //info.popularity = ualApp->info()->popularity();
68− info.valid = true;
69− } catch (const std::runtime_error &e) {
70− qWarning() << "ubuntu-app-launch threw an exception getting app info for appId:" << appId << ":" << e.what();
71− }
72−
73− return info;
74−}
plugins/Unity/Launcher/ualwrapper.hdeleted−36
@@ -1,36 +0,0 @@
1−/*
2− * Copyright (C) 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−#include <QObject>
18−
19−class UalWrapper: public QObject
20−{
21− Q_OBJECT
22−public:
23− struct AppInfo {
24− QString appId;
25− bool valid = false;
26− QString name;
27− QString icon;
28− QStringList keywords;
29− uint popularity = 0;
30− };
31−
32− UalWrapper(QObject* parent = nullptr);
33−
34− static QStringList installedApps();
35− static AppInfo getApplicationInfo(const QString &appId);
36−};
plugins/Unity/Launcher/xdgwatcher.cppdeleted−129
@@ -1,129 +0,0 @@
1−/*
2− * Copyright (C) 2019 UBports Foundation
3− * Author(s): Marius Gripsgard <marius@ubports.com>
4− *
5− * This program is free software; you can redistribute it and/or modify
6− * it under the terms of the GNU General Public License as published by
7− * the Free Software Foundation; version 3.
8− *
9− * This program is distributed in the hope that it will be useful,
10− * but WITHOUT ANY WARRANTY; without even the implied warranty of
11− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12− * GNU General Public License for more details.
13− *
14− * You should have received a copy of the GNU General Public License
15− * along with this program. If not, see <http://www.gnu.org/licenses/>.
16− */
17−
18−#include "xdgwatcher.h"
19−
20−#include <QDebug>
21−#include <QDir>
22−#include <QFile>
23−#include <QStandardPaths>
24−#include <QTextStream>
25−
26−XdgWatcher::XdgWatcher(QObject* parent)
27− : QObject(parent),
28− m_watcher(new QFileSystemWatcher(this))
29−{
30− connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, &XdgWatcher::onDirectoryChanged);
31− connect(m_watcher, &QFileSystemWatcher::fileChanged, this, &XdgWatcher::onFileChanged);
32−
33− const auto paths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
34− for (const auto &path: paths) {
35− const auto qdir = QDir(path);
36− if (!qdir.exists()) {
37− continue;
38− }
39−
40− // Add the path itself to watch for newly added apps
41− m_watcher->addPath(path);
42−
43− // Add watcher for eatch app to watch for changes
44− const auto files = qdir.entryInfoList(QDir::Files);
45− for (const auto &file: files) {
46− if (file.suffix() == "desktop") {
47− const auto path = file.absoluteFilePath();
48− m_watcher->addPath(path);
49− m_registry.insert(path, getAppId(file));
50− }
51− }
52− }
53−}
54−
55−// "Ubuntu style" appID is filename without versionNumber after last "_"
56−const QString XdgWatcher::stripAppIdVersion(const QString rawAppID) const {
57− auto appIdComponents = rawAppID.split("_");
58− appIdComponents.removeLast();
59− return appIdComponents.join("_");
60−}
61−
62−// Standard appID see:
63−// https://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id
64−const QString XdgWatcher::toStandardAppId(const QFileInfo fileInfo) const {
65− const auto paths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
66− for (const auto &path: paths) {
67− if (fileInfo.absolutePath() == path) {
68− break;
69− }
70− if (fileInfo.absolutePath().contains(path)) {
71− auto fileStr = fileInfo.absoluteFilePath();
72− fileStr.replace(path, "");
73− fileStr.replace("/", "-");
74− fileStr.replace(".desktop", "");
75− return fileStr;
76− }
77− }
78− return fileInfo.completeBaseName();
79−}
80−
81−const QString XdgWatcher::getAppId(const QFileInfo fileInfo) const {
82− // We need to open the file to check if its and Ual application
83− // as we cant just rely on the app name as "normal" apps can also
84− // contain 3 _ causing us to belive its an ubuntu app
85− // Example kde_org_kate would become kde_org
86− QFile qFile(fileInfo.absoluteFilePath());
87− qFile.open(QIODevice::ReadOnly);
88− QTextStream fileStream(&qFile);
89− QString line;
90− while (fileStream.readLineInto(&line)) {
91− if (line.startsWith("X-Ubuntu-Application-ID=")) {
92− auto rawAppID = line.replace("X-Ubuntu-Application-ID=", "");
93− qFile.close();
94− return stripAppIdVersion(rawAppID);
95− }
96− }
97− qFile.close();
98−
99− // If it's not an "Ubuntu" appID, we follow freedesktop standard
100− return toStandardAppId(fileInfo);
101−}
102−
103−// Watch for newly added apps
104−void XdgWatcher::onDirectoryChanged(const QString &path) {
105− const auto files = QDir(path).entryInfoList(QDir::Files);
106− const auto watchedFiles = m_watcher->files();
107− for (const auto &file: files) {
108− const auto appPath = file.absoluteFilePath();
109− if (file.suffix() == "desktop" && !watchedFiles.contains(appPath)) {
110− m_watcher->addPath(appPath);
111−
112− const auto appId = getAppId(file);
113− m_registry.insert(appPath, appId);
114− Q_EMIT appAdded(appId);
115− }
116− }
117−}
118−
119−void XdgWatcher::onFileChanged(const QString &path) {
120− QFileInfo file(path);
121− if (file.exists()) {
122− // The file exists, this must be an modify event
123− Q_EMIT appInfoChanged(m_registry.value(path));
124− } else {
125− // File does not exist, assume this is an remove event.
126− // onDirectoryChanged will handle rename event
127− Q_EMIT appRemoved(m_registry.take(path));
128− }
129−}
plugins/Unity/Launcher/xdgwatcher.hdeleted−46
@@ -1,46 +0,0 @@
1−/*
2− * Copyright (C) 2019 UBports Foundation
3− * Author(s): Marius Gripsgard <marius@ubports.com>
4− *
5− * This program is free software; you can redistribute it and/or modify
6− * it under the terms of the GNU General Public License as published by
7− * the Free Software Foundation; version 3.
8− *
9− * This program is distributed in the hope that it will be useful,
10− * but WITHOUT ANY WARRANTY; without even the implied warranty of
11− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12− * GNU General Public License for more details.
13− *
14− * You should have received a copy of the GNU General Public License
15− * along with this program. If not, see <http://www.gnu.org/licenses/>.
16− */
17−
18−#include <QFileSystemWatcher>
19−#include <QHash>
20−#include <QFileInfo>
21−
22−class QFileInfo;
23−
24−class XdgWatcher: public QObject
25−{
26− Q_OBJECT
27−public:
28− XdgWatcher(QObject* parent = nullptr);
29−
30−Q_SIGNALS:
31− void appAdded(const QString &appId);
32− void appRemoved(const QString &appId);
33− void appInfoChanged(const QString &appId);
34−
35−private Q_SLOTS:
36− void onDirectoryChanged(const QString &path);
37− void onFileChanged(const QString &path);
38−
39−private:
40− const QString toStandardAppId(const QFileInfo fileInfo) const;
41− const QString getAppId(const QFileInfo file) const;
42− const QString stripAppIdVersion(const QString rawAppID) const;
43−
44− QFileSystemWatcher* m_watcher;
45− QHash<const QString, QString> m_registry;
46−};
plugins/Unity/Platform/CMakeLists.txt+1−1
@@ -6,6 +6,6 @@ set(platformplugin_SRCS
66
77add_library(Platform-qml SHARED ${platformplugin_SRCS})
88
9−target_link_libraries(Platform-qml Qt5::DBus Qt5::Qml)
9+qt5_use_modules(Platform-qml DBus Qml)
1010
1111add_unity8_plugin(Unity.Platform 1.0 Unity/Platform TARGETS Platform-qml)
plugins/Unity/Platform/Platform.qmltypesnew file+20
@@ -0,0 +1,20 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.Platform 1.0 plugins'
8+
9+Module {
10+ Component {
11+ name: "Platform"
12+ prototype: "QObject"
13+ exports: ["Unity.Platform/Platform 1.0"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Property { name: "chassis"; type: "string"; isReadonly: true }
18+ Property { name: "isPC"; type: "bool"; isReadonly: true }
19+ }
20+}
plugins/Unity/Platform/platform.cpp+2−16
@@ -17,11 +17,9 @@
1717#include "platform.h"
1818
1919#include <QDBusConnection>
20−#include <QSet>
21−#include <QString>
2220
2321Platform::Platform(QObject *parent)
24− : QObject(parent), m_isPC(true), m_isMultiSession(true)
22+ : QObject(parent)
2523{
2624 QMetaObject::invokeMethod(this, "init");
2725}
@@ -33,20 +31,8 @@ void Platform::init()
3331 QDBusInterface seatIface("org.freedesktop.login1", "/org/freedesktop/login1/seat/self", "org.freedesktop.login1.Seat",
3432 QDBusConnection::systemBus(), this);
3533
36− // From the source at https://cgit.freedesktop.org/systemd/systemd/tree/src/hostname/hostnamed.c#n130
37− // "vm\0"
38− // "container\0"
39− // "desktop\0"
40− // "laptop\0"
41− // "server\0"
42− // "tablet\0"
43− // "handset\0"
44− // "watch\0"
45− // "embedded\0",
4634 m_chassis = iface.property("Chassis").toString();
47−
48− // A PC is not a handset, tablet or watch.
49− m_isPC = !QSet<QString>{"handset", "tablet", "watch"}.contains(m_chassis);
35+ m_isPC = (m_chassis == "desktop" || m_chassis == "laptop" || m_chassis == "server");
5036 m_isMultiSession = seatIface.property("CanMultiSession").toBool() && seatIface.property("CanGraphical").toBool();
5137}
5238
plugins/Unity/Session/CMakeLists.txt+1−3
@@ -6,8 +6,6 @@ include_directories(
66 ${libunity8-private_SOURCE_DIR}
77)
88
9−add_definitions(-DSM_BUSNAME=systemBus)
10−
119set(QMLSESSIONPLUGIN_SRC
1210 plugin.cpp
1311 dbusunitysessionservice.cpp
@@ -18,8 +16,8 @@ add_library(UnitySession-qml MODULE
1816 ${QMLSESSIONPLUGIN_SRC}
1917 )
2018
19+qt5_use_modules(UnitySession-qml DBus Qml)
2120target_link_libraries(UnitySession-qml
22− Qt5::DBus Qt5::Qml
2321 unity8-private
2422 ${GIO_LDFLAGS}
2523 ${GLIB_LIBRARIES}
plugins/Unity/Session/Session.qmltypesnew file+85
@@ -0,0 +1,85 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Unity.Session 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "DBusUnitySessionService"
12+ prototype: "UnityDBusObject"
13+ exports: ["Unity.Session/DBusUnitySessionService 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Signal {
18+ name: "LogoutRequested"
19+ Parameter { name: "have_inhibitors"; type: "bool" }
20+ }
21+ Signal {
22+ name: "logoutRequested"
23+ Parameter { name: "have_inhibitors"; type: "bool" }
24+ }
25+ Signal {
26+ name: "RebootRequested"
27+ Parameter { name: "have_inhibitors"; type: "bool" }
28+ }
29+ Signal {
30+ name: "rebootRequested"
31+ Parameter { name: "have_inhibitors"; type: "bool" }
32+ }
33+ Signal {
34+ name: "ShutdownRequested"
35+ Parameter { name: "have_inhibitors"; type: "bool" }
36+ }
37+ Signal {
38+ name: "shutdownRequested"
39+ Parameter { name: "have_inhibitors"; type: "bool" }
40+ }
41+ Signal { name: "LogoutReady" }
42+ Signal { name: "logoutReady" }
43+ Signal { name: "LockRequested" }
44+ Signal { name: "lockRequested" }
45+ Signal { name: "Locked" }
46+ Signal { name: "Unlocked" }
47+ Method { name: "Logout" }
48+ Method { name: "Reboot" }
49+ Method { name: "Shutdown" }
50+ Method { name: "Suspend" }
51+ Method { name: "Hibernate" }
52+ Method { name: "HybridSleep" }
53+ Method { name: "RequestLogout" }
54+ Method { name: "RequestReboot" }
55+ Method { name: "RequestShutdown" }
56+ Method { name: "EndSession" }
57+ Method { name: "CanHibernate"; type: "bool" }
58+ Method { name: "CanSuspend"; type: "bool" }
59+ Method { name: "CanHybridSleep"; type: "bool" }
60+ Method { name: "CanReboot"; type: "bool" }
61+ Method { name: "CanShutdown"; type: "bool" }
62+ Method { name: "CanLock"; type: "bool" }
63+ Method { name: "UserName"; type: "string" }
64+ Method { name: "RealName"; type: "string" }
65+ Method { name: "HostName"; type: "string" }
66+ Method { name: "PromptLock" }
67+ Method { name: "Lock" }
68+ Method { name: "IsLocked"; type: "bool" }
69+ Method { name: "logout" }
70+ Method { name: "reboot" }
71+ Method { name: "shutdown" }
72+ Method { name: "endSession" }
73+ }
74+ Component {
75+ name: "OrientationLock"
76+ prototype: "QObject"
77+ exports: ["Unity.Session/OrientationLock 0.1"]
78+ isCreatable: false
79+ isSingleton: true
80+ exportMetaObjectRevisions: [0]
81+ Property { name: "enabled"; type: "bool"; isReadonly: true }
82+ Property { name: "savedOrientation"; type: "Qt::ScreenOrientation" }
83+ }
84+ Component { name: "UnityDBusObject"; prototype: "QObject" }
85+}
plugins/Unity/Session/dbusunitysessionservice.cpp+22−132
@@ -18,7 +18,6 @@
1818#include "dbusunitysessionservice.h"
1919
2020// system
21−#include <grp.h>
2221#include <sys/types.h>
2322#include <unistd.h>
2423#include <pwd.h>
@@ -65,19 +64,19 @@ public:
6564 QStringLiteral("GetSessionByPID"));
6665 msg << (quint32) getpid();
6766
68− QDBusReply<QDBusObjectPath> reply = QDBusConnection::SM_BUSNAME().call(msg);
67+ QDBusReply<QDBusObjectPath> reply = QDBusConnection::systemBus().call(msg);
6968 if (reply.isValid()) {
7069 logindSessionPath = reply.value().path();
7170
7271 // start watching the Active property
73− QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, logindSessionPath, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"),
74− this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
72+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, logindSessionPath, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"),
73+ this, SLOT(onPropertiesChanged(QString,QVariantMap,QStringList)));
7574
7675 setupSystemdInhibition();
7776
7877 // re-enable the inhibition upon resume from sleep
79− QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QStringLiteral("PrepareForSleep"),
80− this, SLOT(onResuming(bool)));
78+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, QStringLiteral("PrepareForSleep"),
79+ this, SLOT(onResuming(bool)));
8180 } else {
8281 qWarning() << "Failed to get logind session path" << reply.error().message();
8382 }
@@ -97,7 +96,7 @@ public:
9796 msg << "Unity8 handles power events"; // why
9897 msg << "block"; // mode
9998
100− QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
99+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
101100 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
102101 connect(watcher, &QDBusPendingCallWatcher::finished,
103102 this, [this](QDBusPendingCallWatcher* watcher) {
@@ -115,7 +114,7 @@ public:
115114 bool checkLogin1Call(const QString &method) const
116115 {
117116 QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_IFACE, method);
118− QDBusReply<QString> reply = QDBusConnection::SM_BUSNAME().call(msg);
117+ QDBusReply<QString> reply = QDBusConnection::systemBus().call(msg);
119118 return reply.isValid() && (reply == QStringLiteral("yes") || reply == QStringLiteral("challenge"));
120119 }
121120
@@ -126,7 +125,7 @@ public:
126125 LOGIN1_IFACE,
127126 method);
128127 msg.setArguments(args);
129− QDBusConnection::SM_BUSNAME().asyncCall(msg);
128+ QDBusConnection::systemBus().asyncCall(msg);
130129 }
131130
132131 void setActive(bool active)
@@ -158,7 +157,7 @@ public:
158157 msg << LOGIN1_SESSION_IFACE;
159158 msg << ACTIVE_KEY;
160159
161− QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
160+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
162161 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
163162 connect(watcher, &QDBusPendingCallWatcher::finished,
164163 this, [this](QDBusPendingCallWatcher* watcher) {
@@ -192,7 +191,7 @@ public:
192191 msg << LOGIN1_SESSION_IFACE;
193192 msg << IDLE_SINCE_KEY;
194193
195− QDBusReply<QVariant> reply = QDBusConnection::SM_BUSNAME().call(msg);
194+ QDBusReply<QVariant> reply = QDBusConnection::systemBus().call(msg);
196195 if (reply.isValid()) {
197196 return reply.value().value<quint64>();
198197 } else {
@@ -209,24 +208,7 @@ public:
209208 LOGIN1_SESSION_IFACE,
210209 QStringLiteral("SetIdleHint"));
211210 msg << idle;
212− QDBusConnection::SM_BUSNAME().asyncCall(msg);
213− }
214−
215− bool isUserInGroup(const QString &user, const QString &groupName) const
216− {
217− auto group = getgrnam(groupName.toUtf8().data());
218−
219− if (group && group->gr_mem)
220− {
221− for (int i = 0; group->gr_mem[i]; ++i)
222− {
223− if (g_strcmp0(group->gr_mem[i], user.toUtf8().data()) == 0) {
224− return true;
225− }
226− }
227− }
228−
229− return false;
211+ QDBusConnection::systemBus().asyncCall(msg);
230212 }
231213
232214private Q_SLOTS:
@@ -245,14 +227,11 @@ private Q_SLOTS:
245227 {
246228 if (!active) {
247229 setupSystemdInhibition();
248− } else {
249− Q_EMIT prepareForSleep();
250230 }
251231 }
252232
253233Q_SIGNALS:
254234 void screensaverActiveChanged(bool active);
255− void prepareForSleep();
256235};
257236
258237Q_GLOBAL_STATIC(DBusUnitySessionServicePrivate, d)
@@ -261,12 +240,11 @@ DBusUnitySessionService::DBusUnitySessionService()
261240 : UnityDBusObject(QStringLiteral("/com/canonical/Unity/Session"), QStringLiteral("com.canonical.Unity"))
262241{
263242 if (!d->logindSessionPath.isEmpty()) {
264− // connect our PromptLock() slot to the logind's session Lock() signal
265− QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Lock"), this, SLOT(PromptLock()));
243+ // connect our Lock() slot to the logind's session Lock() signal
244+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Lock"), this, SLOT(Lock()));
266245 // ... and our Unlocked() signal to the logind's session Unlock() signal
267246 // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to)
268− QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SLOT(doUnlock()));
269− connect(d, &DBusUnitySessionServicePrivate::prepareForSleep, this, &DBusUnitySessionService::PromptLock);
247+ QDBusConnection::systemBus().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SIGNAL(Unlocked()));
270248 } else {
271249 qWarning() << "Failed to connect to logind's session Lock/Unlock signals";
272250 }
@@ -315,13 +293,7 @@ bool DBusUnitySessionService::CanShutdown() const
315293
316294bool DBusUnitySessionService::CanLock() const
317295{
318− auto user = UserName();
319− if (user.startsWith(QStringLiteral("guest-")) ||
320− d->isUserInGroup(user, QStringLiteral("nopasswdlogin"))) {
321− return false;
322− } else {
323− return true;
324− }
296+ return true; // FIXME
325297}
326298
327299QString DBusUnitySessionService::UserName() const
@@ -356,43 +328,15 @@ QString DBusUnitySessionService::HostName() const
356328
357329void DBusUnitySessionService::PromptLock()
358330{
359− // Prompt as in quick. No locking animation needed. Usually used by
360− // indicator-session in combination with a switch to greeter or other
361− // user session.
362− if (CanLock()) {
363− Q_EMIT LockRequested();
364− Q_EMIT lockRequested();
365− }
331+ Q_EMIT LockRequested();
332+ Q_EMIT lockRequested();
366333}
367334
368335void DBusUnitySessionService::Lock()
369336{
370− // Normal lock (with animation, as compared to PromptLock above). Usually
371− // used by indicator-session to lock the session in place.
372− //
373− // FIXME: We also -- as a bit of a hack around indicator-session not fully
374− // supporting a phone profile -- switch to greeter here. The unity7 flow is
375− // that the user chooses "Lock/Switch" from the indicator, and then can go
376− // to greeter by selecting "Switch" again from the indicator, which is now
377− // exposed by the desktop_lockscreen profile. But since in unity8, we try
378− // to expose most things all the time, we don't use the separate lockscreen
379− // profile. Instead, we just go directly to the greeter the first time
380− // a user presses "Lock/Switch". This isn't what this DBus call is
381− // supposed to do, but we can live with it for now.
382− //
383− // Here's a bug about indicator-session growing a converged Touch profile:
384− // https://launchpad.net/bugs/1557716
385− //
386− // We only do this here in the animated-lock call because that's the only
387− // time the indicator locks without also asking the display manager to
388− // switch sessions on us. And since we are switching screens, we also
389− // don't bother respecting the animate request, simply doing a PromptLock.
337+ // signal u8 to show the lockscreen/greeter
390338 PromptLock();
391− switchToGreeter();
392−}
393339
394−void DBusUnitySessionService::switchToGreeter()
395−{
396340 // lock the session using the org.freedesktop.DisplayManager system DBUS service
397341 const QString sessionPath = QString::fromLocal8Bit(qgetenv("XDG_SESSION_PATH"));
398342 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.DisplayManager"),
@@ -400,7 +344,7 @@ void DBusUnitySessionService::switchToGreeter()
400344 QStringLiteral("org.freedesktop.DisplayManager.Session"),
401345 QStringLiteral("Lock"));
402346
403− QDBusPendingCall pendingCall = QDBusConnection::SM_BUSNAME().asyncCall(msg);
347+ QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(msg);
404348 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this);
405349 connect(watcher, &QDBusPendingCallWatcher::finished,
406350 this, [this](QDBusPendingCallWatcher* watcher) {
@@ -417,12 +361,6 @@ void DBusUnitySessionService::switchToGreeter()
417361 });
418362}
419363
420−void DBusUnitySessionService::doUnlock()
421−{
422− Q_EMIT Unlocked();
423− Q_EMIT unlocked();
424−}
425−
426364bool DBusUnitySessionService::IsLocked() const
427365{
428366 return !d->isSessionActive;
@@ -452,19 +390,16 @@ void DBusUnitySessionService::Shutdown()
452390
453391void DBusUnitySessionService::Suspend()
454392{
455− PromptLock();
456393 d->makeLogin1Call(QStringLiteral("Suspend"), {false});
457394}
458395
459396void DBusUnitySessionService::Hibernate()
460397{
461− PromptLock();
462398 d->makeLogin1Call(QStringLiteral("Hibernate"), {false});
463399}
464400
465401void DBusUnitySessionService::HybridSleep()
466402{
467− PromptLock();
468403 d->makeLogin1Call(QStringLiteral("HybridSleep"), {false});
469404}
470405
@@ -494,56 +429,11 @@ void performAsyncUnityCall(const QString &method)
494429
495430
496431DBusGnomeSessionManagerWrapper::DBusGnomeSessionManagerWrapper()
497− : UnityDBusObject(QStringLiteral("/org/gnome/SessionManager"), QStringLiteral("org.gnome.SessionManager"))
498−{
499−}
500−
501−void DBusGnomeSessionManagerWrapper::Logout(quint32 mode)
502−{
503− auto call = QStringLiteral("RequestLogout");
504−
505− // These modes are documented as bitwise flags, not an enum, even though
506− // they only ever seem to be used as enums.
507−
508− if (mode & 1) // without dialog
509− call = QStringLiteral("Logout");
510− if (mode & 2) // without dialog, ignoring inhibitors (which we don't have)
511− call = QStringLiteral("Logout");
512−
513− performAsyncUnityCall(call);
514−}
515−
516−void DBusGnomeSessionManagerWrapper::Reboot()
517−{
518− // GNOME's Reboot means with dialog (they use Request differently than us).
519− performAsyncUnityCall(QStringLiteral("RequestReboot"));
520−}
521−
522−void DBusGnomeSessionManagerWrapper::RequestReboot()
523−{
524− // GNOME's RequestReboot means no dialog (they use Request differently than us).
525− performAsyncUnityCall(QStringLiteral("Reboot"));
526−}
527−
528−void DBusGnomeSessionManagerWrapper::RequestShutdown()
529−{
530− // GNOME's RequestShutdown means no dialog (they use Request differently than us).
531− performAsyncUnityCall(QStringLiteral("Shutdown"));
532−}
533−
534−void DBusGnomeSessionManagerWrapper::Shutdown()
535−{
536− // GNOME's Shutdown means with dialog (they use Request differently than us).
537− performAsyncUnityCall(QStringLiteral("RequestShutdown"));
538−}
539−
540−
541−DBusGnomeSessionManagerDialogWrapper::DBusGnomeSessionManagerDialogWrapper()
542432 : UnityDBusObject(QStringLiteral("/org/gnome/SessionManager/EndSessionDialog"), QStringLiteral("com.canonical.Unity"))
543433{
544434}
545435
546−void DBusGnomeSessionManagerDialogWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
436+void DBusGnomeSessionManagerWrapper::Open(const unsigned type, const unsigned arg_1, const unsigned max_wait, const QList<QDBusObjectPath> &inhibitors)
547437{
548438 Q_UNUSED(arg_1);
549439 Q_UNUSED(max_wait);
@@ -589,7 +479,7 @@ void DBusGnomeScreensaverWrapper::SetActive(bool lock)
589479
590480void DBusGnomeScreensaverWrapper::Lock()
591481{
592− performAsyncUnityCall(QStringLiteral("PromptLock"));
482+ performAsyncUnityCall(QStringLiteral("Lock"));
593483}
594484
595485quint32 DBusGnomeScreensaverWrapper::GetActiveTime() const
@@ -626,7 +516,7 @@ bool DBusScreensaverWrapper::SetActive(bool lock)
626516
627517void DBusScreensaverWrapper::Lock()
628518{
629− performAsyncUnityCall(QStringLiteral("PromptLock"));
519+ performAsyncUnityCall(QStringLiteral("Lock"));
630520}
631521
632522quint32 DBusScreensaverWrapper::GetActiveTime() const
plugins/Unity/Session/dbusunitysessionservice.h+4−25
@@ -106,7 +106,6 @@ Q_SIGNALS:
106106 * Emitted after the session has been unlocked.
107107 */
108108 Q_SCRIPTABLE void Unlocked();
109− void unlocked();
110109
111110public Q_SLOTS:
112111 /**
@@ -259,42 +258,22 @@ public Q_SLOTS:
259258 * @return whether the session is currently locked
260259 */
261260 Q_SCRIPTABLE bool IsLocked() const;
262−
263−private Q_SLOTS:
264− void doUnlock();
265−
266−private:
267− void switchToGreeter();
268261};
269262
270263class DBusGnomeSessionManagerWrapper : public UnityDBusObject
271264{
272265 Q_OBJECT
273− Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager")
266+ Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager.EndSessionDialog")
274267
275268public:
276269 DBusGnomeSessionManagerWrapper();
277270 ~DBusGnomeSessionManagerWrapper() = default;
278271
279−public Q_SLOTS:
280− Q_SCRIPTABLE void Logout(quint32 mode);
281− Q_SCRIPTABLE void Reboot();
282− Q_SCRIPTABLE void RequestReboot();
283− Q_SCRIPTABLE void RequestShutdown();
284− Q_SCRIPTABLE void Shutdown();
285−};
286−
287−class DBusGnomeSessionManagerDialogWrapper : public UnityDBusObject
288−{
289− Q_OBJECT
290− Q_CLASSINFO("D-Bus Interface", "org.gnome.SessionManager.EndSessionDialog")
291−
292−public:
293− DBusGnomeSessionManagerDialogWrapper();
294− ~DBusGnomeSessionManagerDialogWrapper() = default;
295−
296272public Q_SLOTS:
297273 Q_SCRIPTABLE void Open(const unsigned int type, const unsigned int arg_1, const unsigned int max_wait, const QList<QDBusObjectPath> &inhibitors);
274+
275+private:
276+ void performAsyncCall(const QString &method);
298277};
299278
300279class DBusGnomeScreensaverWrapper: public UnityDBusObject
plugins/Unity/Session/plugin.cpp−1
@@ -26,7 +26,6 @@
2626
2727static QObject *dbusunitysessionservice_provider(QQmlEngine */*engine*/, QJSEngine */*jsEngine*/)
2828{
29− new DBusGnomeSessionManagerDialogWrapper();
3029 new DBusGnomeSessionManagerWrapper();
3130 new DBusGnomeScreensaverWrapper();
3231 new DBusScreensaverWrapper();
plugins/Utils/CMakeLists.txt+4−16
@@ -1,23 +1,15 @@
11include_directories(
22 ${CMAKE_CURRENT_SOURCE_DIR}
33 ${CMAKE_CURRENT_BINARY_DIR}
4−)
5−
6−include_directories(
7− SYSTEM
84 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
95 ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
6+ ${GIO_INCLUDE_DIRS}
107)
118
129set(QMLPLUGIN_SRC
1310 activefocuslogger.cpp
1411 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
15− ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
1612 applicationsfiltermodel.cpp
17− ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/AppDrawerModelInterface.h
18− ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
19− ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
20− appdrawerproxymodel.cpp
2113 constants.cpp
2214 WindowInputMonitor.cpp
2315 inputwatcher.cpp
@@ -32,10 +24,6 @@ set(QMLPLUGIN_SRC
3224 inputeventgenerator.cpp
3325 deviceconfigparser.cpp
3426 globalfunctions.cpp
35− URLDispatcher.cpp
36− tabfocusfence.cpp
37− expressionfiltermodel.cpp
38− quicklistproxymodel.cpp
3927 plugin.cpp
4028 )
4129
@@ -43,9 +31,7 @@ add_library(Utils-qml SHARED
4331 ${QMLPLUGIN_SRC}
4432 )
4533
46−target_link_libraries(Utils-qml
47− Qt5::Qml Qt5::Quick Qt5::DBus Qt5::Network Qt5::Gui Qt5::Sql Qt5::Concurrent
48− )
34+target_link_libraries(Utils-qml ${GIO_LDFLAGS})
4935
5036# Because this is an internal support library, we want
5137# to expose all symbols in it. Consider changing this
@@ -53,4 +39,6 @@ target_link_libraries(Utils-qml
5339# files directly in targets.
5440set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
5541
42+qt5_use_modules(Utils-qml Qml Quick DBus Network Gui Sql Concurrent)
43+
5644add_unity8_plugin(Utils 0.1 Utils TARGETS Utils-qml)
plugins/Utils/ElapsedTimer.h+1−1
@@ -41,7 +41,7 @@ class ElapsedTimer : public AbstractElapsedTimer {
4141public:
4242 void start() override { m_timer.start(); }
4343 qint64 msecsSinceReference() const override { return m_timer.msecsSinceReference(); }
44− qint64 elapsed() const override { return m_timer.isValid() ? m_timer.elapsed() : 0; }
44+ qint64 elapsed() const override { return m_timer.elapsed(); }
4545private:
4646 QElapsedTimer m_timer;
4747};
plugins/Utils/Timer.cpp+2−5
@@ -37,16 +37,13 @@ void Timer::setInterval(int msecs)
3737void Timer::start()
3838{
3939 m_timer.start();
40+ AbstractTimer::start();
4041}
4142
4243void Timer::stop()
4344{
4445 m_timer.stop();
45−}
46−
47−bool Timer::isRunning() const
48−{
49− return m_timer.isActive();
46+ AbstractTimer::stop();
5047}
5148
5249bool Timer::isSingleShot() const
plugins/Utils/Timer.h+6−5
@@ -30,16 +30,18 @@ class AbstractTimer : public QObject
3030{
3131 Q_OBJECT
3232public:
33− AbstractTimer(QObject *parent) : QObject(parent) {}
33+ AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {}
3434 virtual int interval() const = 0;
3535 virtual void setInterval(int msecs) = 0;
36− virtual void start() = 0;
37− virtual void stop() = 0;
38− virtual bool isRunning() const = 0;
36+ virtual void start() { m_isRunning = true; }
37+ virtual void stop() { m_isRunning = false; }
38+ bool isRunning() const { return m_isRunning; }
3939 virtual bool isSingleShot() const = 0;
4040 virtual void setSingleShot(bool value) = 0;
4141Q_SIGNALS:
4242 void timeout();
43+private:
44+ bool m_isRunning;
4345};
4446
4547/** A QTimer wrapper */
@@ -53,7 +55,6 @@ public:
5355 void setInterval(int msecs) override;
5456 void start() override;
5557 void stop() override;
56− bool isRunning() const override;
5758 bool isSingleShot() const override;
5859 void setSingleShot(bool value) override;
5960private:
plugins/Utils/URLDispatcher.cppdeleted−80
@@ -1,80 +0,0 @@
1−/*
2− * Copyright (C) 2016-2017 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−#include "URLDispatcher.h"
18−
19−#include <QDBusConnection>
20−#include <QDebug>
21−
22−class URLDispatcherInterface : public QObject
23−{
24− Q_OBJECT
25− Q_CLASSINFO("D-Bus Interface", "com.canonical.URLDispatcher")
26−
27−public:
28− explicit URLDispatcherInterface(URLDispatcher *parent);
29−
30− Q_SCRIPTABLE void DispatchURL(const QString &url, const QString &package);
31−};
32−
33−URLDispatcherInterface::URLDispatcherInterface(URLDispatcher *parent)
34− : QObject(parent)
35−{
36−}
37−
38−void URLDispatcherInterface::DispatchURL(const QString &url, const QString &package)
39−{
40− Q_UNUSED(package);
41− Q_EMIT static_cast<URLDispatcher *>(parent())->urlRequested(url);
42−}
43−
44−URLDispatcher::URLDispatcher(QObject *parent)
45− : QObject(parent)
46− , m_dispatcher(nullptr)
47−{
48−}
49−
50−bool URLDispatcher::active() const
51−{
52− return m_dispatcher != nullptr;
53−}
54−
55−void URLDispatcher::setActive(bool value)
56−{
57− if (value == active())
58− return;
59−
60− QDBusConnection connection = QDBusConnection::sessionBus();
61−
62− if (value) {
63− URLDispatcherInterface *dispatcher = new URLDispatcherInterface(this);
64− connection.registerObject(QStringLiteral("/com/canonical/URLDispatcher"),
65− dispatcher,
66− QDBusConnection::ExportScriptableContents);
67− if (!connection.registerService(QStringLiteral("com.canonical.URLDispatcher"))) {
68− qWarning() << "Unable to register DBus service com.canonical.URLDispatcher";
69− }
70− m_dispatcher = dispatcher;
71− } else {
72− connection.unregisterService(QStringLiteral("com.canonical.URLDispatcher"));
73− delete m_dispatcher;
74− m_dispatcher = nullptr;
75− }
76−
77− Q_EMIT activeChanged();
78−}
79−
80−#include "URLDispatcher.moc"
plugins/Utils/URLDispatcher.hdeleted−47
@@ -1,47 +0,0 @@
1−/*
2− * Copyright (C) 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−#ifndef UNITY_URLDISPATCHER_H
18−#define UNITY_URLDISPATCHER_H
19−
20−#include <QObject>
21−#include <QString>
22−
23−// This class manages our url-dispatcher interception. We intercept
24−// url-dispatcher because rather than spawning the handler for the URL
25−// in our own session, we want to notify the user session to do it for us
26−// (and start an unlock in the process).
27−
28−class URLDispatcher : public QObject
29−{
30− Q_OBJECT
31− Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
32−
33−public:
34− explicit URLDispatcher(QObject *parent=0);
35−
36− bool active() const;
37− void setActive(bool active);
38−
39−Q_SIGNALS:
40− void urlRequested(const QString &url);
41− void activeChanged();
42−
43−private:
44− QObject *m_dispatcher;
45−};
46−
47−#endif
plugins/Utils/Utils.qmltypesnew file+175
@@ -0,0 +1,175 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Utils 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "EasingCurve"
12+ prototype: "QObject"
13+ exports: ["Utils/EasingCurve 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "type"; type: "QEasingCurve::Type" }
16+ Property { name: "period"; type: "double" }
17+ Property { name: "progress"; type: "double" }
18+ Property { name: "value"; type: "double"; isReadonly: true }
19+ }
20+ Component {
21+ name: "QAbstractProxyModel"
22+ prototype: "QAbstractItemModel"
23+ Property { name: "sourceModel"; type: "QAbstractItemModel"; isPointer: true }
24+ }
25+ Component { name: "QIdentityProxyModel"; prototype: "QAbstractProxyModel" }
26+ Component {
27+ name: "QLimitProxyModelQML"
28+ prototype: "QIdentityProxyModel"
29+ exports: ["Utils/LimitProxyModel 0.1"]
30+ exportMetaObjectRevisions: [0]
31+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
32+ Property { name: "limit"; type: "int" }
33+ Property { name: "count"; type: "int"; isReadonly: true }
34+ Signal { name: "totalCountChanged" }
35+ }
36+ Component {
37+ name: "QSortFilterProxyModel"
38+ prototype: "QAbstractProxyModel"
39+ Property { name: "filterRegExp"; type: "QRegExp" }
40+ Property { name: "filterKeyColumn"; type: "int" }
41+ Property { name: "dynamicSortFilter"; type: "bool" }
42+ Property { name: "filterCaseSensitivity"; type: "Qt::CaseSensitivity" }
43+ Property { name: "sortCaseSensitivity"; type: "Qt::CaseSensitivity" }
44+ Property { name: "isSortLocaleAware"; type: "bool" }
45+ Property { name: "sortRole"; type: "int" }
46+ Property { name: "filterRole"; type: "int" }
47+ Method {
48+ name: "setFilterRegExp"
49+ Parameter { name: "pattern"; type: "string" }
50+ }
51+ Method {
52+ name: "setFilterWildcard"
53+ Parameter { name: "pattern"; type: "string" }
54+ }
55+ Method {
56+ name: "setFilterFixedString"
57+ Parameter { name: "pattern"; type: "string" }
58+ }
59+ Method { name: "clear" }
60+ Method { name: "invalidate" }
61+ }
62+ Component {
63+ name: "RelativeTimeFormatter"
64+ prototype: "TimeFormatter"
65+ exports: ["Utils/RelativeTimeFormatter 0.1"]
66+ exportMetaObjectRevisions: [0]
67+ }
68+ Component {
69+ name: "TimeFormatter"
70+ prototype: "QObject"
71+ exports: ["Utils/GDateTimeFormatter 0.1", "Utils/TimeFormatter 0.1"]
72+ exportMetaObjectRevisions: [0, 0]
73+ Property { name: "format"; type: "string" }
74+ Property { name: "timeString"; type: "string"; isReadonly: true }
75+ Property { name: "time"; type: "qlonglong" }
76+ Signal {
77+ name: "formatChanged"
78+ Parameter { name: "format"; type: "string" }
79+ }
80+ Signal {
81+ name: "timeStringChanged"
82+ Parameter { name: "timeString"; type: "string" }
83+ }
84+ Signal {
85+ name: "timeChanged"
86+ Parameter { name: "time"; type: "qlonglong" }
87+ }
88+ }
89+ Component {
90+ name: "UnityMenuModelPaths"
91+ prototype: "QObject"
92+ exports: ["Utils/UnityMenuModelPaths 0.1"]
93+ exportMetaObjectRevisions: [0]
94+ Property { name: "source"; type: "QVariant" }
95+ Property { name: "busName"; type: "QByteArray"; isReadonly: true }
96+ Property { name: "actions"; type: "QVariantMap"; isReadonly: true }
97+ Property { name: "menuObjectPath"; type: "QByteArray"; isReadonly: true }
98+ Property { name: "busNameHint"; type: "QByteArray" }
99+ Property { name: "actionsHint"; type: "QByteArray" }
100+ Property { name: "menuObjectPathHint"; type: "QByteArray" }
101+ }
102+ Component {
103+ name: "UnitySortFilterProxyModelQML"
104+ prototype: "QSortFilterProxyModel"
105+ exports: ["Utils/UnitySortFilterProxyModel 0.1"]
106+ exportMetaObjectRevisions: [0]
107+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
108+ Property { name: "totalCount"; type: "int"; isReadonly: true }
109+ Property { name: "count"; type: "int"; isReadonly: true }
110+ Property { name: "invertMatch"; type: "bool" }
111+ Signal {
112+ name: "invertMatchChanged"
113+ Parameter { type: "bool" }
114+ }
115+ Method {
116+ name: "get"
117+ type: "QVariantMap"
118+ Parameter { name: "row"; type: "int" }
119+ }
120+ Method {
121+ name: "data"
122+ type: "QVariant"
123+ Parameter { name: "row"; type: "int" }
124+ Parameter { name: "role"; type: "int" }
125+ }
126+ Method { name: "count"; type: "int" }
127+ Method {
128+ name: "findFirst"
129+ type: "int"
130+ Parameter { name: "role"; type: "int" }
131+ Parameter { name: "value"; type: "QVariant" }
132+ }
133+ Method {
134+ name: "mapRowToSource"
135+ type: "int"
136+ Parameter { name: "row"; type: "int" }
137+ }
138+ Method {
139+ name: "mapFromSource"
140+ type: "int"
141+ Parameter { name: "row"; type: "int" }
142+ }
143+ Method {
144+ name: "mapToSource"
145+ type: "int"
146+ Parameter { name: "row"; type: "int" }
147+ }
148+ }
149+ Component {
150+ name: "WindowInputFilter"
151+ defaultProperty: "data"
152+ prototype: "QQuickItem"
153+ exports: ["Utils/WindowInputFilter 0.1"]
154+ exportMetaObjectRevisions: [0]
155+ }
156+ Component {
157+ name: "WindowStateStorage"
158+ prototype: "QObject"
159+ exports: ["Utils/WindowStateStorage 0.1"]
160+ isCreatable: false
161+ isSingleton: true
162+ exportMetaObjectRevisions: [0]
163+ Method {
164+ name: "saveGeometry"
165+ Parameter { name: "windowId"; type: "string" }
166+ Parameter { name: "rect"; type: "QRect" }
167+ }
168+ Method {
169+ name: "getGeometry"
170+ type: "QRect"
171+ Parameter { name: "windowId"; type: "string" }
172+ Parameter { name: "defaultValue"; type: "QRect" }
173+ }
174+ }
175+}
plugins/Utils/WindowInputMonitor.cpp−3
@@ -73,9 +73,6 @@ void WindowInputMonitor::update(QEvent *event)
7373 && m_windowLastTouchedTimer->elapsed() >= msecsWithoutTouches) {
7474 m_pressedHomeKey = keyEvent->key();
7575 m_activationTimer->start();
76− } else if (m_pressedHomeKey != 0 && !m_homeKeys.contains(keyEvent->key())) {
77− // something else came in... cancel activation
78− m_activationTimer->stop();
7976 }
8077
8178 } else if (event->type() == QEvent::KeyRelease) {
plugins/Utils/appdrawerproxymodel.cppdeleted−189
@@ -1,189 +0,0 @@
1−/*
2− * Copyright (C) 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−#include "appdrawerproxymodel.h"
18−
19−#include <unity/shell/launcher/LauncherItemInterface.h>
20−
21−#include <QDebug>
22−
23−AppDrawerProxyModel::AppDrawerProxyModel(QObject *parent):
24− QSortFilterProxyModel(parent)
25−{
26− setSortRole(AppDrawerModelInterface::RoleName);
27− setSortLocaleAware(true);
28− sort(0);
29−
30− connect(this, &QAbstractListModel::rowsInserted, this, &AppDrawerProxyModel::countChanged);
31− connect(this, &QAbstractListModel::rowsRemoved, this, &AppDrawerProxyModel::countChanged);
32− connect(this, &QAbstractListModel::layoutChanged, this, &AppDrawerProxyModel::countChanged);
33−}
34−
35−QAbstractItemModel *AppDrawerProxyModel::source() const
36−{
37− return m_source;
38−}
39−
40−void AppDrawerProxyModel::setSource(QAbstractItemModel *source)
41−{
42− if (m_source != source) {
43− m_source = source;
44− setSourceModel(m_source);
45− setSortRole(m_sortBy == SortByAToZ ? AppDrawerModelInterface::RoleName : AppDrawerModelInterface::RoleUsage);
46− connect(m_source, &QAbstractItemModel::rowsRemoved, this, &AppDrawerProxyModel::invalidate);
47− connect(m_source, &QAbstractItemModel::rowsInserted, this, &AppDrawerProxyModel::invalidate);
48− Q_EMIT sourceChanged();
49− }
50−}
51−
52−AppDrawerProxyModel::GroupBy AppDrawerProxyModel::group() const
53−{
54− return m_group;
55−}
56−
57−void AppDrawerProxyModel::setGroup(AppDrawerProxyModel::GroupBy group)
58−{
59− if (m_group != group) {
60− m_group = group;
61− Q_EMIT groupChanged();
62− invalidateFilter();
63− }
64−}
65−
66−QString AppDrawerProxyModel::filterLetter() const
67−{
68− return m_filterLetter;
69−}
70−
71−void AppDrawerProxyModel::setFilterLetter(const QString &filterLetter)
72−{
73− if (m_filterLetter != filterLetter) {
74− m_filterLetter = filterLetter;
75− Q_EMIT filterLetterChanged();
76− invalidateFilter();
77− }
78−}
79−
80−QString AppDrawerProxyModel::filterString() const
81−{
82− return m_filterString;
83−}
84−
85−void AppDrawerProxyModel::setFilterString(const QString &filterString)
86−{
87− if (m_filterString != filterString) {
88− m_filterString = filterString;
89− Q_EMIT filterStringChanged();
90− invalidateFilter();
91− }
92−}
93−
94−AppDrawerProxyModel::SortBy AppDrawerProxyModel::sortBy() const
95−{
96− return m_sortBy;
97−}
98−
99−void AppDrawerProxyModel::setSortBy(AppDrawerProxyModel::SortBy sortBy)
100−{
101− if (m_sortBy != sortBy) {
102− m_sortBy = sortBy;
103− Q_EMIT sortByChanged();
104− setSortRole(m_sortBy == SortByAToZ ? AppDrawerModelInterface::RoleName : AppDrawerModelInterface::RoleUsage);
105− sort(0);
106− }
107−}
108−
109−int AppDrawerProxyModel::count() const
110−{
111− return rowCount();
112−}
113−
114−QVariant AppDrawerProxyModel::data(const QModelIndex &index, int role) const
115−{
116− QModelIndex idx = mapToSource(index);
117− if (role == Qt::UserRole) {
118− QString name = m_source->data(idx, AppDrawerModelInterface::RoleName).toString();
119− return name.length() > 0 ? QString(name.at(0)).toUpper() : QChar();
120− }
121− return m_source->data(idx, role);
122−}
123−
124−QHash<int, QByteArray> AppDrawerProxyModel::roleNames() const
125−{
126− if (m_source) {
127− QHash<int, QByteArray> roles = m_source->roleNames();
128− roles.insert(Qt::UserRole, "letter");
129− return roles;
130− }
131− return QHash<int, QByteArray>();
132−}
133−
134−bool AppDrawerProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
135−{
136− Q_UNUSED(source_parent)
137−
138− if (m_group == GroupByAToZ && source_row > 0) {
139− QString currentName = m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString();
140− QChar currentLetter = currentName.length() > 0 ? currentName.at(0) : QChar();
141− QString previousName = m_source->data(m_source->index(source_row - 1,0 ), AppDrawerModelInterface::RoleName).toString();
142− QChar previousLetter = previousName.length() > 0 ? previousName.at(0) : QChar();
143− if (currentLetter.toLower() == previousLetter.toLower()) {
144− return false;
145− }
146− } else if(m_group == GroupByAll && source_row > 0) {
147− return false;
148− }
149− if (!m_filterLetter.isEmpty()) {
150− QString currentName = m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString();
151− QString currentLetter = currentName.length() > 0 ? QString(currentName.at(0)) : QString();
152− if (currentLetter.toLower() != m_filterLetter.toLower()) {
153− return false;
154− }
155− }
156− if (!m_filterString.isEmpty()) {
157− QStringList allWords = m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleKeywords).toStringList();
158− allWords.prepend(m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString());
159− bool found = false;
160− Q_FOREACH (const QString ¤tWord, allWords) {
161− if (currentWord.contains(m_filterString, Qt::CaseInsensitive)) {
162− found = true;
163− break;
164− }
165− }
166− if (!found) {
167− return false;
168− }
169− }
170− return true;
171−}
172−
173−QString AppDrawerProxyModel::appId(int index) const
174−{
175− if (index >= 0 && index < rowCount()) {
176− QModelIndex sourceIndex = mapToSource(this->index(index, 0));
177−
178− AppDrawerModelInterface* adm = dynamic_cast<AppDrawerModelInterface*>(m_source);
179− if (adm) {
180− return adm->data(sourceIndex, AppDrawerModelInterface::RoleAppId).toString();
181− }
182−
183− AppDrawerProxyModel* adpm = qobject_cast<AppDrawerProxyModel*>(m_source);
184− if (adpm) {
185− return adpm->appId(sourceIndex.row());
186− }
187− }
188− return QString();
189−}
plugins/Utils/appdrawerproxymodel.hdeleted−87
@@ -1,87 +0,0 @@
1−/*
2− * Copyright (C) 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−#include <QSortFilterProxyModel>
18−
19−#include <unity/shell/launcher/AppDrawerModelInterface.h>
20−
21−using namespace unity::shell::launcher;
22−
23−class AppDrawerProxyModel: public QSortFilterProxyModel
24−{
25− Q_OBJECT
26− Q_PROPERTY(QAbstractItemModel* source READ source WRITE setSource NOTIFY sourceChanged)
27− Q_PROPERTY(GroupBy group READ group WRITE setGroup NOTIFY groupChanged)
28− Q_PROPERTY(QString filterLetter READ filterLetter WRITE setFilterLetter NOTIFY filterLetterChanged)
29− Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged)
30− Q_PROPERTY(SortBy sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged)
31− Q_PROPERTY(int count READ count NOTIFY countChanged)
32−
33−public:
34− enum GroupBy {
35− GroupByNone,
36− GroupByAll,
37− GroupByAToZ
38− };
39− Q_ENUM(GroupBy)
40− enum SortBy {
41− SortByAToZ,
42− SortByUsage
43− };
44− Q_ENUM(SortBy)
45−
46− AppDrawerProxyModel(QObject* parent = nullptr);
47−
48− QAbstractItemModel* source() const;
49− void setSource(QAbstractItemModel* source);
50−
51− GroupBy group() const;
52− void setGroup(GroupBy group);
53−
54− QString filterLetter() const;
55− void setFilterLetter(const QString &filterLetter);
56−
57− QString filterString() const;
58− void setFilterString(const QString &filterString);
59−
60− SortBy sortBy() const;
61− void setSortBy(SortBy sortBy);
62−
63− int count() const;
64−
65− QVariant data(const QModelIndex &index, int role) const override;
66− QHash<int, QByteArray> roleNames() const override;
67−
68− Q_INVOKABLE QString appId(int index) const;
69−
70−protected:
71− bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
72−
73−Q_SIGNALS:
74− void sourceChanged();
75− void groupChanged();
76− void filterLetterChanged();
77− void filterStringChanged();
78− void sortByChanged();
79− void countChanged();
80−
81−private:
82− QAbstractItemModel* m_source = nullptr;
83− GroupBy m_group = GroupByNone;
84− QString m_filterLetter;
85− QString m_filterString;
86− SortBy m_sortBy = SortByAToZ;
87−};
plugins/Utils/constants.cpp+1−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2015-2016 Canonical Ltd.
2+ * Copyright 2015 Canonical Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU Lesser General Public License as published by
@@ -16,8 +16,6 @@
1616
1717#include "constants.h"
1818
19−#include <QFile>
20−
2119Constants::Constants(QObject *parent)
2220 : QObject(parent)
2321{
@@ -26,7 +24,4 @@ Constants::Constants(QObject *parent)
2624 } else {
2725 m_indicatorValueTimeout = 5000;
2826 }
29−
30− QString snapRoot = QFile::decodeName(qgetenv("SNAP"));
31− m_defaultWallpaper = snapRoot + "/usr/share/backgrounds/warty-final-ubuntu.png";
3227}
plugins/Utils/constants.h+5−5
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2015-2016 Canonical Ltd.
2+ * Copyright 2015 Canonical Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU Lesser General Public License as published by
@@ -14,7 +14,8 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515*/
1616
17−#pragma once
17+#ifndef CONSTANTS_H
18+#define CONSTANTS_H
1819
1920#include <QObject>
2021
@@ -29,15 +30,14 @@ class Constants: public QObject
2930{
3031 Q_OBJECT
3132 Q_PROPERTY(int indicatorValueTimeout READ indicatorValueTimeout CONSTANT)
32− Q_PROPERTY(QString defaultWallpaper READ defaultWallpaper CONSTANT)
3333
3434public:
3535 Constants(QObject *parent = 0);
3636
3737 int indicatorValueTimeout() const { return m_indicatorValueTimeout; }
38− QString defaultWallpaper() const { return m_defaultWallpaper; }
3938
4039private:
4140 int m_indicatorValueTimeout;
42− QString m_defaultWallpaper;
4341};
42+
43+#endif
plugins/Utils/deviceconfigparser.cpp+1−19
@@ -26,7 +26,7 @@ DeviceConfigParser::DeviceConfigParser(QObject *parent): QObject(parent)
2626 // Local files have highest priority
2727 QString path;
2828 Q_FOREACH (const QString &standardPath, QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation)) {
29− if (QFileInfo::exists(standardPath + "/devices.conf")) {
29+ if (QFileInfo(standardPath + "/devices.conf").exists()) {
3030 path = standardPath + "/devices.conf";
3131 break;
3232 }
@@ -116,24 +116,6 @@ QString DeviceConfigParser::category() const
116116 return value;
117117}
118118
119−bool DeviceConfigParser::supportsMultiColorLed() const
120−{
121− return readBoolFromConfig("SupportsMultiColorLed", true);
122−}
123−
124−bool DeviceConfigParser::readBoolFromConfig(const QString &key, bool defaultValue) const
125−{
126− m_config->beginGroup(m_name);
127−
128− bool ret = defaultValue;
129− if (m_config->contains(key)) {
130− ret = m_config->value(key).toBool();
131− }
132−
133− m_config->endGroup();
134− return ret;
135−}
136−
137119QStringList DeviceConfigParser::readOrientationsFromConfig(const QString &key) const
138120{
139121 m_config->beginGroup(m_name);
plugins/Utils/deviceconfigparser.h−3
@@ -33,7 +33,6 @@ class DeviceConfigParser: public QObject
3333 Q_PROPERTY(Qt::ScreenOrientation portraitOrientation READ portraitOrientation NOTIFY changed)
3434 Q_PROPERTY(Qt::ScreenOrientation invertedPortraitOrientation READ invertedPortraitOrientation NOTIFY changed)
3535 Q_PROPERTY(QString category READ category NOTIFY changed)
36− Q_PROPERTY(bool supportsMultiColorLed READ supportsMultiColorLed NOTIFY changed)
3736
3837public:
3938 DeviceConfigParser(QObject *parent = nullptr);
@@ -48,7 +47,6 @@ public:
4847 Qt::ScreenOrientation portraitOrientation() const;
4948 Qt::ScreenOrientation invertedPortraitOrientation() const;
5049 QString category() const;
51− bool supportsMultiColorLed() const;
5250
5351Q_SIGNALS:
5452 void changed();
@@ -60,7 +58,6 @@ private:
6058 QStringList readOrientationsFromConfig(const QString &key) const;
6159 QString readOrientationFromConfig(const QString &key) const;
6260 Qt::ScreenOrientation stringToOrientation(const QString &orientationString, Qt::ScreenOrientation defaultValue) const;
63− bool readBoolFromConfig(const QString &key, bool defaultValue) const;
6461};
6562
6663#endif
plugins/Utils/easingcurve.h+1
@@ -36,6 +36,7 @@
3636class EasingCurve: public QObject
3737{
3838 Q_OBJECT
39+ Q_ENUMS(QEasingCurve::Type)
3940 Q_PROPERTY(QEasingCurve::Type type READ type WRITE setType NOTIFY typeChanged)
4041 Q_PROPERTY(qreal period READ period WRITE setPeriod NOTIFY periodChanged)
4142 Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
plugins/Utils/expressionfiltermodel.cppdeleted−49
@@ -1,49 +0,0 @@
1−/*
2− * Copyright (C) 2017 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−#include "expressionfiltermodel.h"
18−
19−ExpressionFilterModel::ExpressionFilterModel(QObject *parent)
20− : UnitySortFilterProxyModelQML(parent)
21−{
22−}
23−
24−QJSValue ExpressionFilterModel::matchExpression() const
25−{
26− return m_matchExpression;
27−}
28−
29−void ExpressionFilterModel::setMatchExpression(const QJSValue &value)
30−{
31− m_matchExpression = value;
32− invalidateFilter();
33−}
34−
35−bool
36−ExpressionFilterModel::filterAcceptsRow(int sourceRow,
37− const QModelIndex &sourceParent) const
38−{
39− if (m_matchExpression.isCallable()) {
40− QJSValueList args;
41− args << sourceRow;
42− QJSValue ret = m_matchExpression.call(args);
43− if (ret.isBool()) {
44− return ret.toBool();
45− }
46− }
47−
48− return UnitySortFilterProxyModelQML::filterAcceptsRow(sourceRow, sourceParent);
49−}
plugins/Utils/expressionfiltermodel.hdeleted−42
@@ -1,42 +0,0 @@
1−/*
2− * Copyright (C) 2017 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#ifndef EXPRESSIONFILTERMODEL_H
18−#define EXPRESSIONFILTERMODEL_H
19−
20−#include "unitysortfilterproxymodelqml.h"
21−#include <QJSValue>
22−
23−class ExpressionFilterModel : public UnitySortFilterProxyModelQML
24−{
25− Q_OBJECT
26− Q_PROPERTY(QJSValue matchExpression READ matchExpression WRITE setMatchExpression NOTIFY matchExpressionChanged)
27−public:
28− explicit ExpressionFilterModel(QObject *parent = 0);
29−
30− bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
31−
32− QJSValue matchExpression() const;
33− void setMatchExpression(const QJSValue& value);
34−
35−Q_SIGNALS:
36− void matchExpressionChanged();
37−
38−private:
39− mutable QJSValue m_matchExpression;
40−};
41−
42−#endif // EXPRESSIONFILTERMODEL_H
plugins/Utils/globalfunctions.cpp+4−6
@@ -16,8 +16,11 @@
1616
1717#include "globalfunctions.h"
1818
19−#include <QQmlEngine>
19+#pragma GCC diagnostic push
20+#pragma GCC diagnostic ignored "-pedantic"
2021#include <private/qquickitem_p.h>
22+#pragma GCC diagnostic pop
23+#include <QQmlEngine>
2124
2225GlobalFunctions::GlobalFunctions(QObject *parent)
2326 : QObject(parent)
@@ -51,8 +54,3 @@ QQuickItem *GlobalFunctions::itemAt(QQuickItem* parent, int x, int y, QJSValue m
5154 }
5255 return nullptr;
5356}
54−
55−bool GlobalFunctions::itemUnderMouse(QQuickItem* item)
56−{
57− return item && item->isUnderMouse();
58−}
plugins/Utils/globalfunctions.h−2
@@ -37,8 +37,6 @@ public:
3737 int x,
3838 int y,
3939 QJSValue matcher);
40−
41− static Q_INVOKABLE bool itemUnderMouse(QQuickItem* item);
4240};
4341
4442#endif // GLOBALFUNCTIONS_H
plugins/Utils/plugin.cpp+1−11
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2012-2017 Canonical, Ltd.
2+ * Copyright (C) 2012-2015 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -38,11 +38,6 @@
3838#include "inputeventgenerator.h"
3939#include "deviceconfigparser.h"
4040#include "globalfunctions.h"
41−#include "URLDispatcher.h"
42−#include "appdrawerproxymodel.h"
43−#include "tabfocusfence.h"
44−#include "expressionfiltermodel.h"
45−#include "quicklistproxymodel.h"
4641
4742static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
4843{
@@ -85,9 +80,4 @@ void UtilsPlugin::registerTypes(const char *uri)
8580 qmlRegisterType<InputEventGenerator>(uri, 0, 1, "InputEventGenerator");
8681 qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
8782 qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions);
88− qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher");
89− qmlRegisterType<AppDrawerProxyModel>(uri, 0, 1, "AppDrawerProxyModel");
90− qmlRegisterType<TabFocusFenceItem>(uri, 0, 1, "TabFocusFence");
91− qmlRegisterType<ExpressionFilterModel>(uri, 0, 1, "ExpressionFilterModel");
92− qmlRegisterType<QuickListProxyModel>(uri, 0, 1, "QuickListProxyModel");
9383}
plugins/Utils/quicklistproxymodel.cppdeleted−72
@@ -1,72 +0,0 @@
1−/*
2− * Copyright (C) 2017 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−#include "quicklistproxymodel.h"
18−
19−#include <QDebug>
20−
21−QuickListProxyModel::QuickListProxyModel(QObject *parent):
22− QSortFilterProxyModel(parent)
23−{
24− connect(this, &QAbstractListModel::rowsInserted, this, &QuickListProxyModel::countChanged);
25− connect(this, &QAbstractListModel::rowsRemoved, this, &QuickListProxyModel::countChanged);
26− connect(this, &QAbstractListModel::layoutChanged, this, &QuickListProxyModel::countChanged);
27−}
28−
29−QAbstractItemModel *QuickListProxyModel::source() const
30−{
31− return m_source;
32−}
33−
34−bool QuickListProxyModel::privateMode() const
35−{
36− return m_privateMode;
37−}
38−
39−void QuickListProxyModel::setPrivateMode(bool privateMode)
40−{
41− if (m_privateMode != privateMode) {
42− m_privateMode = privateMode;
43− invalidateFilter();
44− Q_EMIT privateModeChanged();
45− }
46−}
47−
48−void QuickListProxyModel::setSource(QAbstractItemModel *source)
49−{
50− if (m_source != source) {
51− m_source = source;
52− setSourceModel(m_source);
53− connect(m_source, &QAbstractItemModel::rowsRemoved, this, &QuickListProxyModel::invalidate);
54− connect(m_source, &QAbstractItemModel::rowsInserted, this, &QuickListProxyModel::invalidate);
55− Q_EMIT sourceChanged();
56− }
57−}
58−
59−int QuickListProxyModel::count() const
60−{
61− return rowCount();
62−}
63−
64−bool QuickListProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
65−{
66− Q_UNUSED(source_parent)
67−
68− if (m_privateMode) {
69− return !m_source->data(m_source->index(source_row, 0), QuickListModelInterface::RoleIsPrivate).toBool();
70− }
71− return true;
72−}
plugins/Utils/quicklistproxymodel.hdeleted−52
@@ -1,52 +0,0 @@
1−/*
2− * Copyright (C) 2017 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−#include <QSortFilterProxyModel>
18−
19−#include <unity/shell/launcher/QuickListModelInterface.h>
20−
21−using namespace unity::shell::launcher;
22−
23−class QuickListProxyModel: public QSortFilterProxyModel
24−{
25− Q_OBJECT
26− Q_PROPERTY(QAbstractItemModel* source READ source WRITE setSource NOTIFY sourceChanged)
27− Q_PROPERTY(bool privateMode READ privateMode WRITE setPrivateMode NOTIFY privateModeChanged)
28− Q_PROPERTY(int count READ count NOTIFY countChanged)
29−
30−public:
31− QuickListProxyModel(QObject* parent = nullptr);
32−
33− QAbstractItemModel* source() const;
34− void setSource(QAbstractItemModel* source);
35−
36− bool privateMode() const;
37− void setPrivateMode(bool privateMode);
38−
39− int count() const;
40−
41−protected:
42− bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
43−
44−Q_SIGNALS:
45− void sourceChanged();
46− void privateModeChanged();
47− void countChanged();
48−
49−private:
50− QAbstractItemModel* m_source = nullptr;
51− bool m_privateMode = false;
52−};
plugins/Utils/tabfocusfence.cppdeleted−72
@@ -1,72 +0,0 @@
1−/*
2− * Copyright 2017 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15−*/
16−
17−#include "tabfocusfence.h"
18−
19−#include <private/qquickitem_p.h>
20−
21−TabFocusFenceItem::TabFocusFenceItem(QQuickItem *parent) : QQuickItem(parent)
22−{
23− QQuickItemPrivate *d = QQuickItemPrivate::get(this);
24− d->isTabFence = true;
25− setFlag(ItemIsFocusScope);
26−}
27−
28−bool TabFocusFenceItem::focusNext()
29−{
30− QQuickItem * current = scopedFocusItem();
31− if (current) {
32− QQuickItem * next = current->nextItemInFocusChain(true);
33− if (next) {
34− next->setFocus(true, Qt::TabFocusReason);
35− return true;
36− }
37− }
38− return false;
39−}
40−
41−bool TabFocusFenceItem::focusPrev()
42−{
43− QQuickItem * current = scopedFocusItem();
44− if (current) {
45− QQuickItem * prev = current->nextItemInFocusChain(false);
46− if (prev) {
47− prev->setFocus(true, Qt::BacktabFocusReason);
48− return true;
49− }
50− }
51− return false;
52−}
53−
54−void TabFocusFenceItem::keyPressEvent(QKeyEvent *event)
55−{
56− // Needed so we eat Tab keys when there's only one item inside the fence
57− if (event->key() == Qt::Key_Tab) {
58− event->accept();
59− } else {
60− QQuickItem::keyPressEvent(event);
61− }
62−}
63−
64−void TabFocusFenceItem::keyReleaseEvent(QKeyEvent *event)
65−{
66− // Needed so we eat Tab keys when there's only one item inside the fence
67− if (event->key() == Qt::Key_Tab) {
68− event->accept();
69− } else {
70− QQuickItem::keyReleaseEvent(event);
71− }
72−}
plugins/Utils/tabfocusfence.hdeleted−38
@@ -1,38 +0,0 @@
1−/*
2− * Copyright 2017 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15−*/
16−
17−#ifndef TABFOCUSFENCE_H
18−#define TABFOCUSFENCE_H
19−
20−#include <QQuickItem>
21−
22−// An item that restricts focus Tab travelling
23−// to its children
24−class TabFocusFenceItem : public QQuickItem
25−{
26−Q_OBJECT
27−
28−public:
29− TabFocusFenceItem(QQuickItem *parent = nullptr);
30−
31− Q_INVOKABLE bool focusNext();
32− Q_INVOKABLE bool focusPrev();
33−
34− void keyPressEvent(QKeyEvent *event) override;
35− void keyReleaseEvent(QKeyEvent *event) override;
36−};
37−
38−#endif
plugins/Utils/timezoneFormatter.cpp+1−1
@@ -39,7 +39,7 @@ QString TimezoneFormatter::currentTimeInTimezoneWithAbbrev(const QVariant &tzId)
3939 QTimeZone tz(tzId.toByteArray());
4040 if (tz.isValid()) {
4141 const QDateTime now = QDateTime::currentDateTime().toTimeZone(tz);
42− return QStringLiteral("%1 %2").arg(now.time().toString(QStringLiteral("h:mm")), tz.abbreviation(now));
42+ return QStringLiteral("%1 %2").arg(now.time().toString(QStringLiteral("h:mm"))).arg(tz.abbreviation(now));
4343 }
4444 return QString();
4545}
plugins/Utils/unitysortfilterproxymodelqml.h−5
@@ -38,11 +38,6 @@ public:
3838 Q_INVOKABLE int mapRowToSource(int row);
3939 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
4040
41− // Make the QSortFilterProxyModel variants also accessible
42− using QSortFilterProxyModel::data;
43− using QSortFilterProxyModel::mapFromSource;
44− using QSortFilterProxyModel::mapToSource;
45−
4641 /* getters */
4742 int totalCount() const;
4843 bool invertMatch() const;
plugins/Utils/windowstatestorage.cpp+121−316
This diff is too big to show here.
plugins/Utils/windowstatestorage.h+20−27
This diff is too big to show here.
plugins/WindowManager/AvailableDesktopArea.cppdeleted−50
This diff is too big to show here.
plugins/WindowManager/CMakeLists.txt+2−15
This diff is too big to show here.
plugins/WindowManager/InputMethodManager.cppdeleted−56
This diff is too big to show here.
plugins/WindowManager/InputMethodManager.hdeleted−55
This diff is too big to show here.
plugins/WindowManager/TopLevelSurfaceList.cppnew file+486
This diff is too big to show here.
plugins/WindowManager/TopLevelSurfaceList.hnew file+223
This diff is too big to show here.
plugins/WindowManager/TopLevelWindowModel.cppdeleted−782
This diff is too big to show here.
plugins/WindowManager/TopLevelWindowModel.hdeleted−308
This diff is too big to show here.
plugins/WindowManager/Window.cppdeleted−277
This diff is too big to show here.
plugins/WindowManager/Window.hdeleted−176
This diff is too big to show here.
plugins/WindowManager/WindowManagerGlobal.hdeleted−23
This diff is too big to show here.
plugins/WindowManager/WindowManagerPlugin.cpp+3−19
This diff is too big to show here.
plugins/WindowManager/WindowMargins.cppdeleted−74
This diff is too big to show here.
plugins/WindowManager/WindowMargins.hdeleted−59
This diff is too big to show here.
plugins/Wizard/CMakeLists.txt+3−9
This diff is too big to show here.
plugins/Wizard/Changelog.cppdeleted−58
This diff is too big to show here.
plugins/Wizard/Changelog.hdeleted−52
This diff is too big to show here.
plugins/Wizard/PageList.cpp+1−16
This diff is too big to show here.
plugins/Wizard/System.cpp+8−79
This diff is too big to show here.
plugins/Wizard/System.h+1−22
This diff is too big to show here.
plugins/Wizard/Utils/CMakeLists.txt+1−1
This diff is too big to show here.
plugins/Wizard/Wizard.qmltypesnew file+33
This diff is too big to show here.
plugins/Wizard/keyboardLayoutsModel.cppdeleted−163
This diff is too big to show here.
plugins/Wizard/keyboardLayoutsModel.hdeleted−66
This diff is too big to show here.
plugins/Wizard/plugin.cpp−4
This diff is too big to show here.
plugins/Wizard/qmldir+1
This diff is too big to show here.
plugins/Wizard/test.shnew file+18
This diff is too big to show here.
plugins/Wizard/timezonemodel.cpp+5−5
This diff is too big to show here.
po/aa.po+311−424
This diff is too big to show here.
po/am.po+398−743
This diff is too big to show here.
po/ar.po+468−700
This diff is too big to show here.
po/ast.po+453−789
This diff is too big to show here.
po/az.po+323−456
This diff is too big to show here.
po/be.po+462−655
This diff is too big to show here.
po/bg.po+311−400
This diff is too big to show here.
po/bn.po+442−624
This diff is too big to show here.
po/br.po+395−669
This diff is too big to show here.
po/bs.po+361−547
This diff is too big to show here.
po/ca.po+436−817
This diff is too big to show here.
po/ca@valencia.po+359−517
This diff is too big to show here.
po/ce.po+289−369
This diff is too big to show here.
po/ckb.po+307−393
This diff is too big to show here.
po/co.po+371−696
This diff is too big to show here.
po/cs.po+462−744
This diff is too big to show here.
po/cy.po+354−541
This diff is too big to show here.
po/da.po+394−578
This diff is too big to show here.
po/de.po+429−784
This diff is too big to show here.
po/el.po+428−677
This diff is too big to show here.
po/en_AU.po+405−779
This diff is too big to show here.
po/en_GB.po+398−730
This diff is too big to show here.
po/en_US.podeleted−814
This diff is too big to show here.
po/eo.po+321−439
This diff is too big to show here.
po/es.po+421−775
This diff is too big to show here.
po/et.podeleted−816
This diff is too big to show here.
po/eu.po+364−547
This diff is too big to show here.
po/fa.po+405−783
This diff is too big to show here.
po/fi.po+409−762
This diff is too big to show here.
po/fo.po+353−503
This diff is too big to show here.
po/fr.po+450−807
This diff is too big to show here.
po/ga.po+356−537
This diff is too big to show here.
po/gd.po+417−754
This diff is too big to show here.
po/gl.po+415−771
This diff is too big to show here.
po/gu.podeleted−814
This diff is too big to show here.
po/gv.po+323−429
This diff is too big to show here.
po/he.po+444−599
This diff is too big to show here.
po/hi.po+302−386
This diff is too big to show here.
po/hr.po+423−727
This diff is too big to show here.
po/hu.po+427−777
This diff is too big to show here.
po/hy.po+373−503
This diff is too big to show here.
po/ia.po+400−736
This diff is too big to show here.
po/id.po+341−500
This diff is too big to show here.
po/is.po+338−481
This diff is too big to show here.
po/it.po+415−770
This diff is too big to show here.
po/ja.po+362−522
This diff is too big to show here.
po/kk.podeleted−841
This diff is too big to show here.
po/km.po+361−525
This diff is too big to show here.
po/kn.po+299−377
This diff is too big to show here.
po/ko.po+435−637
This diff is too big to show here.
po/ku.po+324−461
This diff is too big to show here.
po/ky.po+299−377
This diff is too big to show here.
po/lo.po+297−377
This diff is too big to show here.
po/lt.po+391−637
This diff is too big to show here.
po/lv.po+368−552
This diff is too big to show here.
po/ml.po+309−394
This diff is too big to show here.
po/mr.po+299−397
This diff is too big to show here.
po/ms.po+409−702
This diff is too big to show here.
po/my.po+318−441
This diff is too big to show here.
po/nb.po+406−757
This diff is too big to show here.
po/ne.po+294−377
This diff is too big to show here.
po/nl.po+458−819
This diff is too big to show here.
po/nn.po+289−369
This diff is too big to show here.
po/oc.po+425−716
This diff is too big to show here.
po/or.po+289−369
This diff is too big to show here.
po/pa.po+360−540
This diff is too big to show here.
po/pl.po+426−780
This diff is too big to show here.
po/pt.po+415−769
This diff is too big to show here.
po/pt_BR.po+436−634
This diff is too big to show here.
po/ro.po+372−550
This diff is too big to show here.
po/ru.po+415−768
This diff is too big to show here.
po/sc.podeleted−904
This diff is too big to show here.
po/shn.po+290−370
This diff is too big to show here.
po/si.po+313−400
This diff is too big to show here.
po/sk.po+413−767
This diff is too big to show here.
po/sl.po+405−724
This diff is too big to show here.
po/sq.po+349−513
This diff is too big to show here.
po/sr.po+406−739
This diff is too big to show here.
po/sv.po+405−757
This diff is too big to show here.
po/sw.po+345−513
This diff is too big to show here.
po/ta.po+308−393
This diff is too big to show here.
po/te.po+308−402
This diff is too big to show here.
po/th.po+308−389
This diff is too big to show here.
po/tr.po+441−815
This diff is too big to show here.
po/ug.po+379−602
This diff is too big to show here.
po/uk.po+412−749
This diff is too big to show here.
po/unity8.pot+287−366
This diff is too big to show here.
po/update-unity-pot−17
This diff is too big to show here.
po/ur.po+310−393
This diff is too big to show here.
po/uz.po+289−369
This diff is too big to show here.
po/vi.po+289−369
This diff is too big to show here.
po/wo.po+363−546
This diff is too big to show here.
po/xh.po+289−369
This diff is too big to show here.
po/zh_CN.po+400−751
This diff is too big to show here.
po/zh_HK.po+313−415
This diff is too big to show here.
po/zh_TW.po+428−712
This diff is too big to show here.
qml/ApplicationMenus/ApplicationMenuItemFactory.qmldeleted−135
This diff is too big to show here.
qml/ApplicationMenus/MenuBar.qmldeleted−513
This diff is too big to show here.
qml/ApplicationMenus/MenuItem.qmldeleted−146
This diff is too big to show here.
qml/ApplicationMenus/MenuNavigator.qmldeleted−101
This diff is too big to show here.
qml/ApplicationMenus/MenuPopup.qmldeleted−510
This diff is too big to show here.
qml/ApplicationMenus/RegisteredApplicationMenuModel.qmldeleted−56
This diff is too big to show here.
qml/ApplicationMenus/qmldirdeleted−1
This diff is too big to show here.
qml/CMakeLists.txt+2−2
This diff is too big to show here.
qml/Components/Background.qml+1−1
This diff is too big to show here.
qml/Stage/ResizeGrip.qml → qml/Components/BaseCarouselDelegate.qmlrenamed+23−27
This diff is too big to show here.
qml/Components/BlurLayer.qml+40−10
This diff is too big to show here.
qml/Components/BrightnessControl.qmldeleted−54
This diff is too big to show here.
qml/Components/Carousel.qmlnew file+336
This diff is too big to show here.
tests/mocks/Biometryd/MockObserver.cpp → qml/Components/Circle.qmlrenamed+6−6
This diff is too big to show here.
qml/Greeter/DelayedLockscreen.qml → qml/Components/DelayedLockscreen.qmlrenamed+14−6
This diff is too big to show here.
qml/Components/Dialogs.qml+30−101
This diff is too big to show here.
qml/Components/DragHandle.qml−1
This diff is too big to show here.
qml/Components/EdgeBarrier.qml−3
This diff is too big to show here.
qml/Components/EdgeBarrierController.qml−1
This diff is too big to show here.
qml/Components/FadingLabel.qmldeleted−42
This diff is too big to show here.
qml/Components/Flickable.qmldeleted−24
This diff is too big to show here.
qml/Components/FloatingFlickable.qml−4
This diff is too big to show here.
qml/Components/InputMethod.qml+47−13
This diff is too big to show here.
qml/Components/ItemGrabber.qml+1−1
This diff is too big to show here.
qml/Components/KeyboardShortcutsOverlay.qmldeleted−336
This diff is too big to show here.
qml/Components/KeymapSwitcher.qml+3−40
This diff is too big to show here.
qml/Components/LazyImage.qml+1−5
This diff is too big to show here.
qml/Components/ListItems/Header.qmlnew file+64
This diff is too big to show here.
tests/mocks/Unity/Platform/MockPlatform.qml → qml/Components/ListItems/ThinDivider.qmlrenamed+9−7
This diff is too big to show here.
qml/Components/ListItems/graphics/ListItemDividerHorizontal@18.pngnew file
Binary file not shown.
qml/Components/ListView.qmldeleted−24
This diff is too big to show here.
qml/Components/Lockscreen.qml+21−6
This diff is too big to show here.
qml/Components/MediaServices/MediaServices.qmldeleted−386
This diff is too big to show here.
qml/Components/MediaServices/MediaServicesControls.qmldeleted−192
This diff is too big to show here.
qml/Components/MediaServices/MediaServicesHeader.qmldeleted−71
This diff is too big to show here.
qml/Components/MediaServices/VideoPlayer.qmldeleted−155
This diff is too big to show here.
qml/Components/MediaServices/VideoPlayerControls.qmldeleted−158
This diff is too big to show here.
qml/Components/ModeSwitchWarningDialog.qml+2−8
This diff is too big to show here.
qml/Components/NotificationAudio.qml+3−20
This diff is too big to show here.
qml/Components/PanelState/PanelState.qml+3−6
This diff is too big to show here.
qml/Components/PhysicalKeysMapper.qml+26−6
This diff is too big to show here.
qml/Components/ResponsiveGridView.qmlnew file+97
This diff is too big to show here.
qml/Components/ResponsiveVerticalJournal.qmlnew file+81
This diff is too big to show here.
qml/Components/ScrollCalculator.qml+2−21
This diff is too big to show here.
qml/Components/ShellDialog.qml+12−27
This diff is too big to show here.
qml/Components/Showable.qml+12−15
This diff is too big to show here.
qml/Components/UbuntuShapeForItem.qmlnew file+47
This diff is too big to show here.
qml/Components/VirtualTouchPad.qml+1−269
This diff is too big to show here.
qml/Components/VolumeControl.qml+3−3
This diff is too big to show here.
qml/Components/Wallpaper.qmldeleted−96
This diff is too big to show here.
qml/Components/WallpaperResolver.qml+37−34
This diff is too big to show here.
qml/Components/WindowControlButtons.qml+27−27
This diff is too big to show here.
qml/Components/ZoomableImage.qml+1−1
This diff is too big to show here.
qml/Components/flickableUtils.jsdeleted−28
This diff is too big to show here.
qml/Components/graphics/close@20.png
Binary file not shown.
qml/Components/graphics/icon_star_empty@20.png
Binary file not shown.
qml/Components/graphics/icon_star_full@20.png
Binary file not shown.
qml/Components/graphics/icon_star_half@20.png
Binary file not shown.
qml/Components/graphics/icon_star_off@20.png
Binary file not shown.
qml/Components/graphics/icon_star_on@20.png
Binary file not shown.
qml/Components/graphics/non-selected@18.png
Binary file not shown.
qml/Components/graphics/window-close.svg+14−164
This diff is too big to show here.
qml/Components/graphics/window-maximize.svg+12−164
This diff is too big to show here.
qml/Components/graphics/window-minimize.svg+13−164
This diff is too big to show here.
qml/Components/graphics/window-window.svgdeleted−41
This diff is too big to show here.
qml/Dash/CardCarousel.qmlnew file+73
This diff is too big to show here.
qml/Dash/CardGrid.qmlnew file+84
This diff is too big to show here.
qml/Dash/CardHorizontalList.qmlnew file+66
This diff is too big to show here.
qml/Dash/CardTool.qmlnew file+241
This diff is too big to show here.
qml/Dash/CardVerticalJournal.qmlnew file+85
This diff is too big to show here.
qml/Dash/Dash.qmlnew file+381
This diff is too big to show here.
qml/Components/GridView.qml → qml/Dash/DashApplication.qmlrenamed+11−7
This diff is too big to show here.
qml/Greeter/FullLightDMImpl.qml → qml/Dash/DashBackground.qmlrenamed+12−13
This diff is too big to show here.
qml/Dash/DashCategoryBase.qmlnew file+54
This diff is too big to show here.
qml/Dash/DashContent.qmlnew file+213
This diff is too big to show here.
tests/mocks/Biometryd/MockDevice.cpp → qml/Dash/DashContentTabBarStyle.qmlrenamed+9−14
This diff is too big to show here.
qml/Dash/DashNavigation.qmlnew file+198
This diff is too big to show here.
qml/Dash/DashNavigationHeader.qmlnew file+73
This diff is too big to show here.
qml/Dash/DashNavigationList.qmlnew file+115
This diff is too big to show here.
qml/Dash/DashPageHeader.qmlnew file+452
This diff is too big to show here.
qml/Dash/DashRenderer.qmlnew file+66
This diff is too big to show here.
qml/Dash/Filters/FilterExpandableWidget.qmlnew file+96
This diff is too big to show here.
qml/Dash/Filters/FilterOptionSelector.qmlnew file+95
This diff is too big to show here.
qml/Dash/Filters/FilterRangeInput.qmlnew file+136
This diff is too big to show here.
qml/Dash/Filters/FilterValueSlider.qmlnew file+87
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/Update/MockSystemImage.qml → qml/Dash/Filters/FilterWidget.qmlrenamed+12−10
This diff is too big to show here.
qml/Dash/Filters/FilterWidgetFactory.qmlnew file+89
This diff is too big to show here.
qml/Dash/FiltersPopover.qmlnew file+105
This diff is too big to show here.
qml/Dash/GenericScopeView.qmlnew file+854
This diff is too big to show here.
qml/Dash/PageHeaderExtraPanel.qmlnew file+200
This diff is too big to show here.
qml/Dash/PreviewView.qmlnew file+76
This diff is too big to show here.
qml/Dash/Previews/Preview.qmlnew file+116
This diff is too big to show here.
qml/ApplicationMenus/ApplicationMenusLimits.qml → qml/Dash/Previews/PreviewActionButton.qmlrenamed+9−6
This diff is too big to show here.
qml/Dash/Previews/PreviewActionCombo.qmlnew file+68
This diff is too big to show here.
qml/Dash/Previews/PreviewActions.qmlnew file+72
This diff is too big to show here.
qml/Dash/Previews/PreviewAudioPlayback.qmlnew file+150
This diff is too big to show here.
qml/Dash/Previews/PreviewComment.qmlnew file+83
This diff is too big to show here.
qml/Dash/Previews/PreviewCommentInput.qmlnew file+73
This diff is too big to show here.
qml/Dash/Previews/PreviewExpandable.qmlnew file+104
This diff is too big to show here.
qml/Dash/Previews/PreviewHeader.qmlnew file+168
This diff is too big to show here.
qml/Dash/Previews/PreviewIconActions.qmlnew file+87
This diff is too big to show here.
qml/Dash/Previews/PreviewImageGallery.qmlnew file+147
This diff is too big to show here.
qml/Greeter/LoginAreaContainer.qml → qml/Dash/Previews/PreviewMediaToolbar.qmlrenamed+14−15
This diff is too big to show here.
qml/Dash/Previews/PreviewOverlay.qmlnew file+166
This diff is too big to show here.
qml/Dash/Previews/PreviewPayments.qmlnew file+81
This diff is too big to show here.
qml/Dash/Previews/PreviewProgress.qmlnew file+71
This diff is too big to show here.
qml/Dash/Previews/PreviewRatingDisplay.qmlnew file+117
This diff is too big to show here.
qml/Dash/Previews/PreviewRatingEdit.qmlnew file+80
This diff is too big to show here.
qml/Dash/Previews/PreviewRatingInput.qmlnew file+180
This diff is too big to show here.
qml/Dash/Previews/PreviewRatingSingleDisplay.qmlnew file+70
This diff is too big to show here.
qml/Components/SharingPicker.qml → qml/Dash/Previews/PreviewSharing.qmlrenamed+14−2
This diff is too big to show here.
qml/Dash/Previews/PreviewTable.qmlnew file+85
This diff is too big to show here.
qml/Dash/Previews/PreviewTextSummary.qmlnew file+73
This diff is too big to show here.
qml/Dash/Previews/PreviewVideoPlayback.qmlnew file+87
This diff is too big to show here.
qml/Dash/Previews/PreviewWidget.qmlnew file+57
This diff is too big to show here.
qml/Dash/Previews/PreviewWidgetFactory.qmlnew file+92
This diff is too big to show here.
qml/Dash/Previews/PreviewZoomableImage.qmlnew file+102
This diff is too big to show here.
qml/Launcher/PullToRefreshScopeStyle.qml → qml/Dash/PullToRefreshScopeStyle.qmlrenamed−1
This diff is too big to show here.
qml/Dash/ScopeListView.qmlnew file+26
This diff is too big to show here.
qml/Dash/ScopeSettings/ScopeSetting.qmlnew file+46
This diff is too big to show here.
qml/Dash/ScopeSettings/ScopeSettingBoolean.qmlnew file+63
This diff is too big to show here.
qml/Dash/ScopeSettings/ScopeSettingList.qmlnew file+50
This diff is too big to show here.
plugins/LightDM/IntegratedLightDM/QLightDM/SessionsModel → qml/Dash/ScopeSettings/ScopeSettingNumber.qmlrenamed+6−2
This diff is too big to show here.
qml/Dash/ScopeSettings/ScopeSettingString.qmlnew file+89
This diff is too big to show here.
qml/Dash/ScopeSettings/ScopeSettingsWidgetFactory.qmlnew file+61
This diff is too big to show here.
qml/Dash/ScopeSettingsPage.qmlnew file+72
This diff is too big to show here.
qml/Dash/ScopesList.qmlnew file+122
This diff is too big to show here.
qml/Dash/ScopesListCategory.qmlnew file+180
This diff is too big to show here.
qml/Dash/ScopesListCategoryItem.qmlnew file+112
This diff is too big to show here.
qml/Dash/graphics/dark_background.jpgnew file
Binary file not shown.
qml/Dash/graphics/dash_divider_top_darkgrad@27.pngnew file
Binary file not shown.
qml/Dash/graphics/dash_divider_top_lightgrad@27.pngnew file
Binary file not shown.
qml/Dash/graphics/header_handlearrow2@27.pngnew file
Binary file not shown.
qml/Dash/graphics/header_handlearrow@27.pngnew file
Binary file not shown.
qml/Dash/graphics/icon_clear@20.pngnew file
Binary file not shown.
qml/Dash/graphics/icon_search_active@20.pngnew file
Binary file not shown.
qml/Dash/graphics/icon_search_inactive@20.pngnew file
Binary file not shown.
qml/Dash/graphics/navigation_shadow@18.pngnew file
Binary file not shown.
qml/Dash/graphics/navigation_shadow_light@18.pngnew file
Binary file not shown.
qml/Dash/graphics/overview_hint@27.pngnew file
Binary file not shown.
qml/Dash/graphics/pagination_dot_off@30.pngnew file
Binary file not shown.
qml/Dash/graphics/pagination_dot_on@30.pngnew file
Binary file not shown.
qml/Dash/graphics/paper.pngnew file
Binary file not shown.
qml/Dash/graphics/pixel.pngnew file
Binary file not shown.
qml/Dash/graphics/play_button@18.pngnew file
Binary file not shown.
qml/Dash/graphics/play_button_active@18.pngnew file
Binary file not shown.
qml/Dash/graphics/play_button_active_big@20.pngnew file
Binary file not shown.
qml/Dash/graphics/play_button_big@20.pngnew file
Binary file not shown.
qml/Dash/graphics/tabbarchevron@27.pngnew file
Binary file not shown.
qml/Dash/graphics/tablet/icon_close_preview@20.pngnew file
Binary file not shown.
qml/Dash/graphics/tooltip_arrow@27.pngnew file
Binary file not shown.
qml/DeviceConfiguration.qml−12
This diff is too big to show here.
qml/DisabledScreenNotice.qml+55−3
This diff is too big to show here.
qml/Greeter/ButtonPrompt.qmldeleted−51
This diff is too big to show here.
qml/Greeter/Circle.qmldeleted−57
This diff is too big to show here.
qml/Greeter/Clock.qml+2
This diff is too big to show here.
qml/Greeter/CoverPage.qml+18−61
This diff is too big to show here.
qml/Greeter/Greeter.qml+114−273
This diff is too big to show here.
qml/Greeter/GreeterPrompt.qmldeleted−127
This diff is too big to show here.
qml/Greeter/GreeterView.qmldeleted−534
This diff is too big to show here.
qml/Greeter/Infographics.qml+23−44
This diff is too big to show here.
qml/Greeter/IntegratedLightDMImpl.qml+2−4
This diff is too big to show here.
qml/Greeter/LightDMService.qml → qml/Greeter/LightDM.qmlrenamed+3−16
This diff is too big to show here.
qml/Greeter/LoginList.qml+157−147
This diff is too big to show here.
qml/Greeter/NarrowView.qmlnew file+184
This diff is too big to show here.
qml/Greeter/PinPrompt.qmldeleted−184
This diff is too big to show here.
qml/Greeter/PromptList.qmldeleted−151
This diff is too big to show here.
qml/Greeter/SessionIcon.qmldeleted−47
This diff is too big to show here.
qml/Greeter/SessionsList.qmldeleted−205
This diff is too big to show here.
qml/Greeter/ShimGreeter.qml−2
This diff is too big to show here.
qml/Greeter/TextPrompt.qmldeleted−198
This diff is too big to show here.
qml/Greeter/WideView.qmlnew file+135
This diff is too big to show here.
qml/Greeter/graphics/dot_empty.png
Binary file not shown.
qml/Greeter/graphics/dot_filled.png
Binary file not shown.
qml/Greeter/graphics/dot_pointer.png
Binary file not shown.
qml/Greeter/graphics/icon_arrow.png
Binary file not shown.
qml/Greeter/graphics/infographic_circle_back.pngnew file
Binary file not shown.
qml/Greeter/graphics/session_icons/gnome_badge.pngdeleted
Binary file not shown.
qml/Greeter/graphics/session_icons/kde_badge.pngdeleted
Binary file not shown.
qml/Greeter/graphics/session_icons/recovery_console_badge.pngdeleted
Binary file not shown.
qml/Greeter/graphics/session_icons/ubuntu_badge.pngdeleted
Binary file not shown.
qml/Greeter/graphics/session_icons/unknown_badge.pngdeleted
Binary file not shown.
qml/Greeter/qmldirdeleted−1
This diff is too big to show here.
qml/Launcher/BackgroundBlur.qmldeleted−81
This diff is too big to show here.
qml/Launcher/Drawer.qmldeleted−413
This diff is too big to show here.
qml/Launcher/DrawerGridView.qmldeleted−85
This diff is too big to show here.
qml/Launcher/Launcher.qml+69−254
This diff is too big to show here.
qml/Launcher/LauncherDelegate.qml+20−14
This diff is too big to show here.
qml/Launcher/LauncherPanel.qml+46−183
This diff is too big to show here.
qml/Launcher/Tooltip.qmldeleted−72
This diff is too big to show here.
qml/Launcher/graphics/divider-line.png
Binary file not shown.
qml/Launcher/graphics/focused_app_arrow@30.png
Binary file not shown.
qml/Launcher/graphics/home.svgdeleted−243
This diff is too big to show here.
qml/Launcher/graphics/home@18.pngnew file
Binary file not shown.
qml/Launcher/graphics/launcher-app-focus-ring.svgnew file+12
This diff is too big to show here.
qml/Launcher/graphics/quicklist_tooltip@30.png
Binary file not shown.
qml/Notifications/Notification.qml+33−38
This diff is too big to show here.
qml/Notifications/NotificationButton.qml+1−2
This diff is too big to show here.
qml/Notifications/NotificationMenuItemFactory.qml+3
This diff is too big to show here.
qml/Notifications/Notifications.qml+24−14
This diff is too big to show here.
qml/Notifications/ShapedIcon.qml−1
This diff is too big to show here.
qml/Notifications/SwipeToAct.qml−4
This diff is too big to show here.
qml/OrientedShell.qml+10−36
This diff is too big to show here.
qml/Panel/ActiveCallHint.qml−3
This diff is too big to show here.
qml/Components/Handle.qml → qml/Panel/Handle.qmlrenamed−1
This diff is too big to show here.
qml/Panel/Indicators/IndicatorItem.qml → qml/Panel/IndicatorItem.qmlrenamed+3−16
This diff is too big to show here.
qml/Panel/PanelItemRow.qml → qml/Panel/IndicatorItemRow.qmlrenamed+95−65
This diff is too big to show here.
qml/Panel/IndicatorPage.qmlnew file+187
This diff is too big to show here.
qml/Panel/Indicators/IndicatorsLight.qml+12−185
This diff is too big to show here.
qml/Panel/Indicators/IndicatorMenuItemFactory.qml → qml/Panel/Indicators/MenuItemFactory.qmlrenamed+92−183
This diff is too big to show here.
qml/Panel/Indicators/client/IndicatorRepresentation.qml+28−45
This diff is too big to show here.
qml/Panel/Indicators/client/IndicatorsClient.qml+2−8
This diff is too big to show here.
qml/Panel/Indicators/client/IndicatorsList.qml+17−19
This diff is too big to show here.
qml/Panel/Indicators/client/IndicatorsTree.qml+8−6
This diff is too big to show here.
qml/Panel/PanelBar.qml → qml/Panel/IndicatorsBar.qmlrenamed+36−87
This diff is too big to show here.
qml/Panel/PanelMenu.qml → qml/Panel/IndicatorsMenu.qmlrenamed+35−81
This diff is too big to show here.
qml/Panel/MenuContent.qml+12−12
This diff is too big to show here.
qml/Panel/Panel.qml+103−379
This diff is too big to show here.
qml/Panel/PanelMenuPage.qmldeleted−226
This diff is too big to show here.
qml/Panel/graphics/rectangular_dropshadow@30.png
Binary file not shown.
qml/Rotation/HalfLoopRotationAnimation.qml+1−1
This diff is too big to show here.
qml/Rotation/ImmediateRotationAction.qml+1−1
This diff is too big to show here.
qml/Rotation/NinetyRotationAnimation.qml+1−1
This diff is too big to show here.
qml/Rotation/RotationStates.qml+11−2
This diff is too big to show here.
qml/Rotation/UpdateShellTransformations.qml+4−4
This diff is too big to show here.
qml/ScopeTool.qmlnew file+165
This diff is too big to show here.
qml/Shell.qml+256−443
This diff is too big to show here.
qml/Stage/ChildWindow.qmldeleted−203
This diff is too big to show here.
qml/Stage/ChildWindowRepeater.qmldeleted−39
This diff is too big to show here.
qml/Stage/ChildWindowTree.qmldeleted−138
This diff is too big to show here.
qml/Stage/DecoratedWindow.qmldeleted−319
This diff is too big to show here.
qml/Stage/FakeMaximizeDelegate.qmldeleted−233
This diff is too big to show here.
qml/Stage/MoveHandler.qmldeleted−201
This diff is too big to show here.
qml/Stage/Spread/BezierCurve.qmldeleted−45
This diff is too big to show here.
qml/Stage/Spread/KeySpline.jsdeleted−66
This diff is too big to show here.
qml/Stage/Spread/MathUtils.jsdeleted−95
This diff is too big to show here.
qml/Stage/Spread/OpacityMask.qmldeleted−82
This diff is too big to show here.
qml/Stage/Spread/Spread.qmldeleted−173
This diff is too big to show here.
qml/Stage/Spread/SpreadDelegateInputArea.qmldeleted−189
This diff is too big to show here.
qml/Stage/Spread/SpreadMaths.qmldeleted−78
This diff is too big to show here.
qml/Stage/Spread/StagedRightEdgeMaths.qmldeleted−174
This diff is too big to show here.
qml/Stage/Spread/WindowedRightEdgeMaths.qmldeleted−96
This diff is too big to show here.
qml/Stage/Spread/cubic-bezier.jsdeleted−39
This diff is too big to show here.
qml/Stage/Stage.qmldeleted−2241
This diff is too big to show here.
qml/Stage/StageMaths.qmldeleted−93
This diff is too big to show here.
qml/Stage/WindowControlsOverlay.qmldeleted−254
This diff is too big to show here.
qml/Stage/WindowDecoration.qmldeleted−163
This diff is too big to show here.
qml/Stage/WindowInfoItem.qmldeleted−69
This diff is too big to show here.
qml/Stage/WindowStateSaver.qmldeleted−64
This diff is too big to show here.
qml/Stage/graphics/PageHeaderBaseDividerBottom@18.pngdeleted
Binary file not shown.
qml/Stage/graphics/PageHeaderBaseDividerLight@18.pngdeleted
Binary file not shown.
qml/Stage/graphics/arrows-centre.pngdeleted
Binary file not shown.
qml/Stage/graphics/arrows.pngdeleted
Binary file not shown.
qml/Stage/graphics/sidestage_handle@20.pngdeleted
Binary file not shown.
qml/Stages/AbstractStage.qmlnew file+80
This diff is too big to show here.
qml/Stage/ApplicationWindow.qml → qml/Stages/ApplicationWindow.qmlrenamed+50−61
This diff is too big to show here.
qml/Stages/DecoratedWindow.qmlnew file+109
This diff is too big to show here.
qml/Stages/DesktopSpread.qmlnew file+574
This diff is too big to show here.
qml/Stages/DesktopSpreadDelegate.qmlnew file+126
This diff is too big to show here.
qml/Stages/DesktopStage.qmlnew file+684
This diff is too big to show here.
qml/Stage/MainViewStyle.qml → qml/Stages/MainViewStyle.qmlrenamed
The content is the same.
qml/Stage/OrientationChangeAnimation.qml → qml/Stages/OrientationChangeAnimation.qmlrenamed+6−30
This diff is too big to show here.
qml/Stages/PhoneStage.qmlnew file+800
This diff is too big to show here.
qml/Stage/PromptSurfaceAnimations.qml → qml/Stages/PromptSurfaceAnimations.qmlrenamed+3−2
This diff is too big to show here.
tests/mocks/Unity/Application/resources/KateMenu.qml → qml/Stages/ShimStage.qmlrenamed+19−17
This diff is too big to show here.
qml/Stage/SideStage.qml → qml/Stages/SideStage.qmlrenamed+6−10
This diff is too big to show here.
qml/Stage/Splash.qml → qml/Stages/Splash.qmlrenamed+10−7
This diff is too big to show here.
qml/Stages/SpreadDelegate.qmlnew file+437
This diff is too big to show here.
qml/Stages/SpreadMaths.qmlnew file+164
This diff is too big to show here.
qml/Stage/StagedFullscreenPolicy.qml → qml/Stages/StagedFullscreenPolicy.qmlrenamed+13−7
This diff is too big to show here.
qml/Stage/SurfaceContainer.qml → qml/Stages/SurfaceContainer.qmlrenamed+52−5
This diff is too big to show here.
qml/Stage/TabletSideStageTouchGesture.qml → qml/Stages/TabletSideStageTouchGesture.qmlrenamed−3
This diff is too big to show here.
qml/Stages/TabletStage.qmlnew file+1186
This diff is too big to show here.
qml/Stages/TopLevelSurfaceRepeater.qmlnew file+52
This diff is too big to show here.
qml/Stages/TransformedSpreadDelegate.qmlnew file+391
This diff is too big to show here.
qml/Stages/TransformedTabletSpreadDelegate.qmlnew file+437
This diff is too big to show here.
qml/Stages/WindowDecoration.qmlnew file+109
This diff is too big to show here.
qml/Stage/WindowResizeArea.qml → qml/Stages/WindowResizeArea.qmlrenamed+110−45
This diff is too big to show here.
qml/Stage/WindowedFullscreenPolicy.qml → qml/Stages/WindowedFullscreenPolicy.qmlrenamed+12−4
This diff is too big to show here.
qml/Stages/graphics/PageHeaderBaseDividerBottom@18.pngnew file
Binary file not shown.
qml/Stages/graphics/PageHeaderBaseDividerLight@18.pngnew file
Binary file not shown.
qml/Stage/graphics/PageHeaderBaseDividerLight@18.sci → qml/Stages/graphics/PageHeaderBaseDividerLight@18.scirenamed
The content is the same.
qml/Stages/graphics/dropshadow2gu@30.pngnew file
Binary file not shown.
qml/graphics/dropshadow2gu@30.sci → qml/Stages/graphics/dropshadow2gu@30.scirenamed
The content is the same.
qml/Stage/graphics/sidestage_drag.svg → qml/Stages/graphics/sidestage_drag.svgrenamed
The content is the same.
qml/Stages/graphics/sidestage_handle@20.pngnew file
Binary file not shown.
qml/Stage/graphics/sidestage_handle@20.sci → qml/Stages/graphics/sidestage_handle@20.scirenamed
The content is the same.
qml/Stage/graphics/sidestage_open.svg → qml/Stages/graphics/sidestage_open.svgrenamed
The content is the same.
qml/Stage/graphics/window-close.svg → qml/Stages/graphics/window-close.svgrenamed
The content is the same.
qml/Tutorial/InactivityTimer.qml+10−26
This diff is too big to show here.
qml/Tutorial/Tutorial.qml+6−8
This diff is too big to show here.
qml/Tutorial/TutorialBottom.qmlnew file+124
This diff is too big to show here.
qml/Tutorial/TutorialContent.qml+150−85
This diff is too big to show here.
qml/Tutorial/TutorialLeft.qml+3−3
This diff is too big to show here.
qml/Tutorial/TutorialLeftLong.qml+3−5
This diff is too big to show here.
qml/Tutorial/TutorialPage.qml+2−2
This diff is too big to show here.
qml/Tutorial/TutorialRight.qml+5−4
This diff is too big to show here.
qml/Tutorial/TutorialTop.qml+5−4
This diff is too big to show here.
qml/Tutorial/graphics/background1.png
Binary file not shown.
qml/Tutorial/graphics/background2.png
Binary file not shown.
qml/Wizard/Components/InputMethod.qml+9−9
This diff is too big to show here.
qml/Wizard/Page.qml+1−16
This diff is too big to show here.
qml/Wizard/Pages.qml+16−90
This diff is too big to show here.
qml/Wizard/Pages/10-welcome-update.qmldeleted−137
This diff is too big to show here.
qml/Wizard/Pages/10-welcome.qml+5−23
This diff is too big to show here.
qml/Wizard/Pages/11-changelog.qmldeleted−95
This diff is too big to show here.
qml/Wizard/Pages/20-keyboard.qmldeleted−161
This diff is too big to show here.
qml/Wizard/Pages/30-wifi.qml+11−20
This diff is too big to show here.
qml/Wizard/Pages/40-location.qmlnew file+290
This diff is too big to show here.
qml/Wizard/Pages/50-timezone.qml+12−12
This diff is too big to show here.
qml/Wizard/Pages/60-account.qml+10−12
This diff is too big to show here.
qml/Wizard/Pages/70-passwd-type.qml−2
This diff is too big to show here.
qml/Wizard/Pages/75-report-check.qmlnew file+91
This diff is too big to show here.
qml/Wizard/Pages/78-firmware-update.qml.disableddeleted−246
This diff is too big to show here.
qml/Wizard/Pages/79-system-update.qmldeleted−148
This diff is too big to show here.
qml/Wizard/Pages/80-finished.qml+2−4
This diff is too big to show here.
qml/Wizard/Pages/data/Desktop_header_bkg.png
Binary file not shown.
qml/Wizard/Pages/data/Desktop_splash_screen_bkg.png
Binary file not shown.
qml/Wizard/Pages/data/Phone_header_bkg.png
Binary file not shown.
qml/Wizard/Pages/data/Phone_splash_screen_bkg.png
Binary file not shown.
qml/Wizard/Pages/data/Tick@30.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/map.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/pin.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-1.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-10.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-11.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-2.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-3.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-3.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-4.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-4.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-6.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-7.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-8.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-9.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_-9.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_0.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_1.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_10.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_10.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_11.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_12.75.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_12.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_13.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_2.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_3.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_3.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_4.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_4.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_5.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_5.75.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_6.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_6.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_7.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_8.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_8.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_9.5.png
Binary file not shown.
qml/Wizard/Pages/data/timezonemap/timezone_9.png
Binary file not shown.
qml/Wizard/Pages/here-terms.qmlnew file+126
This diff is too big to show here.
qml/Wizard/Pages/passcode-confirm.qml+2−2
This diff is too big to show here.
qml/Wizard/Pages/passcode-desktop.qml+15−42
This diff is too big to show here.
qml/Wizard/Pages/passcode-set.qml+2−2
This diff is too big to show here.
qml/Wizard/Pages/password-set.qml+4−13
This diff is too big to show here.
qml/Wizard/PasswordMeter.qml+1−3
This diff is too big to show here.
qml/Wizard/Wizard.qml+4−11
This diff is too big to show here.
qml/Wizard/WizardItemSelector.qmldeleted−129
This diff is too big to show here.
qml/graphics/dropshadow2gu@30.pngdeleted
Binary file not shown.
qml/graphics/dropshadow_left@20.png
Binary file not shown.
qml/graphics/dropshadow_right@20.png
Binary file not shown.
qml/graphics/phone_background.jpgnew file
Binary file not shown.
qml/graphics/tablet_background.jpgnew file
Binary file not shown.
run.shnew file+70
This diff is too big to show here.
run_on_device.shnew file+164
This diff is too big to show here.
src/ApplicationArguments.h−5
This diff is too big to show here.
src/CMakeLists.txt+6−17
This diff is too big to show here.
src/Dash/CMakeLists.txtnew file+28
This diff is too big to show here.
src/Dash/main.cppnew file+130
This diff is too big to show here.
src/DebuggingController.cppdeleted−92
This diff is too big to show here.
src/DebuggingController.hdeleted−57
This diff is too big to show here.
src/MouseTouchAdaptor.cpp+1−28
This diff is too big to show here.
src/MouseTouchAdaptor.h−1
This diff is too big to show here.
src/Panel/CMakeLists.txtnew file+3
This diff is too big to show here.
src/Panel/Indicators/CMakeLists.txtnew file+1
This diff is too big to show here.
tools/indicatorsclient/CMakeLists.txt → src/Panel/Indicators/client/CMakeLists.txtrenamed+1−1
This diff is too big to show here.
tools/indicatorsclient/indicatorsclient.cpp → src/Panel/Indicators/client/indicatorsclient.cpprenamed+8−10
This diff is too big to show here.
tools/indicatorsclient/indicatorsclient.h → src/Panel/Indicators/client/indicatorsclient.hrenamed+2
This diff is too big to show here.
tools/indicatorsclient/main.cpp → src/Panel/Indicators/client/main.cpprenamed
The content is the same.
src/SecondaryWindow.cpp+1−1
This diff is too big to show here.
src/ShellApplication.cpp+6−33
This diff is too big to show here.
src/ShellApplication.h+3−1
This diff is too big to show here.
src/ShellView.cpp−22
This diff is too big to show here.
src/libunity8-private/CMakeLists.txt+1−1
This diff is too big to show here.
src/libunity8-private/abstractdbusservicemonitor.h+1−1
This diff is too big to show here.
src/main.cpp+3−28
This diff is too big to show here.
tests/CMakeLists.txt+23−43
This diff is too big to show here.
tests/autopilot/unity8/dash.pynew file+263
This diff is too big to show here.
tests/autopilot/unity8/fixture_setup.py+1−1
This diff is too big to show here.
tests/autopilot/unity8/greeter/__init__.py+1−1
This diff is too big to show here.
tests/autopilot/unity8/greeter/tests/test_args.py+5
This diff is too big to show here.
tests/autopilot/unity8/shell/__init__.py−2
This diff is too big to show here.
tests/autopilot/unity8/shell/fixture_setup.py+27−1
This diff is too big to show here.
tests/autopilot/unity8/shell/tests/__init__.py+2−5
This diff is too big to show here.
tests/autopilot/unity8/shell/tests/test_helpers.py+122
This diff is too big to show here.
tests/autopilot/unity8/shell/tests/test_notifications.py+9−9
This diff is too big to show here.
tests/autopilot/unity8/shell/tests/test_rotation.py+3−3
This diff is too big to show here.
tests/copyright/check_copyright.sh+4−35
This diff is too big to show here.
tests/data/unity/backgrounds/20x30.pngdeleted
Binary file not shown.
tests/data/unity/backgrounds/black.pngdeleted
Binary file not shown.
tests/data/unity/backgrounds/blue.png
Binary file not shown.
tests/data/unity/backgrounds/red.png
Binary file not shown.
tests/graphics/applicationIcons/browser@18.png
Binary file not shown.
tests/graphics/applicationIcons/calendar@18.png
Binary file not shown.
tests/graphics/applicationIcons/camera@18.png
Binary file not shown.
tests/graphics/applicationIcons/contacts-app@18.png
Binary file not shown.
tests/graphics/applicationIcons/dash.pngnew file
Binary file not shown.
tests/graphics/applicationIcons/dash@18.pngdeleted
Binary file not shown.
tests/graphics/applicationIcons/dialer-app@18.png
Binary file not shown.
tests/graphics/applicationIcons/evernote@18.png
Binary file not shown.
tests/graphics/applicationIcons/facebook@18.png
Binary file not shown.
tests/graphics/applicationIcons/gallery@18.png
Binary file not shown.
tests/graphics/applicationIcons/gmail@18.png
Binary file not shown.
tests/graphics/applicationIcons/libreoffice@18.png
Binary file not shown.
tests/graphics/applicationIcons/map@18.png
Binary file not shown.
tests/graphics/applicationIcons/messages-app@18.png
Binary file not shown.
tests/graphics/applicationIcons/notepad@18.png
Binary file not shown.
tests/graphics/applicationIcons/pinterest@18.png
Binary file not shown.
tests/graphics/applicationIcons/soundcloud@18.png
Binary file not shown.
tests/graphics/applicationIcons/system-settings@18.png
Binary file not shown.
tests/graphics/applicationIcons/twitter@18.png
Binary file not shown.
tests/graphics/applicationIcons/weather@18.png
Binary file not shown.
tests/graphics/applicationIcons/wikipedia@18.png
Binary file not shown.
tests/graphics/applicationIcons/youtube@18.png
Binary file not shown.
tests/graphics/avatars/amanda@12.png
Binary file not shown.
tests/graphics/avatars/anna_olsson@12.png
Binary file not shown.
tests/graphics/avatars/funky@12.png
Binary file not shown.
tests/graphics/clock@18.png
Binary file not shown.
tests/graphics/screenshots/gallery@12.pngdeleted
Binary file not shown.
tests/imports/CMakeLists.txt+1−1
This diff is too big to show here.
tests/imports/check_imports.py−58
This diff is too big to show here.
tests/mocks/AccountsService/AccountsService.cpp+32−35
This diff is too big to show here.
tests/mocks/AccountsService/AccountsService.h+26−22
This diff is too big to show here.
tests/mocks/AccountsService/AccountsService.qmltypesnew file+41
This diff is too big to show here.
tests/mocks/AccountsService/CMakeLists.txt+2−15
This diff is too big to show here.
tests/mocks/Biometryd/CMakeLists.txtdeleted−14
This diff is too big to show here.
tests/mocks/Biometryd/MockBiometryd.cppdeleted−43
This diff is too big to show here.
tests/mocks/Biometryd/MockBiometryd.hdeleted−50
This diff is too big to show here.
tests/mocks/Biometryd/MockOperation.cppdeleted−56
This diff is too big to show here.
tests/mocks/Biometryd/MockOperation.hdeleted−47
This diff is too big to show here.
tests/mocks/Biometryd/qmldirdeleted−3
This diff is too big to show here.
tests/mocks/CMakeLists.txt+16−18
This diff is too big to show here.
tests/mocks/Cursor/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Cursor/Cursor.qml+1−12
This diff is too big to show here.
tests/mocks/Cursor/qmldir+1−1
This diff is too big to show here.
tests/mocks/GSettings.1.0/CMakeLists.txt+2−1
This diff is too big to show here.
tests/mocks/GSettings.1.0/GSettings.qmltypesnew file+42
This diff is too big to show here.
tests/mocks/GSettings.1.0/fake_gsettings.cpp−65
This diff is too big to show here.
tests/mocks/GSettings.1.0/fake_gsettings.h−18
This diff is too big to show here.
tests/mocks/IntegratedLightDM/CMakeLists.txtnew file+49
This diff is too big to show here.
tests/mocks/IntegratedLightDM/IntegratedLightDM.qmltypesnew file+269
This diff is too big to show here.
tests/mocks/Utils/URLDispatcher.cpp → tests/mocks/IntegratedLightDM/MockGreeter.cpprenamed+12−15
This diff is too big to show here.
tests/mocks/Biometryd/MockDevice.h → tests/mocks/IntegratedLightDM/MockGreeter.hrenamed+14−17
This diff is too big to show here.
tests/mocks/IntegratedLightDM/MockUsersModel.cppnew file+39
This diff is too big to show here.
plugins/Lights/LegacyLights.h → tests/mocks/IntegratedLightDM/MockUsersModel.hrenamed+11−19
This diff is too big to show here.
plugins/LightDM/IntegratedLightDM/QLightDM/Greeter → tests/mocks/IntegratedLightDM/QLightDM/Greeterrenamed+1−1
This diff is too big to show here.
plugins/LightDM/IntegratedLightDM/QLightDM/UsersModel → tests/mocks/IntegratedLightDM/QLightDM/UsersModelrenamed+1−1
This diff is too big to show here.
tests/mocks/IntegratedLightDM/liblightdm/CMakeLists.txtnew file+18
This diff is too big to show here.
tests/mocks/IntegratedLightDM/liblightdm/Greeter.cppnew file+199
This diff is too big to show here.
tests/mocks/liblightdm/MockGreeter.h → tests/mocks/IntegratedLightDM/liblightdm/Greeter.hrenamed+24−10
This diff is too big to show here.
tests/mocks/liblightdm/GreeterPrivate.cpp → tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.cpprenamed
The content is the same.
tests/mocks/liblightdm/GreeterPrivate.h → tests/mocks/IntegratedLightDM/liblightdm/GreeterPrivate.hrenamed+1−1
This diff is too big to show here.
tests/mocks/IntegratedLightDM/liblightdm/UsersModel.cppnew file+120
This diff is too big to show here.
tests/mocks/liblightdm/MockUsersModel.h → tests/mocks/IntegratedLightDM/liblightdm/UsersModel.hrenamed+19−11
This diff is too big to show here.
tests/mocks/liblightdm/UsersModelPrivate.cpp → tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.cpprenamed+23−43
This diff is too big to show here.
tests/mocks/liblightdm/UsersModelPrivate.h → tests/mocks/IntegratedLightDM/liblightdm/UsersModelPrivate.hrenamed+1−2
This diff is too big to show here.
tests/mocks/IntegratedLightDM/plugin.cppnew file+68
This diff is too big to show here.
plugins/LightDM/plugin.h → tests/mocks/IntegratedLightDM/plugin.hrenamed+5−6
This diff is too big to show here.
tests/mocks/IntegratedLightDM/qmldirnew file+3
This diff is too big to show here.
tests/mocks/LightDMController/CMakeLists.txtdeleted−14
This diff is too big to show here.
tests/mocks/LightDMController/qmldirdeleted−2
This diff is too big to show here.
tests/mocks/Lights/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Lights/Lights.h+1−1
This diff is too big to show here.
tests/mocks/Lights/Lights.qmltypesnew file+45
This diff is too big to show here.
tests/mocks/MeeGo/QOfono/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/MeeGo/QOfono/QOfono.qmltypesnew file+30
This diff is too big to show here.
tests/mocks/Powerd/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Powerd/Powerd.h+2−2
This diff is too big to show here.
tests/mocks/Powerd/Powerd.qmltypesnew file+39
This diff is too big to show here.
tests/mocks/QMenuModel/CMakeLists.txt+2−1
This diff is too big to show here.
tests/mocks/QMenuModel/QMenuModel.qmltypesnew file+111
This diff is too big to show here.
tests/mocks/QMenuModel/dbus-enums.h+3−2
This diff is too big to show here.
tests/mocks/QMenuModel/unitymenumodel.cpp+13−78
This diff is too big to show here.
tests/mocks/QMenuModel/unitymenumodel.h+1−12
This diff is too big to show here.
tests/mocks/QtMultimedia/CMakeLists.txt+2−8
This diff is too big to show here.
tests/mocks/QtMultimedia/QtMultimedia.qmltypesnew file+62
This diff is too big to show here.
tests/mocks/QtMultimedia/VideoSurface.qmldeleted−111
This diff is too big to show here.
tests/mocks/QtMultimedia/audio.cppnew file+132
This diff is too big to show here.
tests/mocks/QtMultimedia/audio.hnew file+103
This diff is too big to show here.
tests/mocks/QtMultimedia/mediaplayer.cppdeleted−319
This diff is too big to show here.
tests/mocks/QtMultimedia/mediaplayer.hdeleted−224
This diff is too big to show here.
tests/mocks/QtMultimedia/plugin.cpp+3−7
This diff is too big to show here.
tests/mocks/QtMultimedia/videooutput.cppdeleted−127
This diff is too big to show here.
tests/mocks/QtMultimedia/videooutput.hdeleted−52
This diff is too big to show here.
tests/mocks/SessionBroadcast/CMakeLists.txtdeleted−8
This diff is too big to show here.
tests/mocks/SessionBroadcast/SessionBroadcast.cppdeleted−34
This diff is too big to show here.
tests/mocks/SessionBroadcast/SessionBroadcast.hdeleted−39
This diff is too big to show here.
tests/mocks/SessionBroadcast/qmldirdeleted−2
This diff is too big to show here.
tests/mocks/UInput/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/UInput/mockuinput.h+1−1
This diff is too big to show here.
tests/mocks/Ubuntu/CMakeLists.txt+2
This diff is too big to show here.
tests/mocks/Ubuntu/Connectivity/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Ubuntu/Connectivity/networking-status.cpp+1−7
This diff is too big to show here.
tests/mocks/Ubuntu/Connectivity/networking-status.h+6−7
This diff is too big to show here.
tests/mocks/Ubuntu/DownloadDaemonListener/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Ubuntu/DownloadDaemonListener/DownloadDaemonListener.qmltypesnew file+60
This diff is too big to show here.
tests/mocks/Ubuntu/DownloadDaemonListener/MockDownloadTracker.cpp+1−3
This diff is too big to show here.
tests/mocks/Ubuntu/DownloadDaemonListener/MockDownloadTracker.h+1−2
This diff is too big to show here.
tests/mocks/Ubuntu/Payments/CMakeLists.txtnew file+10
This diff is too big to show here.
tests/mocks/Ubuntu/Payments/MockPayments.cppnew file+94
This diff is too big to show here.
tests/mocks/Ubuntu/Payments/MockPayments.hnew file+62
This diff is too big to show here.
tests/mocks/Ubuntu/Payments/Payments.qmltypesnew file+44
This diff is too big to show here.
tests/mocks/Ubuntu/Payments/plugin.cppnew file+28
This diff is too big to show here.
tests/mocks/LightDMController/plugin.h → tests/mocks/Ubuntu/Payments/plugin.hrenamed+6−4
This diff is too big to show here.
tests/mocks/Ubuntu/Payments/qmldirnew file+3
This diff is too big to show here.
tests/mocks/Ubuntu/SystemImage/CMakeLists.txtnew file+10
This diff is too big to show here.
qml/Panel/FakePanelMenu.qml → tests/mocks/Ubuntu/SystemImage/MockSystemImage.cpprenamed+9−8
This diff is too big to show here.
tests/mocks/Biometryd/MockObserver.h → tests/mocks/Ubuntu/SystemImage/MockSystemImage.hrenamed+10−11
This diff is too big to show here.
tests/mocks/Ubuntu/SystemImage/SystemImage.qmltypesnew file+20
This diff is too big to show here.
tests/mocks/Biometryd/plugin.cpp → tests/mocks/Ubuntu/SystemImage/plugin.cpprenamed+7−14
This diff is too big to show here.
tests/mocks/Ubuntu/SystemImage/plugin.hnew file+31
This diff is too big to show here.
tests/mocks/Ubuntu/SystemImage/qmldirnew file+3
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/CMakeLists.txt−1
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/LanguagePlugin.qmltypesnew file+10
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/LanguagePlugin/MockLanguagePlugin.qml+2−3
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+2−2
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.h+1−1
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/SecurityPrivacy.qmltypesnew file+39
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/Update/CMakeLists.txtdeleted−1
This diff is too big to show here.
tests/mocks/Ubuntu/SystemSettings/Update/qmldirdeleted−2
This diff is too big to show here.
tests/mocks/Ubuntu/Telephony/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp−27
This diff is too big to show here.
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h−22
This diff is too big to show here.
tests/mocks/Ubuntu/Telephony/Telephony.qmltypesnew file+58
This diff is too big to show here.
tests/mocks/Ubuntu/Thumbnailer/Thumbnailer.qmltypesnew file+17
This diff is too big to show here.
tests/mocks/Unity/Application/Application.qmltypesnew file+517
This diff is too big to show here.
tests/mocks/Unity/Application/ApplicationInfo.cpp+56−84
This diff is too big to show here.
tests/mocks/Unity/Application/ApplicationInfo.h+17−13
This diff is too big to show here.
tests/mocks/Unity/Application/ApplicationManager.cpp+75−134
This diff is too big to show here.
tests/mocks/Unity/Application/ApplicationManager.h+10−32
This diff is too big to show here.
tests/mocks/Unity/Application/CMakeLists.txt+5−5
This diff is too big to show here.
tests/mocks/Unity/Application/MirMock.cppdeleted−62
This diff is too big to show here.
tests/mocks/Unity/Application/MirMock.hdeleted−43
This diff is too big to show here.
tests/mocks/Unity/Application/MirSurface.cpp+80−146
This diff is too big to show here.
tests/mocks/Unity/Application/MirSurface.h+27−57
This diff is too big to show here.
tests/mocks/Unity/Application/MirSurfaceItem.cpp+17−73
This diff is too big to show here.
tests/mocks/Unity/Application/MirSurfaceItem.h+2−3
This diff is too big to show here.
tests/mocks/Unity/Application/MirSurfaceListModel.cpp+35−22
This diff is too big to show here.
tests/mocks/Unity/Application/MirSurfaceListModel.h+14−7
This diff is too big to show here.
tests/mocks/Unity/Application/SurfaceManager.cpp+31−186
This diff is too big to show here.
tests/mocks/Unity/Application/SurfaceManager.h+10−32
This diff is too big to show here.
tests/mocks/Unity/Application/UbuntuKeyboardInfo.cppnew file+58
This diff is too big to show here.
tests/mocks/Unity/Application/UbuntuKeyboardInfo.hnew file+57
This diff is too big to show here.
tests/mocks/Unity/Application/VirtualKeyboard.cpp+5−27
This diff is too big to show here.
tests/mocks/Unity/Application/VirtualKeyboard.h+1−4
This diff is too big to show here.
tests/mocks/Unity/Application/plugin.cpp+35−6
This diff is too big to show here.
tests/mocks/Unity/Application/resources/Kate.qmldeleted−49
This diff is too big to show here.
tests/mocks/Unity/Application/resources/KateDialog.qmldeleted−48
This diff is too big to show here.
tests/mocks/Unity/Application/resources/MirSurfaceItem.qml+5−2
This diff is too big to show here.
tests/mocks/Unity/Application/resources/VirtualKeyboard.qml+6−1
This diff is too big to show here.
tests/mocks/Unity/Application/resources/screenshots/browser@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/camera@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/dialer@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/facebook@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/gallery@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/libreoffice@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/map@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/music@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/twitter@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/unity8-dash@12.png
Binary file not shown.
tests/mocks/Unity/Application/resources/screenshots/vkb_portrait.png
Binary file not shown.
tests/mocks/Unity/Application/resources/surfaces.qrc−3
This diff is too big to show here.
tests/mocks/Unity/Application/resources/vkb_portrait.png
Binary file not shown.
tests/mocks/Unity/ApplicationMenu/CMakeLists.txtdeleted−18
This diff is too big to show here.
tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.cppdeleted−47
This diff is too big to show here.
tests/mocks/Unity/ApplicationMenu/mockapplicationmenuregistry.hdeleted−41
This diff is too big to show here.
tests/mocks/Unity/ApplicationMenu/plugin.cppdeleted−42
This diff is too big to show here.
tests/mocks/Unity/ApplicationMenu/plugin.hdeleted−32
This diff is too big to show here.
tests/mocks/Unity/ApplicationMenu/qmldirdeleted−3
This diff is too big to show here.
tests/mocks/Unity/CMakeLists.txt+63−2
This diff is too big to show here.
tests/mocks/Unity/Connectivity/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Unity/Connectivity/Connectivity.qmltypesnew file+20
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/CMakeLists.txtnew file+18
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/DashCommunicator.qmltypesnew file+46
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/dashcommunicator.cppnew file+42
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/dashcommunicator.hnew file+39
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cppnew file+46
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.hnew file+41
This diff is too big to show here.
plugins/LightDM/IntegratedLightDM/liblightdm/SessionsModelPrivate.cpp → tests/mocks/Unity/DashCommunicator/plugin.cpprenamed+11−16
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/plugin.hnew file+34
This diff is too big to show here.
tests/mocks/Unity/DashCommunicator/qmldirnew file+3
This diff is too big to show here.
tests/mocks/Unity/Indicators/CMakeLists.txt+1−5
This diff is too big to show here.
tests/mocks/Unity/Indicators/Indicators.qmltypesnew file+232
This diff is too big to show here.
tests/mocks/Unity/Indicators/IndicatorsModel.qml+14−97
This diff is too big to show here.
tests/mocks/Unity/Indicators/fakeindicatorsmodel.h+1
This diff is too big to show here.
tests/mocks/Unity/Indicators/fakeindicatorsmodeldata.jsdeleted−1328
This diff is too big to show here.
tests/mocks/Unity/Indicators/fakeplugin.cpp−2
This diff is too big to show here.
tests/mocks/Unity/InputInfo/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Unity/InputInfo/qinputdeviceinfo_mock.cpp+2−6
This diff is too big to show here.
tests/mocks/Unity/Launcher/CMakeLists.txt+3−5
This diff is too big to show here.
tests/mocks/Unity/Launcher/Launcher.qmltypesnew file+187
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockAppDrawerModel.cppdeleted−98
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+1−41
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockLauncherItem.h−12
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−12
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockLauncherModel.h+2−2
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockQuickListModel.cpp+1−5
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockQuickListModel.h−2
This diff is too big to show here.
tests/mocks/Unity/Launcher/plugin.cpp−4
This diff is too big to show here.
tests/mocks/Unity/Notifications/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/Unity/Notifications/MockActionModel.h+1−1
This diff is too big to show here.
tests/mocks/Unity/Notifications/MockNotification.cpp−15
This diff is too big to show here.
tests/mocks/Unity/Notifications/MockNotification.h+1−7
This diff is too big to show here.
tests/mocks/Unity/Notifications/MockNotificationModel.cpp+6−4
This diff is too big to show here.
tests/mocks/Unity/Notifications/MockNotificationModel.h+4−2
This diff is too big to show here.
tests/mocks/Unity/Notifications/Notifications.qmltypesnew file+149
This diff is too big to show here.
tests/mocks/Unity/Platform/CMakeLists.txtdeleted−1
This diff is too big to show here.
tests/mocks/Unity/Platform/qmldirdeleted−2
This diff is too big to show here.
tests/mocks/Unity/Screens/CMakeLists.txt+2−2
This diff is too big to show here.
tests/mocks/Unity/Screens/screens.cpp+1−1
This diff is too big to show here.
tests/mocks/Unity/Screens/screens.h+1−1
This diff is too big to show here.
tests/mocks/Unity/Unity.qmltypesnew file+469
This diff is too big to show here.
tests/mocks/Unity/fake_categories.cppnew file+161
This diff is too big to show here.
tests/mocks/Unity/fake_categories.hnew file+54
This diff is too big to show here.
tests/mocks/Unity/fake_expandablefilterwidget.cppnew file+53
This diff is too big to show here.
tests/mocks/Unity/fake_expandablefilterwidget.hnew file+48
This diff is too big to show here.
tests/mocks/Unity/fake_filters.cppnew file+136
This diff is too big to show here.
tests/mocks/Unity/Launcher/MockAppDrawerModel.h → tests/mocks/Unity/fake_filters.hrenamed+17−14
This diff is too big to show here.
tests/mocks/Unity/fake_navigation.cppnew file+123
This diff is too big to show here.
tests/mocks/Unity/fake_navigation.hnew file+61
This diff is too big to show here.
tests/mocks/Unity/fake_optionselectorfilter.cppnew file+65
This diff is too big to show here.
tests/mocks/Unity/fake_optionselectorfilter.hnew file+52
This diff is too big to show here.
tests/mocks/Unity/fake_optionselectoroptions.cppnew file+77
This diff is too big to show here.
tests/mocks/Unity/fake_optionselectoroptions.hnew file+47
This diff is too big to show here.
tests/mocks/Unity/fake_previewmodel.cppnew file+95
This diff is too big to show here.
tests/mocks/Unity/fake_previewmodel.hnew file+58
This diff is too big to show here.
tests/mocks/Unity/fake_previewwidgetmodel.cppnew file+89
This diff is too big to show here.
tests/mocks/Unity/fake_previewwidgetmodel.hnew file+47
This diff is too big to show here.
tests/mocks/Unity/fake_rangeinputfilter.cppnew file+167
This diff is too big to show here.
tests/mocks/Unity/fake_rangeinputfilter.hnew file+79
This diff is too big to show here.
tests/mocks/Unity/fake_resultsmodel.cppnew file+92
This diff is too big to show here.
tests/mocks/Unity/fake_resultsmodel.hnew file+52
This diff is too big to show here.
tests/mocks/Unity/fake_scope.cppnew file+363
This diff is too big to show here.
tests/mocks/Unity/fake_scope.hnew file+127
This diff is too big to show here.
tests/mocks/Unity/fake_scopes.cppnew file+279
This diff is too big to show here.
tests/mocks/Unity/fake_scopes.hnew file+83
This diff is too big to show here.
tests/mocks/Unity/fake_scopesoverview.cppnew file+340
This diff is too big to show here.
tests/mocks/Unity/fake_scopesoverview.hnew file+117
This diff is too big to show here.
tests/mocks/Unity/fake_settingsmodel.cppnew file+95
This diff is too big to show here.
tests/mocks/Unity/fake_settingsmodel.hnew file+54
This diff is too big to show here.
tests/mocks/Unity/fake_unity_plugin.cppnew file+62
This diff is too big to show here.
tests/mocks/Unity/fake_unity_plugin.hnew file+34
This diff is too big to show here.
tests/mocks/Unity/fake_valuesliderfilter.cppnew file+84
This diff is too big to show here.
tests/mocks/Unity/fake_valuesliderfilter.hnew file+55
This diff is too big to show here.
tests/mocks/Unity/fake_valueslidervalues.cppnew file+51
This diff is too big to show here.
plugins/Lights/HfdLights.h → tests/mocks/Unity/fake_valueslidervalues.hrenamed+9−15
This diff is too big to show here.
tests/mocks/Unity/qmldirnew file+3
This diff is too big to show here.
tests/mocks/Utils/CMakeLists.txt+4−18
This diff is too big to show here.
tests/mocks/Utils/URLDispatcher.hdeleted−47
This diff is too big to show here.
tests/mocks/Utils/Utils.qmltypesnew file+178
This diff is too big to show here.
tests/mocks/Utils/constants.cpp+1−2
This diff is too big to show here.
tests/mocks/Utils/constants.h+5−5
This diff is too big to show here.
tests/mocks/Utils/plugin.cpp+1−11
This diff is too big to show here.
tests/mocks/Utils/windowstatestorage.cpp+4−27
This diff is too big to show here.
tests/mocks/Utils/windowstatestorage.h+7−15
This diff is too big to show here.
tests/mocks/Wizard/CMakeLists.txt+3−6
This diff is too big to show here.
tests/mocks/Wizard/MockSystem.cpp+1−24
This diff is too big to show here.
tests/mocks/Wizard/MockSystem.h+1−15
This diff is too big to show here.
tests/mocks/Wizard/Wizard.qmltypesnew file+37
This diff is too big to show here.
tests/mocks/Wizard/mockplugin.cpp−4
This diff is too big to show here.
tests/mocks/liblightdm/CMakeLists.txtdeleted−18
This diff is too big to show here.
tests/mocks/liblightdm/MockController.cppdeleted−192
This diff is too big to show here.
tests/mocks/liblightdm/MockController.hdeleted−106
This diff is too big to show here.
tests/mocks/liblightdm/MockGreeter.cppdeleted−316
This diff is too big to show here.
tests/mocks/liblightdm/MockSessionsModel.cppdeleted−118
This diff is too big to show here.
tests/mocks/liblightdm/MockSessionsModel.hdeleted−64
This diff is too big to show here.
tests/mocks/liblightdm/MockUsersModel.cppdeleted−220
This diff is too big to show here.
tests/mocks/liblightdm/SessionsModelPrivate.cppdeleted−83
This diff is too big to show here.
tests/mocks/liblightdm/SessionsModelPrivate.hdeleted−63
This diff is too big to show here.
tests/mocks/liblightdm/demo/CMakeLists.txt+1−1
This diff is too big to show here.
tests/mocks/libusermetrics/CMakeLists.txt+1−2
This diff is too big to show here.
tests/mocks/libusermetrics/ColorTheme.cpp−4
This diff is too big to show here.
tests/mocks/libusermetrics/UserMetrics.cpp+14−39
This diff is too big to show here.
tests/mocks/libusermetrics/UserMetrics.h−2
This diff is too big to show here.
tests/mocks/libusermetrics/libusermetricsoutput/ColorTheme.hnew file+1
This diff is too big to show here.
tests/mocks/libusermetrics/libusermetricsoutput/UserMetrics.hnew file+1
This diff is too big to show here.
tests/plugins/AccountsService/CMakeLists.txt+7−8
This diff is too big to show here.
tests/plugins/AccountsService/PropertiesServer.cpp+1−1
This diff is too big to show here.
tests/plugins/AccountsService/client.cpp+34−6
This diff is too big to show here.
tests/plugins/CMakeLists.txt+3−5
This diff is too big to show here.
tests/plugins/Cursor/CMakeLists.txtdeleted−8
This diff is too big to show here.
tests/plugins/Cursor/tst_Cursor.qmldeleted−151
This diff is too big to show here.
tests/plugins/Dash/CMakeLists.txtnew file+75
This diff is too big to show here.
tests/plugins/Dash/cardcreator/1.resnew file+95
This diff is too big to show here.
tests/plugins/Dash/cardcreator/1.res.cardcreatornew file+94
This diff is too big to show here.
tests/plugins/Dash/cardcreator/1.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/10.resnew file+130
This diff is too big to show here.
tests/plugins/Dash/cardcreator/10.res.cardcreatornew file+128
This diff is too big to show here.
tests/plugins/Dash/cardcreator/10.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/11.resnew file+189
This diff is too big to show here.
tests/plugins/Dash/cardcreator/11.res.cardcreatornew file+185
This diff is too big to show here.
tests/plugins/Dash/cardcreator/11.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/12.resnew file+121
This diff is too big to show here.
tests/plugins/Dash/cardcreator/12.res.cardcreatornew file+120
This diff is too big to show here.
tests/plugins/Dash/cardcreator/12.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/2.resnew file+129
This diff is too big to show here.
tests/plugins/Dash/cardcreator/2.res.cardcreatornew file+127
This diff is too big to show here.
tests/plugins/Dash/cardcreator/2.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/3.resnew file+104
This diff is too big to show here.
tests/plugins/Dash/cardcreator/3.res.cardcreatornew file+102
This diff is too big to show here.
tests/plugins/Dash/cardcreator/3.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/4.resnew file+110
This diff is too big to show here.
tests/plugins/Dash/cardcreator/4.res.cardcreatornew file+108
This diff is too big to show here.
tests/plugins/Dash/cardcreator/4.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/5.resnew file+117
This diff is too big to show here.
tests/plugins/Dash/cardcreator/5.res.cardcreatornew file+116
This diff is too big to show here.
tests/plugins/Dash/cardcreator/5.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/6.resnew file+126
This diff is too big to show here.
tests/plugins/Dash/cardcreator/6.res.cardcreatornew file+125
This diff is too big to show here.
tests/plugins/Dash/cardcreator/6.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/7.resnew file+142
This diff is too big to show here.
tests/plugins/Dash/cardcreator/7.res.cardcreatornew file+140
This diff is too big to show here.
tests/plugins/Dash/cardcreator/7.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/8.resnew file+108
This diff is too big to show here.
tests/plugins/Dash/cardcreator/8.res.cardcreatornew file+106
This diff is too big to show here.
tests/plugins/Dash/cardcreator/8.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreator/9.resnew file+119
This diff is too big to show here.
tests/plugins/Dash/cardcreator/9.res.cardcreatornew file+118
This diff is too big to show here.
tests/plugins/Dash/cardcreator/9.tstnew file+4
This diff is too big to show here.
tests/plugins/Dash/cardcreatortest.cppnew file+121
This diff is too big to show here.
tests/plugins/Dash/cardcreatortest.qmlnew file+29
This diff is too big to show here.
tests/plugins/Dash/horizontaljournaltest.cppnew file+490
This diff is too big to show here.
tests/plugins/Dash/horizontaljournaltest.qmlnew file+44
This diff is too big to show here.
tests/plugins/Dash/horizontaljournaltry.cppnew file+89
This diff is too big to show here.
tests/plugins/Dash/horizontaljournaltry.qmlnew file+120
This diff is too big to show here.
tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cppnew file+246
This diff is too big to show here.
tests/plugins/Dash/listviewwithpageheadersectiontest.cppnew file+2207
This diff is too big to show here.
tests/plugins/Dash/listviewwithpageheadertest.cppnew file+2004
This diff is too big to show here.
tests/plugins/Dash/listviewwithpageheadertest.qmlnew file+96
This diff is too big to show here.
tests/plugins/Dash/listviewwithpageheadertestsection.qmlnew file+108
This diff is too big to show here.
tests/plugins/Dash/listviewwithpageheadertestsectionexternalmodel.qmlnew file+76
This diff is too big to show here.
tests/plugins/Dash/organicgridtest.cppnew file+533
This diff is too big to show here.
tests/plugins/Dash/organicgridtest.qmlnew file+44
This diff is too big to show here.
tests/plugins/Dash/organicgridtry.cppnew file+97
This diff is too big to show here.
tests/plugins/Dash/organicgridtry.qmlnew file+114
This diff is too big to show here.
tests/plugins/Dash/tst_CardAttributes.qmlnew file+57
This diff is too big to show here.
tests/plugins/Dash/tst_CroppedImageMinimumSourceSize.qmlnew file+56
This diff is too big to show here.
tests/plugins/Dash/tst_ListViewWithPageHeaderQML.qmlnew file+140
This diff is too big to show here.
tests/plugins/Dash/tst_ScopeStyle.qmlnew file+188
This diff is too big to show here.
tests/plugins/Dash/verticaljournaltest.cppnew file+502
This diff is too big to show here.
tests/plugins/Dash/verticaljournaltest.qmlnew file+45
This diff is too big to show here.
tests/plugins/Dash/verticaljournaltry.cppnew file+89
This diff is too big to show here.
tests/plugins/Dash/verticaljournaltry.qmlnew file+121
This diff is too big to show here.
tests/plugins/GlobalShortcut/CMakeLists.txt+7−12
This diff is too big to show here.
tests/plugins/GlobalShortcut/GlobalShortcutTest.cpp+2−3
This diff is too big to show here.
tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+23−5
This diff is too big to show here.
tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+1−4
This diff is too big to show here.
tests/plugins/IntegratedLightDM/CMakeLists.txtnew file+93
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/dbus.cpp → tests/plugins/IntegratedLightDM/dbus.cpprenamed+12−22
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/greeter.qml → tests/plugins/IntegratedLightDM/greeter.qmlrenamed+7−2
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/integrated.cpp → tests/plugins/IntegratedLightDM/integrated.cpprenamed
The content is the same.
tests/plugins/LightDM/IntegratedLightDM/pam.cpp → tests/plugins/IntegratedLightDM/pam.cpprenamed
The content is the same.
tests/plugins/IntegratedLightDM/usersmodel.cppnew file+84
This diff is too big to show here.
tests/plugins/LightDM/CMakeLists.txtdeleted−1
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/CMakeLists.txtdeleted−157
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/promptsmodel.cppdeleted−175
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/sessionsmodel.cppdeleted−134
This diff is too big to show here.
tests/plugins/LightDM/IntegratedLightDM/usersmodel.cppdeleted−168
This diff is too big to show here.
tests/plugins/SessionBroadcast/BroadcastServer.cppdeleted−33
This diff is too big to show here.
tests/plugins/SessionBroadcast/BroadcastServer.hdeleted−40
This diff is too big to show here.
tests/plugins/SessionBroadcast/CMakeLists.txtdeleted−51
This diff is too big to show here.
tests/plugins/SessionBroadcast/interfaces.xmldeleted−18
This diff is too big to show here.
tests/plugins/SessionBroadcast/server.cppdeleted−37
This diff is too big to show here.
tests/plugins/SessionBroadcast/sessionbroadcasttest.cppdeleted−111
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/CMakeLists.txt+8−16
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/GestureTest.cpp+5−15
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/GestureTest.h+5−4
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/tst_AxisVelocityCalculator.cpp+1−1
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.cpp+1−1
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/tst_FloatingFlickable.qml+1−1
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/tst_TouchGate.cpp+4−17
This diff is too big to show here.
tests/plugins/Ubuntu/Gestures/tst_TouchGestureArea.cpp−30
This diff is too big to show here.
tests/plugins/Unity/CMakeLists.txt−1
This diff is too big to show here.
tests/plugins/Unity/Indicators/CMakeLists.txt+2−12
This diff is too big to show here.
tests/plugins/Unity/Indicators/IndicatorsManagerTest.cpp+1−1
This diff is too big to show here.
tests/plugins/Unity/Indicators/IndicatorsModelTest.cpp+1−1
This diff is too big to show here.
tests/plugins/Unity/Indicators/MenuContentActivatorTest.cpp−1
This diff is too big to show here.
tests/plugins/Unity/Launcher/CMakeLists.txt+21−57
This diff is too big to show here.
tests/plugins/Unity/Launcher/applications/abs-icon.desktop → tests/plugins/Unity/Launcher/abs-icon.desktoprenamed−1
This diff is too big to show here.
tests/plugins/Unity/Launcher/appdrawermodeltest.cppdeleted−68
This diff is too big to show here.
tests/plugins/Unity/Launcher/applications/click-icon.desktop → tests/plugins/Unity/Launcher/click-icon.desktoprenamed−1
This diff is too big to show here.
tests/plugins/Unity/Launcher/applications/click-icon.svg → tests/plugins/Unity/Launcher/click-icon.svgrenamed
The content is the same.
tests/plugins/Unity/Launcher/launchermodeltest.cpp+27−165
This diff is too big to show here.
tests/plugins/Unity/Launcher/no-icon.desktopnew file+2
This diff is too big to show here.
tests/plugins/Unity/Launcher/applications/no-name.desktop → tests/plugins/Unity/Launcher/no-name.desktoprenamed−1
This diff is too big to show here.
tests/plugins/Unity/Launcher/applications/rel-icon.desktop → tests/plugins/Unity/Launcher/rel-icon.desktoprenamed−1
This diff is too big to show here.
tests/plugins/Unity/Launcher/applications/rel-icon.svg → tests/plugins/Unity/Launcher/rel-icon.svgrenamed
The content is the same.
tests/plugins/Unity/Launcher/ualwrapper.cppdeleted−58
This diff is too big to show here.
tests/plugins/Unity/Launcher/ualwrapper.hdeleted−55
This diff is too big to show here.
tests/plugins/Unity/Launcher/xdgwatcher.cppdeleted−45
This diff is too big to show here.
tests/plugins/Unity/Launcher/xdgwatcher.hdeleted−39
This diff is too big to show here.
tests/plugins/Unity/Platform/CMakeLists.txtdeleted−30
This diff is too big to show here.
tests/plugins/Unity/Platform/platformtest.cppdeleted−142
This diff is too big to show here.
tests/plugins/Unity/Session/CMakeLists.txt+2−48
This diff is too big to show here.
tests/plugins/Unity/Session/LightDMServer.cppdeleted−29
This diff is too big to show here.
tests/plugins/Unity/Session/LightDMServer.hdeleted−38
This diff is too big to show here.
tests/plugins/Unity/Session/LogindServer.cppdeleted−43
This diff is too big to show here.
tests/plugins/Unity/Session/LogindServer.hdeleted−48
This diff is too big to show here.
tests/plugins/Unity/Session/interfaces.xmldeleted−29
This diff is too big to show here.
tests/plugins/Unity/Session/preload.cdeleted−43
This diff is too big to show here.
tests/plugins/Unity/Session/server.cppdeleted−50
This diff is too big to show here.
tests/plugins/Unity/Session/sessionbackendtest.cpp+9−142
This diff is too big to show here.
tests/plugins/Utils/CMakeLists.txt+3−20
This diff is too big to show here.
tests/plugins/Utils/DeviceConfigParserTest.cpp+1−7
This diff is too big to show here.
tests/plugins/Utils/ModelTest.cpp+1−2
This diff is too big to show here.
tests/plugins/Utils/URLDispatcherTest.cppdeleted−78
This diff is too big to show here.
tests/plugins/Utils/WindowInputMonitorTest.cpp+10−107
This diff is too big to show here.
tests/plugins/Utils/WindowStateStorageTest.cppdeleted−121
This diff is too big to show here.
tests/plugins/WindowManager/CMakeLists.txtdeleted−36
This diff is too big to show here.
tests/plugins/WindowManager/UnityApplicationMocks.hdeleted−211
This diff is too big to show here.
tests/plugins/WindowManager/tst_TopLevelWindowModel.cppdeleted−193
This diff is too big to show here.
tests/plugins/Wizard/CMakeLists.txt+2−8
This diff is too big to show here.
tests/plugins/Wizard/tst_pagelist.cpp+1−30
This diff is too big to show here.
tests/qmltests/ApplicationMenuDataLoader.qmldeleted−99
This diff is too big to show here.
tests/qmltests/ApplicationMenus/tst_MenuBar.qmldeleted−437
This diff is too big to show here.
tests/qmltests/ApplicationMenus/tst_MenuPopup.qmldeleted−361
This diff is too big to show here.
tests/qmltests/CMakeLists.txt+68−45
This diff is too big to show here.
tests/qmltests/Components/CMakeLists.txt+8−31
This diff is too big to show here.
tests/qmltests/Components/tst_Carousel.qmlnew file+293
This diff is too big to show here.
tests/qmltests/Components/tst_Dialogs.qml+1
This diff is too big to show here.
tests/qmltests/Components/tst_DragHandle.cpp+6−25
This diff is too big to show here.
tests/qmltests/Components/tst_DraggingArea.qml+6−6
This diff is too big to show here.
tests/qmltests/Components/tst_EdgeDragEvaluator.cpp+4−6
This diff is too big to show here.
tests/qmltests/Components/tst_LazyImage/portrait.png
Binary file not shown.
tests/qmltests/Components/tst_LazyImage/square.png
Binary file not shown.
tests/qmltests/Components/tst_LazyImage/wide.png
Binary file not shown.
tests/qmltests/Components/tst_Lockscreen.qml+32−14
This diff is too big to show here.
tests/qmltests/Components/tst_MediaServices.qmldeleted−231
This diff is too big to show here.
tests/qmltests/Components/tst_PhysicalKeysMapper.qml+27−19
This diff is too big to show here.
tests/qmltests/Components/tst_Rating.qml+1−1
This diff is too big to show here.
tests/qmltests/Components/tst_ResponsiveGridView.qmlnew file+157
This diff is too big to show here.
tests/qmltests/Components/tst_ResponsiveVerticalJournal.qmlnew file+183
This diff is too big to show here.
tests/qmltests/Components/tst_Showable.qml−13
This diff is too big to show here.
tests/qmltests/Components/tst_VirtualTouchPad.qml+1−55
This diff is too big to show here.
tests/qmltests/Components/tst_Wallpaper.qmldeleted−118
This diff is too big to show here.
tests/qmltests/Components/tst_WallpaperResolver.qml+43−115
This diff is too big to show here.
tests/qmltests/Components/tst_ZoomableImage.qml+2−2
This diff is too big to show here.
tests/qmltests/Dash/CardHelpers.jsnew file+115
This diff is too big to show here.
tests/qmltests/Dash/Filters/tst_FilterExpandableWidget.qmlnew file+99
This diff is too big to show here.
tests/qmltests/Dash/Filters/tst_FilterOptionSelector.qmlnew file+96
This diff is too big to show here.
tests/qmltests/Dash/Filters/tst_FilterRangeInput.qmlnew file+247
This diff is too big to show here.
tests/qmltests/Dash/Filters/tst_FilterValueSlider.qmlnew file+101
This diff is too big to show here.
tests/qmltests/Dash/Filters/tst_FilterWidgetFactory.qmlnew file+59
This diff is too big to show here.
tests/qmltests/Dash/Previews/MockPreviewWidget.qmlnew file+27
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_Preview.qmlnew file+134
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewActions.qmlnew file+231
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qmlnew file+184
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewComment.qmlnew file+84
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewCommentInput.qmlnew file+85
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewExpandable.qmlnew file+339
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewHeader.qmlnew file+187
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewIconActions.qmlnew file+136
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qmlnew file+147
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewMediaToolbar.qmlnew file+69
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewPayments.qmlnew file+203
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewProgress.qmlnew file+87
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qmlnew file+123
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewRatingDisplayCreationRanges.qmlnew file+94
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewRatingEdit.qmlnew file+84
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qmlnew file+214
This diff is too big to show here.
tests/qmltests/Components/tst_SharingPicker.qml → tests/qmltests/Dash/Previews/tst_PreviewSharing.qmlrenamed+11−11
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewTable.qmlnew file+126
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewTextSummary.qmlnew file+87
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewVideoPlayback.qmlnew file+61
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qmlnew file+103
This diff is too big to show here.
tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qmlnew file+133
This diff is too big to show here.
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qmlnew file+62
This diff is too big to show here.
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingList.qmlnew file+84
This diff is too big to show here.
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qmlnew file+98
This diff is too big to show here.
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qmlnew file+88
This diff is too big to show here.
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingsWidgetFactory.qmlnew file+65
This diff is too big to show here.
tests/qmltests/Dash/artwork/avatar@12.pngnew file
Binary file not shown.
tests/qmltests/Dash/artwork/background.pngnew file
Binary file not shown.
tests/qmltests/Dash/artwork/checkers.pngnew file
Binary file not shown.
tests/qmltests/Dash/artwork/emblem.pngnew file
Binary file not shown.
tests/qmltests/Dash/artwork/music-player-design.pngnew file
Binary file not shown.
tests/qmltests/Dash/tst_Card.qmlnew file+692
This diff is too big to show here.
tests/qmltests/Dash/tst_CardBenchmark.qmlnew file+95
This diff is too big to show here.
tests/qmltests/Dash/tst_CardCarousel.qmlnew file+87
This diff is too big to show here.
tests/qmltests/Dash/tst_CardTool.qmlnew file+379
This diff is too big to show here.
tests/qmltests/Dash/tst_Dash.qmlnew file+672
This diff is too big to show here.
tests/qmltests/Dash/tst_DashContent.qmlnew file+688
This diff is too big to show here.
tests/qmltests/Dash/tst_DashPageHeader.qmlnew file+316
This diff is too big to show here.
tests/qmltests/Dash/tst_DashShell.qmlnew file+139
This diff is too big to show here.
tests/qmltests/Dash/tst_GenericScopeView.qmlnew file+664
This diff is too big to show here.
tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svgnew file+60
This diff is too big to show here.
tests/qmltests/Dash/tst_PreviewView.qmlnew file+122
This diff is too big to show here.
tests/qmltests/Greeter/TestView.qml+22−24
This diff is too big to show here.
tests/qmltests/Greeter/tst_Greeter.qml+151−277
This diff is too big to show here.
tests/qmltests/Greeter/tst_GreeterView.qmldeleted−1366
This diff is too big to show here.
tests/qmltests/Greeter/tst_Infographics.qml+24−78
This diff is too big to show here.
tests/qmltests/Greeter/tst_NarrowView.qmlnew file+533
This diff is too big to show here.
tests/qmltests/Greeter/tst_WideView.qmlnew file+537
This diff is too big to show here.
tests/qmltests/Launcher/tst_Drawer.qmldeleted−520
This diff is too big to show here.
tests/qmltests/Launcher/tst_Launcher.qml+84−453
This diff is too big to show here.
tests/qmltests/Notifications/Notification.qml−1
This diff is too big to show here.
tests/qmltests/Notifications/tst_Notifications.qml+50−106
This diff is too big to show here.
tests/qmltests/Notifications/tst_OptionToggle.qml+22−13
This diff is too big to show here.
tests/qmltests/Notifications/tst_SwipeToAct.qml+26−19
This diff is too big to show here.
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+26−10
This diff is too big to show here.
tests/qmltests/Panel/PanelTest.qml → tests/qmltests/Panel/IndicatorTest.qmlrenamed+5
This diff is too big to show here.
tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml+8−168
This diff is too big to show here.
tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml → tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qmlrenamed+89−96
This diff is too big to show here.
tests/qmltests/Panel/PanelUI.qml−286
This diff is too big to show here.
tests/qmltests/Panel/tst_ActiveCallHint.qml+10−29
This diff is too big to show here.
tests/qmltests/Panel/tst_IndicatorItem.qml+4−5
This diff is too big to show here.
tests/qmltests/Panel/tst_IndicatorItemRow.qml+12−41
This diff is too big to show here.
tests/qmltests/Panel/tst_IndicatorPage.qml+49−53
This diff is too big to show here.
tests/qmltests/Panel/tst_IndicatorsBar.qml+34−25
This diff is too big to show here.
tests/qmltests/Panel/tst_IndicatorsMenu.qml+34−137
This diff is too big to show here.
tests/qmltests/Panel/tst_MenuContent.qml+4−16
This diff is too big to show here.
tests/qmltests/Panel/tst_Panel.qml+233−434
This diff is too big to show here.
tests/qmltests/Panel/tst_PanelSmallScreen.qml−133
This diff is too big to show here.
tests/qmltests/Stage/tst_DecoratedWindow.qml−267
This diff is too big to show here.
tests/qmltests/Stage/tst_DesktopStage.qml−1085
This diff is too big to show here.
tests/qmltests/Stage/tst_QMLTopLevelWindowModel.qml−191
This diff is too big to show here.
tests/qmltests/Stage/tst_WindowDecoration.qml−244
This diff is too big to show here.
tests/qmltests/Stages/ApplicationCheckBox.qml+9−9
This diff is too big to show here.
tests/qmltests/Stages/SizeHintField.qml
This diff is too big to show here.
tests/qmltests/Stages/SurfaceManagerControls.qml+1−1
This diff is too big to show here.
tests/qmltests/Stages/SurfaceManagerField.qml
This diff is too big to show here.
tests/qmltests/Stages/tst_ApplicationWindow.qml+41−52
This diff is too big to show here.
tests/qmltests/Stages/tst_DesktopStage.qml+658
This diff is too big to show here.
tests/qmltests/Stages/tst_PhoneStage.qml+285−239
This diff is too big to show here.
tests/qmltests/Stages/tst_Splash.qml+2−16
This diff is too big to show here.
tests/qmltests/Stages/tst_SpreadDelegate.qml+320
This diff is too big to show here.
tests/qmltests/Stages/tst_SurfaceContainer.qml+10−15
This diff is too big to show here.
tests/qmltests/Stages/tst_TabletStage.qml+309−315
This diff is too big to show here.
tests/qmltests/Stages/tst_WindowResizeArea.qml+115−73
This diff is too big to show here.
tests/qmltests/Tutorial/tst_Tutorial.qml+332−319
This diff is too big to show here.
tests/qmltests/UnityLogo.png
This diff is too big to show here.
tests/qmltests/Wizard/tst_Wizard.qml+135−138
This diff is too big to show here.
tests/qmltests/tst_DisabledScreenNotice.qml+10−24
This diff is too big to show here.
tests/qmltests/tst_OrientedShell.qml+489−513
This diff is too big to show here.
tests/qmltests/tst_Shell.qml+851−1775
This diff is too big to show here.
tests/qmltests/tst_ShellWithPin.qml+231−167
This diff is too big to show here.
tests/qmltests/utils/Unity/Test/tst_UnityTest.qml−31
This diff is too big to show here.
tests/scripts/alert-launcher-icon.sh−16
This diff is too big to show here.
tests/scripts/get-progress.sh−16
This diff is too big to show here.
tests/scripts/list-launcher-icons.sh−16
This diff is too big to show here.
tests/scripts/set-count-visible.sh−16
This diff is too big to show here.
tests/scripts/set-count.sh−16
This diff is too big to show here.
tests/scripts/set-progress.sh−16
This diff is too big to show here.
tests/uqmlscene/CMakeLists.txt+2−14
This diff is too big to show here.
tests/uqmlscene/main.cpp+4−7
This diff is too big to show here.
tests/utils/modules/Unity/Test/CMakeLists.txt+6−11
This diff is too big to show here.
tests/utils/modules/Unity/Test/MouseTouchEmulationCheckbox.qml+1−5
This diff is too big to show here.
tests/utils/modules/Unity/Test/StageTestCase.qml−64
This diff is too big to show here.
tests/utils/modules/Unity/Test/Test.qmltypes+60
This diff is too big to show here.
tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.cpp+4−18
This diff is too big to show here.
tests/utils/modules/Unity/Test/TouchEventSequenceWrapper.h+2−4
This diff is too big to show here.
tests/utils/modules/Unity/Test/UnityTestCase.qml+26−35
This diff is too big to show here.
tests/utils/modules/Unity/Test/qmldir+1−2
This diff is too big to show here.
tests/utils/modules/Unity/Test/testutil.cpp+5−33
This diff is too big to show here.
tests/utils/modules/Unity/Test/testutil.h−1
This diff is too big to show here.
tools/CMakeLists.txt+12−2
This diff is too big to show here.
tools/menutool/CMakeLists.txt−5
This diff is too big to show here.
tools/menutool/README−11
This diff is too big to show here.
tools/menutool/menutool.cpp−62
This diff is too big to show here.
tools/menutool/menutool.qml−118
This diff is too big to show here.
tools/registry-tracker.cpp+146
This diff is too big to show here.
tools/registry-tracker.h+49
This diff is too big to show here.
tools/scopetool.cpp+112
This diff is too big to show here.
tools/unix-signal-handler.cpp+6−4
This diff is too big to show here.
tools/unix-signal-handler.h
This diff is too big to show here.
tools/unlock-device−16
This diff is too big to show here.