Merge lp:~nick-dedekind/ubuntu-settings-components/1390136.laggy-backends into lp:~registry/ubuntu-settings-components/trunk

Proposed by Nick Dedekind
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
Reviewer Review Type Date Requested Status
Michał Sawicz (community) Abstain
PS Jenkins bot (community) continuous-integration Approve
Andrea Cimitan (community) Approve
Review via email: mp+252754@code.launchpad.net

Commit message

Added ServerActivationSync control for laggy backends (lp#1390136)

Description of the change

Added ServerActivationSync control for laggy backends (lp#1390136)

 * 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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
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

review: Approve
Revision history for this message
Michał Sawicz (saviq) wrote :

You need a bumped debian/changelog here.

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
Michał Sawicz (saviq) wrote :

CMake Error at CMakeLists.txt:98 (add_subdirectory):
  The source directory

    /build/buildd/ubuntu-settings-components-0.6+15.04.20150407/plugins

  does not contain a CMakeLists.txt file.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
99. By Nick Dedekind

added missing files

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) :
review: Abstain

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-07-31 16:55:11 +0000
+++ CMakeLists.txt 2015-04-09 12:58:32 +0000
@@ -95,6 +95,6 @@
95# Tests95# Tests
96enable_testing()96enable_testing()
9797
98add_subdirectory(Ubuntu)98add_subdirectory(plugins)
99add_subdirectory(examples)99add_subdirectory(examples)
100add_subdirectory(tests)100add_subdirectory(tests)
101101
=== modified file 'cmake/modules/QmlPlugins.cmake'
--- cmake/modules/QmlPlugins.cmake 2014-06-26 14:21:52 +0000
+++ cmake/modules/QmlPlugins.cmake 2015-04-09 12:58:32 +0000
@@ -12,6 +12,12 @@
12 set_target_properties(qmlplugindump PROPERTIES IMPORTED_LOCATION ${qmlplugindump_exe})12 set_target_properties(qmlplugindump PROPERTIES IMPORTED_LOCATION ${qmlplugindump_exe})
13endif()13endif()
1414
15#
16# A custom target for building the qmltypes files manually.
17#
18if (NOT TARGET qmltypes)
19 add_custom_target(qmltypes)
20endif()
1521
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.
17#23#
@@ -33,7 +39,7 @@
33macro(export_qmlfiles PLUGIN PATH)39macro(export_qmlfiles PLUGIN PATH)
34 set(single SEARCH_PATH BINARY_DIR DESTINATION TARGET_PREFIX)40 set(single SEARCH_PATH BINARY_DIR DESTINATION TARGET_PREFIX)
35 cmake_parse_arguments(QMLFILES "" "${single}" "" ${ARGN})41 cmake_parse_arguments(QMLFILES "" "${single}" "" ${ARGN})
36 42
37 if(NOT QMLFILES_SEARCH_PATH)43 if(NOT QMLFILES_SEARCH_PATH)
38 set(QMLFILES_SEARCH_PATH ${CMAKE_CURRENT_SOURCE_DIR})44 set(QMLFILES_SEARCH_PATH ${CMAKE_CURRENT_SOURCE_DIR})
39 endif()45 endif()
@@ -51,6 +57,7 @@
51 ${QMLFILES_SEARCH_PATH}/*.png57 ${QMLFILES_SEARCH_PATH}/*.png
52 ${QMLFILES_SEARCH_PATH}/*.sci58 ${QMLFILES_SEARCH_PATH}/*.sci
53 ${QMLFILES_SEARCH_PATH}/*.svg59 ${QMLFILES_SEARCH_PATH}/*.svg
60 ${QMLFILES_SEARCH_PATH}/*.qmltypes
54 ${QMLFILES_SEARCH_PATH}/qmldir61 ${QMLFILES_SEARCH_PATH}/qmldir
55 )62 )
5663
@@ -69,14 +76,14 @@
69 DESTINATION ${QMLFILES_DESTINATION}/${PATH}76 DESTINATION ${QMLFILES_DESTINATION}/${PATH}
70 )77 )
71 endif()78 endif()
72endmacro(export_qmlfiles)79endmacro()
7380
7481
75# Creates a target for generating the typeinfo file for a QML plugin and optionally installs it82# Creates a target for generating the typeinfo file for a QML plugin and/or installs the plugin
76# and additional targets.83# targets.
77#84#
78# Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed85# Files will be copied into ${BINARY_DIR}/${path} or ${CMAKE_CURRENT_BINARY_DIR} and installed
79# into ${DESTINATION}/${path}. If you don't pass BINARY_DIR, it's assumed that current source86# into ${DESTINATION}/${path}. If you don't pass BINARY_DIR, it's assumed that current source
80# path ends with ${path}.87# path ends with ${path}.
81#88#
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.
@@ -87,15 +94,18 @@
87# [TARGET_PREFIX string] # Will be prefixed to the target name94# [TARGET_PREFIX string] # Will be prefixed to the target name
88# [ENVIRONMENT string] # Will be added to qmlplugindump's env95# [ENVIRONMENT string] # Will be added to qmlplugindump's env
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)
97# [NO_TYPES] # Do not create the qmltypes target
90# )98# )
91#99#
92# Created target:100# Created target:
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.
102# It will be made a dependency of the "qmltypes" target.
94103
95macro(export_qmlplugin PLUGIN VERSION PATH)104macro(export_qmlplugin PLUGIN VERSION PATH)
105 set(options NO_TYPES)
96 set(single BINARY_DIR DESTINATION TARGET_PREFIX ENVIRONMENT)106 set(single BINARY_DIR DESTINATION TARGET_PREFIX ENVIRONMENT)
97 set(multi TARGETS)107 set(multi TARGETS)
98 cmake_parse_arguments(QMLPLUGIN "" "${single}" "${multi}" ${ARGN})108 cmake_parse_arguments(QMLPLUGIN "${options}" "${single}" "${multi}" ${ARGN})
99109
100 get_target_property(qmlplugindump_executable qmlplugindump LOCATION)110 get_target_property(qmlplugindump_executable qmlplugindump LOCATION)
101111
@@ -103,29 +113,26 @@
103 set(qmlplugin_dir ${QMLPLUGIN_BINARY_DIR}/${PATH})113 set(qmlplugin_dir ${QMLPLUGIN_BINARY_DIR}/${PATH})
104 else()114 else()
105 # Find import path to point qmlplugindump at115 # Find import path to point qmlplugindump at
106 string(REGEX REPLACE "${PATH}$" "" QMLPLUGIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")116 string(REGEX REPLACE "/${PATH}$" "" QMLPLUGIN_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
107 set(qmlplugin_dir ${CMAKE_CURRENT_BINARY_DIR})117 set(qmlplugin_dir ${CMAKE_CURRENT_BINARY_DIR})
108 endif()118 endif()
109119
110 # Find the last segment of the plugin name to use as qmltypes basename120 if(NOT QMLPLUGIN_NO_TYPES)
111 string(REGEX MATCH "[^.]+$" plugin_suffix ${PLUGIN})121 # Relative path for the module
112 set(target_prefix ${QMLPLUGIN_TARGET_PREFIX}${PLUGIN})122 string(REPLACE "${CMAKE_BINARY_DIR}/" "" QMLPLUGIN_MODULE_DIR "${QMLPLUGIN_BINARY_DIR}")
113 set(qmltypes_path ${qmlplugin_dir}/${plugin_suffix}.qmltypes)123
114124 # Find the last segment of the plugin name to use as qmltypes basename
115 # Only generate typeinfo if not cross compiling125 string(REGEX MATCH "[^.]+$" plugin_suffix ${PLUGIN})
116 if(NOT CMAKE_CROSSCOMPILING)126 set(target_prefix ${QMLPLUGIN_TARGET_PREFIX}${PLUGIN})
117 add_custom_target(${target_prefix}-qmltypes ALL127 set(qmltypes_path ${CMAKE_CURRENT_SOURCE_DIR}/${plugin_suffix}.qmltypes)
128
129 add_custom_target(${target_prefix}-qmltypes
118 COMMAND env ${QMLPLUGIN_ENVIRONMENT} ${qmlplugindump_executable} -notrelocatable130 COMMAND env ${QMLPLUGIN_ENVIRONMENT} ${qmlplugindump_executable} -notrelocatable
119 ${PLUGIN} ${VERSION} ${QMLPLUGIN_BINARY_DIR} > ${qmltypes_path}131 ${PLUGIN} ${VERSION} ${QMLPLUGIN_MODULE_DIR} > ${qmltypes_path}
132 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
120 )133 )
121 add_dependencies(${target_prefix}-qmltypes ${target_prefix}-qmlfiles ${QMLPLUGIN_TARGETS})134 add_dependencies(${target_prefix}-qmltypes ${target_prefix}-qmlfiles ${QMLPLUGIN_TARGETS})
122135 add_dependencies(qmltypes ${target_prefix}-qmltypes)
123 if (QMLPLUGIN_DESTINATION)
124 # Install the typeinfo file
125 install(FILES ${qmltypes_path}
126 DESTINATION ${QMLPLUGIN_DESTINATION}/${PATH}
127 )
128 endif()
129 endif()136 endif()
130137
131 set_target_properties(${QMLPLUGIN_TARGETS} PROPERTIES138 set_target_properties(${QMLPLUGIN_TARGETS} PROPERTIES
132139
=== modified file 'debian/changelog'
--- debian/changelog 2015-01-23 12:17:25 +0000
+++ debian/changelog 2015-04-09 12:58:32 +0000
@@ -1,3 +1,10 @@
1ubuntu-settings-components (0.6-0ubuntu1) UNRELEASED; urgency=medium
2
3 [ Nick Dedekind ]
4 * Added ServerActivationSync
5
6 -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 12 Mar 2015 14:04:34 +0000
7
1ubuntu-settings-components (0.5+15.04.20150123.1-0ubuntu1) vivid; urgency=medium8ubuntu-settings-components (0.5+15.04.20150123.1-0ubuntu1) vivid; urgency=medium
29
3 [ Sebastien Bacher ]10 [ Sebastien Bacher ]
@@ -5,6 +12,12 @@
512
6 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 23 Jan 2015 12:17:25 +000013 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 23 Jan 2015 12:17:25 +0000
714
15ubuntu-settings-components (0.5-0ubuntu1) UNRELEASED; urgency=medium
16
17 * Added SyncSwitch & SyncCheckBox components
18
19 -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 23 Oct 2014 17:09:21 -0400
20
8ubuntu-settings-components (0.4+15.04.20141105-0ubuntu1) vivid; urgency=low21ubuntu-settings-components (0.4+15.04.20141105-0ubuntu1) vivid; urgency=low
922
10 [ Sebastien Bacher ]23 [ Sebastien Bacher ]
1124
=== added directory 'plugins'
=== added file 'plugins/CMakeLists.txt'
--- plugins/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/CMakeLists.txt 2015-04-09 12:58:32 +0000
@@ -0,0 +1,8 @@
1include(QmlPlugins)
2
3macro(add_usc_plugin PLUGIN VERSION PATH)
4 export_qmlfiles(${PLUGIN} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN})
5 export_qmlplugin(${PLUGIN} ${VERSION} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN})
6endmacro()
7
8add_subdirectory(Ubuntu)
09
=== renamed directory 'Ubuntu' => 'plugins/Ubuntu'
=== modified file 'plugins/Ubuntu/Settings/CMakeLists.txt'
--- Ubuntu/Settings/CMakeLists.txt 2014-06-26 14:21:52 +0000
+++ plugins/Ubuntu/Settings/CMakeLists.txt 2015-04-09 12:58:32 +0000
@@ -1,9 +1,2 @@
1include(QmlPlugins)
2
3macro(add_usc_plugin PLUGIN VERSION PATH)
4 export_qmlfiles(${PLUGIN} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN})
5 export_qmlplugin(${PLUGIN} ${VERSION} ${PATH} DESTINATION ${QT_IMPORTS_DIR} ${ARGN})
6endmacro()
7
8add_subdirectory(Components)1add_subdirectory(Components)
9add_subdirectory(Menus)2add_subdirectory(Menus)
103
=== modified file 'plugins/Ubuntu/Settings/Components/CMakeLists.txt'
--- Ubuntu/Settings/Components/CMakeLists.txt 2014-07-31 13:05:44 +0000
+++ plugins/Ubuntu/Settings/Components/CMakeLists.txt 2015-04-09 12:58:32 +0000
@@ -1,1 +1,19 @@
1add_usc_plugin(Ubuntu.Settings.Components 0.1 Ubuntu/Settings/Components)1project(UbuntuSettingsComponentsQml)
2
3find_package(Qt5Core REQUIRED)
4
5include_directories(
6 ${CMAKE_CURRENT_SOURCE_DIR}
7 ${CMAKE_CURRENT_BINARY_DIR}
8)
9
10add_definitions(-DUBUNTUSETTINGSCOMPONENTS_LIBRARY)
11
12add_library(UbuntuSettingsComponentsQml MODULE
13 plugin.cpp
14 serverpropertysynchroniser.cpp
15)
16
17qt5_use_modules(UbuntuSettingsComponentsQml Core Qml Quick)
18
19add_usc_plugin(Ubuntu.Settings.Components 0.1 Ubuntu/Settings/Components TARGETS UbuntuSettingsComponentsQml)
220
=== added file 'plugins/Ubuntu/Settings/Components/Components.qmltypes'
--- plugins/Ubuntu/Settings/Components/Components.qmltypes 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/Settings/Components/Components.qmltypes 2015-04-09 12:58:32 +0000
@@ -0,0 +1,73 @@
1import 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.Settings.Components 0.1 plugins'
8
9Module {
10 Component {
11 name: "ServerPropertySynchroniser"
12 prototype: "QObject"
13 exports: ["Ubuntu.Settings.Components/ServerPropertySynchroniser 0.1"]
14 exportMetaObjectRevisions: [0]
15 Property { name: "serverTarget"; type: "QObject"; isPointer: true }
16 Property { name: "serverProperty"; type: "string" }
17 Property { name: "userTarget"; type: "QObject"; isPointer: true }
18 Property { name: "userProperty"; type: "string" }
19 Property { name: "userTrigger"; type: "string" }
20 Property { name: "syncTimeout"; type: "int" }
21 Property { name: "useWaitBuffer"; type: "bool" }
22 Property { name: "maximumWaitBufferInterval"; type: "int" }
23 Property { name: "bufferedSyncTimeout"; type: "bool" }
24 Property { name: "syncWaiting"; type: "bool"; isReadonly: true }
25 Signal {
26 name: "serverTargetChanged"
27 Parameter { name: "serverTarget"; type: "QObject"; isPointer: true }
28 }
29 Signal {
30 name: "serverPropertyChanged"
31 Parameter { name: "serverProperty"; type: "string" }
32 }
33 Signal {
34 name: "userTargetChanged"
35 Parameter { name: "userTarget"; type: "QObject"; isPointer: true }
36 }
37 Signal {
38 name: "userPropertyChanged"
39 Parameter { name: "serverProperty"; type: "string" }
40 }
41 Signal {
42 name: "userTriggerChanged"
43 Parameter { name: "userTrigger"; type: "string" }
44 }
45 Signal {
46 name: "syncTimeoutChanged"
47 Parameter { name: "timeout"; type: "int" }
48 }
49 Signal {
50 name: "syncWaitingChanged"
51 Parameter { name: "waiting"; type: "bool" }
52 }
53 Signal {
54 name: "bufferedSyncTimeoutChanged"
55 Parameter { type: "bool" }
56 }
57 Signal {
58 name: "useWaitBufferChanged"
59 Parameter { name: "useWaitBuffer"; type: "bool" }
60 }
61 Signal {
62 name: "maximumWaitBufferIntervalChanged"
63 Parameter { name: "timeout"; type: "int" }
64 }
65 Signal {
66 name: "syncTriggered"
67 Parameter { name: "value"; type: "QVariant" }
68 }
69 Method { name: "updateUserValue" }
70 Method { name: "activate" }
71 Method { name: "reset" }
72 }
73}
074
=== added file 'plugins/Ubuntu/Settings/Components/plugin.cpp'
--- plugins/Ubuntu/Settings/Components/plugin.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/Settings/Components/plugin.cpp 2015-04-09 12:58:32 +0000
@@ -0,0 +1,27 @@
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 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// local
18#include "plugin.h"
19#include "serverpropertysynchroniser.h"
20
21// Qt
22#include <QtQml/qqml.h>
23
24void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri)
25{
26 qmlRegisterType<ServerPropertySynchroniser>(uri, 0, 1, "ServerPropertySynchroniser");
27}
028
=== added file 'plugins/Ubuntu/Settings/Components/plugin.h'
--- plugins/Ubuntu/Settings/Components/plugin.h 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/Settings/Components/plugin.h 2015-04-09 12:58:32 +0000
@@ -0,0 +1,30 @@
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 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 UBUNTUSETTINGSCOMPONENTS_PLUGIN_H
18#define UBUNTUSETTINGSCOMPONENTS_PLUGIN_H
19
20#include <QtQml/QQmlExtensionPlugin>
21
22class UbuntuSettingsComponentsPlugin : public QQmlExtensionPlugin
23{
24 Q_OBJECT
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
26public:
27 void registerTypes(const char *uri);
28};
29
30#endif // UBUNTUSETTINGSCOMPONENTS_PLUGIN_H
031
=== modified file 'plugins/Ubuntu/Settings/Components/qmldir'
--- Ubuntu/Settings/Components/qmldir 2014-09-15 17:18:27 +0000
+++ plugins/Ubuntu/Settings/Components/qmldir 2015-04-09 12:58:32 +0000
@@ -1,4 +1,6 @@
1module Ubuntu.Settings.Components1module Ubuntu.Settings.Components
2plugin UbuntuSettingsComponentsQml
3typeinfo Components.qmltypes
24
3ActionTextField 0.1 ActionTextField.qml5ActionTextField 0.1 ActionTextField.qml
4Calendar 0.1 Calendar.qml6Calendar 0.1 Calendar.qml
57
=== added file 'plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp'
--- plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.cpp 2015-04-09 12:58:32 +0000
@@ -0,0 +1,382 @@
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 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 "serverpropertysynchroniser.h"
18
19#include <QQmlProperty>
20#include <QTimer>
21#include <QDebug>
22
23ServerPropertySynchroniser::ServerPropertySynchroniser(QObject* parent)
24 : QObject(parent)
25 , m_serverTarget(nullptr)
26 , m_userTarget(nullptr)
27 , m_classComplete(false)
28 , m_busy(false)
29 , m_connectedServerTarget(nullptr)
30 , m_connectedUserTarget(nullptr)
31 , m_serverSyncTimer(new QTimer(this))
32 , m_bufferTimeout(nullptr)
33 , m_useWaitBuffer(true)
34 , m_buffering(false)
35 , m_bufferedSyncTimeout(false)
36{
37 m_serverSyncTimer->setSingleShot(true);
38 m_serverSyncTimer->setInterval(30000);
39 connect(m_serverSyncTimer, &QTimer::timeout, this, &ServerPropertySynchroniser::serverSyncTimedOut);
40}
41
42void ServerPropertySynchroniser::classBegin()
43{
44 m_classComplete = false;
45}
46
47void ServerPropertySynchroniser::componentComplete()
48{
49 m_classComplete = true;
50 connectServer();
51 connectUser();
52}
53
54void ServerPropertySynchroniser::reset()
55{
56 if (m_serverSyncTimer->isActive()) {
57 m_serverSyncTimer->stop();
58 Q_EMIT syncWaitingChanged(false);
59 }
60 if (m_bufferTimeout) m_bufferTimeout->stop();
61 m_buffering = false;
62}
63
64QObject *ServerPropertySynchroniser::serverTarget() const
65{
66 return m_serverTarget;
67}
68
69void ServerPropertySynchroniser::setServerTarget(QObject *target)
70{
71 if (m_serverTarget != target) {
72 m_serverTarget = target;
73 Q_EMIT serverTargetChanged(m_serverTarget);
74
75 connectServer();
76 }
77}
78
79QString ServerPropertySynchroniser::serverProperty() const
80{
81 return m_serverProperty;
82}
83
84void ServerPropertySynchroniser::setServerProperty(const QString &property)
85{
86 if (m_serverProperty != property) {
87 m_serverProperty = property;
88 Q_EMIT serverPropertyChanged(m_serverProperty);
89
90 connectServer();
91 }
92}
93
94QObject *ServerPropertySynchroniser::userTarget() const
95{
96 return m_userTarget;
97}
98
99void ServerPropertySynchroniser::setUserTarget(QObject *target)
100{
101 if (m_userTarget != target) {
102 m_userTarget = target;
103 Q_EMIT userTargetChanged(m_userTarget);
104
105 connectUser();
106 }
107}
108
109QString ServerPropertySynchroniser::userProperty() const
110{
111 return m_userProperty;
112}
113
114void ServerPropertySynchroniser::setUserProperty(const QString &property)
115{
116 if (m_userProperty != property) {
117 m_userProperty = property;
118 Q_EMIT userPropertyChanged(m_userProperty);
119
120 connectUser();
121 }
122}
123
124QString ServerPropertySynchroniser::userTrigger() const
125{
126 return m_userTrigger;
127}
128
129void ServerPropertySynchroniser::setUserTrigger(const QString &trigger)
130{
131 if (m_userTrigger != trigger) {
132 m_userTrigger = trigger;
133 Q_EMIT userPropertyChanged(m_userTrigger);
134
135 connectUser();
136 }
137}
138
139int ServerPropertySynchroniser::syncTimeout() const
140{
141 return m_serverSyncTimer->interval();
142}
143
144void ServerPropertySynchroniser::setSyncTimeout(int timeout)
145{
146 if (m_serverSyncTimer->interval() != timeout) {
147 m_serverSyncTimer->setInterval(timeout);
148 Q_EMIT syncTimeoutChanged(timeout);
149 }
150}
151
152bool ServerPropertySynchroniser::useWaitBuffer() const
153{
154 return m_useWaitBuffer;
155}
156
157void ServerPropertySynchroniser::setUseWaitBuffer(bool value)
158{
159 if (m_useWaitBuffer != value) {
160 m_useWaitBuffer = value;
161 Q_EMIT useWaitBufferChanged(m_useWaitBuffer);
162 }
163}
164
165int ServerPropertySynchroniser::maximumWaitBufferInterval() const
166{
167 return m_bufferTimeout ? m_bufferTimeout->interval() : -1;
168}
169
170void ServerPropertySynchroniser::setMaximumWaitBufferInterval(int timeout)
171{
172 if (timeout >= 0) {
173 if (!m_bufferTimeout) {
174 m_bufferTimeout = new QTimer(this);
175 m_bufferTimeout->setInterval(timeout);
176 m_bufferTimeout->setSingleShot(true);
177 connect(m_bufferTimeout, &QTimer::timeout, this, &ServerPropertySynchroniser::bufferTimedOut);
178
179 Q_EMIT maximumWaitBufferIntervalChanged(timeout);
180 }
181 else if (timeout != m_bufferTimeout->interval()) {
182 m_bufferTimeout->setInterval(timeout);
183 Q_EMIT maximumWaitBufferIntervalChanged(timeout);
184 }
185
186 } else if (m_bufferTimeout) {
187 if (m_bufferTimeout->isActive()) {
188 m_buffering = false;
189 }
190 delete m_bufferTimeout;
191 m_bufferTimeout = nullptr;
192 Q_EMIT maximumWaitBufferIntervalChanged(timeout);
193 }
194}
195
196bool ServerPropertySynchroniser::bufferedSyncTimeout() const
197{
198 return m_bufferedSyncTimeout;
199}
200
201void ServerPropertySynchroniser::setBufferedSyncTimeout(bool value)
202{
203 if (m_bufferedSyncTimeout != value) {
204 m_bufferedSyncTimeout = value;
205 Q_EMIT bufferedSyncTimeoutChanged(value);
206 }
207}
208
209bool ServerPropertySynchroniser::syncWaiting() const
210{
211 return m_serverSyncTimer->isActive();
212}
213
214void ServerPropertySynchroniser::activate()
215{
216 // Don't want any signals we fire to create binding loops.
217 if (m_busy) return;
218 m_busy = true;
219
220 if (m_useWaitBuffer) {
221 // Dampen the activations? Buffer the change.
222 if (m_bufferTimeout) {
223 if (m_bufferTimeout->isActive()) {
224 m_buffering = true;
225 m_busy = false;
226 return;
227 }
228 m_bufferTimeout->start();
229 // Not using a buffer timer? Buffer the change till server timeout
230 } else if (m_serverSyncTimer->isActive()) {
231 m_buffering = true;
232 m_busy = false;
233 return;
234 }
235 }
236
237 m_serverSyncTimer->start();
238 Q_EMIT syncWaitingChanged(true);
239
240 // Fire off a change to the server user property value
241 QQmlProperty userProp(m_userTarget, m_userProperty);
242 if (!userProp.isValid()) {
243 Q_EMIT syncTriggered(QVariant());
244 } else {
245 Q_EMIT syncTriggered(userProp.read());
246 }
247 m_busy = false;
248}
249
250void ServerPropertySynchroniser::connectServer()
251{
252 // if we havent finished constructing the class, then wait
253 if (!m_classComplete) return;
254
255 if (m_connectedServerTarget) QObject::disconnect(m_connectedServerTarget, 0, this, 0);
256 if (!m_serverTarget || m_serverProperty.isEmpty()) {
257 return;
258 }
259
260 // Connect to the server property change
261 QQmlProperty prop(m_serverTarget, m_serverProperty);
262 if (prop.isValid()) {
263 if (prop.connectNotifySignal(this, SLOT(updateUserValue()))) {
264 m_connectedServerTarget = m_serverTarget;
265 }
266 // once we're connected to the server property, we need to make sure the user target is
267 // set to the server value
268 updateUserValue();
269 }
270}
271
272void ServerPropertySynchroniser::connectUser()
273{
274 // if we havent finished constructing the class, then wait
275 if (!m_classComplete) return;
276
277 if (m_connectedUserTarget) QObject::disconnect(m_connectedUserTarget, 0, this, 0);
278 if (!m_userTarget) {
279 if (!parent()) return;
280 m_userTarget = parent();
281 Q_EMIT userTargetChanged(m_userTarget);
282 }
283
284 if (m_userTrigger.isEmpty()) {
285 // Connect to the user property change
286 QQmlProperty prop(m_userTarget, m_userProperty);
287 if (prop.isValid()) {
288 if (prop.connectNotifySignal(this, SLOT(activate()))) {
289 m_connectedUserTarget = m_userTarget;
290 }
291 // once we're connected to the user property, we need to make sure the user target is
292 // set to the server value
293 updateUserValue();
294 }
295 } else {
296 QQmlProperty prop(m_userTarget, m_userTrigger);
297 if (prop.isValid() && prop.isSignalProperty()) {
298 if (connect(m_userTarget, ("2" + prop.method().methodSignature()).constData(),
299 this, SLOT(activate()))) {
300 m_connectedUserTarget = m_userTarget;
301 }
302
303 // once we're connected to the user signal, we need to make sure the user target is
304 // set to the server value
305 updateUserValue();
306 }
307 }
308}
309
310void ServerPropertySynchroniser::updateUserValue()
311{
312 // Don't want any signals we fire to create binding loops.
313 if (m_busy) return;
314 m_busy = true;
315
316 bool waitingBufferedServerChange = m_bufferTimeout && m_bufferTimeout->isActive();
317
318 // If we've been waiting for a sync, stop the wait.
319 if (m_serverSyncTimer->isActive()) {
320 m_serverSyncTimer->stop();
321 Q_EMIT syncWaitingChanged(false);
322 }
323
324 QQmlProperty userProp(m_userTarget, m_userProperty);
325 QQmlProperty serverProp(m_serverTarget, m_serverProperty);
326 if (!userProp.isValid() || !serverProp.isValid()) {
327 m_busy = false;
328 return;
329 }
330
331 // If we've been buffering changes since last change was send,
332 // we verify that what the server gave us is what we want, and send another
333 // activation if not.
334 if (m_buffering) {
335 m_buffering = false;
336 m_busy = false;
337 if (serverProp.read() != userProp.read()) {
338 activate();
339 }
340 return;
341 }
342
343 // Don't update until we hit the buffer timeout.
344 if (waitingBufferedServerChange) {
345 m_busy = false;
346 return;
347 }
348
349 // update the user target property.
350 userProp.write(serverProp.read());
351 m_busy = false;
352}
353
354void ServerPropertySynchroniser::serverSyncTimedOut()
355{
356 if (m_buffering && !m_bufferedSyncTimeout) {
357 m_buffering = false;
358 }
359 Q_EMIT syncWaitingChanged(false);
360 updateUserValue();
361}
362
363void ServerPropertySynchroniser::bufferTimedOut()
364{
365 if (m_buffering) {
366 m_buffering = false;
367 activate();
368 } else {
369 // Update the user value.
370 if (m_busy) return;
371 m_busy = true;
372
373 QQmlProperty userProp(m_userTarget, m_userProperty);
374 QQmlProperty serverProp(m_serverTarget, m_serverProperty);
375 if (!userProp.isValid() || !serverProp.isValid()) {
376 m_busy = false;
377 return;
378 }
379 userProp.write(serverProp.read());
380 m_busy = false;
381 }
382}
0383
=== added file 'plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h'
--- plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/Settings/Components/serverpropertysynchroniser.h 2015-04-09 12:58:32 +0000
@@ -0,0 +1,157 @@
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 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 SERVERPROPERTYSYNCHRONISER_H
18#define SERVERPROPERTYSYNCHRONISER_H
19
20#include <QObject>
21#include <QQmlParserStatus>
22#include <QVariant>
23
24class QTimer;
25
26class ServerPropertySynchroniser : public QObject, public QQmlParserStatus
27{
28 Q_OBJECT
29 Q_INTERFACES(QQmlParserStatus)
30
31 // Target object which contains the property to keep the user property in sync with.
32 Q_PROPERTY(QObject* serverTarget READ serverTarget WRITE setServerTarget NOTIFY serverTargetChanged)
33 // Server property to keep the user property in sync with.
34 Q_PROPERTY(QString serverProperty READ serverProperty WRITE setServerProperty NOTIFY serverPropertyChanged)
35
36 // User object (control) which sources the property to update the server property.
37 // Defaults to the object's parent if not set.
38 Q_PROPERTY(QObject* userTarget READ userTarget WRITE setUserTarget NOTIFY userTargetChanged)
39 // User property to update the server property.
40 Q_PROPERTY(QString userProperty READ userProperty WRITE setUserProperty NOTIFY userPropertyChanged)
41 // Trigger that causes an update. By default, the control will use the userProperty change notification.
42 // eg. "onTriggered"
43 Q_PROPERTY(QString userTrigger READ userTrigger WRITE setUserTrigger NOTIFY userTriggerChanged)
44
45 // Time to wait for a change verification before re-asserting the server value.
46 Q_PROPERTY(int syncTimeout READ syncTimeout WRITE setSyncTimeout NOTIFY syncTimeoutChanged)
47
48 // Buffer user property changes until the previous change is verified
49 Q_PROPERTY(bool useWaitBuffer
50 READ useWaitBuffer
51 WRITE setUseWaitBuffer
52 NOTIFY useWaitBufferChanged)
53
54 // Maximum intervals between buffers for the server to respond. If we don't get a response within this interval,
55 // the next buffer will be sent. Good for live sliders. Defaults to disabled.
56 Q_PROPERTY(int maximumWaitBufferInterval
57 READ maximumWaitBufferInterval
58 WRITE setMaximumWaitBufferInterval
59 NOTIFY maximumWaitBufferIntervalChanged)
60
61 // Resend the buffered value if we timeout waiting for a change from the server. Defaults to false
62 Q_PROPERTY(bool bufferedSyncTimeout
63 READ bufferedSyncTimeout
64 WRITE setBufferedSyncTimeout
65 NOTIFY bufferedSyncTimeoutChanged)
66
67 // True if we're waiting for a change verification from the server
68 Q_PROPERTY(bool syncWaiting READ syncWaiting NOTIFY syncWaitingChanged)
69
70public:
71 ServerPropertySynchroniser(QObject* parent = nullptr);
72
73 QObject* serverTarget() const;
74 void setServerTarget(QObject* target);
75
76 QString serverProperty() const;
77 void setServerProperty(const QString& property);
78
79 QObject* userTarget() const;
80 void setUserTarget(QObject* target);
81
82 QString userProperty() const;
83 void setUserProperty(const QString& property);
84
85 QString userTrigger() const;
86 void setUserTrigger(const QString& trigger);
87
88 int syncTimeout() const;
89 void setSyncTimeout(int timeout);
90
91 bool useWaitBuffer() const;
92 void setUseWaitBuffer(bool value);
93
94 int maximumWaitBufferInterval() const;
95 void setMaximumWaitBufferInterval(int timeout);
96
97 bool bufferedSyncTimeout() const;
98 void setBufferedSyncTimeout(bool);
99
100 bool syncWaiting() const;
101
102 void classBegin() override;
103 void componentComplete() override;
104
105 Q_INVOKABLE void reset();
106
107public Q_SLOTS:
108 void updateUserValue();
109 void activate();
110
111Q_SIGNALS:
112 void serverTargetChanged(QObject* serverTarget);
113 void serverPropertyChanged(QString serverProperty);
114
115 void userTargetChanged(QObject* userTarget);
116 void userPropertyChanged(QString serverProperty);
117 void userTriggerChanged(QString userTrigger);
118
119 void syncTimeoutChanged(int timeout);
120 void syncWaitingChanged(bool waiting);
121 void bufferedSyncTimeoutChanged(bool);
122
123 void useWaitBufferChanged(bool useWaitBuffer);
124 void maximumWaitBufferIntervalChanged(int timeout);
125
126 // Emitted when we want to update the backend.
127 void syncTriggered(const QVariant& value);
128
129private Q_SLOTS:
130 void serverSyncTimedOut();
131 void bufferTimedOut();
132
133private:
134 void connectServer();
135 void connectUser();
136
137 QObject* m_serverTarget;
138 QString m_serverProperty;
139
140 QObject* m_userTarget;
141 QString m_userProperty;
142 QString m_userTrigger;
143
144 bool m_classComplete;
145 bool m_busy;
146
147 QObject* m_connectedServerTarget;
148 QObject* m_connectedUserTarget;
149
150 QTimer* m_serverSyncTimer;
151 QTimer* m_bufferTimeout;
152 bool m_useWaitBuffer;
153 bool m_buffering;
154 bool m_bufferedSyncTimeout;
155};
156
157#endif // SERVERPROPERTYSYNCHRONISER_H
0158
=== added file 'plugins/Ubuntu/Settings/Menus/Menus.qmltypes'
--- plugins/Ubuntu/Settings/Menus/Menus.qmltypes 1970-01-01 00:00:00 +0000
+++ plugins/Ubuntu/Settings/Menus/Menus.qmltypes 2015-04-09 12:58:32 +0000
@@ -0,0 +1,30 @@
1import 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.Settings.Menus 0.1 plugins'
8
9Module {
10 Component {
11 name: "TransferState"
12 prototype: "QObject"
13 exports: ["Ubuntu.Settings.Menus/TransferState 0.1"]
14 isCreatable: false
15 exportMetaObjectRevisions: [0]
16 Enum {
17 name: "TransferStates"
18 values: {
19 "Queued": 0,
20 "Running": 1,
21 "Paused": 2,
22 "Canceled": 3,
23 "Hashing": 4,
24 "Processing": 5,
25 "Finished": 6,
26 "Error": 7
27 }
28 }
29 }
30}
031
=== modified file 'plugins/Ubuntu/Settings/Menus/plugin.cpp'
--- Ubuntu/Settings/Menus/plugin.cpp 2014-06-27 13:56:26 +0000
+++ plugins/Ubuntu/Settings/Menus/plugin.cpp 2015-04-09 12:58:32 +0000
@@ -21,7 +21,7 @@
21// Qt21// Qt
22#include <QtQml/qqml.h>22#include <QtQml/qqml.h>
2323
24void UbuntuSettingsComponentsPlugin::registerTypes(const char *uri)24void UbuntuSettingsMenusPlugin::registerTypes(const char *uri)
25{25{
26 qmlRegisterUncreatableType<TransferState>(uri, 0, 1, "TransferState", "Can't create TransferState class");26 qmlRegisterUncreatableType<TransferState>(uri, 0, 1, "TransferState", "Can't create TransferState class");
27}27}
2828
=== modified file 'plugins/Ubuntu/Settings/Menus/plugin.h'
--- Ubuntu/Settings/Menus/plugin.h 2014-06-27 09:39:18 +0000
+++ plugins/Ubuntu/Settings/Menus/plugin.h 2015-04-09 12:58:32 +0000
@@ -14,12 +14,12 @@
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/>.
15 */15 */
1616
17#ifndef UBUNTUSETTINGSCOMPOENNTS_PLUGIN_H17#ifndef UBUNTUSETTINGSMENUS_PLUGIN_H
18#define UBUNTUSETTINGSCOMPOENNTS_PLUGIN_H18#define UBUNTUSETTINGSMENUS_PLUGIN_H
1919
20#include <QtQml/QQmlExtensionPlugin>20#include <QtQml/QQmlExtensionPlugin>
2121
22class UbuntuSettingsComponentsPlugin : public QQmlExtensionPlugin22class UbuntuSettingsMenusPlugin : public QQmlExtensionPlugin
23{23{
24 Q_OBJECT24 Q_OBJECT
25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")25 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
@@ -27,4 +27,4 @@
27 void registerTypes(const char *uri);27 void registerTypes(const char *uri);
28};28};
2929
30#endif // UBUNTUSETTINGSCOMPOENNTS_PLUGIN_H30#endif // UBUNTUSETTINGSMENUS_PLUGIN_H
3131
=== modified file 'plugins/Ubuntu/Settings/Menus/qmldir'
--- Ubuntu/Settings/Menus/qmldir 2014-07-25 17:53:08 +0000
+++ plugins/Ubuntu/Settings/Menus/qmldir 2015-04-09 12:58:32 +0000
@@ -1,6 +1,6 @@
1module Ubuntu.Settings.Menus1module Ubuntu.Settings.Menus
2plugin UbuntuSettingsMenusQml2plugin UbuntuSettingsMenusQml
3typeinfo plugin.qmltypes3typeinfo Menus.qmltypes
44
5AccessPointMenu 0.1 AccessPointMenu.qml5AccessPointMenu 0.1 AccessPointMenu.qml
6ButtonMenu 0.1 ButtonMenu.qml6ButtonMenu 0.1 ButtonMenu.qml
77
=== modified file 'tests/qmltests/CMakeLists.txt'
--- tests/qmltests/CMakeLists.txt 2014-07-31 11:29:03 +0000
+++ tests/qmltests/CMakeLists.txt 2015-04-09 12:58:32 +0000
@@ -6,11 +6,12 @@
6set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")6set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LC_ALL=C")
77
8set(qmltest_DEFAULT_IMPORT_PATHS8set(qmltest_DEFAULT_IMPORT_PATHS
9 ${CMAKE_BINARY_DIR}9 ${CMAKE_BINARY_DIR}/plugins
10 ${CMAKE_BINARY_DIR}/tests/utils/modules10 ${CMAKE_BINARY_DIR}/tests/utils/modules
11)11)
1212
13add_qml_test(Components Calendar)13add_qml_test(Components Calendar)
14add_qml_test(Components ServerPropertySynchroniser)
14add_qml_test(Components StatusIcon)15add_qml_test(Components StatusIcon)
1516
16add_qml_test(Menus AccessPointMenu)17add_qml_test(Menus AccessPointMenu)
1718
=== added file 'tests/qmltests/Components/tst_ServerPropertySynchroniser.qml'
--- tests/qmltests/Components/tst_ServerPropertySynchroniser.qml 1970-01-01 00:00:00 +0000
+++ tests/qmltests/Components/tst_ServerPropertySynchroniser.qml 2015-04-09 12:58:32 +0000
@@ -0,0 +1,398 @@
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
17import QtQuick 2.3
18import QtTest 1.0
19import Ubuntu.Test 0.1
20import Ubuntu.Settings.Components 0.1 as USC
21import Ubuntu.Settings.Menus 0.1 as USM
22import Ubuntu.Components 0.1
23
24Item {
25 id: root
26 width: units.gu(60)
27 height: units.gu(70)
28
29 QtObject {
30 id: switchBackend
31
32 property bool checked: false
33 property bool inSync: checked === switchControl.checked
34
35 property Timer timer: Timer {
36 interval: 2000
37 onTriggered: switchBackend.checked = !switchBackend.checked
38 }
39 }
40
41 QtObject {
42 id: checkBackend
43
44 property bool checked: false
45 property bool inSync: checked === checkControl.checked
46
47 property Timer timer: Timer {
48 interval: 2000
49 onTriggered: checkBackend.checked = !checkBackend.checked
50 }
51 }
52
53 QtObject {
54 id: sliderBackend
55
56 property real value: 50
57 property bool inSync: value === slider.value
58 property var changeToValue: undefined
59
60 property Timer timer: Timer {
61 interval: 200
62
63 onTriggered: {
64 sliderBackend.value = sliderBackend.changeToValue;
65 }
66 }
67 }
68
69 QtObject {
70 id: apBackend
71
72 property bool active: false
73 property bool inSync: active === apMenu.active
74
75 property Timer timer: Timer {
76 interval: 2000
77 onTriggered: apBackend.active = !apBackend.active
78 }
79 }
80
81
82 Column {
83 anchors.fill: parent
84 anchors.margins: units.gu(1)
85
86 spacing: units.gu(2)
87
88 Row {
89 spacing: units.gu(3)
90
91 Switch {
92 id: switchControl
93 anchors.verticalCenter: parent.verticalCenter
94
95 USC.ServerPropertySynchroniser {
96 id: switchSync
97 objectName: "switchSync"
98
99 syncTimeout: 3000
100
101 userTarget: switchControl
102 userProperty: "checked"
103
104 serverTarget: switchBackend
105 serverProperty: "checked"
106
107 onSyncTriggered: switchBackend.timer.start()
108 onSyncWaitingChanged: switchSyncSpy.clear()
109 }
110 }
111
112 Column {
113 Label { text: switchBackend.inSync ? "synced" : "out of sync" }
114 Label { text: switchSync.syncWaiting ? "syncWait" : "no syncWait" }
115 Label { text: "activates: " + switchSyncSpy.count }
116 }
117 }
118
119 Row {
120 spacing: units.gu(3)
121
122 CheckBox {
123 id: checkControl
124 anchors.verticalCenter: parent.verticalCenter
125
126 USC.ServerPropertySynchroniser {
127 id: checkSync
128 objectName: "checkSync"
129
130 syncTimeout: 3000
131
132 userTarget: checkControl
133 userProperty: "checked"
134
135 serverTarget: checkBackend
136 serverProperty: "checked"
137
138 onSyncTriggered: checkBackend.timer.start()
139
140 onSyncWaitingChanged: checkSyncSpy.clear()
141 }
142 }
143
144 Column {
145 Label { text: checkBackend.inSync ? "synced" : "out of sync" }
146 Label { text: checkSync.syncWaiting ? "syncWait" : "no syncWait" }
147 Label { text: "activates: " + checkSyncSpy.count }
148 }
149 }
150
151 Row {
152 id: sliderRoot
153 spacing: units.gu(3)
154
155 Slider {
156 id: slider
157 anchors.verticalCenter: parent.verticalCenter
158 live: true
159 minimumValue: 0.0
160 maximumValue: 100.0
161
162 property real serverValue: sliderBackend.value
163 USC.ServerPropertySynchroniser {
164 id: sliderSync
165 objectName: "sliderSync"
166
167 syncTimeout: 3000
168
169 userTarget: slider
170 userProperty: "value"
171
172 serverTarget: slider
173 serverProperty: "serverValue"
174
175 onSyncTriggered: {
176 sliderBackend.changeToValue = value;
177 sliderBackend.timer.start();
178 }
179
180 onSyncWaitingChanged: sliderSyncSpy.clear()
181 }
182 }
183
184 Column {
185 Label { text: sliderBackend.inSync ? "synced" : "out of sync" }
186 Label { text: sliderSync.syncWaiting ? "syncWait" : "no syncWait" }
187 Label { text: "activates: " + sliderSyncSpy.count }
188 }
189 }
190
191 Row {
192 spacing: units.gu(3)
193 height: childrenRect.height
194 anchors.left: parent.left
195 anchors.right: parent.right
196
197 USM.AccessPointMenu {
198 id: apMenu
199 width: units.gu(30)
200
201 text: "Test Check Menu"
202
203 USC.ServerPropertySynchroniser {
204 id: apMenuSync
205 objectName: "apMenuSync"
206
207 syncTimeout: 3000
208
209 userTarget: apMenu
210 userProperty: "active"
211 userTrigger: "onTriggered"
212
213 serverTarget: apBackend
214 serverProperty: "active"
215
216 onSyncTriggered: apBackend.timer.start()
217
218 onSyncWaitingChanged: switchSyncSpy.clear()
219 }
220 }
221
222 Column {
223 Label { text: apBackend.inSync ? "synced" : "out of sync" }
224 Label { text: apMenuSync.syncWaiting ? "syncWait" : "no syncWait" }
225 Label { text: "activates: " + apSyncSpy.count }
226 }
227 }
228 }
229
230 SignalSpy {
231 id: switchSyncSpy
232 target: switchControl
233 signalName: "triggered"
234 }
235 SignalSpy {
236 id: checkSyncSpy
237 target: checkControl
238 signalName: "triggered"
239 }
240 SignalSpy {
241 id: sliderSyncSpy
242 target: slider
243 signalName: "valueChanged"
244 }
245 SignalSpy {
246 id: apSyncSpy
247 target: apMenu
248 signalName: "triggered"
249 }
250 SignalSpy {
251 id: sliderSyncActivatedSpy
252 target: sliderSync
253 signalName: "syncTriggered"
254 }
255 SignalSpy {
256 id:apSyncActivatedSpy
257 target: apMenuSync
258 signalName: "syncTriggered"
259 }
260
261 QtObject {
262 id: switchBackend2
263
264 property bool checked2: false
265 property bool inSync: checked2 === switchControl.checked
266
267 property Timer switchTimer: Timer {
268 interval: 1000
269 onTriggered: switchBackend2.checked2 = !switchBackend2.checked2
270 }
271 }
272
273 UbuntuTestCase {
274 name: "ServerActivationSync"
275 when: windowShown
276
277 function init() {
278 waitForRendering(root);
279 switchBackend.timer.interval = 100;
280 checkBackend.timer.interval = 100;
281 sliderBackend.timer.interval = 100;
282 apBackend.timer.interval = 100;
283
284 switchSync.syncTimeout = 200;
285 checkSync.syncTimeout = 200;
286 sliderSync.syncTimeout = 200;
287 apMenuSync.syncTimeout = 200;
288
289 sliderSyncActivatedSpy.clear();
290 apSyncActivatedSpy.clear();
291 }
292
293 function cleanup() {
294 switchBackend.timer.stop();
295 checkBackend.timer.stop();
296 sliderBackend.timer.stop();
297
298 switchBackend.checked = false;
299 checkBackend.checked = false;
300 sliderBackend.value = 50;
301 apBackend.active = false;
302
303 switchSync.reset();
304 checkSync.reset();
305 sliderSync.reset();
306 apMenuSync.reset();
307 sliderSync.maximumWaitBufferInterval = -1
308
309 tryCompare(switchBackend, "inSync", true);
310 tryCompare(checkBackend, "inSync", true);
311 tryCompare(sliderBackend, "inSync", true);
312
313 switchSync.serverTarget = switchBackend;
314 switchSync.serverProperty = "checked";
315 }
316
317 function test_backend_change() {
318 switchBackend.checked = true;
319 compare(switchControl.checked, true, "Switch should have been toggled");
320 switchBackend.checked = false;
321 compare(switchControl.checked, false, "Switch should have been toggled");
322 }
323
324 function test_frontend_change() {
325 switchControl.clicked();
326 tryCompare(switchBackend, "checked", true);
327 }
328
329 function test_frontend_change_with_value() {
330 slider.value = 60;
331 tryCompare(sliderBackend, "value", 60);
332 }
333
334 function test_break_binding_change() {
335 switchControl.checked = true;
336 switchBackend.checked = true;
337 switchBackend.checked = false;
338 compare(switchControl.checked, false, "Switch should have been toggled");
339 }
340
341 function test_buffered_change_with_value() {
342 slider.value = 60;
343 compare(sliderSyncActivatedSpy.count, 1, "activated signal should have been sent")
344 slider.value = 70;
345 slider.value = 80;
346 slider.value = 90;
347 compare(sliderSyncActivatedSpy.count, 1, "activated signals should have been buffered")
348 tryCompare(sliderBackend, "value", 90);
349 tryCompare(sliderSyncActivatedSpy, "count", 2)
350 }
351
352 function test_buffered_change_with_maximum_interval() {
353 sliderSync.maximumWaitBufferInterval = 50;
354 sliderSync.syncTimeout = 5000;
355
356 slider.value = 60;
357 compare(sliderSyncActivatedSpy.count, 1, "activated signal should have been sent")
358 slider.value = 70;
359 slider.value = 80;
360 tryCompare(sliderSyncActivatedSpy, "count", 2, 500, "activated signal should have been sent after max interval")
361 slider.value = 90;
362 tryCompare(sliderSyncActivatedSpy, "count", 3, 500, "activated signal should have been sent after max interval")
363 slider.value = 100;
364 tryCompare(sliderSyncActivatedSpy, "count", 4, 500);
365 tryCompare(sliderBackend, "value", 100);
366 }
367
368 function test_connect_to_another_object() {
369 switchSync.serverTarget = switchBackend2;
370 switchSync.serverProperty = "checked2";
371
372 switchBackend2.checked2 = true;
373 compare(switchControl.checked, true, "Switch should have been toggled");
374 switchBackend2.checked2 = false;
375 compare(switchControl.checked, false, "Switch should have been toggled");
376 }
377
378 function test_client_revert() {
379 switchBackend.timer.interval = 500;
380 switchControl.clicked();
381 compare(switchControl.checked, true);
382 tryCompare(switchControl, "checked", false);
383 }
384
385 function test_user_trigger() {
386 apMenu.trigger();
387
388 compare(apSyncActivatedSpy.count, 1, "Triggering should have caused signal to be emitted");
389 tryCompare(apBackend, "active", true);
390 compare(apMenu.active, true, "User value should have updated to match server");
391 }
392
393 function test_user_trigger_doesnt_activate_on_user_property_change() {
394 apMenu.active = true;
395 compare(apSyncActivatedSpy.count, 0);
396 }
397 }
398}
0399
=== modified file 'tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml'
--- tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml 2014-08-14 11:51:14 +0000
+++ tests/utils/modules/Ubuntu/Test/UbuntuTestCase.qml 2015-04-09 12:58:32 +0000
@@ -14,13 +14,23 @@
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/>.
15 */15 */
1616
17import QtQuick 2.0
17import QtTest 1.018import QtTest 1.0
18import Ubuntu.Components 1.119import Ubuntu.Components 1.1
19import Ubuntu.Test 0.1 as UT20import Ubuntu.Test 0.1 as UT
2021
21TestCase {22TestCase {
23 id: testCase
22 TestUtil {id:util}24 TestUtil {id:util}
2325
26 ActivityIndicator {
27 visible: testCase.running
28 anchors.centerIn: parent
29 Component.onCompleted: parent = testCase.parent
30 z: 100
31 running: visible
32 }
33
24 // Fake implementation to be provided to items under test34 // Fake implementation to be provided to items under test
25 property var fakeDateTime: new function() {35 property var fakeDateTime: new function() {
26 this.currentTimeMs = 036 this.currentTimeMs = 0
@@ -297,4 +307,13 @@
297 event.release(0 /* touchId */, x, y)307 event.release(0 /* touchId */, x, y)
298 event.commit()308 event.commit()
299 }309 }
310
311 // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
312 function waitForRendering(item, timeout) {
313 if (timeout === undefined)
314 timeout = 5000;
315 if (!item)
316 qtest_fail("No item given to waitForRendering", 1);
317 return qtest_results.waitForRendering(item, timeout);
318 }
300}319}

Subscribers

People subscribed via source and target branches

to all changes: