Merge lp:~renatofilho/buteo-syncfw-qml/initial-code into lp:~renatofilho/buteo-syncfw-qml/trunk

Proposed by Renato Araujo Oliveira Filho on 2015-07-08
Status: Merged
Approved by: Renato Araujo Oliveira Filho on 2015-07-09
Approved revision: no longer in the source branch.
Merged at revision: 2
Proposed branch: lp:~renatofilho/buteo-syncfw-qml/initial-code
Merge into: lp:~renatofilho/buteo-syncfw-qml/trunk
Diff against target: 1073 lines (+979/-0)
18 files modified
.bzr-builddeb/default.conf (+2/-0)
Buteo/CMakeLists.txt (+39/-0)
Buteo/buteo-sync-qml.cpp (+204/-0)
Buteo/buteo-sync-qml.h (+181/-0)
Buteo/plugin.cpp (+27/-0)
Buteo/plugin.h (+31/-0)
Buteo/qmldir (+2/-0)
CMakeLists.txt (+30/-0)
cmake_uninstall.cmake.in (+21/-0)
debian/changelog (+5/-0)
debian/compat (+1/-0)
debian/control (+34/-0)
debian/copyright (+19/-0)
debian/rules (+9/-0)
tests/CMakeLists.txt (+1/-0)
tests/qml/CMakeLists.txt (+36/-0)
tests/qml/buteo-syncfw.py (+163/-0)
tests/qml/tst_ButeoSyncFW.qml (+174/-0)
To merge this branch: bzr merge lp:~renatofilho/buteo-syncfw-qml/initial-code
Reviewer Review Type Date Requested Status
Michael Sheldon (community) Approve on 2015-07-09
Ken VanDine (community) Needs Fixing on 2015-07-08
Renato Araujo Oliveira Filho Pending
Review via email: mp+264160@code.launchpad.net

Commit message

Implemented QML bindings for buteo syncfw DBUS service.

Description of the change

Server implementation can be found here: https://github.com/nemomobile/buteo-syncfw

To post a comment you must log in.
Michael Sheldon (michael-sheldon) wrote :

Not sure if "gnome" is the best section for the package?

review: Needs Information
Ken VanDine (ken-vandine) wrote :

I pushed a few packaging fixes to lp:~ken-vandine/buteo-syncfw-qml/packaging_tweaks

review: Needs Fixing
Ken VanDine (ken-vandine) wrote :

> Not sure if "gnome" is the best section for the package?

Agreed, but those sections aren't really all that useful these days. It seems all the apps with a GUI tend to go in "gnome", not opposed to changing that but also not really concerned.

Michael Sheldon (michael-sheldon) wrote :

I'm not sure the reinitialization that's done after an owner change will work, see the diff comment for details

review: Needs Fixing
Michael Sheldon (michael-sheldon) wrote :

Ah, no my mistake; presumably a call to deinitialize() will happen when the original owner is lost, which then calls reset on m_iface, so when the new owner appears it is null again.

Michael Sheldon (michael-sheldon) wrote :

One small in-line comment added about one of the copyright statements, but otherwise the code for this all looks good to me.

Michael Sheldon (michael-sheldon) wrote :

Looks good :)

review: Approve
2. By Renato Araujo Oliveira Filho on 2015-07-09

Implemented QML bindings for buteo syncfw DBUS service.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.bzr-builddeb'
2=== added file '.bzr-builddeb/default.conf'
3--- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000
4+++ .bzr-builddeb/default.conf 2015-07-09 14:03:36 +0000
5@@ -0,0 +1,2 @@
6+[BUILDDEB]
7+split = True
8
9=== added directory 'Buteo'
10=== added file 'Buteo/CMakeLists.txt'
11--- Buteo/CMakeLists.txt 1970-01-01 00:00:00 +0000
12+++ Buteo/CMakeLists.txt 2015-07-09 14:03:36 +0000
13@@ -0,0 +1,39 @@
14+set(BUTEO_SYNC_QML_PLUGIN "buteo-syncfw-qml")
15+
16+set(BUTEO_SYNC_QML_PLUGIN_SRCS
17+ buteo-sync-qml.cpp
18+ buteo-sync-qml.h
19+ plugin.h
20+ plugin.cpp
21+)
22+
23+set(BUTEO_SYNC_QML_PLUGIN_FILES
24+ qmldir
25+)
26+
27+add_library(${BUTEO_SYNC_QML_PLUGIN} MODULE
28+ ${BUTEO_SYNC_QML_PLUGIN_SRCS}
29+)
30+
31+target_link_libraries(${BUTEO_SYNC_QML_PLUGIN}
32+ Qt5::Core
33+ Qt5::Qml
34+ Qt5::DBus
35+ Qt5::Xml
36+)
37+
38+#copy qml files to build dir to make it possible to run without install
39+add_custom_target(buteo_components_QmlFiles ALL SOURCES ${BUTEO_SYNC_QML_PLUGIN_FILES})
40+if(NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
41+ add_custom_command(TARGET buteo_components_QmlFiles PRE_BUILD
42+ COMMAND ${CMAKE_COMMAND} -E
43+ copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/)
44+endif()
45+
46+execute_process(
47+ COMMAND qmake -query QT_INSTALL_QML
48+ OUTPUT_VARIABLE QT_IMPORTS_DIR
49+ OUTPUT_STRIP_TRAILING_WHITESPACE
50+)
51+install(TARGETS ${BUTEO_SYNC_QML_PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/Buteo/)
52+install(FILES ${BUTEO_SYNC_QML_PLUGIN_FILES} DESTINATION ${QT_IMPORTS_DIR}/Buteo/)
53
54=== added file 'Buteo/buteo-sync-qml.cpp'
55--- Buteo/buteo-sync-qml.cpp 1970-01-01 00:00:00 +0000
56+++ Buteo/buteo-sync-qml.cpp 2015-07-09 14:03:36 +0000
57@@ -0,0 +1,204 @@
58+/*
59+ * Copyright (C) 2015 Canonical, Ltd.
60+ *
61+ * This program is free software; you can redistribute it and/or modify
62+ * it under the terms of the GNU General Public License as published by
63+ * the Free Software Foundation; version 3.
64+ *
65+ * This program is distributed in the hope that it will be useful,
66+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
67+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68+ * GNU General Public License for more details.
69+ *
70+ * You should have received a copy of the GNU General Public License
71+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
72+ */
73+
74+#include "buteo-sync-qml.h"
75+
76+#include <QtCore/QDebug>
77+#include <QtDBus/QDBusInterface>
78+#include <QtDBus/QDBusReply>
79+#include <QtXml/QDomDocument>
80+
81+#define BUTEO_DBUS_SERVICE_NAME "com.meego.msyncd"
82+#define BUTEO_DBUS_OBJECT_PATH "/synchronizer"
83+#define BUTEO_DBUS_INTERFACE "com.meego.msyncd"
84+
85+ButeoSyncFW::ButeoSyncFW(QObject *parent)
86+ : QObject(parent)
87+{
88+}
89+
90+bool ButeoSyncFW::syncing() const
91+{
92+ return !(getRunningSyncList().isEmpty());
93+}
94+
95+QStringList ButeoSyncFW::visibleSyncProfiles() const
96+{
97+ if (m_iface) {
98+ QDBusReply<QStringList> result = m_iface->call("allVisibleSyncProfiles");
99+ return result.value();
100+ }
101+ return QStringList();
102+}
103+
104+void ButeoSyncFW::classBegin()
105+{
106+}
107+
108+void ButeoSyncFW::componentComplete()
109+{
110+ m_serviceWatcher.reset(new QDBusServiceWatcher(BUTEO_DBUS_SERVICE_NAME,
111+ QDBusConnection::sessionBus(),
112+ QDBusServiceWatcher::WatchForOwnerChange,
113+ this));
114+ connect(m_serviceWatcher.data(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
115+ this, SLOT(serviceOwnerChanged(QString,QString,QString)));
116+
117+ initialize();
118+}
119+
120+void ButeoSyncFW::initialize()
121+{
122+ if (!m_iface.isNull()) {
123+ return;
124+ }
125+
126+ m_iface.reset(new QDBusInterface(BUTEO_DBUS_SERVICE_NAME,
127+ BUTEO_DBUS_OBJECT_PATH,
128+ BUTEO_DBUS_INTERFACE));
129+
130+ if (!m_iface->isValid()) {
131+ m_iface.reset();
132+ qWarning() << "Fail to connect with syncfw";
133+ return;
134+ }
135+
136+ connect(m_iface.data(),
137+ SIGNAL(syncStatus(QString, int, QString, int)),
138+ SIGNAL(syncStatus(QString, int, QString, int)), Qt::QueuedConnection);
139+ connect(m_iface.data(),
140+ SIGNAL(signalProfileChanged(QString, int, QString)),
141+ SIGNAL(profileChanged(QString, int, QString)), Qt::QueuedConnection);
142+
143+ // notify changes on properties
144+ emit syncStatus("", 0, "", 0);
145+ emit profileChanged("", 0, "");
146+}
147+
148+bool ButeoSyncFW::startSync(const QString &aProfileId) const
149+{
150+ if (m_iface) {
151+ QDBusReply<bool> result = m_iface->call("startSync", aProfileId);
152+ return result.value();
153+ }
154+ return false;
155+}
156+
157+bool ButeoSyncFW::startSyncByCategory(const QString &category) const
158+{
159+ foreach(const QString &profile, syncProfilesByCategory(category)) {
160+ if (!startSync(profile)) {
161+ return false;
162+ }
163+ }
164+ return true;
165+}
166+
167+void ButeoSyncFW::abortSync(const QString &aProfileId) const
168+{
169+ if (m_iface) {
170+ m_iface->call("abortSync", aProfileId);
171+ }
172+}
173+
174+QStringList ButeoSyncFW::getRunningSyncList() const
175+{
176+ if (m_iface) {
177+ QDBusReply<QStringList> syncList = m_iface->call("runningSyncs");
178+ return syncList;
179+ }
180+ return QStringList();
181+}
182+
183+QStringList ButeoSyncFW::syncProfilesByCategory(const QString &category) const
184+{
185+ if (m_iface) {
186+ QDBusReply<QStringList> profiles = m_iface->call("syncProfilesByKey", "category", category);
187+ // extract ids
188+ QStringList ids;
189+ foreach(const QString &profile, profiles.value()) {
190+ QDomDocument doc;
191+ QString errorMsg;
192+ int errorLine;
193+ int errorColumn;
194+ if (doc.setContent(profile, &errorMsg, &errorLine, &errorColumn)) {
195+ QDomNodeList profileElements = doc.elementsByTagName("profile");
196+ if (!profileElements.isEmpty()) {
197+ //check if is enabled
198+ QDomElement e = profileElements.item(0).toElement();
199+ QDomNodeList values = e.elementsByTagName("key");
200+ bool enabled = true;
201+ for(int i = 0; i < values.count(); i++) {
202+ QDomElement v = values.at(i).toElement();
203+ if ((v.attribute("name") == "enabled") &&
204+ (v.attribute("value") == "false")) {
205+ enabled = false;
206+ continue;
207+ }
208+ }
209+ if (!enabled) {
210+ continue;
211+ }
212+ QString profileName = e.attribute("name", "");
213+ if (!profileName.isEmpty()) {
214+ ids << profileName;
215+ } else {
216+ qWarning() << "Profile name is empty in:" << profile;
217+ }
218+ } else {
219+ qWarning() << "Profile not found in:" << profile;
220+ }
221+ } else {
222+ qWarning() << "Fail to parse profile:" << profile;
223+ qWarning() << "Error:" << errorMsg << errorLine << errorColumn;
224+ }
225+ }
226+ return ids;
227+ }
228+ return QStringList();
229+}
230+
231+bool ButeoSyncFW::removeProfile(const QString &profileId) const
232+{
233+ if (m_iface) {
234+ QDBusReply<bool> result = m_iface->call("removeProfile", profileId);
235+ return result;
236+ }
237+ return false;
238+}
239+
240+void ButeoSyncFW::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
241+{
242+ Q_UNUSED(oldOwner);
243+
244+ if (name == BUTEO_DBUS_SERVICE_NAME) {
245+ if (!newOwner.isEmpty()) {
246+ // service appear
247+ initialize();
248+ } else if (!m_iface.isNull()) {
249+ // lost service
250+ deinitialize();
251+ }
252+ }
253+}
254+
255+void ButeoSyncFW::deinitialize()
256+{
257+ m_iface.reset();
258+ // notify changes on properties
259+ emit syncStatus("", 0, "", 0);
260+ emit profileChanged("", 0, "");
261+}
262
263=== added file 'Buteo/buteo-sync-qml.h'
264--- Buteo/buteo-sync-qml.h 1970-01-01 00:00:00 +0000
265+++ Buteo/buteo-sync-qml.h 2015-07-09 14:03:36 +0000
266@@ -0,0 +1,181 @@
267+/*
268+ * Copyright (C) 2015 Canonical, Ltd.
269+ *
270+ * This program is free software; you can redistribute it and/or modify
271+ * it under the terms of the GNU General Public License as published by
272+ * the Free Software Foundation; version 3.
273+ *
274+ * This program is distributed in the hope that it will be useful,
275+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
276+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
277+ * GNU General Public License for more details.
278+ *
279+ * You should have received a copy of the GNU General Public License
280+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
281+ */
282+
283+#include <QtCore/QObject>
284+#include <QtQml/QQmlParserStatus>
285+#include <QtDBus/QDBusInterface>
286+#include <QtDBus/QDBusServiceWatcher>
287+
288+class ButeoSyncFW : public QObject, public QQmlParserStatus
289+{
290+ Q_OBJECT
291+ Q_INTERFACES(QQmlParserStatus)
292+
293+ Q_PROPERTY(bool syncing READ syncing NOTIFY syncStatus)
294+ Q_PROPERTY(QStringList visibleSyncProfiles READ visibleSyncProfiles NOTIFY profileChanged)
295+
296+public:
297+ ButeoSyncFW(QObject *parent = 0);
298+
299+ bool syncing() const;
300+ QStringList visibleSyncProfiles() const;
301+
302+ // QQmlParserStatus
303+ void classBegin();
304+ void componentComplete();
305+
306+ //! \brief Enum to indicate the change type of the Profile Operation
307+ enum ProfileChangeType
308+ {
309+ //! a New Profile has been added
310+ ProfileAdded = 0,
311+ //! a Existing Profile has been modified
312+ ProfileModified,
313+ //! Profile has been Removed
314+ ProfileRemoved,
315+ //! Profile log file Modified.
316+ ProfileLogsModified
317+ };
318+ Q_ENUMS(ProfileChangeType)
319+
320+ //! \brief Enum to indicate the change type of the Profile Operation
321+ enum SyncStatus
322+ {
323+ //! Sync request has been queued
324+ SyncQueued = 0,
325+ //! Sync session has been started
326+ SyncStarted,
327+ //! Sync session is progressing
328+ SyncProgress,
329+ //! Sync session has encountered an error
330+ SyncError,
331+ //! Sync session was successfully completed
332+ SyncDone,
333+ //! Sync session was aborted
334+ SyncAborted
335+ };
336+ Q_ENUMS(SyncStatus)
337+
338+signals:
339+ /*! \brief Notifies about a change in profile.
340+ *
341+ * This signal is sent when the profile data is modified or when a profile
342+ * is added or deleted in msyncd.
343+ * \param aProfileId Id of the changed profile.
344+ * \param aChangeType
345+ * 0 (ADDITION): Profile was added.
346+ * 1 (MODIFICATION): Profile was modified.
347+ * 2 (DELETION): Profile was deleted.
348+ * \param aChangedProfile changed sync profie as XMl string.
349+ *
350+ */
351+ void profileChanged(QString aProfileId,int aChangeType, QString aChangedProfile);
352+
353+ /*!
354+ * \brief Notifies about a change in synchronization status.
355+ *
356+ * \param aProfileId Id of the profile used in the sync session whose
357+ * status has changed.
358+ * \param aStatus The new status. One of the following:
359+ * 0 (QUEUED): Sync request has been queued or was already in the
360+ * queue when sync start was requested.
361+ * 1 (STARTED): Sync session has been started.
362+ * 2 (PROGRESS): Sync session is progressing.
363+ * 3 (ERROR): Sync session has encountered an error and has been stopped,
364+ * or the session could not be started at all.
365+ * 4 (DONE): Sync session was successfully completed.
366+ * 5 (ABORTED): Sync session was aborted.
367+ * Statuses 3-5 are final, no more status changes will be sent from the
368+ * same sync session.
369+ * \param aMessage A message describing the status change in detail. This
370+ * can for example be shown to the user or written to a log
371+ * \param aStatusDetails
372+ * When aStatus is ERROR, this parameter contains a specific error code.
373+ * When aStatus is PROGRESS, this parameter contains more details about the progress
374+ * \see SyncCommonDefs::SyncProgressDetails
375+ */
376+ void syncStatus(QString aProfileId, int aStatus,
377+ QString aMessage, int aStatusDetails);
378+
379+public slots:
380+ /*!
381+ * \brief Requests to starts synchronizing using a profile Id
382+ *
383+ * A status change signal (QUEUED, STARTED or ERROR) will be sent by the
384+ * daemon when the request is processed. If there is a sync already in
385+ * progress using the same resources that are needed by the given profile,
386+ * adds the sync request to a sync queue. Otherwise a sync session is
387+ * started immediately.
388+ *
389+ * \param aProfileId Id of the profile to use in sync.
390+ * \return True if a profile with the Id was found. Otherwise
391+ * false and no status change signals will follow from this request.
392+ */
393+ bool startSync(const QString &aProfileId) const;
394+
395+ /*!
396+ * \brief Requests to starts synchronizing using a profile category
397+ *
398+ * \param category Category name of the profile.
399+ * \return True if a profile with the Id was found. Otherwise
400+ * false and no status change signals will follow from this request.
401+ *
402+ * \see ButeoSyncFW::startSync
403+ */
404+ bool startSyncByCategory(const QString &category) const;
405+
406+ /*!
407+ * \brief Stops synchronizing the profile with the given Id.
408+ *
409+ * If the sync request is still in queue and not yet started, the queue
410+ * entry is removed.
411+ *
412+ * \param aProfileId Id of the profile to stop syncing.
413+ */
414+ void abortSync(const QString &aProfileId) const;
415+
416+ /*!
417+ * \brief Gets the list of profile names of currently running syncs.
418+ *
419+ * \return Profile name list.
420+ */
421+ QStringList getRunningSyncList() const;
422+
423+ /*! \brief Gets enabled profiles matching the profile category.
424+ *
425+ * \param category Category name of the profile.
426+ * \return The sync profile ids as string list.
427+ */
428+ QStringList syncProfilesByCategory(const QString &category) const;
429+
430+ /*!
431+ * \brief This function should be called when sync profile has to be deleted
432+ *
433+ * \param aProfileId Id of the profile to be deleted.
434+ * \return status of the remove operation
435+ */
436+ bool removeProfile(const QString &profileId) const;
437+
438+private slots:
439+ void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
440+
441+private:
442+ QScopedPointer<QDBusInterface> m_iface;
443+ QScopedPointer<QDBusServiceWatcher> m_serviceWatcher;
444+
445+ void initialize();
446+ void deinitialize();
447+};
448
449=== added file 'Buteo/plugin.cpp'
450--- Buteo/plugin.cpp 1970-01-01 00:00:00 +0000
451+++ Buteo/plugin.cpp 2015-07-09 14:03:36 +0000
452@@ -0,0 +1,27 @@
453+/*
454+ * Copyright (C) 2015 Canonical, Ltd.
455+ *
456+ * This program is free software; you can redistribute it and/or modify
457+ * it under the terms of the GNU General Public License as published by
458+ * the Free Software Foundation; version 3.
459+ *
460+ * This program is distributed in the hope that it will be useful,
461+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
462+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
463+ * GNU General Public License for more details.
464+ *
465+ * You should have received a copy of the GNU General Public License
466+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
467+ */
468+
469+#include "plugin.h"
470+#include "buteo-sync-qml.h"
471+
472+#include <QtQml/qqml.h>
473+
474+
475+void ButeoSyncQmlPlugin::registerTypes(const char *uri)
476+{
477+ // @uri Buteo.ButeoSync
478+ qmlRegisterType<ButeoSyncFW>(uri, 0, 1, "ButeoSync");
479+}
480
481=== added file 'Buteo/plugin.h'
482--- Buteo/plugin.h 1970-01-01 00:00:00 +0000
483+++ Buteo/plugin.h 2015-07-09 14:03:36 +0000
484@@ -0,0 +1,31 @@
485+/*
486+ * Copyright (C) 2015 Canonical, Ltd.
487+ *
488+ * This program is free software; you can redistribute it and/or modify
489+ * it under the terms of the GNU General Public License as published by
490+ * the Free Software Foundation; version 3.
491+ *
492+ * This program is distributed in the hope that it will be useful,
493+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
494+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
495+ * GNU General Public License for more details.
496+ *
497+ * You should have received a copy of the GNU General Public License
498+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
499+ */
500+
501+#ifndef BUTE_SYNC_FW_QML_PLUGIN_H
502+#define BUTE_SYNC_FW_QML_PLUGIN_H
503+
504+#include <QQmlExtensionPlugin>
505+
506+class ButeoSyncQmlPlugin : public QQmlExtensionPlugin
507+{
508+ Q_OBJECT
509+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
510+
511+public:
512+ void registerTypes(const char *uri);
513+};
514+
515+#endif //BUTE_SYNC_FW_QML_PLUGIN_H
516
517=== added file 'Buteo/qmldir'
518--- Buteo/qmldir 1970-01-01 00:00:00 +0000
519+++ Buteo/qmldir 2015-07-09 14:03:36 +0000
520@@ -0,0 +1,2 @@
521+module Buteo
522+plugin buteo-syncfw-qml
523
524=== added file 'CMakeLists.txt'
525--- CMakeLists.txt 1970-01-01 00:00:00 +0000
526+++ CMakeLists.txt 2015-07-09 14:03:36 +0000
527@@ -0,0 +1,30 @@
528+project(buteo-sync-qml)
529+
530+cmake_minimum_required(VERSION 2.8.9)
531+
532+# Find includes in corresponding build directories
533+set(CMAKE_INCLUDE_CURRENT_DIR ON)
534+
535+# Instruct CMake to run moc automatically when needed.
536+set(CMAKE_AUTOMOC ON)
537+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DQT_QML_DEBUG")
538+
539+# Standard install paths
540+include(GNUInstallDirs)
541+
542+find_package(PkgConfig REQUIRED)
543+find_package(Qt5Core REQUIRED)
544+find_package(Qt5Qml REQUIRED)
545+find_package(Qt5DBus REQUIRED)
546+find_package(Qt5Xml REQUIRED)
547+
548+enable_testing()
549+add_subdirectory(Buteo)
550+add_subdirectory(tests)
551+
552+# uninstall target
553+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
554+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
555+ IMMEDIATE @ONLY)
556+add_custom_target(uninstall "${CMAKE_COMMAND}"
557+ -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
558
559=== added file 'cmake_uninstall.cmake.in'
560--- cmake_uninstall.cmake.in 1970-01-01 00:00:00 +0000
561+++ cmake_uninstall.cmake.in 2015-07-09 14:03:36 +0000
562@@ -0,0 +1,21 @@
563+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
564+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
565+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
566+
567+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
568+STRING(REGEX REPLACE "\n" ";" files "${files}")
569+FOREACH(file ${files})
570+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
571+ IF(EXISTS "$ENV{DESTDIR}${file}")
572+ EXEC_PROGRAM(
573+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
574+ OUTPUT_VARIABLE rm_out
575+ RETURN_VALUE rm_retval
576+ )
577+ IF(NOT "${rm_retval}" STREQUAL 0)
578+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
579+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
580+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
581+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
582+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
583+ENDFOREACH(file)
584
585=== added directory 'debian'
586=== added file 'debian/changelog'
587--- debian/changelog 1970-01-01 00:00:00 +0000
588+++ debian/changelog 2015-07-09 14:03:36 +0000
589@@ -0,0 +1,5 @@
590+buteo-syncfw-qml (0.1-0ubuntu1) vivid; urgency=medium
591+
592+ * New package
593+
594+ -- Renato Araujo Oliveira Filho <renato.filho@canonical.com> Wed, 08 Jul 2015 12:01:34 -0300
595
596=== added file 'debian/compat'
597--- debian/compat 1970-01-01 00:00:00 +0000
598+++ debian/compat 2015-07-09 14:03:36 +0000
599@@ -0,0 +1,1 @@
600+9
601
602=== added file 'debian/control'
603--- debian/control 1970-01-01 00:00:00 +0000
604+++ debian/control 2015-07-09 14:03:36 +0000
605@@ -0,0 +1,34 @@
606+Source: buteo-syncfw-qml
607+Section: libs
608+Priority: optional
609+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
610+Build-Depends: cmake,
611+ dbus-test-runner,
612+ debhelper (>= 9),
613+ pkg-config,
614+ qml-module-qttest,
615+ qtchooser,
616+ qt5-default,
617+ qtbase5-dev,
618+ qtdeclarative5-dev,
619+Standards-Version: 3.9.5
620+Homepage: https://launchpad.net/buteo-syncfw-qml
621+# if you don't have have commit access to this branch but would like to upload
622+# directly to Ubuntu, don't worry: your changes will be merged back into the
623+# upstream branch
624+Vcs-Bzr: lp:buteo-syncfw-qml
625+X-Ubuntu-Use-Langpack: yes
626+
627+Package: qtdeclarative5-buteo-syncfw0.1
628+Architecture: any
629+Multi-Arch: same
630+Pre-Depends: ${misc:Pre-Depends}
631+Depends: ${misc:Depends},
632+ ${shlibs:Depends},
633+ buteo-syncfw-qt5,
634+Description: Buteo sync framework client - QML bindings
635+ buteo-syncfw manages data synchronization
636+ .
637+ This package contains the QML plugin providing the features from the buteo
638+ to applications.
639+
640
641=== added file 'debian/copyright'
642--- debian/copyright 1970-01-01 00:00:00 +0000
643+++ debian/copyright 2015-07-09 14:03:36 +0000
644@@ -0,0 +1,19 @@
645+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
646+Source: https://launchpad.net/buteo-syncfw-qml
647+Upstream-Name: buteo-syncfw-qml
648+
649+Files: *
650+Copyright: 2015 Canonical Ltd.
651+License: GPL-3
652+ This program is free software: you can redistribute it and/or modify
653+ it under the terms of the GNU General Public License version 3 as
654+ published by the Free Software Foundation.
655+ .
656+ This program is distributed in the hope that it will be useful,
657+ but WITHOUT ANY WARRANTY; without even the implied warranty of
658+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
659+ GNU General Public License for more details.
660+ .
661+ On Debian systems, the full text of the GNU General Public
662+ License version 3 can be found in the file
663+ `/usr/share/common-licenses/GPL-3'.
664
665=== added file 'debian/rules'
666--- debian/rules 1970-01-01 00:00:00 +0000
667+++ debian/rules 2015-07-09 14:03:36 +0000
668@@ -0,0 +1,9 @@
669+#!/usr/bin/make -f
670+# -*- makefile -*-
671+export DPKG_GENSYMBOLS_CHECK_LEVEL=4
672+
673+# Uncomment this to turn on verbose mode.
674+#export DH_VERBOSE=1
675+
676+%:
677+ dh $@ --parallel --fail-missing
678
679=== added directory 'tests'
680=== added file 'tests/CMakeLists.txt'
681--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
682+++ tests/CMakeLists.txt 2015-07-09 14:03:36 +0000
683@@ -0,0 +1,1 @@
684+add_subdirectory(qml)
685
686=== added directory 'tests/qml'
687=== added file 'tests/qml/CMakeLists.txt'
688--- tests/qml/CMakeLists.txt 1970-01-01 00:00:00 +0000
689+++ tests/qml/CMakeLists.txt 2015-07-09 14:03:36 +0000
690@@ -0,0 +1,36 @@
691+find_program(QMLTESTRUNNER_BIN
692+ NAMES qmltestrunner
693+ PATHS /usr/lib/*/qt5/bin
694+ NO_DEFAULT_PATH
695+)
696+
697+find_program(DBUS_RUNNER_BIN dbus-test-runner)
698+macro(DECLARE_QML_TEST TST_NAME TST_QML_FILE)
699+ set(TEST_COMMAND "")
700+ add_test(NAME ${TST_NAME}
701+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
702+ COMMAND ${DBUS_RUNNER_BIN}
703+ --task ${CMAKE_CURRENT_SOURCE_DIR}/buteo-syncfw.py -r -n buteo-syncfw
704+ --task ${QMLTESTRUNNER_BIN}
705+ -p -input -p ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE}
706+ -p -import -p ${CMAKE_BINARY_DIR}
707+ -p -platform -p offscreen
708+ --wait-for=com.meego.msyncd
709+ -n ${TST_NAME}
710+ )
711+endmacro()
712+
713+if(QMLTESTRUNNER_BIN AND DBUS_RUNNER_BIN)
714+ declare_qml_test("buteo_syncfw_component" tst_ButeoSyncFW.qml)
715+else()
716+ if (NOT QMLTESTRUNNER_BIN)
717+ message(WARNING "Qml tests disabled: qmltestrunner not found")
718+ else()
719+ message(WARNING "Qml tests disabled: dbus-test-runner not found")
720+ endif()
721+endif()
722+
723+set(QML_TST_FILES
724+ tst_ButeoSyncFW.qml
725+)
726+add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES})
727
728=== added file 'tests/qml/buteo-syncfw.py'
729--- tests/qml/buteo-syncfw.py 1970-01-01 00:00:00 +0000
730+++ tests/qml/buteo-syncfw.py 2015-07-09 14:03:36 +0000
731@@ -0,0 +1,163 @@
732+#!/usr/bin/python3
733+
734+'''buteo syncfw mock template
735+
736+This creates the expected methods and properties of the main
737+com.meego.msyncd object. You can specify D-BUS property values
738+'''
739+
740+# This program is free software; you can redistribute it and/or modify it under
741+# the terms of the GNU Lesser General Public License as published by the Free
742+# Software Foundation; either version 3 of the License, or (at your option) any
743+# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text
744+# of the license.
745+
746+__author__ = 'Renato Araujo Oliveira Filho'
747+__email__ = 'renatofilho@canonical.com'
748+__copyright__ = '(c) 2015 Canonical Ltd.'
749+__license__ = 'LGPL 3+'
750+
751+import dbus
752+from gi.repository import GObject
753+
754+import dbus
755+import dbus.service
756+import dbus.mainloop.glib
757+
758+BUS_NAME = 'com.meego.msyncd'
759+MAIN_OBJ = '/synchronizer'
760+MAIN_IFACE = 'com.meego.msyncd'
761+SYSTEM_BUS = False
762+
763+class ButeoSyncFw(dbus.service.Object):
764+ PROFILES = [
765+"""<?xml version=\"1.0\" encoding=\"UTF-8\"?>
766+<profile type=\"sync\" name=\"test-profile\">
767+ <key value=\"45\" name=\"accountid\"/>
768+ <key value=\"contacts\" name=\"category\"/>
769+ <key value=\"google.Contacts-\" name=\"displayname\"/>
770+ <key value=\"true\" name=\"enabled\"/>
771+ <key value=\"true\" name=\"hidden\"/>
772+ <key value=\"30\" name=\"sync_since_days_past\"/>
773+ <key value=\"true\" name=\"use_accounts\"/>
774+ <profile type=\"client\" name=\"googlecontacts\">
775+ <key value=\"two-way\" name=\"Sync Direction\"/>
776+ </profile>
777+ <schedule time=\"05:00:00\" days=\"4,5,2,3,1,6,7\" syncconfiguredtime=\"\" interval=\"0\" enabled=\"true\">
778+ <rush end=\"\" externalsync=\"false\" days=\"\" interval=\"15\" begin=\"\" enabled=\"false\"/>
779+ </schedule>
780+</profile>""",
781+"""<?xml version=\"1.0\" encoding=\"UTF-8\"?>
782+<profile type=\"sync\" name=\"testsync-ovi\">
783+ <key value=\"calendar\" name=\"category\"/>
784+ <schedule syncconfiguredtime=\"\" interval=\"0\" days=\"\" externalsync=\"true\" time=\"\" enabled=\"false\">
785+ <rush interval=\"0\" days=\"\" externalsync=\"false\" begin=\"\" enabled=\"false\" end=\"\"/>
786+ </schedule>
787+</profile>""",
788+"""<?xml version=\"1.0\" encoding=\"UTF-8\"?>
789+<profile name=\"63807467\" type=\"sync\">
790+ <key value=\"110\" name=\"accountid\"/>
791+ <key value=\"contacts\" name=\"category\"/>
792+ <key value=\"online\" name=\"destinationtype\"/>
793+ <key value=\"google-contacts-renato.teste2@gmail.com\" name=\"displayname\"/>
794+ <key value=\"true\" name=\"enabled\"/>
795+ <key value=\"true\" name=\"hidden\"/>
796+ <key value=\"false\" name=\"scheduled\"/>
797+ <key value=\"true\" name=\"sync_always_up_to_date\"/>
798+ <key value=\"true\" name=\"sync_on_change\"/>
799+ <key value=\"30\" name=\"sync_since_days_past\"/>
800+ <key value=\"true\" name=\"use_accounts\"/>
801+ <profile name=\"googlecontacts\" type=\"client\">
802+ <key value=\"two-way\" name=\"Sync Direction\"/>
803+ <key value=\"gdata\" name=\"Sync Protocol\"/>
804+ <key value=\"HTTP\" name=\"Sync Transport\"/>
805+ <key value=\"prefer remote\" name=\"conflictpolicy\"/>
806+ <key value=\"true\" name=\"sync_on_change\"/>
807+ </profile>
808+ <schedule syncconfiguredtime=\"\" days=\"5,4,7,6,1,3,2\" interval=\"60\" enabled=\"false\" time=\"\">
809+ <rush begin=\"00:00:00\" end=\"00:00:00\" days=\"\" interval=\"60\" enabled=\"false\" externalsync=\"false\"/>
810+ </schedule>
811+</profile>""",
812+"""<?xml version=\"1.0\" encoding=\"UTF-8\"?>
813+<profile type=\"sync\" name=\"template-profile\">
814+ <key value=\"contacts\" name=\"category\"/>
815+ <key value=\"false\" name=\"enabled\"/>
816+ <schedule syncconfiguredtime=\"\" interval=\"0\" days=\"\" externalsync=\"true\" time=\"\" enabled=\"false\">
817+ <rush interval=\"0\" days=\"\" externalsync=\"false\" begin=\"\" enabled=\"false\" end=\"\"/>
818+ </schedule>
819+</profile>"""
820+ ]
821+
822+ def __init__(self, object_path):
823+ dbus.service.Object.__init__(self, dbus.SessionBus(), object_path)
824+ self._activeSync = []
825+ self._profiles = ButeoSyncFw.PROFILES
826+
827+ @dbus.service.method(dbus_interface=MAIN_IFACE,
828+ in_signature='', out_signature='as')
829+ def allVisibleSyncProfiles(self):
830+ return self._profiles
831+
832+ @dbus.service.method(dbus_interface=MAIN_IFACE,
833+ in_signature='ss', out_signature='as')
834+ def syncProfilesByKey(self, key, value):
835+ print ("syncProfilesByKey:", key, value)
836+ if key == 'category':
837+ if value == 'contacts':
838+ return [ButeoSyncFw.PROFILES[0], ButeoSyncFw.PROFILES[2], ButeoSyncFw.PROFILES[3]]
839+ if value == 'calendar':
840+ return [ButeoSyncFw.PROFILES[1]]
841+ return []
842+
843+ @dbus.service.method(dbus_interface=MAIN_IFACE,
844+ in_signature='s', out_signature='')
845+ def abortSync(self, profileId):
846+ if profileId in self._activeSync:
847+ self._activeSync.remove(profileId)
848+ self.syncStatus(profileId, 5, 'aborted by the user', 0)
849+ return
850+
851+ @dbus.service.method(dbus_interface=MAIN_IFACE,
852+ in_signature='s', out_signature='b')
853+ def startSync(self, profileId):
854+ if profileId in ['63807467', 'testsync-ovi', 'test-profile']:
855+ self._activeSync.append(profileId)
856+ self.syncStatus(profileId, 1, '', 0)
857+ return True
858+ return False
859+
860+ @dbus.service.method(dbus_interface=MAIN_IFACE,
861+ in_signature='', out_signature='as')
862+ def runningSyncs(self):
863+ return self._activeSync
864+
865+ @dbus.service.signal(dbus_interface=MAIN_IFACE,
866+ signature='sisi')
867+ def syncStatus(self, profileId, status, message, statusDetails):
868+ print("SyncStatus called")
869+
870+ @dbus.service.signal(dbus_interface=MAIN_IFACE,
871+ signature='sis')
872+ def signalProfileChanged(self, profileId, status, changedProfile):
873+ print("profileChanged called")
874+
875+ @dbus.service.method(dbus_interface=MAIN_IFACE,
876+ in_signature='s', out_signature='b')
877+ def removeProfile(self, profileId):
878+ if int(profileId) < len(self._profiles):
879+ self._profiles.remove(self._profiles[int(profileId)])
880+ self.signalProfileChanged(profileId, 2, 'deleted')
881+ return True
882+ else:
883+ return False
884+
885+
886+
887+if __name__ == '__main__':
888+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
889+
890+ name = dbus.service.BusName(BUS_NAME)
891+ mainloop = GObject.MainLoop()
892+ buteo = ButeoSyncFw(MAIN_OBJ)
893+ mainloop.run()
894+
895
896=== added file 'tests/qml/tst_ButeoSyncFW.qml'
897--- tests/qml/tst_ButeoSyncFW.qml 1970-01-01 00:00:00 +0000
898+++ tests/qml/tst_ButeoSyncFW.qml 2015-07-09 14:03:36 +0000
899@@ -0,0 +1,174 @@
900+/*
901+ * Copyright (C) 2015 Canonical, Ltd.
902+ *
903+ * This program is free software; you can redistribute it and/or modify
904+ * it under the terms of the GNU General Public License as published by
905+ * the Free Software Foundation; version 3.
906+ *
907+ * This program is distributed in the hope that it will be useful,
908+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
909+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
910+ * GNU General Public License for more details.
911+ *
912+ * You should have received a copy of the GNU General Public License
913+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
914+ */
915+
916+import QtQuick 2.2
917+import Buteo 0.1
918+import QtTest 1.0
919+
920+Item {
921+ id: root
922+
923+ property var buteoComponent
924+
925+ TestCase {
926+ id: vcardParser
927+ name: 'ButeoSyncFWTestCase'
928+
929+ function init()
930+ {
931+ buteoComponent = Qt.createQmlObject('import Buteo 0.1; ButeoSync{ }', root);
932+ }
933+
934+ function cleanup()
935+ {
936+ if (buteoComponent) {
937+ var activeProfiles = buteoComponent.getRunningSyncList()
938+ for (var i in activeProfiles) {
939+ buteoComponent.abortSync(activeProfiles[i])
940+ }
941+ activeProfiles = buteoComponent.getRunningSyncList()
942+ compare(activeProfiles.length, 0)
943+
944+ buteoComponent.destroy()
945+ buteoComponent = null
946+ }
947+ }
948+
949+ function test_start_sync()
950+ {
951+ var spy = Qt.createQmlObject('import QtTest 1.0; SignalSpy{ }', root);
952+ spy.target = buteoComponent
953+ spy.signalName = "syncStatus"
954+
955+ compare(buteoComponent.startSync('1234'), false)
956+ compare(buteoComponent.startSync('63807467'), true)
957+
958+ tryCompare(spy, "count", 1)
959+ compare(spy.signalArguments[0][0], '63807467')
960+ compare(spy.signalArguments[0][1], ButeoSync.SyncStarted)
961+ compare(spy.signalArguments[0][2], '')
962+ }
963+
964+ function test_abort_sync()
965+ {
966+ var spy = Qt.createQmlObject('import QtTest 1.0; SignalSpy{ }', root);
967+ spy.target = buteoComponent
968+ spy.signalName = "syncStatus"
969+
970+ compare(buteoComponent.startSync('63807467'), true)
971+ tryCompare(spy, "count", 1)
972+
973+ var spy2 = Qt.createQmlObject('import QtTest 1.0; SignalSpy{ }', root);
974+ spy2.target = buteoComponent
975+ spy2.signalName = "syncStatus"
976+
977+ buteoComponent.abortSync('63807467')
978+
979+ tryCompare(spy2, "count", 1)
980+ compare(spy2.signalArguments[0][0], '63807467')
981+ compare(spy2.signalArguments[0][1], ButeoSync.SyncAborted)
982+ compare(spy2.signalArguments[0][2], 'aborted by the user')
983+ }
984+
985+ function test_syncing_property()
986+ {
987+ // check if no sync is running
988+ compare(buteoComponent.syncing, false)
989+
990+ // start a new sync and check if the property changed to true
991+ buteoComponent.startSync('63807467')
992+ tryCompare(buteoComponent, 'syncing', true)
993+
994+ // abort current sync and check if sync property changed to false
995+ buteoComponent.abortSync('63807467')
996+ tryCompare(buteoComponent, 'syncing', false)
997+ }
998+
999+ function test_visibleSyncProfiles_property()
1000+ {
1001+ compare(buteoComponent.visibleSyncProfiles.length, 4)
1002+ var spy = Qt.createQmlObject('import QtTest 1.0; SignalSpy{ }', root);
1003+ spy.target = buteoComponent
1004+ spy.signalName = "profileChanged"
1005+
1006+ buteoComponent.removeProfile('3')
1007+ tryCompare(spy, "count", 1)
1008+ compare(spy.signalArguments[0][0], '3')
1009+ compare(spy.signalArguments[0][1], ButeoSync.ProfileRemoved)
1010+ compare(spy.signalArguments[0][2], 'deleted')
1011+ compare(buteoComponent.visibleSyncProfiles.length, 3)
1012+ spy.clear()
1013+
1014+ buteoComponent.removeProfile('2')
1015+ tryCompare(spy, "count", 1)
1016+ compare(spy.signalArguments[0][0], '2')
1017+ compare(spy.signalArguments[0][1], ButeoSync.ProfileRemoved)
1018+ compare(spy.signalArguments[0][2], 'deleted')
1019+ compare(buteoComponent.visibleSyncProfiles.length, 2)
1020+ spy.clear()
1021+
1022+ buteoComponent.removeProfile('1')
1023+ tryCompare(spy, "count", 1)
1024+ compare(spy.signalArguments[0][0], '1')
1025+ compare(spy.signalArguments[0][1], ButeoSync.ProfileRemoved)
1026+ compare(spy.signalArguments[0][2], 'deleted')
1027+ compare(buteoComponent.visibleSyncProfiles.length, 1)
1028+ spy.clear()
1029+
1030+ buteoComponent.removeProfile('0')
1031+ tryCompare(spy, "count", 1)
1032+ compare(spy.signalArguments[0][0], '0')
1033+ compare(spy.signalArguments[0][1], ButeoSync.ProfileRemoved)
1034+ compare(spy.signalArguments[0][2], 'deleted')
1035+ compare(buteoComponent.visibleSyncProfiles.length, 0)
1036+ spy.clear()
1037+ }
1038+
1039+ function test_sync_by_profile_by_category()
1040+ {
1041+ var profiles = buteoComponent.syncProfilesByCategory('contacts')
1042+ compare(profiles.length, 2)
1043+ compare(profiles[0], 'test-profile')
1044+ compare(profiles[1], '63807467')
1045+ }
1046+
1047+ function test_sync_by_category()
1048+ {
1049+ var spy = Qt.createQmlObject('import QtTest 1.0; SignalSpy{ }', root);
1050+ spy.target = buteoComponent
1051+ spy.signalName = "syncStatus"
1052+
1053+ compare(buteoComponent.startSyncByCategory('contacts'), true)
1054+
1055+ // wait for two signals (since we have two contacts profiles)
1056+ tryCompare(spy, "count", 2)
1057+ // first profile
1058+ compare(spy.signalArguments[0][0], 'test-profile')
1059+ compare(spy.signalArguments[0][1], ButeoSync.SyncStarted)
1060+ compare(spy.signalArguments[0][2], '')
1061+
1062+ // secound profile
1063+ compare(spy.signalArguments[1][0], '63807467')
1064+ compare(spy.signalArguments[1][1], ButeoSync.SyncStarted)
1065+ compare(spy.signalArguments[1][2], '')
1066+
1067+ var activeProfiles = buteoComponent.getRunningSyncList()
1068+ compare(activeProfiles.length, 2)
1069+ compare(activeProfiles[0], 'test-profile')
1070+ compare(activeProfiles[1], '63807467')
1071+ }
1072+ }
1073+}

Subscribers

People subscribed via source and target branches