Merge lp:~nick-dedekind/ubuntu-settings-components/1390136.laggy-backends into lp:~registry/ubuntu-settings-components/trunk
- 1390136.laggy-backends
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michał Sawicz |
Approved revision: | 99 |
Merged at revision: | 86 |
Proposed branch: | lp:~nick-dedekind/ubuntu-settings-components/1390136.laggy-backends |
Merge into: | lp:~registry/ubuntu-settings-components/trunk |
Diff against target: |
1467 lines (+1200/-42) 19 files modified
CMakeLists.txt (+1/-1) cmake/modules/QmlPlugins.cmake (+33/-26) debian/changelog (+13/-0) plugins/CMakeLists.txt (+8/-0) plugins/Ubuntu/Settings/CMakeLists.txt (+0/-7) plugins/Ubuntu/Settings/Components/CMakeLists.txt (+19/-1) plugins/Ubuntu/Settings/Components/Components.qmltypes (+73/-0) plugins/Ubuntu/Settings/Components/plugin.cpp (+27/-0) plugins/Ubuntu/Settings/Components/plugin.h (+30/-0) plugins/Ubuntu/Settings/Components/qmldir (+2/-0) plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp (+382/-0) plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h (+157/-0) plugins/Ubuntu/Settings/Menus/Menus.qmltypes (+30/-0) plugins/Ubuntu/Settings/Menus/plugin.cpp (+1/-1) plugins/Ubuntu/Settings/Menus/plugin.h (+4/-4) plugins/Ubuntu/Settings/Menus/qmldir (+1/-1) tests/qmltests/CMakeLists.txt (+2/-1) tests/qmltests/Components/tst_ServerPropertySynchroniser.qml (+398/-0) tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml (+19/-0) |
To merge this branch: | bzr merge lp:~nick-dedekind/ubuntu-settings-components/1390136.laggy-backends |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michał Sawicz (community) | Abstain | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Andrea Cimitan (community) | Approve | ||
Review via email:
|
Commit message
Added ServerActivatio
Description of the change
Added ServerActivatio
* Are there any related MPs required for this MP to build/function as expected? Please list.
No
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
N/A
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:90
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:91
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:92
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:94
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:94
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:95
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:96
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Andrea Cimitan (cimi) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass? If not, please explain why.
Yes
* Did you make sure that the branch does not contain spurious tags?
Yes
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
You need a bumped debian/changelog here.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Nick Dedekind (nick-dedekind) wrote : | # |
> You need a bumped debian/changelog here.
Changelog is there already.
I've moved the plugins to a plugins folder. Mostly because it resolves the relative path issue without changing the QmlPlugins.cmake so that we keep in line with unity8, but also because they are actually plugins anyway.
Fixed other comments as well.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) wrote : | # |
CMake Error at CMakeLists.txt:98 (add_subdirectory):
The source directory
/build/
does not contain a CMakeLists.txt file.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:98
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 99. By Nick Dedekind
-
added missing files
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:99
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Sawicz (saviq) : | # |
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2014-07-31 16:55:11 +0000 | |||
3 | +++ CMakeLists.txt 2015-04-09 12:58:32 +0000 | |||
4 | @@ -95,6 +95,6 @@ | |||
5 | 95 | # Tests | 95 | # Tests |
6 | 96 | enable_testing() | 96 | enable_testing() |
7 | 97 | 97 | ||
9 | 98 | add_subdirectory(Ubuntu) | 98 | add_subdirectory(plugins) |
10 | 99 | add_subdirectory(examples) | 99 | add_subdirectory(examples) |
11 | 100 | add_subdirectory(tests) | 100 | add_subdirectory(tests) |
12 | 101 | 101 | ||
13 | === modified file 'cmake/modules/QmlPlugins.cmake' | |||
14 | --- cmake/modules/QmlPlugins.cmake 2014-06-26 14:21:52 +0000 | |||
15 | +++ cmake/modules/QmlPlugins.cmake 2015-04-09 12:58:32 +0000 | |||
16 | @@ -12,6 +12,12 @@ | |||
17 | 12 | set_target_properties(qmlplugindump PROPERTIES IMPORTED_LOCATION ${qmlplugindump_exe}) | 12 | set_target_properties(qmlplugindump PROPERTIES IMPORTED_LOCATION ${qmlplugindump_exe}) |
18 | 13 | endif() | 13 | endif() |
19 | 14 | 14 | ||
20 | 15 | # | ||
21 | 16 | # A custom target for building the qmltypes files manually. | ||
22 | 17 | # | ||
23 | 18 | if (NOT TARGET qmltypes) | ||
24 | 19 | add_custom_target(qmltypes) | ||
25 | 20 | endif() | ||
26 | 15 | 21 | ||
27 | 16 | # Creates a target for copying resource files into build dir and optionally installing them. | 22 | # Creates a target for copying resource files into build dir and optionally installing them. |
28 | 17 | # | 23 | # |
29 | @@ -33,7 +39,7 @@ | |||
30 | 33 | macro(export_qmlfiles PLUGIN PATH) | 39 | macro(export_qmlfiles PLUGIN PATH) |
31 | 34 | set(single SEARCH_PATH BINARY_DIR DESTINATION TARGET_PREFIX) | 40 | set(single SEARCH_PATH BINARY_DIR DESTINATION TARGET_PREFIX) |
32 | 35 | cmake_parse_arguments(QMLFILES "" "${single}" "" ${ARGN}) | 41 | cmake_parse_arguments(QMLFILES "" "${single}" "" ${ARGN}) |
34 | 36 | 42 | ||
35 | 37 | if(NOT QMLFILES_SEARCH_PATH) | 43 | if(NOT QMLFILES_SEARCH_PATH) |
36 | 38 | set(QMLFILES_SEARCH_PATH ${CMAKE_CURRENT_SOURCE_DIR}) | 44 | set(QMLFILES_SEARCH_PATH ${CMAKE_CURRENT_SOURCE_DIR}) |
37 | 39 | endif() | 45 | endif() |
38 | @@ -51,6 +57,7 @@ | |||
39 | 51 | ${QMLFILES_SEARCH_PATH}/*.png | 57 | ${QMLFILES_SEARCH_PATH}/*.png |
40 | 52 | ${QMLFILES_SEARCH_PATH}/*.sci | 58 | ${QMLFILES_SEARCH_PATH}/*.sci |
41 | 53 | ${QMLFILES_SEARCH_PATH}/*.svg | 59 | ${QMLFILES_SEARCH_PATH}/*.svg |
42 | 60 | ${QMLFILES_SEARCH_PATH}/*.qmltypes | ||
43 | 54 | ${QMLFILES_SEARCH_PATH}/qmldir | 61 | ${QMLFILES_SEARCH_PATH}/qmldir |
44 | 55 | ) | 62 | ) |
45 | 56 | 63 | ||
46 | @@ -69,14 +76,14 @@ | |||
47 | 69 | DESTINATION ${QMLFILES_DESTINATION}/${PATH} | 76 | DESTINATION ${QMLFILES_DESTINATION}/${PATH} |
48 | 70 | ) | 77 | ) |
49 | 71 | endif() | 78 | endif() |
55 | 72 | endmacro(export_qmlfiles) | 79 | endmacro() |
56 | 73 | 80 | ||
57 | 74 | 81 | ||
58 | 75 | # Creates a target for generating the typeinfo file for a QML plugin and optionally installs it | 82 | # Creates a target for generating the typeinfo file for a QML plugin and/or installs the plugin |
59 | 76 | # and additional targets. | 83 | # targets. |
60 | 77 | # | 84 | # |
61 | 78 | # Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed | 85 | # Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed |
63 | 79 | # into ${DESTINATION}/${path}. If you don't pass BINARY_DIR, it's assumed that current source | 86 | # into ${DESTINATION}/${path}. If you don't pass BINARY_DIR, it's assumed that current source |
64 | 80 | # path ends with ${path}. | 87 | # path ends with ${path}. |
65 | 81 | # | 88 | # |
66 | 82 | # The generated file will be named after the last segment of the plugin name, e.g. Foo.qmltypes. | 89 | # The generated file will be named after the last segment of the plugin name, e.g. Foo.qmltypes. |
67 | @@ -87,15 +94,18 @@ | |||
68 | 87 | # [TARGET_PREFIX string] # Will be prefixed to the target name | 94 | # [TARGET_PREFIX string] # Will be prefixed to the target name |
69 | 88 | # [ENVIRONMENT string] # Will be added to qmlplugindump's env | 95 | # [ENVIRONMENT string] # Will be added to qmlplugindump's env |
70 | 89 | # [TARGETS target1 [target2 ...]] # Targets to depend on and install (e.g. the plugin shared object) | 96 | # [TARGETS target1 [target2 ...]] # Targets to depend on and install (e.g. the plugin shared object) |
71 | 97 | # [NO_TYPES] # Do not create the qmltypes target | ||
72 | 90 | # ) | 98 | # ) |
73 | 91 | # | 99 | # |
74 | 92 | # Created target: | 100 | # Created target: |
76 | 93 | # - ${TARGET_PREFIX}${plugin}-qmltypes - Generates the qmltypes file in the binary dir. | 101 | # - ${TARGET_PREFIX}${plugin}-qmltypes - Generates the qmltypes file in the source dir. |
77 | 102 | # It will be made a dependency of the "qmltypes" target. | ||
78 | 94 | 103 | ||
79 | 95 | macro(export_qmlplugin PLUGIN VERSION PATH) | 104 | macro(export_qmlplugin PLUGIN VERSION PATH) |
80 | 105 | set(options NO_TYPES) | ||
81 | 96 | set(single BINARY_DIR DESTINATION TARGET_PREFIX ENVIRONMENT) | 106 | set(single BINARY_DIR DESTINATION TARGET_PREFIX ENVIRONMENT) |
82 | 97 | set(multi TARGETS) | 107 | set(multi TARGETS) |
84 | 98 | cmake_parse_arguments(QMLPLUGIN "" "${single}" "${multi}" ${ARGN}) | 108 | cmake_parse_arguments(QMLPLUGIN "${options}" "${single}" "${multi}" ${ARGN}) |
85 | 99 | 109 | ||
86 | 100 | get_target_property(qmlplugindump_executable qmlplugindump LOCATION) | 110 | get_target_property(qmlplugindump_executable qmlplugindump LOCATION) |
87 | 101 | 111 | ||
88 | @@ -103,29 +113,26 @@ | |||
89 | 103 | set(qmlplugin_dir ${QMLPLUGIN_BINARY_DIR}/${PATH}) | 113 | set(qmlplugin_dir ${QMLPLUGIN_BINARY_DIR}/${PATH}) |
90 | 104 | else() | 114 | else() |
91 | 105 | # Find import path to point qmlplugindump at | 115 | # Find import path to point qmlplugindump at |
93 | 106 | string(REGEX REPLACE "${PATH}$" "" QMLPLUGIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") | 116 | string(REGEX REPLACE "/${PATH}$" "" QMLPLUGIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") |
94 | 107 | set(qmlplugin_dir ${CMAKE_CURRENT_BINARY_DIR}) | 117 | set(qmlplugin_dir ${CMAKE_CURRENT_BINARY_DIR}) |
95 | 108 | endif() | 118 | endif() |
96 | 109 | 119 | ||
105 | 110 | # Find the last segment of the plugin name to use as qmltypes basename | 120 | if(NOT QMLPLUGIN_NO_TYPES) |
106 | 111 | string(REGEX MATCH "[^.]+$" plugin_suffix ${PLUGIN}) | 121 | # Relative path for the module |
107 | 112 | set(target_prefix ${QMLPLUGIN_TARGET_PREFIX}${PLUGIN}) | 122 | string(REPLACE "${CMAKE_BINARY_DIR}/" "" QMLPLUGIN_MODULE_DIR "${QMLPLUGIN_BINARY_DIR}") |
108 | 113 | set(qmltypes_path ${qmlplugin_dir}/${plugin_suffix}.qmltypes) | 123 | |
109 | 114 | 124 | # Find the last segment of the plugin name to use as qmltypes basename | |
110 | 115 | # Only generate typeinfo if not cross compiling | 125 | string(REGEX MATCH "[^.]+$" plugin_suffix ${PLUGIN}) |
111 | 116 | if(NOT CMAKE_CROSSCOMPILING) | 126 | set(target_prefix ${QMLPLUGIN_TARGET_PREFIX}${PLUGIN}) |
112 | 117 | add_custom_target(${target_prefix}-qmltypes ALL | 127 | set(qmltypes_path ${CMAKE_CURRENT_SOURCE_DIR}/${plugin_suffix}.qmltypes) |
113 | 128 | |||
114 | 129 | add_custom_target(${target_prefix}-qmltypes | ||
115 | 118 | COMMAND env ${QMLPLUGIN_ENVIRONMENT} ${qmlplugindump_executable} -notrelocatable | 130 | COMMAND env ${QMLPLUGIN_ENVIRONMENT} ${qmlplugindump_executable} -notrelocatable |
117 | 119 | ${PLUGIN} ${VERSION} ${QMLPLUGIN_BINARY_DIR} > ${qmltypes_path} | 131 | ${PLUGIN} ${VERSION} ${QMLPLUGIN_MODULE_DIR} > ${qmltypes_path} |
118 | 132 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | ||
119 | 120 | ) | 133 | ) |
120 | 121 | add_dependencies(${target_prefix}-qmltypes ${target_prefix}-qmlfiles ${QMLPLUGIN_TARGETS}) | 134 | add_dependencies(${target_prefix}-qmltypes ${target_prefix}-qmlfiles ${QMLPLUGIN_TARGETS}) |
128 | 122 | 135 | add_dependencies(qmltypes ${target_prefix}-qmltypes) | |
122 | 123 | if (QMLPLUGIN_DESTINATION) | ||
123 | 124 | # Install the typeinfo file | ||
124 | 125 | install(FILES ${qmltypes_path} | ||
125 | 126 | DESTINATION ${QMLPLUGIN_DESTINATION}/${PATH} | ||
126 | 127 | ) | ||
127 | 128 | endif() | ||
129 | 129 | endif() | 136 | endif() |
130 | 130 | 137 | ||
131 | 131 | set_target_properties(${QMLPLUGIN_TARGETS} PROPERTIES | 138 | set_target_properties(${QMLPLUGIN_TARGETS} PROPERTIES |
132 | 132 | 139 | ||
133 | === modified file 'debian/changelog' | |||
134 | --- debian/changelog 2015-01-23 12:17:25 +0000 | |||
135 | +++ debian/changelog 2015-04-09 12:58:32 +0000 | |||
136 | @@ -1,3 +1,10 @@ | |||
137 | 1 | ubuntu-settings-components (0.6-0ubuntu1) UNRELEASED; urgency=medium | ||
138 | 2 | |||
139 | 3 | [ Nick Dedekind ] | ||
140 | 4 | * Added ServerActivationSync | ||
141 | 5 | |||
142 | 6 | -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 12 Mar 2015 14:04:34 +0000 | ||
143 | 7 | |||
144 | 1 | ubuntu-settings-components (0.5+15.04.20150123.1-0ubuntu1) vivid; urgency=medium | 8 | ubuntu-settings-components (0.5+15.04.20150123.1-0ubuntu1) vivid; urgency=medium |
145 | 2 | 9 | ||
146 | 3 | [ Sebastien Bacher ] | 10 | [ Sebastien Bacher ] |
147 | @@ -5,6 +12,12 @@ | |||
148 | 5 | 12 | ||
149 | 6 | -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 23 Jan 2015 12:17:25 +0000 | 13 | -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 23 Jan 2015 12:17:25 +0000 |
150 | 7 | 14 | ||
151 | 15 | ubuntu-settings-components (0.5-0ubuntu1) UNRELEASED; urgency=medium | ||
152 | 16 | |||
153 | 17 | * Added SyncSwitch & SyncCheckBox components | ||
154 | 18 | |||
155 | 19 | -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 23 Oct 2014 17:09:21 -0400 | ||
156 | 20 | |||
157 | 8 | ubuntu-settings-components (0.4+15.04.20141105-0ubuntu1) vivid; urgency=low | 21 | ubuntu-settings-components (0.4+15.04.20141105-0ubuntu1) vivid; urgency=low |
158 | 9 | 22 | ||
159 | 10 | [ Sebastien Bacher ] | 23 | [ Sebastien Bacher ] |
160 | 11 | 24 | ||
161 | === added directory 'plugins' | |||
162 | === added file 'plugins/CMakeLists.txt' | |||
163 | --- plugins/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
164 | +++ plugins/CMakeLists.txt 2015-04-09 12:58:32 +0000 | |||
165 | @@ -0,0 +1,8 @@ | |||
166 | 1 | include(QmlPlugins) | ||
167 | 2 | |||
168 | 3 | macro(add_usc_plugin PLUGIN VERSION PATH) | ||
169 | 4 | export_qmlfiles(${PLUGIN} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN}) | ||
170 | 5 | export_qmlplugin(${PLUGIN} ${VERSION} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN}) | ||
171 | 6 | endmacro() | ||
172 | 7 | |||
173 | 8 | add_subdirectory(Ubuntu) | ||
174 | 0 | 9 | ||
175 | === renamed directory 'Ubuntu' => 'plugins/Ubuntu' | |||
176 | === modified file 'plugins/Ubuntu/Settings/CMakeLists.txt' | |||
177 | --- Ubuntu/Settings/CMakeLists.txt 2014-06-26 14:21:52 +0000 | |||
178 | +++ plugins/Ubuntu/Settings/CMakeLists.txt 2015-04-09 12:58:32 +0000 | |||
179 | @@ -1,9 +1,2 @@ | |||
180 | 1 | include(QmlPlugins) | ||
181 | 2 | |||
182 | 3 | macro(add_usc_plugin PLUGIN VERSION PATH) | ||
183 | 4 | export_qmlfiles(${PLUGIN} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN}) | ||
184 | 5 | export_qmlplugin(${PLUGIN} ${VERSION} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN}) | ||
185 | 6 | endmacro() | ||
186 | 7 | |||
187 | 8 | add_subdirectory(Components) | 1 | add_subdirectory(Components) |
188 | 9 | add_subdirectory(Menus) | 2 | add_subdirectory(Menus) |
189 | 10 | 3 | ||
190 | === modified file 'plugins/Ubuntu/Settings/Components/CMakeLists.txt' | |||
191 | --- Ubuntu/Settings/Components/CMakeLists.txt 2014-07-31 13:05:44 +0000 | |||
192 | +++ plugins/Ubuntu/Settings/Components/CMakeLists.txt 2015-04-09 12:58:32 +0000 | |||
193 | @@ -1,1 +1,19 @@ | |||
195 | 1 | add_usc_plugin(Ubuntu.Settings.Components 0.1 Ubuntu/Settings/Components) | 1 | project(UbuntuSettingsComponentsQml) |
196 | 2 | |||
197 | 3 | find_package(Qt5Core REQUIRED) | ||
198 | 4 | |||
199 | 5 | include_directories( | ||
200 | 6 | ${CMAKE_CURRENT_SOURCE_DIR} | ||
201 | 7 | ${CMAKE_CURRENT_BINARY_DIR} | ||
202 | 8 | ) | ||
203 | 9 | |||
204 | 10 | add_definitions(-DUBUNTUSETTINGSCOMPONENTS_LIBRARY) | ||
205 | 11 | |||
206 | 12 | add_library(UbuntuSettingsComponentsQml MODULE | ||
207 | 13 | plugin.cpp | ||
208 | 14 | serverpropertysynchroniser.cpp | ||
209 | 15 | ) | ||
210 | 16 | |||
211 | 17 | qt5_use_modules(UbuntuSettingsComponentsQml Core Qml Quick) | ||
212 | 18 | |||
213 | 19 | add_usc_plugin(Ubuntu.Settings.Components 0.1 Ubuntu/Settings/Components TARGETS UbuntuSettingsComponentsQml) | ||
214 | 2 | 20 | ||
215 | === added file 'plugins/Ubuntu/Settings/Components/Components.qmltypes' | |||
216 | --- plugins/Ubuntu/Settings/Components/Components.qmltypes 1970-01-01 00:00:00 +0000 | |||
217 | +++ plugins/Ubuntu/Settings/Components/Components.qmltypes 2015-04-09 12:58:32 +0000 | |||
218 | @@ -0,0 +1,73 @@ | |||
219 | 1 | import QtQuick.tooling 1.1 | ||
220 | 2 | |||
221 | 3 | // This file describes the plugin-supplied types contained in the library. | ||
222 | 4 | // It is used for QML tooling purposes only. | ||
223 | 5 | // | ||
224 | 6 | // This file was auto-generated by: | ||
225 | 7 | // 'qmlplugindump -notrelocatable Ubuntu.Settings.Components 0.1 plugins' | ||
226 | 8 | |||
227 | 9 | Module { | ||
228 | 10 | Component { | ||
229 | 11 | name: "ServerPropertySynchroniser" | ||
230 | 12 | prototype: "QObject" | ||
231 | 13 | exports: ["Ubuntu.Settings.Components/ServerPropertySynchroniser 0.1"] | ||
232 | 14 | exportMetaObjectRevisions: [0] | ||
233 | 15 | Property { name: "serverTarget"; type: "QObject"; isPointer: true } | ||
234 | 16 | Property { name: "serverProperty"; type: "string" } | ||
235 | 17 | Property { name: "userTarget"; type: "QObject"; isPointer: true } | ||
236 | 18 | Property { name: "userProperty"; type: "string" } | ||
237 | 19 | Property { name: "userTrigger"; type: "string" } | ||
238 | 20 | Property { name: "syncTimeout"; type: "int" } | ||
239 | 21 | Property { name: "useWaitBuffer"; type: "bool" } | ||
240 | 22 | Property { name: "maximumWaitBufferInterval"; type: "int" } | ||
241 | 23 | Property { name: "bufferedSyncTimeout"; type: "bool" } | ||
242 | 24 | Property { name: "syncWaiting"; type: "bool"; isReadonly: true } | ||
243 | 25 | Signal { | ||
244 | 26 | name: "serverTargetChanged" | ||
245 | 27 | Parameter { name: "serverTarget"; type: "QObject"; isPointer: true } | ||
246 | 28 | } | ||
247 | 29 | Signal { | ||
248 | 30 | name: "serverPropertyChanged" | ||
249 | 31 | Parameter { name: "serverProperty"; type: "string" } | ||
250 | 32 | } | ||
251 | 33 | Signal { | ||
252 | 34 | name: "userTargetChanged" | ||
253 | 35 | Parameter { name: "userTarget"; type: "QObject"; isPointer: true } | ||
254 | 36 | } | ||
255 | 37 | Signal { | ||
256 | 38 | name: "userPropertyChanged" | ||
257 | 39 | Parameter { name: "serverProperty"; type: "string" } | ||
258 | 40 | } | ||
259 | 41 | Signal { | ||
260 | 42 | name: "userTriggerChanged" | ||
261 | 43 | Parameter { name: "userTrigger"; type: "string" } | ||
262 | 44 | } | ||
263 | 45 | Signal { | ||
264 | 46 | name: "syncTimeoutChanged" | ||
265 | 47 | Parameter { name: "timeout"; type: "int" } | ||
266 | 48 | } | ||
267 | 49 | Signal { | ||
268 | 50 | name: "syncWaitingChanged" | ||
269 | 51 | Parameter { name: "waiting"; type: "bool" } | ||
270 | 52 | } | ||
271 | 53 | Signal { | ||
272 | 54 | name: "bufferedSyncTimeoutChanged" | ||
273 | 55 | Parameter { type: "bool" } | ||
274 | 56 | } | ||
275 | 57 | Signal { | ||
276 | 58 | name: "useWaitBufferChanged" | ||
277 | 59 | Parameter { name: "useWaitBuffer"; type: "bool" } | ||
278 | 60 | } | ||
279 | 61 | Signal { | ||
280 | 62 | name: "maximumWaitBufferIntervalChanged" | ||
281 | 63 | Parameter { name: "timeout"; type: "int" } | ||
282 | 64 | } | ||
283 | 65 | Signal { | ||
284 | 66 | name: "syncTriggered" | ||
285 | 67 | Parameter { name: "value"; type: "QVariant" } | ||
286 | 68 | } | ||
287 | 69 | Method { name: "updateUserValue" } | ||
288 | 70 | Method { name: "activate" } | ||
289 | 71 | Method { name: "reset" } | ||
290 | 72 | } | ||
291 | 73 | } | ||
292 | 0 | 74 | ||
293 | === added file 'plugins/Ubuntu/Settings/Components/plugin.cpp' | |||
294 | --- plugins/Ubuntu/Settings/Components/plugin.cpp 1970-01-01 00:00:00 +0000 | |||
295 | +++ plugins/Ubuntu/Settings/Components/plugin.cpp 2015-04-09 12:58:32 +0000 | |||
296 | @@ -0,0 +1,27 @@ | |||
297 | 1 | /* | ||
298 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
299 | 3 | * | ||
300 | 4 | * This program is free software; you can redistribute it and/or modify | ||
301 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
302 | 6 | * the Free Software Foundation; version 3. | ||
303 | 7 | * | ||
304 | 8 | * This program is distributed in the hope that it will be useful, | ||
305 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
306 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
307 | 11 | * GNU Lesser General Public License for more details. | ||
308 | 12 | * | ||
309 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
310 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
311 | 15 | */ | ||
312 | 16 | |||
313 | 17 | // local | ||
314 | 18 | #include "plugin.h" | ||
315 | 19 | #include "serverpropertysynchroniser.h" | ||
316 | 20 | |||
317 | 21 | // Qt | ||
318 | 22 | #include <QtQml/qqml.h> | ||
319 | 23 | |||
320 | 24 | void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri) | ||
321 | 25 | { | ||
322 | 26 | qmlRegisterType<ServerPropertySynchroniser>(uri, 0, 1, "ServerPropertySynchroniser"); | ||
323 | 27 | } | ||
324 | 0 | 28 | ||
325 | === added file 'plugins/Ubuntu/Settings/Components/plugin.h' | |||
326 | --- plugins/Ubuntu/Settings/Components/plugin.h 1970-01-01 00:00:00 +0000 | |||
327 | +++ plugins/Ubuntu/Settings/Components/plugin.h 2015-04-09 12:58:32 +0000 | |||
328 | @@ -0,0 +1,30 @@ | |||
329 | 1 | /* | ||
330 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
331 | 3 | * | ||
332 | 4 | * This program is free software; you can redistribute it and/or modify | ||
333 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
334 | 6 | * the Free Software Foundation; version 3. | ||
335 | 7 | * | ||
336 | 8 | * This program is distributed in the hope that it will be useful, | ||
337 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
338 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
339 | 11 | * GNU Lesser General Public License for more details. | ||
340 | 12 | * | ||
341 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
342 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
343 | 15 | */ | ||
344 | 16 | |||
345 | 17 | #ifndef UBUNTUSETTINGSCOMPONENTS_PLUGIN_H | ||
346 | 18 | #define UBUNTUSETTINGSCOMPONENTS_PLUGIN_H | ||
347 | 19 | |||
348 | 20 | #include <QtQml/QQmlExtensionPlugin> | ||
349 | 21 | |||
350 | 22 | class UbuntuSettingsComponentsPlugin : public QQmlExtensionPlugin | ||
351 | 23 | { | ||
352 | 24 | Q_OBJECT | ||
353 | 25 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") | ||
354 | 26 | public: | ||
355 | 27 | void registerTypes(const char *uri); | ||
356 | 28 | }; | ||
357 | 29 | |||
358 | 30 | #endif // UBUNTUSETTINGSCOMPONENTS_PLUGIN_H | ||
359 | 0 | 31 | ||
360 | === modified file 'plugins/Ubuntu/Settings/Components/qmldir' | |||
361 | --- Ubuntu/Settings/Components/qmldir 2014-09-15 17:18:27 +0000 | |||
362 | +++ plugins/Ubuntu/Settings/Components/qmldir 2015-04-09 12:58:32 +0000 | |||
363 | @@ -1,4 +1,6 @@ | |||
364 | 1 | module Ubuntu.Settings.Components | 1 | module Ubuntu.Settings.Components |
365 | 2 | plugin UbuntuSettingsComponentsQml | ||
366 | 3 | typeinfo Components.qmltypes | ||
367 | 2 | 4 | ||
368 | 3 | ActionTextField 0.1 ActionTextField.qml | 5 | ActionTextField 0.1 ActionTextField.qml |
369 | 4 | Calendar 0.1 Calendar.qml | 6 | Calendar 0.1 Calendar.qml |
370 | 5 | 7 | ||
371 | === added file 'plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp' | |||
372 | --- plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp 1970-01-01 00:00:00 +0000 | |||
373 | +++ plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp 2015-04-09 12:58:32 +0000 | |||
374 | @@ -0,0 +1,382 @@ | |||
375 | 1 | /* | ||
376 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
377 | 3 | * | ||
378 | 4 | * This program is free software; you can redistribute it and/or modify | ||
379 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
380 | 6 | * the Free Software Foundation; version 3. | ||
381 | 7 | * | ||
382 | 8 | * This program is distributed in the hope that it will be useful, | ||
383 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
384 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
385 | 11 | * GNU Lesser General Public License for more details. | ||
386 | 12 | * | ||
387 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
388 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
389 | 15 | */ | ||
390 | 16 | |||
391 | 17 | #include "serverpropertysynchroniser.h" | ||
392 | 18 | |||
393 | 19 | #include <QQmlProperty> | ||
394 | 20 | #include <QTimer> | ||
395 | 21 | #include <QDebug> | ||
396 | 22 | |||
397 | 23 | ServerPropertySynchroniser::ServerPropertySynchroniser(QObject* parent) | ||
398 | 24 | : QObject(parent) | ||
399 | 25 | , m_serverTarget(nullptr) | ||
400 | 26 | , m_userTarget(nullptr) | ||
401 | 27 | , m_classComplete(false) | ||
402 | 28 | , m_busy(false) | ||
403 | 29 | , m_connectedServerTarget(nullptr) | ||
404 | 30 | , m_connectedUserTarget(nullptr) | ||
405 | 31 | , m_serverSyncTimer(new QTimer(this)) | ||
406 | 32 | , m_bufferTimeout(nullptr) | ||
407 | 33 | , m_useWaitBuffer(true) | ||
408 | 34 | , m_buffering(false) | ||
409 | 35 | , m_bufferedSyncTimeout(false) | ||
410 | 36 | { | ||
411 | 37 | m_serverSyncTimer->setSingleShot(true); | ||
412 | 38 | m_serverSyncTimer->setInterval(30000); | ||
413 | 39 | connect(m_serverSyncTimer, &QTimer::timeout, this, &ServerPropertySynchroniser::serverSyncTimedOut); | ||
414 | 40 | } | ||
415 | 41 | |||
416 | 42 | void ServerPropertySynchroniser::classBegin() | ||
417 | 43 | { | ||
418 | 44 | m_classComplete = false; | ||
419 | 45 | } | ||
420 | 46 | |||
421 | 47 | void ServerPropertySynchroniser::componentComplete() | ||
422 | 48 | { | ||
423 | 49 | m_classComplete = true; | ||
424 | 50 | connectServer(); | ||
425 | 51 | connectUser(); | ||
426 | 52 | } | ||
427 | 53 | |||
428 | 54 | void ServerPropertySynchroniser::reset() | ||
429 | 55 | { | ||
430 | 56 | if (m_serverSyncTimer->isActive()) { | ||
431 | 57 | m_serverSyncTimer->stop(); | ||
432 | 58 | Q_EMIT syncWaitingChanged(false); | ||
433 | 59 | } | ||
434 | 60 | if (m_bufferTimeout) m_bufferTimeout->stop(); | ||
435 | 61 | m_buffering = false; | ||
436 | 62 | } | ||
437 | 63 | |||
438 | 64 | QObject *ServerPropertySynchroniser::serverTarget() const | ||
439 | 65 | { | ||
440 | 66 | return m_serverTarget; | ||
441 | 67 | } | ||
442 | 68 | |||
443 | 69 | void ServerPropertySynchroniser::setServerTarget(QObject *target) | ||
444 | 70 | { | ||
445 | 71 | if (m_serverTarget != target) { | ||
446 | 72 | m_serverTarget = target; | ||
447 | 73 | Q_EMIT serverTargetChanged(m_serverTarget); | ||
448 | 74 | |||
449 | 75 | connectServer(); | ||
450 | 76 | } | ||
451 | 77 | } | ||
452 | 78 | |||
453 | 79 | QString ServerPropertySynchroniser::serverProperty() const | ||
454 | 80 | { | ||
455 | 81 | return m_serverProperty; | ||
456 | 82 | } | ||
457 | 83 | |||
458 | 84 | void ServerPropertySynchroniser::setServerProperty(const QString &property) | ||
459 | 85 | { | ||
460 | 86 | if (m_serverProperty != property) { | ||
461 | 87 | m_serverProperty = property; | ||
462 | 88 | Q_EMIT serverPropertyChanged(m_serverProperty); | ||
463 | 89 | |||
464 | 90 | connectServer(); | ||
465 | 91 | } | ||
466 | 92 | } | ||
467 | 93 | |||
468 | 94 | QObject *ServerPropertySynchroniser::userTarget() const | ||
469 | 95 | { | ||
470 | 96 | return m_userTarget; | ||
471 | 97 | } | ||
472 | 98 | |||
473 | 99 | void ServerPropertySynchroniser::setUserTarget(QObject *target) | ||
474 | 100 | { | ||
475 | 101 | if (m_userTarget != target) { | ||
476 | 102 | m_userTarget = target; | ||
477 | 103 | Q_EMIT userTargetChanged(m_userTarget); | ||
478 | 104 | |||
479 | 105 | connectUser(); | ||
480 | 106 | } | ||
481 | 107 | } | ||
482 | 108 | |||
483 | 109 | QString ServerPropertySynchroniser::userProperty() const | ||
484 | 110 | { | ||
485 | 111 | return m_userProperty; | ||
486 | 112 | } | ||
487 | 113 | |||
488 | 114 | void ServerPropertySynchroniser::setUserProperty(const QString &property) | ||
489 | 115 | { | ||
490 | 116 | if (m_userProperty != property) { | ||
491 | 117 | m_userProperty = property; | ||
492 | 118 | Q_EMIT userPropertyChanged(m_userProperty); | ||
493 | 119 | |||
494 | 120 | connectUser(); | ||
495 | 121 | } | ||
496 | 122 | } | ||
497 | 123 | |||
498 | 124 | QString ServerPropertySynchroniser::userTrigger() const | ||
499 | 125 | { | ||
500 | 126 | return m_userTrigger; | ||
501 | 127 | } | ||
502 | 128 | |||
503 | 129 | void ServerPropertySynchroniser::setUserTrigger(const QString &trigger) | ||
504 | 130 | { | ||
505 | 131 | if (m_userTrigger != trigger) { | ||
506 | 132 | m_userTrigger = trigger; | ||
507 | 133 | Q_EMIT userPropertyChanged(m_userTrigger); | ||
508 | 134 | |||
509 | 135 | connectUser(); | ||
510 | 136 | } | ||
511 | 137 | } | ||
512 | 138 | |||
513 | 139 | int ServerPropertySynchroniser::syncTimeout() const | ||
514 | 140 | { | ||
515 | 141 | return m_serverSyncTimer->interval(); | ||
516 | 142 | } | ||
517 | 143 | |||
518 | 144 | void ServerPropertySynchroniser::setSyncTimeout(int timeout) | ||
519 | 145 | { | ||
520 | 146 | if (m_serverSyncTimer->interval() != timeout) { | ||
521 | 147 | m_serverSyncTimer->setInterval(timeout); | ||
522 | 148 | Q_EMIT syncTimeoutChanged(timeout); | ||
523 | 149 | } | ||
524 | 150 | } | ||
525 | 151 | |||
526 | 152 | bool ServerPropertySynchroniser::useWaitBuffer() const | ||
527 | 153 | { | ||
528 | 154 | return m_useWaitBuffer; | ||
529 | 155 | } | ||
530 | 156 | |||
531 | 157 | void ServerPropertySynchroniser::setUseWaitBuffer(bool value) | ||
532 | 158 | { | ||
533 | 159 | if (m_useWaitBuffer != value) { | ||
534 | 160 | m_useWaitBuffer = value; | ||
535 | 161 | Q_EMIT useWaitBufferChanged(m_useWaitBuffer); | ||
536 | 162 | } | ||
537 | 163 | } | ||
538 | 164 | |||
539 | 165 | int ServerPropertySynchroniser::maximumWaitBufferInterval() const | ||
540 | 166 | { | ||
541 | 167 | return m_bufferTimeout ? m_bufferTimeout->interval() : -1; | ||
542 | 168 | } | ||
543 | 169 | |||
544 | 170 | void ServerPropertySynchroniser::setMaximumWaitBufferInterval(int timeout) | ||
545 | 171 | { | ||
546 | 172 | if (timeout >= 0) { | ||
547 | 173 | if (!m_bufferTimeout) { | ||
548 | 174 | m_bufferTimeout = new QTimer(this); | ||
549 | 175 | m_bufferTimeout->setInterval(timeout); | ||
550 | 176 | m_bufferTimeout->setSingleShot(true); | ||
551 | 177 | connect(m_bufferTimeout, &QTimer::timeout, this, &ServerPropertySynchroniser::bufferTimedOut); | ||
552 | 178 | |||
553 | 179 | Q_EMIT maximumWaitBufferIntervalChanged(timeout); | ||
554 | 180 | } | ||
555 | 181 | else if (timeout != m_bufferTimeout->interval()) { | ||
556 | 182 | m_bufferTimeout->setInterval(timeout); | ||
557 | 183 | Q_EMIT maximumWaitBufferIntervalChanged(timeout); | ||
558 | 184 | } | ||
559 | 185 | |||
560 | 186 | } else if (m_bufferTimeout) { | ||
561 | 187 | if (m_bufferTimeout->isActive()) { | ||
562 | 188 | m_buffering = false; | ||
563 | 189 | } | ||
564 | 190 | delete m_bufferTimeout; | ||
565 | 191 | m_bufferTimeout = nullptr; | ||
566 | 192 | Q_EMIT maximumWaitBufferIntervalChanged(timeout); | ||
567 | 193 | } | ||
568 | 194 | } | ||
569 | 195 | |||
570 | 196 | bool ServerPropertySynchroniser::bufferedSyncTimeout() const | ||
571 | 197 | { | ||
572 | 198 | return m_bufferedSyncTimeout; | ||
573 | 199 | } | ||
574 | 200 | |||
575 | 201 | void ServerPropertySynchroniser::setBufferedSyncTimeout(bool value) | ||
576 | 202 | { | ||
577 | 203 | if (m_bufferedSyncTimeout != value) { | ||
578 | 204 | m_bufferedSyncTimeout = value; | ||
579 | 205 | Q_EMIT bufferedSyncTimeoutChanged(value); | ||
580 | 206 | } | ||
581 | 207 | } | ||
582 | 208 | |||
583 | 209 | bool ServerPropertySynchroniser::syncWaiting() const | ||
584 | 210 | { | ||
585 | 211 | return m_serverSyncTimer->isActive(); | ||
586 | 212 | } | ||
587 | 213 | |||
588 | 214 | void ServerPropertySynchroniser::activate() | ||
589 | 215 | { | ||
590 | 216 | // Don't want any signals we fire to create binding loops. | ||
591 | 217 | if (m_busy) return; | ||
592 | 218 | m_busy = true; | ||
593 | 219 | |||
594 | 220 | if (m_useWaitBuffer) { | ||
595 | 221 | // Dampen the activations? Buffer the change. | ||
596 | 222 | if (m_bufferTimeout) { | ||
597 | 223 | if (m_bufferTimeout->isActive()) { | ||
598 | 224 | m_buffering = true; | ||
599 | 225 | m_busy = false; | ||
600 | 226 | return; | ||
601 | 227 | } | ||
602 | 228 | m_bufferTimeout->start(); | ||
603 | 229 | // Not using a buffer timer? Buffer the change till server timeout | ||
604 | 230 | } else if (m_serverSyncTimer->isActive()) { | ||
605 | 231 | m_buffering = true; | ||
606 | 232 | m_busy = false; | ||
607 | 233 | return; | ||
608 | 234 | } | ||
609 | 235 | } | ||
610 | 236 | |||
611 | 237 | m_serverSyncTimer->start(); | ||
612 | 238 | Q_EMIT syncWaitingChanged(true); | ||
613 | 239 | |||
614 | 240 | // Fire off a change to the server user property value | ||
615 | 241 | QQmlProperty userProp(m_userTarget, m_userProperty); | ||
616 | 242 | if (!userProp.isValid()) { | ||
617 | 243 | Q_EMIT syncTriggered(QVariant()); | ||
618 | 244 | } else { | ||
619 | 245 | Q_EMIT syncTriggered(userProp.read()); | ||
620 | 246 | } | ||
621 | 247 | m_busy = false; | ||
622 | 248 | } | ||
623 | 249 | |||
624 | 250 | void ServerPropertySynchroniser::connectServer() | ||
625 | 251 | { | ||
626 | 252 | // if we havent finished constructing the class, then wait | ||
627 | 253 | if (!m_classComplete) return; | ||
628 | 254 | |||
629 | 255 | if (m_connectedServerTarget) QObject::disconnect(m_connectedServerTarget, 0, this, 0); | ||
630 | 256 | if (!m_serverTarget || m_serverProperty.isEmpty()) { | ||
631 | 257 | return; | ||
632 | 258 | } | ||
633 | 259 | |||
634 | 260 | // Connect to the server property change | ||
635 | 261 | QQmlProperty prop(m_serverTarget, m_serverProperty); | ||
636 | 262 | if (prop.isValid()) { | ||
637 | 263 | if (prop.connectNotifySignal(this, SLOT(updateUserValue()))) { | ||
638 | 264 | m_connectedServerTarget = m_serverTarget; | ||
639 | 265 | } | ||
640 | 266 | // once we're connected to the server property, we need to make sure the user target is | ||
641 | 267 | // set to the server value | ||
642 | 268 | updateUserValue(); | ||
643 | 269 | } | ||
644 | 270 | } | ||
645 | 271 | |||
646 | 272 | void ServerPropertySynchroniser::connectUser() | ||
647 | 273 | { | ||
648 | 274 | // if we havent finished constructing the class, then wait | ||
649 | 275 | if (!m_classComplete) return; | ||
650 | 276 | |||
651 | 277 | if (m_connectedUserTarget) QObject::disconnect(m_connectedUserTarget, 0, this, 0); | ||
652 | 278 | if (!m_userTarget) { | ||
653 | 279 | if (!parent()) return; | ||
654 | 280 | m_userTarget = parent(); | ||
655 | 281 | Q_EMIT userTargetChanged(m_userTarget); | ||
656 | 282 | } | ||
657 | 283 | |||
658 | 284 | if (m_userTrigger.isEmpty()) { | ||
659 | 285 | // Connect to the user property change | ||
660 | 286 | QQmlProperty prop(m_userTarget, m_userProperty); | ||
661 | 287 | if (prop.isValid()) { | ||
662 | 288 | if (prop.connectNotifySignal(this, SLOT(activate()))) { | ||
663 | 289 | m_connectedUserTarget = m_userTarget; | ||
664 | 290 | } | ||
665 | 291 | // once we're connected to the user property, we need to make sure the user target is | ||
666 | 292 | // set to the server value | ||
667 | 293 | updateUserValue(); | ||
668 | 294 | } | ||
669 | 295 | } else { | ||
670 | 296 | QQmlProperty prop(m_userTarget, m_userTrigger); | ||
671 | 297 | if (prop.isValid() && prop.isSignalProperty()) { | ||
672 | 298 | if (connect(m_userTarget, ("2" + prop.method().methodSignature()).constData(), | ||
673 | 299 | this, SLOT(activate()))) { | ||
674 | 300 | m_connectedUserTarget = m_userTarget; | ||
675 | 301 | } | ||
676 | 302 | |||
677 | 303 | // once we're connected to the user signal, we need to make sure the user target is | ||
678 | 304 | // set to the server value | ||
679 | 305 | updateUserValue(); | ||
680 | 306 | } | ||
681 | 307 | } | ||
682 | 308 | } | ||
683 | 309 | |||
684 | 310 | void ServerPropertySynchroniser::updateUserValue() | ||
685 | 311 | { | ||
686 | 312 | // Don't want any signals we fire to create binding loops. | ||
687 | 313 | if (m_busy) return; | ||
688 | 314 | m_busy = true; | ||
689 | 315 | |||
690 | 316 | bool waitingBufferedServerChange = m_bufferTimeout && m_bufferTimeout->isActive(); | ||
691 | 317 | |||
692 | 318 | // If we've been waiting for a sync, stop the wait. | ||
693 | 319 | if (m_serverSyncTimer->isActive()) { | ||
694 | 320 | m_serverSyncTimer->stop(); | ||
695 | 321 | Q_EMIT syncWaitingChanged(false); | ||
696 | 322 | } | ||
697 | 323 | |||
698 | 324 | QQmlProperty userProp(m_userTarget, m_userProperty); | ||
699 | 325 | QQmlProperty serverProp(m_serverTarget, m_serverProperty); | ||
700 | 326 | if (!userProp.isValid() || !serverProp.isValid()) { | ||
701 | 327 | m_busy = false; | ||
702 | 328 | return; | ||
703 | 329 | } | ||
704 | 330 | |||
705 | 331 | // If we've been buffering changes since last change was send, | ||
706 | 332 | // we verify that what the server gave us is what we want, and send another | ||
707 | 333 | // activation if not. | ||
708 | 334 | if (m_buffering) { | ||
709 | 335 | m_buffering = false; | ||
710 | 336 | m_busy = false; | ||
711 | 337 | if (serverProp.read() != userProp.read()) { | ||
712 | 338 | activate(); | ||
713 | 339 | } | ||
714 | 340 | return; | ||
715 | 341 | } | ||
716 | 342 | |||
717 | 343 | // Don't update until we hit the buffer timeout. | ||
718 | 344 | if (waitingBufferedServerChange) { | ||
719 | 345 | m_busy = false; | ||
720 | 346 | return; | ||
721 | 347 | } | ||
722 | 348 | |||
723 | 349 | // update the user target property. | ||
724 | 350 | userProp.write(serverProp.read()); | ||
725 | 351 | m_busy = false; | ||
726 | 352 | } | ||
727 | 353 | |||
728 | 354 | void ServerPropertySynchroniser::serverSyncTimedOut() | ||
729 | 355 | { | ||
730 | 356 | if (m_buffering && !m_bufferedSyncTimeout) { | ||
731 | 357 | m_buffering = false; | ||
732 | 358 | } | ||
733 | 359 | Q_EMIT syncWaitingChanged(false); | ||
734 | 360 | updateUserValue(); | ||
735 | 361 | } | ||
736 | 362 | |||
737 | 363 | void ServerPropertySynchroniser::bufferTimedOut() | ||
738 | 364 | { | ||
739 | 365 | if (m_buffering) { | ||
740 | 366 | m_buffering = false; | ||
741 | 367 | activate(); | ||
742 | 368 | } else { | ||
743 | 369 | // Update the user value. | ||
744 | 370 | if (m_busy) return; | ||
745 | 371 | m_busy = true; | ||
746 | 372 | |||
747 | 373 | QQmlProperty userProp(m_userTarget, m_userProperty); | ||
748 | 374 | QQmlProperty serverProp(m_serverTarget, m_serverProperty); | ||
749 | 375 | if (!userProp.isValid() || !serverProp.isValid()) { | ||
750 | 376 | m_busy = false; | ||
751 | 377 | return; | ||
752 | 378 | } | ||
753 | 379 | userProp.write(serverProp.read()); | ||
754 | 380 | m_busy = false; | ||
755 | 381 | } | ||
756 | 382 | } | ||
757 | 0 | 383 | ||
758 | === added file 'plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h' | |||
759 | --- plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h 1970-01-01 00:00:00 +0000 | |||
760 | +++ plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h 2015-04-09 12:58:32 +0000 | |||
761 | @@ -0,0 +1,157 @@ | |||
762 | 1 | /* | ||
763 | 2 | * Copyright (C) 2015 Canonical, Ltd. | ||
764 | 3 | * | ||
765 | 4 | * This program is free software; you can redistribute it and/or modify | ||
766 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
767 | 6 | * the Free Software Foundation; version 3. | ||
768 | 7 | * | ||
769 | 8 | * This program is distributed in the hope that it will be useful, | ||
770 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
771 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
772 | 11 | * GNU Lesser General Public License for more details. | ||
773 | 12 | * | ||
774 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
775 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
776 | 15 | */ | ||
777 | 16 | |||
778 | 17 | #ifndef SERVERPROPERTYSYNCHRONISER_H | ||
779 | 18 | #define SERVERPROPERTYSYNCHRONISER_H | ||
780 | 19 | |||
781 | 20 | #include <QObject> | ||
782 | 21 | #include <QQmlParserStatus> | ||
783 | 22 | #include <QVariant> | ||
784 | 23 | |||
785 | 24 | class QTimer; | ||
786 | 25 | |||
787 | 26 | class ServerPropertySynchroniser : public QObject, public QQmlParserStatus | ||
788 | 27 | { | ||
789 | 28 | Q_OBJECT | ||
790 | 29 | Q_INTERFACES(QQmlParserStatus) | ||
791 | 30 | |||
792 | 31 | // Target object which contains the property to keep the user property in sync with. | ||
793 | 32 | Q_PROPERTY(QObject* serverTarget READ serverTarget WRITE setServerTarget NOTIFY serverTargetChanged) | ||
794 | 33 | // Server property to keep the user property in sync with. | ||
795 | 34 | Q_PROPERTY(QString serverProperty READ serverProperty WRITE setServerProperty NOTIFY serverPropertyChanged) | ||
796 | 35 | |||
797 | 36 | // User object (control) which sources the property to update the server property. | ||
798 | 37 | // Defaults to the object's parent if not set. | ||
799 | 38 | Q_PROPERTY(QObject* userTarget READ userTarget WRITE setUserTarget NOTIFY userTargetChanged) | ||
800 | 39 | // User property to update the server property. | ||
801 | 40 | Q_PROPERTY(QString userProperty READ userProperty WRITE setUserProperty NOTIFY userPropertyChanged) | ||
802 | 41 | // Trigger that causes an update. By default, the control will use the userProperty change notification. | ||
803 | 42 | // eg. "onTriggered" | ||
804 | 43 | Q_PROPERTY(QString userTrigger READ userTrigger WRITE setUserTrigger NOTIFY userTriggerChanged) | ||
805 | 44 | |||
806 | 45 | // Time to wait for a change verification before re-asserting the server value. | ||
807 | 46 | Q_PROPERTY(int syncTimeout READ syncTimeout WRITE setSyncTimeout NOTIFY syncTimeoutChanged) | ||
808 | 47 | |||
809 | 48 | // Buffer user property changes until the previous change is verified | ||
810 | 49 | Q_PROPERTY(bool useWaitBuffer | ||
811 | 50 | READ useWaitBuffer | ||
812 | 51 | WRITE setUseWaitBuffer | ||
813 | 52 | NOTIFY useWaitBufferChanged) | ||
814 | 53 | |||
815 | 54 | // Maximum intervals between buffers for the server to respond. If we don't get a response within this interval, | ||
816 | 55 | // the next buffer will be sent. Good for live sliders. Defaults to disabled. | ||
817 | 56 | Q_PROPERTY(int maximumWaitBufferInterval | ||
818 | 57 | READ maximumWaitBufferInterval | ||
819 | 58 | WRITE setMaximumWaitBufferInterval | ||
820 | 59 | NOTIFY maximumWaitBufferIntervalChanged) | ||
821 | 60 | |||
822 | 61 | // Resend the buffered value if we timeout waiting for a change from the server. Defaults to false | ||
823 | 62 | Q_PROPERTY(bool bufferedSyncTimeout | ||
824 | 63 | READ bufferedSyncTimeout | ||
825 | 64 | WRITE setBufferedSyncTimeout | ||
826 | 65 | NOTIFY bufferedSyncTimeoutChanged) | ||
827 | 66 | |||
828 | 67 | // True if we're waiting for a change verification from the server | ||
829 | 68 | Q_PROPERTY(bool syncWaiting READ syncWaiting NOTIFY syncWaitingChanged) | ||
830 | 69 | |||
831 | 70 | public: | ||
832 | 71 | ServerPropertySynchroniser(QObject* parent = nullptr); | ||
833 | 72 | |||
834 | 73 | QObject* serverTarget() const; | ||
835 | 74 | void setServerTarget(QObject* target); | ||
836 | 75 | |||
837 | 76 | QString serverProperty() const; | ||
838 | 77 | void setServerProperty(const QString& property); | ||
839 | 78 | |||
840 | 79 | QObject* userTarget() const; | ||
841 | 80 | void setUserTarget(QObject* target); | ||
842 | 81 | |||
843 | 82 | QString userProperty() const; | ||
844 | 83 | void setUserProperty(const QString& property); | ||
845 | 84 | |||
846 | 85 | QString userTrigger() const; | ||
847 | 86 | void setUserTrigger(const QString& trigger); | ||
848 | 87 | |||
849 | 88 | int syncTimeout() const; | ||
850 | 89 | void setSyncTimeout(int timeout); | ||
851 | 90 | |||
852 | 91 | bool useWaitBuffer() const; | ||
853 | 92 | void setUseWaitBuffer(bool value); | ||
854 | 93 | |||
855 | 94 | int maximumWaitBufferInterval() const; | ||
856 | 95 | void setMaximumWaitBufferInterval(int timeout); | ||
857 | 96 | |||
858 | 97 | bool bufferedSyncTimeout() const; | ||
859 | 98 | void setBufferedSyncTimeout(bool); | ||
860 | 99 | |||
861 | 100 | bool syncWaiting() const; | ||
862 | 101 | |||
863 | 102 | void classBegin() override; | ||
864 | 103 | void componentComplete() override; | ||
865 | 104 | |||
866 | 105 | Q_INVOKABLE void reset(); | ||
867 | 106 | |||
868 | 107 | public Q_SLOTS: | ||
869 | 108 | void updateUserValue(); | ||
870 | 109 | void activate(); | ||
871 | 110 | |||
872 | 111 | Q_SIGNALS: | ||
873 | 112 | void serverTargetChanged(QObject* serverTarget); | ||
874 | 113 | void serverPropertyChanged(QString serverProperty); | ||
875 | 114 | |||
876 | 115 | void userTargetChanged(QObject* userTarget); | ||
877 | 116 | void userPropertyChanged(QString serverProperty); | ||
878 | 117 | void userTriggerChanged(QString userTrigger); | ||
879 | 118 | |||
880 | 119 | void syncTimeoutChanged(int timeout); | ||
881 | 120 | void syncWaitingChanged(bool waiting); | ||
882 | 121 | void bufferedSyncTimeoutChanged(bool); | ||
883 | 122 | |||
884 | 123 | void useWaitBufferChanged(bool useWaitBuffer); | ||
885 | 124 | void maximumWaitBufferIntervalChanged(int timeout); | ||
886 | 125 | |||
887 | 126 | // Emitted when we want to update the backend. | ||
888 | 127 | void syncTriggered(const QVariant& value); | ||
889 | 128 | |||
890 | 129 | private Q_SLOTS: | ||
891 | 130 | void serverSyncTimedOut(); | ||
892 | 131 | void bufferTimedOut(); | ||
893 | 132 | |||
894 | 133 | private: | ||
895 | 134 | void connectServer(); | ||
896 | 135 | void connectUser(); | ||
897 | 136 | |||
898 | 137 | QObject* m_serverTarget; | ||
899 | 138 | QString m_serverProperty; | ||
900 | 139 | |||
901 | 140 | QObject* m_userTarget; | ||
902 | 141 | QString m_userProperty; | ||
903 | 142 | QString m_userTrigger; | ||
904 | 143 | |||
905 | 144 | bool m_classComplete; | ||
906 | 145 | bool m_busy; | ||
907 | 146 | |||
908 | 147 | QObject* m_connectedServerTarget; | ||
909 | 148 | QObject* m_connectedUserTarget; | ||
910 | 149 | |||
911 | 150 | QTimer* m_serverSyncTimer; | ||
912 | 151 | QTimer* m_bufferTimeout; | ||
913 | 152 | bool m_useWaitBuffer; | ||
914 | 153 | bool m_buffering; | ||
915 | 154 | bool m_bufferedSyncTimeout; | ||
916 | 155 | }; | ||
917 | 156 | |||
918 | 157 | #endif // SERVERPROPERTYSYNCHRONISER_H | ||
919 | 0 | 158 | ||
920 | === added file 'plugins/Ubuntu/Settings/Menus/Menus.qmltypes' | |||
921 | --- plugins/Ubuntu/Settings/Menus/Menus.qmltypes 1970-01-01 00:00:00 +0000 | |||
922 | +++ plugins/Ubuntu/Settings/Menus/Menus.qmltypes 2015-04-09 12:58:32 +0000 | |||
923 | @@ -0,0 +1,30 @@ | |||
924 | 1 | import QtQuick.tooling 1.1 | ||
925 | 2 | |||
926 | 3 | // This file describes the plugin-supplied types contained in the library. | ||
927 | 4 | // It is used for QML tooling purposes only. | ||
928 | 5 | // | ||
929 | 6 | // This file was auto-generated by: | ||
930 | 7 | // 'qmlplugindump -notrelocatable Ubuntu.Settings.Menus 0.1 plugins' | ||
931 | 8 | |||
932 | 9 | Module { | ||
933 | 10 | Component { | ||
934 | 11 | name: "TransferState" | ||
935 | 12 | prototype: "QObject" | ||
936 | 13 | exports: ["Ubuntu.Settings.Menus/TransferState 0.1"] | ||
937 | 14 | isCreatable: false | ||
938 | 15 | exportMetaObjectRevisions: [0] | ||
939 | 16 | Enum { | ||
940 | 17 | name: "TransferStates" | ||
941 | 18 | values: { | ||
942 | 19 | "Queued": 0, | ||
943 | 20 | "Running": 1, | ||
944 | 21 | "Paused": 2, | ||
945 | 22 | "Canceled": 3, | ||
946 | 23 | "Hashing": 4, | ||
947 | 24 | "Processing": 5, | ||
948 | 25 | "Finished": 6, | ||
949 | 26 | "Error": 7 | ||
950 | 27 | } | ||
951 | 28 | } | ||
952 | 29 | } | ||
953 | 30 | } | ||
954 | 0 | 31 | ||
955 | === modified file 'plugins/Ubuntu/Settings/Menus/plugin.cpp' | |||
956 | --- Ubuntu/Settings/Menus/plugin.cpp 2014-06-27 13:56:26 +0000 | |||
957 | +++ plugins/Ubuntu/Settings/Menus/plugin.cpp 2015-04-09 12:58:32 +0000 | |||
958 | @@ -21,7 +21,7 @@ | |||
959 | 21 | // Qt | 21 | // Qt |
960 | 22 | #include <QtQml/qqml.h> | 22 | #include <QtQml/qqml.h> |
961 | 23 | 23 | ||
963 | 24 | void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri) | 24 | void UbuntuSettingsMenusPlugin::registerTypes(const char *uri) |
964 | 25 | { | 25 | { |
965 | 26 | qmlRegisterUncreatableType<TransferState>(uri, 0, 1, "TransferState", "Can't create TransferState class"); | 26 | qmlRegisterUncreatableType<TransferState>(uri, 0, 1, "TransferState", "Can't create TransferState class"); |
966 | 27 | } | 27 | } |
967 | 28 | 28 | ||
968 | === modified file 'plugins/Ubuntu/Settings/Menus/plugin.h' | |||
969 | --- Ubuntu/Settings/Menus/plugin.h 2014-06-27 09:39:18 +0000 | |||
970 | +++ plugins/Ubuntu/Settings/Menus/plugin.h 2015-04-09 12:58:32 +0000 | |||
971 | @@ -14,12 +14,12 @@ | |||
972 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
973 | 15 | */ | 15 | */ |
974 | 16 | 16 | ||
977 | 17 | #ifndef UBUNTUSETTINGSCOMPOENNTS_PLUGIN_H | 17 | #ifndef UBUNTUSETTINGSMENUS_PLUGIN_H |
978 | 18 | #define UBUNTUSETTINGSCOMPOENNTS_PLUGIN_H | 18 | #define UBUNTUSETTINGSMENUS_PLUGIN_H |
979 | 19 | 19 | ||
980 | 20 | #include <QtQml/QQmlExtensionPlugin> | 20 | #include <QtQml/QQmlExtensionPlugin> |
981 | 21 | 21 | ||
983 | 22 | class UbuntuSettingsComponentsPlugin : public QQmlExtensionPlugin | 22 | class UbuntuSettingsMenusPlugin : public QQmlExtensionPlugin |
984 | 23 | { | 23 | { |
985 | 24 | Q_OBJECT | 24 | Q_OBJECT |
986 | 25 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") | 25 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
987 | @@ -27,4 +27,4 @@ | |||
988 | 27 | void registerTypes(const char *uri); | 27 | void registerTypes(const char *uri); |
989 | 28 | }; | 28 | }; |
990 | 29 | 29 | ||
992 | 30 | #endif // UBUNTUSETTINGSCOMPOENNTS_PLUGIN_H | 30 | #endif // UBUNTUSETTINGSMENUS_PLUGIN_H |
993 | 31 | 31 | ||
994 | === modified file 'plugins/Ubuntu/Settings/Menus/qmldir' | |||
995 | --- Ubuntu/Settings/Menus/qmldir 2014-07-25 17:53:08 +0000 | |||
996 | +++ plugins/Ubuntu/Settings/Menus/qmldir 2015-04-09 12:58:32 +0000 | |||
997 | @@ -1,6 +1,6 @@ | |||
998 | 1 | module Ubuntu.Settings.Menus | 1 | module Ubuntu.Settings.Menus |
999 | 2 | plugin UbuntuSettingsMenusQml | 2 | plugin UbuntuSettingsMenusQml |
1001 | 3 | typeinfo plugin.qmltypes | 3 | typeinfo Menus.qmltypes |
1002 | 4 | 4 | ||
1003 | 5 | AccessPointMenu 0.1 AccessPointMenu.qml | 5 | AccessPointMenu 0.1 AccessPointMenu.qml |
1004 | 6 | ButtonMenu 0.1 ButtonMenu.qml | 6 | ButtonMenu 0.1 ButtonMenu.qml |
1005 | 7 | 7 | ||
1006 | === modified file 'tests/qmltests/CMakeLists.txt' | |||
1007 | --- tests/qmltests/CMakeLists.txt 2014-07-31 11:29:03 +0000 | |||
1008 | +++ tests/qmltests/CMakeLists.txt 2015-04-09 12:58:32 +0000 | |||
1009 | @@ -6,11 +6,12 @@ | |||
1010 | 6 | set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C") | 6 | set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C") |
1011 | 7 | 7 | ||
1012 | 8 | set(qmltest_DEFAULT_IMPORT_PATHS | 8 | set(qmltest_DEFAULT_IMPORT_PATHS |
1014 | 9 | ${CMAKE_BINARY_DIR} | 9 | ${CMAKE_BINARY_DIR}/plugins |
1015 | 10 | ${CMAKE_BINARY_DIR}/tests/utils/modules | 10 | ${CMAKE_BINARY_DIR}/tests/utils/modules |
1016 | 11 | ) | 11 | ) |
1017 | 12 | 12 | ||
1018 | 13 | add_qml_test(Components Calendar) | 13 | add_qml_test(Components Calendar) |
1019 | 14 | add_qml_test(Components ServerPropertySynchroniser) | ||
1020 | 14 | add_qml_test(Components StatusIcon) | 15 | add_qml_test(Components StatusIcon) |
1021 | 15 | 16 | ||
1022 | 16 | add_qml_test(Menus AccessPointMenu) | 17 | add_qml_test(Menus AccessPointMenu) |
1023 | 17 | 18 | ||
1024 | === added file 'tests/qmltests/Components/tst_ServerPropertySynchroniser.qml' | |||
1025 | --- tests/qmltests/Components/tst_ServerPropertySynchroniser.qml 1970-01-01 00:00:00 +0000 | |||
1026 | +++ tests/qmltests/Components/tst_ServerPropertySynchroniser.qml 2015-04-09 12:58:32 +0000 | |||
1027 | @@ -0,0 +1,398 @@ | |||
1028 | 1 | /* | ||
1029 | 2 | * Copyright 2015 Canonical Ltd. | ||
1030 | 3 | * | ||
1031 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1032 | 5 | * it under the terms of the GNU General Public License as published by | ||
1033 | 6 | * the Free Software Foundation; version 3. | ||
1034 | 7 | * | ||
1035 | 8 | * This program is distributed in the hope that it will be useful, | ||
1036 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1037 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1038 | 11 | * GNU General Public License for more details. | ||
1039 | 12 | * | ||
1040 | 13 | * You should have received a copy of the GNU General Public License | ||
1041 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1042 | 15 | */ | ||
1043 | 16 | |||
1044 | 17 | import QtQuick 2.3 | ||
1045 | 18 | import QtTest 1.0 | ||
1046 | 19 | import Ubuntu.Test 0.1 | ||
1047 | 20 | import Ubuntu.Settings.Components 0.1 as USC | ||
1048 | 21 | import Ubuntu.Settings.Menus 0.1 as USM | ||
1049 | 22 | import Ubuntu.Components 0.1 | ||
1050 | 23 | |||
1051 | 24 | Item { | ||
1052 | 25 | id: root | ||
1053 | 26 | width: units.gu(60) | ||
1054 | 27 | height: units.gu(70) | ||
1055 | 28 | |||
1056 | 29 | QtObject { | ||
1057 | 30 | id: switchBackend | ||
1058 | 31 | |||
1059 | 32 | property bool checked: false | ||
1060 | 33 | property bool inSync: checked === switchControl.checked | ||
1061 | 34 | |||
1062 | 35 | property Timer timer: Timer { | ||
1063 | 36 | interval: 2000 | ||
1064 | 37 | onTriggered: switchBackend.checked = !switchBackend.checked | ||
1065 | 38 | } | ||
1066 | 39 | } | ||
1067 | 40 | |||
1068 | 41 | QtObject { | ||
1069 | 42 | id: checkBackend | ||
1070 | 43 | |||
1071 | 44 | property bool checked: false | ||
1072 | 45 | property bool inSync: checked === checkControl.checked | ||
1073 | 46 | |||
1074 | 47 | property Timer timer: Timer { | ||
1075 | 48 | interval: 2000 | ||
1076 | 49 | onTriggered: checkBackend.checked = !checkBackend.checked | ||
1077 | 50 | } | ||
1078 | 51 | } | ||
1079 | 52 | |||
1080 | 53 | QtObject { | ||
1081 | 54 | id: sliderBackend | ||
1082 | 55 | |||
1083 | 56 | property real value: 50 | ||
1084 | 57 | property bool inSync: value === slider.value | ||
1085 | 58 | property var changeToValue: undefined | ||
1086 | 59 | |||
1087 | 60 | property Timer timer: Timer { | ||
1088 | 61 | interval: 200 | ||
1089 | 62 | |||
1090 | 63 | onTriggered: { | ||
1091 | 64 | sliderBackend.value = sliderBackend.changeToValue; | ||
1092 | 65 | } | ||
1093 | 66 | } | ||
1094 | 67 | } | ||
1095 | 68 | |||
1096 | 69 | QtObject { | ||
1097 | 70 | id: apBackend | ||
1098 | 71 | |||
1099 | 72 | property bool active: false | ||
1100 | 73 | property bool inSync: active === apMenu.active | ||
1101 | 74 | |||
1102 | 75 | property Timer timer: Timer { | ||
1103 | 76 | interval: 2000 | ||
1104 | 77 | onTriggered: apBackend.active = !apBackend.active | ||
1105 | 78 | } | ||
1106 | 79 | } | ||
1107 | 80 | |||
1108 | 81 | |||
1109 | 82 | Column { | ||
1110 | 83 | anchors.fill: parent | ||
1111 | 84 | anchors.margins: units.gu(1) | ||
1112 | 85 | |||
1113 | 86 | spacing: units.gu(2) | ||
1114 | 87 | |||
1115 | 88 | Row { | ||
1116 | 89 | spacing: units.gu(3) | ||
1117 | 90 | |||
1118 | 91 | Switch { | ||
1119 | 92 | id: switchControl | ||
1120 | 93 | anchors.verticalCenter: parent.verticalCenter | ||
1121 | 94 | |||
1122 | 95 | USC.ServerPropertySynchroniser { | ||
1123 | 96 | id: switchSync | ||
1124 | 97 | objectName: "switchSync" | ||
1125 | 98 | |||
1126 | 99 | syncTimeout: 3000 | ||
1127 | 100 | |||
1128 | 101 | userTarget: switchControl | ||
1129 | 102 | userProperty: "checked" | ||
1130 | 103 | |||
1131 | 104 | serverTarget: switchBackend | ||
1132 | 105 | serverProperty: "checked" | ||
1133 | 106 | |||
1134 | 107 | onSyncTriggered: switchBackend.timer.start() | ||
1135 | 108 | onSyncWaitingChanged: switchSyncSpy.clear() | ||
1136 | 109 | } | ||
1137 | 110 | } | ||
1138 | 111 | |||
1139 | 112 | Column { | ||
1140 | 113 | Label { text: switchBackend.inSync ? "synced" : "out of sync" } | ||
1141 | 114 | Label { text: switchSync.syncWaiting ? "syncWait" : "no syncWait" } | ||
1142 | 115 | Label { text: "activates: " + switchSyncSpy.count } | ||
1143 | 116 | } | ||
1144 | 117 | } | ||
1145 | 118 | |||
1146 | 119 | Row { | ||
1147 | 120 | spacing: units.gu(3) | ||
1148 | 121 | |||
1149 | 122 | CheckBox { | ||
1150 | 123 | id: checkControl | ||
1151 | 124 | anchors.verticalCenter: parent.verticalCenter | ||
1152 | 125 | |||
1153 | 126 | USC.ServerPropertySynchroniser { | ||
1154 | 127 | id: checkSync | ||
1155 | 128 | objectName: "checkSync" | ||
1156 | 129 | |||
1157 | 130 | syncTimeout: 3000 | ||
1158 | 131 | |||
1159 | 132 | userTarget: checkControl | ||
1160 | 133 | userProperty: "checked" | ||
1161 | 134 | |||
1162 | 135 | serverTarget: checkBackend | ||
1163 | 136 | serverProperty: "checked" | ||
1164 | 137 | |||
1165 | 138 | onSyncTriggered: checkBackend.timer.start() | ||
1166 | 139 | |||
1167 | 140 | onSyncWaitingChanged: checkSyncSpy.clear() | ||
1168 | 141 | } | ||
1169 | 142 | } | ||
1170 | 143 | |||
1171 | 144 | Column { | ||
1172 | 145 | Label { text: checkBackend.inSync ? "synced" : "out of sync" } | ||
1173 | 146 | Label { text: checkSync.syncWaiting ? "syncWait" : "no syncWait" } | ||
1174 | 147 | Label { text: "activates: " + checkSyncSpy.count } | ||
1175 | 148 | } | ||
1176 | 149 | } | ||
1177 | 150 | |||
1178 | 151 | Row { | ||
1179 | 152 | id: sliderRoot | ||
1180 | 153 | spacing: units.gu(3) | ||
1181 | 154 | |||
1182 | 155 | Slider { | ||
1183 | 156 | id: slider | ||
1184 | 157 | anchors.verticalCenter: parent.verticalCenter | ||
1185 | 158 | live: true | ||
1186 | 159 | minimumValue: 0.0 | ||
1187 | 160 | maximumValue: 100.0 | ||
1188 | 161 | |||
1189 | 162 | property real serverValue: sliderBackend.value | ||
1190 | 163 | USC.ServerPropertySynchroniser { | ||
1191 | 164 | id: sliderSync | ||
1192 | 165 | objectName: "sliderSync" | ||
1193 | 166 | |||
1194 | 167 | syncTimeout: 3000 | ||
1195 | 168 | |||
1196 | 169 | userTarget: slider | ||
1197 | 170 | userProperty: "value" | ||
1198 | 171 | |||
1199 | 172 | serverTarget: slider | ||
1200 | 173 | serverProperty: "serverValue" | ||
1201 | 174 | |||
1202 | 175 | onSyncTriggered: { | ||
1203 | 176 | sliderBackend.changeToValue = value; | ||
1204 | 177 | sliderBackend.timer.start(); | ||
1205 | 178 | } | ||
1206 | 179 | |||
1207 | 180 | onSyncWaitingChanged: sliderSyncSpy.clear() | ||
1208 | 181 | } | ||
1209 | 182 | } | ||
1210 | 183 | |||
1211 | 184 | Column { | ||
1212 | 185 | Label { text: sliderBackend.inSync ? "synced" : "out of sync" } | ||
1213 | 186 | Label { text: sliderSync.syncWaiting ? "syncWait" : "no syncWait" } | ||
1214 | 187 | Label { text: "activates: " + sliderSyncSpy.count } | ||
1215 | 188 | } | ||
1216 | 189 | } | ||
1217 | 190 | |||
1218 | 191 | Row { | ||
1219 | 192 | spacing: units.gu(3) | ||
1220 | 193 | height: childrenRect.height | ||
1221 | 194 | anchors.left: parent.left | ||
1222 | 195 | anchors.right: parent.right | ||
1223 | 196 | |||
1224 | 197 | USM.AccessPointMenu { | ||
1225 | 198 | id: apMenu | ||
1226 | 199 | width: units.gu(30) | ||
1227 | 200 | |||
1228 | 201 | text: "Test Check Menu" | ||
1229 | 202 | |||
1230 | 203 | USC.ServerPropertySynchroniser { | ||
1231 | 204 | id: apMenuSync | ||
1232 | 205 | objectName: "apMenuSync" | ||
1233 | 206 | |||
1234 | 207 | syncTimeout: 3000 | ||
1235 | 208 | |||
1236 | 209 | userTarget: apMenu | ||
1237 | 210 | userProperty: "active" | ||
1238 | 211 | userTrigger: "onTriggered" | ||
1239 | 212 | |||
1240 | 213 | serverTarget: apBackend | ||
1241 | 214 | serverProperty: "active" | ||
1242 | 215 | |||
1243 | 216 | onSyncTriggered: apBackend.timer.start() | ||
1244 | 217 | |||
1245 | 218 | onSyncWaitingChanged: switchSyncSpy.clear() | ||
1246 | 219 | } | ||
1247 | 220 | } | ||
1248 | 221 | |||
1249 | 222 | Column { | ||
1250 | 223 | Label { text: apBackend.inSync ? "synced" : "out of sync" } | ||
1251 | 224 | Label { text: apMenuSync.syncWaiting ? "syncWait" : "no syncWait" } | ||
1252 | 225 | Label { text: "activates: " + apSyncSpy.count } | ||
1253 | 226 | } | ||
1254 | 227 | } | ||
1255 | 228 | } | ||
1256 | 229 | |||
1257 | 230 | SignalSpy { | ||
1258 | 231 | id: switchSyncSpy | ||
1259 | 232 | target: switchControl | ||
1260 | 233 | signalName: "triggered" | ||
1261 | 234 | } | ||
1262 | 235 | SignalSpy { | ||
1263 | 236 | id: checkSyncSpy | ||
1264 | 237 | target: checkControl | ||
1265 | 238 | signalName: "triggered" | ||
1266 | 239 | } | ||
1267 | 240 | SignalSpy { | ||
1268 | 241 | id: sliderSyncSpy | ||
1269 | 242 | target: slider | ||
1270 | 243 | signalName: "valueChanged" | ||
1271 | 244 | } | ||
1272 | 245 | SignalSpy { | ||
1273 | 246 | id: apSyncSpy | ||
1274 | 247 | target: apMenu | ||
1275 | 248 | signalName: "triggered" | ||
1276 | 249 | } | ||
1277 | 250 | SignalSpy { | ||
1278 | 251 | id: sliderSyncActivatedSpy | ||
1279 | 252 | target: sliderSync | ||
1280 | 253 | signalName: "syncTriggered" | ||
1281 | 254 | } | ||
1282 | 255 | SignalSpy { | ||
1283 | 256 | id:apSyncActivatedSpy | ||
1284 | 257 | target: apMenuSync | ||
1285 | 258 | signalName: "syncTriggered" | ||
1286 | 259 | } | ||
1287 | 260 | |||
1288 | 261 | QtObject { | ||
1289 | 262 | id: switchBackend2 | ||
1290 | 263 | |||
1291 | 264 | property bool checked2: false | ||
1292 | 265 | property bool inSync: checked2 === switchControl.checked | ||
1293 | 266 | |||
1294 | 267 | property Timer switchTimer: Timer { | ||
1295 | 268 | interval: 1000 | ||
1296 | 269 | onTriggered: switchBackend2.checked2 = !switchBackend2.checked2 | ||
1297 | 270 | } | ||
1298 | 271 | } | ||
1299 | 272 | |||
1300 | 273 | UbuntuTestCase { | ||
1301 | 274 | name: "ServerActivationSync" | ||
1302 | 275 | when: windowShown | ||
1303 | 276 | |||
1304 | 277 | function init() { | ||
1305 | 278 | waitForRendering(root); | ||
1306 | 279 | switchBackend.timer.interval = 100; | ||
1307 | 280 | checkBackend.timer.interval = 100; | ||
1308 | 281 | sliderBackend.timer.interval = 100; | ||
1309 | 282 | apBackend.timer.interval = 100; | ||
1310 | 283 | |||
1311 | 284 | switchSync.syncTimeout = 200; | ||
1312 | 285 | checkSync.syncTimeout = 200; | ||
1313 | 286 | sliderSync.syncTimeout = 200; | ||
1314 | 287 | apMenuSync.syncTimeout = 200; | ||
1315 | 288 | |||
1316 | 289 | sliderSyncActivatedSpy.clear(); | ||
1317 | 290 | apSyncActivatedSpy.clear(); | ||
1318 | 291 | } | ||
1319 | 292 | |||
1320 | 293 | function cleanup() { | ||
1321 | 294 | switchBackend.timer.stop(); | ||
1322 | 295 | checkBackend.timer.stop(); | ||
1323 | 296 | sliderBackend.timer.stop(); | ||
1324 | 297 | |||
1325 | 298 | switchBackend.checked = false; | ||
1326 | 299 | checkBackend.checked = false; | ||
1327 | 300 | sliderBackend.value = 50; | ||
1328 | 301 | apBackend.active = false; | ||
1329 | 302 | |||
1330 | 303 | switchSync.reset(); | ||
1331 | 304 | checkSync.reset(); | ||
1332 | 305 | sliderSync.reset(); | ||
1333 | 306 | apMenuSync.reset(); | ||
1334 | 307 | sliderSync.maximumWaitBufferInterval = -1 | ||
1335 | 308 | |||
1336 | 309 | tryCompare(switchBackend, "inSync", true); | ||
1337 | 310 | tryCompare(checkBackend, "inSync", true); | ||
1338 | 311 | tryCompare(sliderBackend, "inSync", true); | ||
1339 | 312 | |||
1340 | 313 | switchSync.serverTarget = switchBackend; | ||
1341 | 314 | switchSync.serverProperty = "checked"; | ||
1342 | 315 | } | ||
1343 | 316 | |||
1344 | 317 | function test_backend_change() { | ||
1345 | 318 | switchBackend.checked = true; | ||
1346 | 319 | compare(switchControl.checked, true, "Switch should have been toggled"); | ||
1347 | 320 | switchBackend.checked = false; | ||
1348 | 321 | compare(switchControl.checked, false, "Switch should have been toggled"); | ||
1349 | 322 | } | ||
1350 | 323 | |||
1351 | 324 | function test_frontend_change() { | ||
1352 | 325 | switchControl.clicked(); | ||
1353 | 326 | tryCompare(switchBackend, "checked", true); | ||
1354 | 327 | } | ||
1355 | 328 | |||
1356 | 329 | function test_frontend_change_with_value() { | ||
1357 | 330 | slider.value = 60; | ||
1358 | 331 | tryCompare(sliderBackend, "value", 60); | ||
1359 | 332 | } | ||
1360 | 333 | |||
1361 | 334 | function test_break_binding_change() { | ||
1362 | 335 | switchControl.checked = true; | ||
1363 | 336 | switchBackend.checked = true; | ||
1364 | 337 | switchBackend.checked = false; | ||
1365 | 338 | compare(switchControl.checked, false, "Switch should have been toggled"); | ||
1366 | 339 | } | ||
1367 | 340 | |||
1368 | 341 | function test_buffered_change_with_value() { | ||
1369 | 342 | slider.value = 60; | ||
1370 | 343 | compare(sliderSyncActivatedSpy.count, 1, "activated signal should have been sent") | ||
1371 | 344 | slider.value = 70; | ||
1372 | 345 | slider.value = 80; | ||
1373 | 346 | slider.value = 90; | ||
1374 | 347 | compare(sliderSyncActivatedSpy.count, 1, "activated signals should have been buffered") | ||
1375 | 348 | tryCompare(sliderBackend, "value", 90); | ||
1376 | 349 | tryCompare(sliderSyncActivatedSpy, "count", 2) | ||
1377 | 350 | } | ||
1378 | 351 | |||
1379 | 352 | function test_buffered_change_with_maximum_interval() { | ||
1380 | 353 | sliderSync.maximumWaitBufferInterval = 50; | ||
1381 | 354 | sliderSync.syncTimeout = 5000; | ||
1382 | 355 | |||
1383 | 356 | slider.value = 60; | ||
1384 | 357 | compare(sliderSyncActivatedSpy.count, 1, "activated signal should have been sent") | ||
1385 | 358 | slider.value = 70; | ||
1386 | 359 | slider.value = 80; | ||
1387 | 360 | tryCompare(sliderSyncActivatedSpy, "count", 2, 500, "activated signal should have been sent after max interval") | ||
1388 | 361 | slider.value = 90; | ||
1389 | 362 | tryCompare(sliderSyncActivatedSpy, "count", 3, 500, "activated signal should have been sent after max interval") | ||
1390 | 363 | slider.value = 100; | ||
1391 | 364 | tryCompare(sliderSyncActivatedSpy, "count", 4, 500); | ||
1392 | 365 | tryCompare(sliderBackend, "value", 100); | ||
1393 | 366 | } | ||
1394 | 367 | |||
1395 | 368 | function test_connect_to_another_object() { | ||
1396 | 369 | switchSync.serverTarget = switchBackend2; | ||
1397 | 370 | switchSync.serverProperty = "checked2"; | ||
1398 | 371 | |||
1399 | 372 | switchBackend2.checked2 = true; | ||
1400 | 373 | compare(switchControl.checked, true, "Switch should have been toggled"); | ||
1401 | 374 | switchBackend2.checked2 = false; | ||
1402 | 375 | compare(switchControl.checked, false, "Switch should have been toggled"); | ||
1403 | 376 | } | ||
1404 | 377 | |||
1405 | 378 | function test_client_revert() { | ||
1406 | 379 | switchBackend.timer.interval = 500; | ||
1407 | 380 | switchControl.clicked(); | ||
1408 | 381 | compare(switchControl.checked, true); | ||
1409 | 382 | tryCompare(switchControl, "checked", false); | ||
1410 | 383 | } | ||
1411 | 384 | |||
1412 | 385 | function test_user_trigger() { | ||
1413 | 386 | apMenu.trigger(); | ||
1414 | 387 | |||
1415 | 388 | compare(apSyncActivatedSpy.count, 1, "Triggering should have caused signal to be emitted"); | ||
1416 | 389 | tryCompare(apBackend, "active", true); | ||
1417 | 390 | compare(apMenu.active, true, "User value should have updated to match server"); | ||
1418 | 391 | } | ||
1419 | 392 | |||
1420 | 393 | function test_user_trigger_doesnt_activate_on_user_property_change() { | ||
1421 | 394 | apMenu.active = true; | ||
1422 | 395 | compare(apSyncActivatedSpy.count, 0); | ||
1423 | 396 | } | ||
1424 | 397 | } | ||
1425 | 398 | } | ||
1426 | 0 | 399 | ||
1427 | === modified file 'tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml' | |||
1428 | --- tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml 2014-08-14 11:51:14 +0000 | |||
1429 | +++ tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml 2015-04-09 12:58:32 +0000 | |||
1430 | @@ -14,13 +14,23 @@ | |||
1431 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1432 | 15 | */ | 15 | */ |
1433 | 16 | 16 | ||
1434 | 17 | import QtQuick 2.0 | ||
1435 | 17 | import QtTest 1.0 | 18 | import QtTest 1.0 |
1436 | 18 | import Ubuntu.Components 1.1 | 19 | import Ubuntu.Components 1.1 |
1437 | 19 | import Ubuntu.Test 0.1 as UT | 20 | import Ubuntu.Test 0.1 as UT |
1438 | 20 | 21 | ||
1439 | 21 | TestCase { | 22 | TestCase { |
1440 | 23 | id: testCase | ||
1441 | 22 | TestUtil {id:util} | 24 | TestUtil {id:util} |
1442 | 23 | 25 | ||
1443 | 26 | ActivityIndicator { | ||
1444 | 27 | visible: testCase.running | ||
1445 | 28 | anchors.centerIn: parent | ||
1446 | 29 | Component.onCompleted: parent = testCase.parent | ||
1447 | 30 | z: 100 | ||
1448 | 31 | running: visible | ||
1449 | 32 | } | ||
1450 | 33 | |||
1451 | 24 | // Fake implementation to be provided to items under test | 34 | // Fake implementation to be provided to items under test |
1452 | 25 | property var fakeDateTime: new function() { | 35 | property var fakeDateTime: new function() { |
1453 | 26 | this.currentTimeMs = 0 | 36 | this.currentTimeMs = 0 |
1454 | @@ -297,4 +307,13 @@ | |||
1455 | 297 | event.release(0 /* touchId */, x, y) | 307 | event.release(0 /* touchId */, x, y) |
1456 | 298 | event.commit() | 308 | event.commit() |
1457 | 299 | } | 309 | } |
1458 | 310 | |||
1459 | 311 | // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature | ||
1460 | 312 | function waitForRendering(item, timeout) { | ||
1461 | 313 | if (timeout === undefined) | ||
1462 | 314 | timeout = 5000; | ||
1463 | 315 | if (!item) | ||
1464 | 316 | qtest_fail("No item given to waitForRendering", 1); | ||
1465 | 317 | return qtest_results.waitForRendering(item, timeout); | ||
1466 | 318 | } | ||
1467 | 300 | } | 319 | } |
PASSED: Continuous integration, rev:89 jenkins. qa.ubuntu. com/job/ ubuntu- settings- components- ci/97/ jenkins. qa.ubuntu. com/job/ ubuntu- settings- components- qmltests- vivid/16 jenkins. qa.ubuntu. com/job/ ubuntu- settings- components- vivid-amd64- ci/4 jenkins. qa.ubuntu. com/job/ ubuntu- settings- components- vivid-armhf- ci/4 jenkins. qa.ubuntu. com/job/ ubuntu- settings- components- vivid-armhf- ci/4/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- settings- components- ci/97/rebuild
http://