Merge lp:~charlesk/indicator-transfer/add-plugins into lp:indicator-transfer/15.10

Proposed by Charles Kerr
Status: Merged
Approved by: Renato Araujo Oliveira Filho
Approved revision: 51
Merged at revision: 33
Proposed branch: lp:~charlesk/indicator-transfer/add-plugins
Merge into: lp:indicator-transfer/15.10
Diff against target: 2168 lines (+1134/-224)
36 files modified
CMakeLists.txt (+18/-4)
cmake/FindValgrind.cmake (+41/-0)
cmake_uninstall.cmake.in (+21/-0)
data/CMakeLists.txt (+9/-0)
data/indicator-transfer.pc.in (+8/-0)
debian/control (+30/-2)
debian/indicator-transfer-download-manager.install (+1/-0)
debian/indicator-transfer.install (+5/-0)
debian/libindicator-transfer-dev.install (+3/-0)
debian/libindicator-transfer0.install (+1/-0)
include/transfer/CMakeLists.txt (+6/-2)
include/transfer/controller.h (+3/-3)
include/transfer/dm-source.h (+15/-14)
include/transfer/multisource.h (+58/-0)
include/transfer/plugin-source.h (+49/-0)
include/transfer/source.h (+15/-5)
include/transfer/transfer.h (+5/-5)
src/CMakeLists.txt (+19/-8)
src/controller.cpp (+8/-8)
src/dm-plugin/CMakeLists.txt (+21/-0)
src/dm-plugin/dm-plugin.cpp (+32/-0)
src/dm-plugin/dm-source.cpp (+46/-36)
src/main.cpp (+4/-4)
src/multisource.cpp (+207/-0)
src/plugin-source.cpp (+108/-0)
src/source.cpp (+2/-2)
tests/CMakeLists.txt (+18/-12)
tests/controller-mock.h (+2/-2)
tests/data/valgrind.suppression (+2/-0)
tests/glib-fixture.h (+27/-36)
tests/mock-source-plugin.cpp (+32/-0)
tests/source-mock.h (+11/-6)
tests/test-controller.cpp (+68/-68)
tests/test-multisource.cpp (+166/-0)
tests/test-plugin-source.cpp (+66/-0)
tests/test-view-gmenu.cpp (+7/-7)
To merge this branch: bzr merge lp:~charlesk/indicator-transfer/add-plugins
Reviewer Review Type Date Requested Status
Ken VanDine Approve
Renato Araujo Oliveira Filho (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+266320@code.launchpad.net

Commit message

Add a plugin architecture so that Transfer objects can be added from multiple sources, rather than just from DownloadManager.

Description of the change

Add a plugin architecture so that Transfer objects can be added from multiple sources, rather than just from DownloadManager.

This is for Renato and Bill so that the transfer indicator can monitor syncevolution as well.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
40. By Charles Kerr

in comments, better statement of intent for the Source class

41. By Charles Kerr

sync with trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
42. By Charles Kerr

hm, it helps if you bzr add all the new files... :/

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
43. By Charles Kerr

add -fPIC to make linker happy

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

Could you create a "dev" package to allow us to implement plugins from external projects?

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

Should the Transfer class methods be virtual?

In buteo we do not support resume and I would like to override the "can_remume" method to always return false.

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) :
Revision history for this message
Charles Kerr (charlesk) wrote :

> do we really need this declared twice?

Possibly not; I was following the code from glib's unit tests. Removed r44

> Should the Transfer class methods be virtual?

Okay. Added r45

44. By Charles Kerr

remove unnecessary function declarations

45. By Charles Kerr

make Transfer class method virtual

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

What about transfers that is not possible to determine the progress?

Should "Transfer.progress" allow -1 to say that the progress is unknown or should we create a new property?

OBS: The client UI should be updated to support that.

46. By Charles Kerr

merge renato's dev package branch <lp:~renatofilho/indicator-transfer/dev-package>

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
47. By Charles Kerr

add target_link_libraries for libindicator-transfer.so

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
48. By Charles Kerr

use target_link_libraries for the mock-source-plugin test module too

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
49. By Charles Kerr

remove unused google test cmake rules; use a more selective target_link_library for the test plugin library

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
50. By Renato Filho

merge lp:~renatofilho/indicator-transfer/add-plugins-fix-build

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
51. By Charles Kerr

sync with trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?
YES
Did CI run pass? If not, please explain why.
YES
Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
YES

review: Approve
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Packaging changes look fine

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-08-25 20:39:23 +0000
3+++ CMakeLists.txt 2015-08-13 14:17:16 +0000
4@@ -14,7 +14,7 @@
5
6 ##
7 ## GNU standard installation directories
8-##
9+##
10
11 include (GNUInstallDirs)
12 if (EXISTS "/etc/debian_version") # Workaround for libexecdir on debian
13@@ -25,6 +25,15 @@
14 set (CMAKE_INSTALL_FULL_PKGLIBEXECDIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/${CMAKE_PROJECT_NAME}")
15
16 ##
17+## Version
18+##
19+
20+set(INDICATOR_TRANSFER_VERSION_MAJOR 0)
21+set(INDICATOR_TRANSFER_VERSION_MINOR 0)
22+set(INDICATOR_TRANSFER_VERSION_PATCH 1)
23+set(INDICATOR_TRANSFER_VERSION "${INDICATOR_TRANSFER_VERSION_MAJOR}.${INDICATOR_TRANSFER_VERSION_MINOR}.${INDICATOR_TRANSFER_VERSION_PATCH}")
24+
25+##
26 ## Check for prerequisites
27 ##
28
29@@ -33,6 +42,7 @@
30
31 pkg_check_modules(SERVICE_DEPS REQUIRED
32 glib-2.0>=2.36
33+ gmodule-2.0>=2.36
34 gio-unix-2.0>=2.36
35 properties-cpp>=0.0.1
36 click-0.4>=0.4.30
37@@ -65,9 +75,6 @@
38 # testing & coverage
39 if (${enable_tests})
40 pkg_check_modules (DBUSTEST REQUIRED dbustest-1>=14.04.0)
41- set (GTEST_SOURCE_DIR /usr/src/gtest/src)
42- set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..)
43- set (GTEST_LIBS -lpthread)
44 enable_testing ()
45 if (${enable_lcov})
46 include(GCov)
47@@ -83,3 +90,10 @@
48 add_subdirectory(tests)
49 endif ()
50
51+# uninstall target
52+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
53+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
54+ IMMEDIATE @ONLY)
55+add_custom_target(uninstall "${CMAKE_COMMAND}"
56+ -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
57+
58
59=== added file 'cmake/FindValgrind.cmake'
60--- cmake/FindValgrind.cmake 1970-01-01 00:00:00 +0000
61+++ cmake/FindValgrind.cmake 2015-08-13 14:17:16 +0000
62@@ -0,0 +1,41 @@
63+
64+option(
65+ ENABLE_MEMCHECK_OPTION
66+ "If set to ON, enables automatic creation of memcheck targets"
67+ OFF
68+)
69+
70+find_program(
71+ VALGRIND_PROGRAM
72+ NAMES valgrind
73+)
74+
75+if(VALGRIND_PROGRAM)
76+ set(VALGRIND_PROGRAM_OPTIONS
77+ "--suppressions=${CMAKE_SOURCE_DIR}/tests/data/valgrind.suppression"
78+ "--error-exitcode=1"
79+ "--leak-check=full"
80+ "--gen-suppressions=all"
81+ "--quiet"
82+ )
83+endif()
84+
85+find_package_handle_standard_args(
86+ VALGRIND DEFAULT_MSG
87+ VALGRIND_PROGRAM
88+)
89+
90+function(add_valgrind_test)
91+ foreach(_arg ${ARGN})
92+ if ("VALGRIND" STREQUAL ${_arg})
93+ if(ENABLE_MEMCHECK_OPTION AND VALGRIND_PROGRAM)
94+ list(APPEND _vgargs ${VALGRIND_PROGRAM} ${VALGRIND_PROGRAM_OPTIONS})
95+ endif()
96+ else()
97+ list(APPEND _vgargs ${_arg})
98+ endif()
99+ endforeach()
100+
101+ add_test(${_vgargs})
102+endfunction()
103+
104
105=== added file 'cmake_uninstall.cmake.in'
106--- cmake_uninstall.cmake.in 1970-01-01 00:00:00 +0000
107+++ cmake_uninstall.cmake.in 2015-08-13 14:17:16 +0000
108@@ -0,0 +1,21 @@
109+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
110+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
111+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
112+
113+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
114+STRING(REGEX REPLACE "\n" ";" files "${files}")
115+FOREACH(file ${files})
116+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
117+ IF(EXISTS "$ENV{DESTDIR}${file}")
118+ EXEC_PROGRAM(
119+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
120+ OUTPUT_VARIABLE rm_out
121+ RETURN_VALUE rm_retval
122+ )
123+ IF(NOT "${rm_retval}" STREQUAL 0)
124+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
125+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
126+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
127+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
128+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
129+ENDFOREACH(file)
130
131=== modified file 'data/CMakeLists.txt'
132--- data/CMakeLists.txt 2014-03-29 17:17:09 +0000
133+++ data/CMakeLists.txt 2015-08-13 14:17:16 +0000
134@@ -73,3 +73,12 @@
135
136 install (FILES "${UNITY_INDICATOR_FILE}"
137 DESTINATION "${UNITY_INDICATOR_DIR}")
138+
139+##
140+## Pkg dev file
141+set (INDICATOR_PKG_NAME "${CMAKE_PROJECT_NAME}.pc")
142+set (INDICATOR_PKG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${INDICATOR_PKG_NAME}")
143+set (INDICATOR_PKG_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${INDICATOR_PKG_NAME}.in")
144+configure_file ("${INDICATOR_PKG_FILE_IN}" "${INDICATOR_PKG_FILE}" @ONLY)
145+install (FILES "${INDICATOR_PKG_FILE}"
146+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
147
148=== added file 'data/indicator-transfer.pc.in'
149--- data/indicator-transfer.pc.in 1970-01-01 00:00:00 +0000
150+++ data/indicator-transfer.pc.in 2015-08-13 14:17:16 +0000
151@@ -0,0 +1,8 @@
152+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
153+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@/@CMAKE_PROJECT_NAME@
154+
155+Name: @CMAKE_PROJECT_NAME@
156+Description: Developer files for @CMAKE_PROJECT_NAME@
157+Version: @INDICATOR_TRANSFER_VERSION@
158+Libs: -L${libdir} -lindicator-transfer
159+Cflags: -I${includedir}
160
161=== modified file 'debian/control'
162--- debian/control 2015-07-15 14:41:03 +0000
163+++ debian/control 2015-08-13 14:17:16 +0000
164@@ -17,8 +17,9 @@
165 libgtest-dev,
166 libdbustest1-dev,
167 google-mock (>= 1.6.0+svn437),
168+ valgrind [amd64 armhf i386 powerpc],
169 # for packaging
170- debhelper (>= 9),
171+ debhelper (>= 9),
172 dh-translations,
173 Standards-Version: 3.9.5
174 Homepage: https://launchpad.net/indicator-transfer
175@@ -31,10 +32,37 @@
176
177 Package: indicator-transfer
178 Architecture: any
179-Depends: ${shlibs:Depends},
180+Depends: ${shlibs:Depends},
181 ${misc:Depends},
182+ libindicator-transfer0 (= ${binary:Version}),
183 Recommends: indicator-applet | indicator-renderer,
184 content-hub,
185 ubuntu-download-manager,
186+ indicator-transfer-download-manager (>= ${binary:Version}),
187 Description: Shows Transfers
188 Show file/data transfers in the indicator bar
189+
190+Package: indicator-transfer-download-manager
191+Architecture: any
192+Depends: ${shlibs:Depends},
193+ ${misc:Depends},
194+ indicator-transfer (= ${binary:Version}),
195+Description: Download manager plugin for trasfer indicator
196+ Show file/data transfers in the indicator bar
197+
198+Package: libindicator-transfer0
199+Section: libs
200+Architecture: any
201+Depends: ${shlibs:Depends},
202+ ${misc:Depends},
203+Description: Shared library used by transfer-indicator and plugins
204+ Show file/data transfers in the indicator bar
205+
206+Package: libindicator-transfer-dev
207+Section: libdevel
208+Architecture: any
209+Depends: ${shlibs:Depends},
210+ ${misc:Depends},
211+ libindicator-transfer0 (= ${binary:Version}),
212+Description: Development files for indicator-transfer
213+ Show file/data transfers in the indicator bar
214
215=== added file 'debian/indicator-transfer-download-manager.install'
216--- debian/indicator-transfer-download-manager.install 1970-01-01 00:00:00 +0000
217+++ debian/indicator-transfer-download-manager.install 2015-08-13 14:17:16 +0000
218@@ -0,0 +1,1 @@
219+usr/lib/*/indicator-transfer/libdmtransfers.so
220
221=== added file 'debian/indicator-transfer.install'
222--- debian/indicator-transfer.install 1970-01-01 00:00:00 +0000
223+++ debian/indicator-transfer.install 2015-08-13 14:17:16 +0000
224@@ -0,0 +1,5 @@
225+usr/share/upstart/sessions/indicator-transfer.conf
226+etc/xdg/autostart/indicator-transfer.desktop
227+usr/share/upstart/xdg/autostart/indicator-transfer.desktop
228+usr/share/unity/indicators/com.canonical.indicator.transfer
229+usr/lib/*/indicator-transfer/indicator-transfer-service
230
231=== added file 'debian/libindicator-transfer-dev.install'
232--- debian/libindicator-transfer-dev.install 1970-01-01 00:00:00 +0000
233+++ debian/libindicator-transfer-dev.install 2015-08-13 14:17:16 +0000
234@@ -0,0 +1,3 @@
235+usr/include/indicator-transfer/*
236+usr/lib/*/libindicator-transfer.so
237+usr/lib/*/pkgconfig/indicator-transfer.pc
238
239=== added file 'debian/libindicator-transfer0.install'
240--- debian/libindicator-transfer0.install 1970-01-01 00:00:00 +0000
241+++ debian/libindicator-transfer0.install 2015-08-13 14:17:16 +0000
242@@ -0,0 +1,1 @@
243+usr/lib/*/libindicator-transfer.so.*
244
245=== modified file 'include/transfer/CMakeLists.txt'
246--- include/transfer/CMakeLists.txt 2014-03-29 17:17:09 +0000
247+++ include/transfer/CMakeLists.txt 2015-08-13 14:17:16 +0000
248@@ -1,2 +1,6 @@
249-
250-
251+set (SERVICE_LIB_PUBLIC_HEADERS
252+ model.h
253+ source.h
254+ transfer.h)
255+
256+install (FILES ${SERVICE_LIB_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR}/${CMAKE_PROJECT_NAME}/transfer)
257
258=== modified file 'include/transfer/controller.h'
259--- include/transfer/controller.h 2014-06-17 01:36:16 +0000
260+++ include/transfer/controller.h 2015-08-13 14:17:16 +0000
261@@ -22,7 +22,7 @@
262
263 #include <transfer/model.h>
264 #include <transfer/transfer.h>
265-#include <transfer/world.h>
266+#include <transfer/source.h>
267
268 #include <memory> // std::shared_ptr
269
270@@ -37,7 +37,7 @@
271 {
272 public:
273 Controller(const std::shared_ptr<MutableModel>& model,
274- const std::shared_ptr<World>& world);
275+ const std::shared_ptr<Source>& source);
276 virtual ~Controller();
277
278 virtual void pause_all();
279@@ -53,7 +53,7 @@
280
281 private:
282 std::shared_ptr<MutableModel> m_model;
283- std::shared_ptr<World> m_world;
284+ std::shared_ptr<Source> m_source;
285 };
286
287 } // namespace transfer
288
289=== renamed file 'include/transfer/world-dbus.h' => 'include/transfer/dm-source.h'
290--- include/transfer/world-dbus.h 2014-10-22 18:39:24 +0000
291+++ include/transfer/dm-source.h 2015-08-13 14:17:16 +0000
292@@ -17,10 +17,10 @@
293 * Charles Kerr <charles.kerr@canonical.com>
294 */
295
296-#ifndef INDICATOR_TRANSFER_WORLD_DBUS_H
297-#define INDICATOR_TRANSFER_WORLD_DBUS_H
298+#ifndef INDICATOR_TRANSFER_DM_SOURCE_H
299+#define INDICATOR_TRANSFER_DM_SOURCE_H
300
301-#include <transfer/world.h>
302+#include <transfer/source.h>
303
304 #include <gio/gio.h>
305
306@@ -31,20 +31,21 @@
307 namespace transfer {
308
309 /**
310- * \brief a World that gets its updates & events from DBus
311+ * \brief a Source that gets its updates & events from the Download Manager.
312 */
313-class DBusWorld: public World
314+class DMSource: public Source
315 {
316 public:
317- explicit DBusWorld(const std::shared_ptr<MutableModel>& model);
318- ~DBusWorld();
319+ DMSource();
320+ ~DMSource();
321
322- void open(const Transfer::Id& id);
323- void start(const Transfer::Id& id);
324- void pause(const Transfer::Id& id);
325- void resume(const Transfer::Id& id);
326- void cancel(const Transfer::Id& id);
327- void open_app(const Transfer::Id& id);
328+ void open(const Transfer::Id& id) override;
329+ void start(const Transfer::Id& id) override;
330+ void pause(const Transfer::Id& id) override;
331+ void resume(const Transfer::Id& id) override;
332+ void cancel(const Transfer::Id& id) override;
333+ void open_app(const Transfer::Id& id) override;
334+ std::shared_ptr<MutableModel> get_model() override;
335
336 private:
337 class Impl;
338@@ -55,4 +56,4 @@
339 } // namespace indicator
340 } // namespace unity
341
342-#endif // INDICATOR_TRANSFER_WORLD_H
343+#endif // INDICATOR_TRANSFER_DM_SOURCE_H
344
345=== added file 'include/transfer/multisource.h'
346--- include/transfer/multisource.h 1970-01-01 00:00:00 +0000
347+++ include/transfer/multisource.h 2015-08-13 14:17:16 +0000
348@@ -0,0 +1,58 @@
349+/*
350+ * Copyright 2015 Canonical Ltd.
351+ *
352+ * This program is free software: you can redistribute it and/or modify it
353+ * under the terms of the GNU General Public License version 3, as published
354+ * by the Free Software Foundation.
355+ *
356+ * This program is distributed in the hope that it will be useful, but
357+ * WITHOUT ANY WARRANTY; without even the implied warranties of
358+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
359+ * PURPOSE. See the GNU General Public License for more details.
360+ *
361+ * You should have received a copy of the GNU General Public License along
362+ * with this program. If not, see <http://www.gnu.org/licenses/>.
363+ *
364+ * Authors:
365+ * Charles Kerr <charles.kerr@canonical.com>
366+ */
367+
368+#ifndef INDICATOR_TRANSFER_MULTISOURCE_H
369+#define INDICATOR_TRANSFER_MULTISOURCE_H
370+
371+#include <transfer/source.h>
372+
373+namespace unity {
374+namespace indicator {
375+namespace transfer {
376+
377+/**
378+ * \brief A multiplexer/demultiplexer for sources
379+ */
380+class MultiSource: public Source
381+{
382+public:
383+ MultiSource();
384+ virtual ~MultiSource();
385+
386+ // Source
387+ void open(const Transfer::Id& id) override;
388+ void start(const Transfer::Id& id) override;
389+ void pause(const Transfer::Id& id) override;
390+ void resume(const Transfer::Id& id) override;
391+ void cancel(const Transfer::Id& id) override;
392+ void open_app(const Transfer::Id& id) override;
393+ std::shared_ptr<MutableModel> get_model() override;
394+
395+ void add_source(const std::shared_ptr<Source>& source);
396+
397+private:
398+ class Impl;
399+ std::unique_ptr<Impl> impl;
400+};
401+
402+} // namespace transfer
403+} // namespace indicator
404+} // namespace unity
405+
406+#endif // INDICATOR_TRANSFER_MULTISOURCE_H
407
408=== added file 'include/transfer/plugin-source.h'
409--- include/transfer/plugin-source.h 1970-01-01 00:00:00 +0000
410+++ include/transfer/plugin-source.h 2015-08-13 14:17:16 +0000
411@@ -0,0 +1,49 @@
412+/*
413+ * Copyright 2015 Canonical Ltd.
414+ *
415+ * This program is free software: you can redistribute it and/or modify it
416+ * under the terms of the GNU General Public License version 3, as published
417+ * by the Free Software Foundation.
418+ *
419+ * This program is distributed in the hope that it will be useful, but
420+ * WITHOUT ANY WARRANTY; without even the implied warranties of
421+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
422+ * PURPOSE. See the GNU General Public License for more details.
423+ *
424+ * You should have received a copy of the GNU General Public License along
425+ * with this program. If not, see <http://www.gnu.org/licenses/>.
426+ *
427+ * Authors:
428+ * Charles Kerr <charles.kerr@canonical.com>
429+ */
430+
431+#ifndef INDICATOR_TRANSFER_SOURCE_PLUGIN_H
432+#define INDICATOR_TRANSFER_SOURCE_PLUGIN_H
433+
434+#include <transfer/multisource.h>
435+
436+#include <memory> // unique_ptr
437+
438+namespace unity {
439+namespace indicator {
440+namespace transfer {
441+
442+/**
443+ * \brief a MultiSource that gets its sources from plugins
444+ */
445+class PluginSource: public MultiSource
446+{
447+public:
448+ explicit PluginSource(const std::string& plugin_dir);
449+ ~PluginSource();
450+
451+private:
452+ class Impl;
453+ std::unique_ptr<Impl> impl;
454+};
455+
456+} // namespace transfer
457+} // namespace indicator
458+} // namespace unity
459+
460+#endif // INDICATOR_TRANSFER_SOURCE_PLUGINSH
461
462=== renamed file 'include/transfer/world.h' => 'include/transfer/source.h'
463--- include/transfer/world.h 2014-06-17 01:36:16 +0000
464+++ include/transfer/source.h 2015-08-13 14:17:16 +0000
465@@ -17,8 +17,8 @@
466 * Charles Kerr <charles.kerr@canonical.com>
467 */
468
469-#ifndef INDICATOR_TRANSFER_WORLD_H
470-#define INDICATOR_TRANSFER_WORLD_H
471+#ifndef INDICATOR_TRANSFER_SOURCE_H
472+#define INDICATOR_TRANSFER_SOURCE_H
473
474 #include <transfer/model.h>
475 #include <transfer/transfer.h> // Id
476@@ -31,11 +31,19 @@
477
478 /**
479 * \brief Facade for everything outside of indicator-transfer
480+ *
481+ * A Source is where Transfer items come from; e.g. DMSource
482+ * watches DownloadManager on the bus and pulls Transfers from
483+ * signals emitted by it.
484+ *
485+ * It also handles indicator-transfer pauses, stops, resumes,
486+ * etc. Transfers. For example, DMSource delegates these requests
487+ * to DownloadManager over dbus.
488 */
489-class World
490+class Source
491 {
492 public:
493- virtual ~World();
494+ virtual ~Source();
495
496 virtual void open(const Transfer::Id& id) =0;
497 virtual void start(const Transfer::Id& id) =0;
498@@ -43,10 +51,12 @@
499 virtual void resume(const Transfer::Id& id) =0;
500 virtual void cancel(const Transfer::Id& id) =0;
501 virtual void open_app(const Transfer::Id& id) =0;
502+
503+ virtual std::shared_ptr<MutableModel> get_model() =0;
504 };
505
506 } // namespace transfer
507 } // namespace indicator
508 } // namespace unity
509
510-#endif // INDICATOR_TRANSFER_WORLD_H
511+#endif // INDICATOR_TRANSFER_SOURCE_H
512
513=== modified file 'include/transfer/transfer.h'
514--- include/transfer/transfer.h 2014-08-25 20:39:23 +0000
515+++ include/transfer/transfer.h 2015-08-13 14:17:16 +0000
516@@ -42,11 +42,11 @@
517 HASHING, PROCESSING, FINISHED,
518 ERROR } State;
519 State state = QUEUED;
520- bool can_start() const;
521- bool can_resume() const;
522- bool can_pause() const;
523- bool can_cancel() const;
524- bool can_clear() const;
525+ virtual bool can_start() const;
526+ virtual bool can_resume() const;
527+ virtual bool can_pause() const;
528+ virtual bool can_cancel() const;
529+ virtual bool can_clear() const;
530
531 // -1 == unknown
532 int seconds_left = -1;
533
534=== modified file 'src/CMakeLists.txt'
535--- src/CMakeLists.txt 2014-06-25 22:39:05 +0000
536+++ src/CMakeLists.txt 2015-08-13 14:17:16 +0000
537@@ -1,4 +1,4 @@
538-set (SERVICE_LIB "indicatortransferservice")
539+set (SERVICE_LIB "indicator-transfer")
540 set (SERVICE_EXEC "indicator-transfer-service")
541
542 add_definitions (-DG_LOG_DOMAIN="${CMAKE_PROJECT_NAME}")
543@@ -7,14 +7,22 @@
544 set (SERVICE_LIB_HANDWRITTEN_SOURCES
545 controller.cpp
546 model.cpp
547+ plugin-source.cpp
548 transfer.cpp
549 view.cpp
550 view-gmenu.cpp
551- world.cpp
552- world-dbus.cpp)
553-
554-add_library (${SERVICE_LIB} STATIC
555- ${SERVICE_LIB_HANDWRITTEN_SOURCES})
556+ source.cpp
557+ multisource.cpp)
558+
559+add_library(${SERVICE_LIB} SHARED ${SERVICE_LIB_HANDWRITTEN_SOURCES})
560+target_link_libraries (${SERVICE_LIB} PRIVATE ${SERVICE_DEPS_LIBRARIES} ${GCOV_LIBS})
561+
562+set_target_properties(${SERVICE_LIB} PROPERTIES
563+ VERSION ${INDICATOR_TRANSFER_VERSION}
564+ SOVERSION ${INDICATOR_TRANSFER_VERSION_MAJOR}
565+)
566+install (TARGETS ${SERVICE_LIB} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
567+
568
569 # add the bin dir to the include path so that
570 # the compiler can find the generated header files
571@@ -30,5 +38,8 @@
572 # add warnings/coverage info on handwritten files
573 # but not the generated ones...
574 set_property (SOURCE ${SERVICE_LIB_HANDWRITTEN_SOURCES} ${SERVICE_EXEC_HANDWRITTEN_SOURCES}
575- APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++11 -g ${CXX_WARNING_ARGS} ${GCOV_FLAGS}")
576-
577+ APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++11 -fPIC -g ${CXX_WARNING_ARGS} ${GCOV_FLAGS}")
578+
579+set_property (SOURCE main.cpp APPEND PROPERTY COMPILE_DEFINITIONS PLUGINDIR="${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}")
580+
581+add_subdirectory (dm-plugin)
582
583=== modified file 'src/controller.cpp'
584--- src/controller.cpp 2014-06-17 01:36:16 +0000
585+++ src/controller.cpp 2015-08-13 14:17:16 +0000
586@@ -28,9 +28,9 @@
587 ***/
588
589 Controller::Controller(const std::shared_ptr<MutableModel>& model,
590- const std::shared_ptr<World>& world):
591+ const std::shared_ptr<Source>& source):
592 m_model(model),
593- m_world(world)
594+ m_source(source)
595 {
596 }
597
598@@ -77,38 +77,38 @@
599 {
600 const auto& transfer = m_model->get(id);
601 if (transfer && transfer->can_pause())
602- m_world->pause(id);
603+ m_source->pause(id);
604 }
605
606 void Controller::cancel(const Transfer::Id& id)
607 {
608 const auto& transfer = m_model->get(id);
609 if (transfer && transfer->can_cancel())
610- m_world->cancel(id);
611+ m_source->cancel(id);
612 }
613
614 void Controller::resume(const Transfer::Id& id)
615 {
616 const auto& transfer = m_model->get(id);
617 if (transfer && transfer->can_resume())
618- m_world->resume(id);
619+ m_source->resume(id);
620 }
621
622 void Controller::start(const Transfer::Id& id)
623 {
624 const auto& transfer = m_model->get(id);
625 if (transfer && transfer->can_start())
626- m_world->start(id);
627+ m_source->start(id);
628 }
629
630 void Controller::open(const Transfer::Id& id)
631 {
632- m_world->open(id);
633+ m_source->open(id);
634 }
635
636 void Controller::open_app(const Transfer::Id& id)
637 {
638- m_world->open_app(id);
639+ m_source->open_app(id);
640 }
641
642 /***
643
644=== added directory 'src/dm-plugin'
645=== added file 'src/dm-plugin/CMakeLists.txt'
646--- src/dm-plugin/CMakeLists.txt 1970-01-01 00:00:00 +0000
647+++ src/dm-plugin/CMakeLists.txt 2015-08-13 14:17:16 +0000
648@@ -0,0 +1,21 @@
649+# the DownloadManager source plugin...
650+set(DM_LIB "dmtransfers")
651+
652+set(DM_SOURCES
653+ dm-source.cpp
654+ dm-plugin.cpp)
655+
656+include_directories (
657+ ${CAMAKE_SOURCE_DIR}/src)
658+
659+add_library(${DM_LIB} MODULE ${DM_SOURCES})
660+
661+target_link_libraries (${DM_LIB}
662+ indicator-transfer
663+ ${SERVICE_DEPS_LIBRARIES}
664+ ${GCOV_LIBS})
665+
666+install(TARGETS ${DM_LIB} LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR})
667+
668+set_property (SOURCE ${DM_SOURCES}
669+ APPEND_STRING PROPERTY COMPILE_FLAGS " -std=c++11 -fPIC -g ${CXX_WARNING_ARGS} ${GCOV_FLAGS}")
670
671=== added file 'src/dm-plugin/dm-plugin.cpp'
672--- src/dm-plugin/dm-plugin.cpp 1970-01-01 00:00:00 +0000
673+++ src/dm-plugin/dm-plugin.cpp 2015-08-13 14:17:16 +0000
674@@ -0,0 +1,32 @@
675+/*
676+ * Copyright 2015 Canonical Ltd.
677+ *
678+ * This program is free software: you can redistribute it and/or modify it
679+ * under the terms of the GNU General Public License version 3, as published
680+ * by the Free Software Foundation.
681+ *
682+ * This program is distributed in the hope that it will be useful, but
683+ * WITHOUT ANY WARRANTY; without even the implied warranties of
684+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
685+ * PURPOSE. See the GNU General Public License for more details.
686+ *
687+ * You should have received a copy of the GNU General Public License along
688+ * with this program. If not, see <http://www.gnu.org/licenses/>.
689+ *
690+ * Authors:
691+ * Charles Kerr <charles.kerr@canonical.com>
692+ */
693+
694+#include <transfer/dm-source.h>
695+
696+#include <gmodule.h>
697+
698+using namespace unity::indicator::transfer;
699+
700+extern "C"
701+{
702+G_MODULE_EXPORT Source* get_source()
703+{
704+ return new unity::indicator::transfer::DMSource{};
705+}
706+}
707
708=== renamed file 'src/world-dbus.cpp' => 'src/dm-plugin/dm-source.cpp'
709--- src/world-dbus.cpp 2015-07-15 18:18:52 +0000
710+++ src/dm-plugin/dm-source.cpp 2015-08-13 14:17:16 +0000
711@@ -17,7 +17,7 @@
712 * Charles Kerr <charles.kerr@canonical.com>
713 */
714
715-#include <transfer/world-dbus.h>
716+#include <transfer/dm-source.h>
717
718 #include <click.h>
719 #include <ubuntu-app-launch.h>
720@@ -44,21 +44,21 @@
721 /**
722 * A Transfer whose state comes from content-hub and ubuntu-download-manager.
723 *
724- * Each DBusTransfer tracks a com.canonical.applications.Download (ccad) object
725+ * Each DMTransfer tracks a com.canonical.applications.Download (ccad) object
726 * from ubuntu-download-manager. The ccad is used for pause/resume/cancel,
727 * state change / download progress signals, etc.
728 *
729- * Each DBusTransfer also tracks a com.ubuntu.content.dbus.Transfer (cucdt)
730+ * Each DMTransfer also tracks a com.ubuntu.content.dbus.Transfer (cucdt)
731 * object from content-hub. The cucdt is used for learning the download's peer
732 * and for calling Charge() to launch the peer's app.
733 */
734-class DBusTransfer: public Transfer
735+class DMTransfer: public Transfer
736 {
737 public:
738
739- DBusTransfer(GDBusConnection* connection,
740- const std::string& ccad_path,
741- const std::string& cucdt_path):
742+ DMTransfer(GDBusConnection* connection,
743+ const std::string& ccad_path,
744+ const std::string& cucdt_path):
745 m_bus(G_DBUS_CONNECTION(g_object_ref(connection))),
746 m_cancellable(g_cancellable_new()),
747 m_ccad_path(ccad_path),
748@@ -70,7 +70,7 @@
749 get_cucdt_properties();
750 }
751
752- ~DBusTransfer()
753+ ~DMTransfer()
754 {
755 if (m_changed_tag)
756 g_source_remove(m_changed_tag);
757@@ -250,7 +250,7 @@
758
759 static gboolean emit_changed_now(gpointer gself)
760 {
761- auto self = static_cast<DBusTransfer*>(gself);
762+ auto self = static_cast<DMTransfer*>(gself);
763 self->m_changed_tag = 0;
764 self->m_changed();
765 return G_SOURCE_REMOVE;
766@@ -496,7 +496,7 @@
767 const gchar* store = nullptr;
768 g_variant_get_child(v, 0, "&s", &store);
769 if (store != nullptr)
770- static_cast<DBusTransfer*>(gself)->set_store(store);
771+ static_cast<DMTransfer*>(gself)->set_store(store);
772 g_variant_unref(v);
773 }
774 }
775@@ -533,7 +533,7 @@
776 g_variant_get_child(v, 0, "t", &n);
777 g_variant_unref(v);
778
779- auto self = static_cast<DBusTransfer*>(gself);
780+ auto self = static_cast<DMTransfer*>(gself);
781 self->m_total_size = n;
782 self->update_progress();
783 }
784@@ -550,7 +550,7 @@
785 g_variant_get_child(v, 0, "t", &n);
786 g_variant_unref(v);
787
788- auto self = static_cast<DBusTransfer*>(gself);
789+ auto self = static_cast<DMTransfer*>(gself);
790 self->m_received = n;
791 self->update_progress();
792 }
793@@ -622,13 +622,13 @@
794 ****
795 ***/
796
797-class DBusWorld::Impl
798+class DMSource::Impl
799 {
800 public:
801
802- explicit Impl(const std::shared_ptr<MutableModel>& model):
803+ Impl():
804 m_cancellable(g_cancellable_new()),
805- m_model(model)
806+ m_model(std::make_shared<MutableModel>())
807 {
808 g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_ready, this);
809
810@@ -690,6 +690,11 @@
811 transfer->open_app();
812 }
813
814+ std::shared_ptr<MutableModel> get_model()
815+ {
816+ return m_model;
817+ }
818+
819 private:
820
821 static void on_bus_ready(GObject * /*source_object*/,
822@@ -788,7 +793,7 @@
823 }
824 else
825 {
826- // Route this signal to the DBusTransfer for processing
827+ // Route this signal to the DMTransfer for processing
828 auto transfer = find_transfer_by_cucdt_path(cucdt_path);
829 if (transfer)
830 transfer->handle_cucdt_signal(signal_name, parameters);
831@@ -807,7 +812,7 @@
832 g_debug("download signal: %s %s %s", ccad_path, signal_name, variant_str);
833 g_free(variant_str);
834
835- // Route this signal to the DBusTransfer for processing
836+ // Route this signal to the DMTransfer for processing
837 auto self = static_cast<Impl*>(gself);
838 auto transfer = self->find_transfer_by_ccad_path(ccad_path);
839 if (transfer)
840@@ -818,11 +823,11 @@
841 ****
842 ***/
843
844- std::shared_ptr<DBusTransfer> find_transfer_by_ccad_path(const std::string& path)
845+ std::shared_ptr<DMTransfer> find_transfer_by_ccad_path(const std::string& path)
846 {
847 for (const auto& transfer : m_model->get_all())
848 {
849- const auto tmp = std::static_pointer_cast<DBusTransfer>(transfer);
850+ const auto tmp = std::static_pointer_cast<DMTransfer>(transfer);
851
852 if (tmp && (path == tmp->ccad_path()))
853 return tmp;
854@@ -831,11 +836,11 @@
855 return nullptr;
856 }
857
858- std::shared_ptr<DBusTransfer> find_transfer_by_cucdt_path(const std::string& path)
859+ std::shared_ptr<DMTransfer> find_transfer_by_cucdt_path(const std::string& path)
860 {
861 for (const auto& transfer : m_model->get_all())
862 {
863- const auto tmp = std::static_pointer_cast<DBusTransfer>(transfer);
864+ const auto tmp = std::static_pointer_cast<DMTransfer>(transfer);
865
866 if (tmp && (path == tmp->cucdt_path()))
867 return tmp;
868@@ -851,11 +856,11 @@
869 if (m_removed_ccad.count(ccad_path))
870 return;
871
872- auto new_transfer = std::make_shared<DBusTransfer>(m_bus, ccad_path, cucdt_path);
873+ auto new_transfer = std::make_shared<DMTransfer>(m_bus, ccad_path, cucdt_path);
874
875 m_model->add(new_transfer);
876
877- // when one of the DBusTransfer's properties changes,
878+ // when one of the DMTransfer's properties changes,
879 // emit a change signal for the model
880 const auto id = new_transfer->id;
881 new_transfer->changed().connect([this,id]{
882@@ -864,11 +869,11 @@
883 });
884 }
885
886- std::shared_ptr<DBusTransfer> find_transfer_by_id(const Transfer::Id& id)
887+ std::shared_ptr<DMTransfer> find_transfer_by_id(const Transfer::Id& id)
888 {
889 auto transfer = m_model->get(id);
890- g_return_val_if_fail(transfer, std::shared_ptr<DBusTransfer>());
891- return std::static_pointer_cast<DBusTransfer>(transfer);
892+ g_return_val_if_fail(transfer, std::shared_ptr<DMTransfer>());
893+ return std::static_pointer_cast<DMTransfer>(transfer);
894 }
895
896 GDBusConnection* m_bus = nullptr;
897@@ -882,56 +887,61 @@
898 ****
899 ***/
900
901-DBusWorld::DBusWorld(const std::shared_ptr<MutableModel>& model):
902- impl(new Impl(model))
903+DMSource::DMSource():
904+ impl(new Impl{})
905 {
906 }
907
908-DBusWorld::~DBusWorld()
909+DMSource::~DMSource()
910 {
911 }
912
913 void
914-DBusWorld::open(const Transfer::Id& id)
915+DMSource::open(const Transfer::Id& id)
916 {
917 impl->open(id);
918 }
919
920 void
921-DBusWorld::start(const Transfer::Id& id)
922+DMSource::start(const Transfer::Id& id)
923 {
924 impl->start(id);
925 }
926
927 void
928-DBusWorld::pause(const Transfer::Id& id)
929+DMSource::pause(const Transfer::Id& id)
930 {
931 impl->pause(id);
932 }
933
934 void
935-DBusWorld::resume(const Transfer::Id& id)
936+DMSource::resume(const Transfer::Id& id)
937 {
938 impl->resume(id);
939 }
940
941 void
942-DBusWorld::cancel(const Transfer::Id& id)
943+DMSource::cancel(const Transfer::Id& id)
944 {
945 impl->cancel(id);
946 }
947
948 void
949-DBusWorld::open_app(const Transfer::Id& id)
950+DMSource::open_app(const Transfer::Id& id)
951 {
952 impl->open_app(id);
953 }
954
955+std::shared_ptr<MutableModel>
956+DMSource::get_model()
957+{
958+ return impl->get_model();
959+}
960+
961 /***
962 ****
963 ***/
964
965-
966 } // namespace transfer
967 } // namespace indicator
968 } // namespace unity
969
970=== modified file 'src/main.cpp'
971--- src/main.cpp 2014-06-17 01:36:16 +0000
972+++ src/main.cpp 2015-08-13 14:17:16 +0000
973@@ -20,7 +20,7 @@
974 #include <transfer/controller.h>
975 #include <transfer/model.h>
976 #include <transfer/view-gmenu.h>
977-#include <transfer/world-dbus.h>
978+#include <transfer/plugin-source.h>
979
980 #include <glib/gi18n.h> // bindtextdomain()
981 #include <gio/gio.h>
982@@ -44,9 +44,9 @@
983 auto loop = g_main_loop_new(nullptr, false);
984
985 // run until we lose the busname
986- auto model = std::make_shared<MutableModel>();
987- auto world = std::shared_ptr<World>(new DBusWorld(model));
988- auto controller = std::make_shared<Controller>(model, world);
989+ auto source = std::make_shared<PluginSource>(PLUGINDIR);
990+ auto model = source->get_model();
991+ auto controller = std::make_shared<Controller>(model, source);
992 GMenuView menu_view (model, controller);
993 // FIXME: listen for busname-lost
994 g_main_loop_run(loop);
995
996=== added file 'src/multisource.cpp'
997--- src/multisource.cpp 1970-01-01 00:00:00 +0000
998+++ src/multisource.cpp 2015-08-13 14:17:16 +0000
999@@ -0,0 +1,207 @@
1000+/*
1001+ * Copyright 2015 Canonical Ltd.
1002+ *
1003+ * This program is free software: you can redistribute it and/or modify it
1004+ * under the terms of the GNU General Public License version 3, as published
1005+ * by the Free Software Foundation.
1006+ *
1007+ * This program is distributed in the hope that it will be useful, but
1008+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1009+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1010+ * PURPOSE. See the GNU General Public License for more details.
1011+ *
1012+ * You should have received a copy of the GNU General Public License along
1013+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1014+ *
1015+ * Authors:
1016+ * Charles Kerr <charles.kerr@canonical.com>
1017+ */
1018+
1019+#include <transfer/multisource.h>
1020+
1021+#include <set>
1022+#include <string>
1023+#include <vector>
1024+
1025+namespace unity {
1026+namespace indicator {
1027+namespace transfer {
1028+
1029+/***
1030+****
1031+***/
1032+
1033+class MultiSource::Impl
1034+{
1035+public:
1036+
1037+ Impl():
1038+ m_model(std::make_shared<MutableModel>())
1039+ {
1040+ }
1041+
1042+ std::shared_ptr<MutableModel> get_model()
1043+ {
1044+ return m_model;
1045+ }
1046+
1047+ void add_source(const std::shared_ptr<Source>& source)
1048+ {
1049+ g_return_if_fail(source);
1050+
1051+ const auto idx = m_sources.size();
1052+ m_sources.push_back(source);
1053+
1054+ auto model = source->get_model();
1055+
1056+ m_connections.insert(
1057+ model->added().connect([this,idx](const Transfer::Id& id){
1058+ auto s = m_sources[idx];
1059+ m_id2source[id] = s;
1060+ m_model->add(s->get_model()->get(id));
1061+ })
1062+ );
1063+
1064+ m_connections.insert(
1065+ model->removed().connect([this](const Transfer::Id& id){
1066+ m_id2source.erase(id);
1067+ m_model->remove(id);
1068+ })
1069+ );
1070+
1071+ m_connections.insert(
1072+ model->changed().connect([this](const Transfer::Id& id){
1073+ m_model->emit_changed(id);
1074+ })
1075+ );
1076+ }
1077+
1078+ void start(const Transfer::Id& id)
1079+ {
1080+ auto source = lookup_source(id);
1081+ g_return_if_fail(source);
1082+ source->start(id);
1083+ }
1084+
1085+ void pause(const Transfer::Id& id)
1086+ {
1087+ auto source = lookup_source(id);
1088+ g_return_if_fail(source);
1089+ source->pause(id);
1090+ }
1091+
1092+ void resume(const Transfer::Id& id)
1093+ {
1094+ auto source = lookup_source(id);
1095+ g_return_if_fail(source);
1096+ source->resume(id);
1097+ }
1098+
1099+ void cancel(const Transfer::Id& id)
1100+ {
1101+ auto source = lookup_source(id);
1102+ g_return_if_fail(source);
1103+ source->cancel(id);
1104+ }
1105+
1106+ void open(const Transfer::Id& id)
1107+ {
1108+ auto source = lookup_source(id);
1109+ g_return_if_fail(source);
1110+ source->open(id);
1111+ }
1112+
1113+ void open_app(const Transfer::Id& id)
1114+ {
1115+ auto source = lookup_source(id);
1116+ g_return_if_fail(source);
1117+ source->open_app(id);
1118+ }
1119+
1120+private:
1121+
1122+ std::shared_ptr<Source> lookup_source(const Transfer::Id& id)
1123+ {
1124+ std::shared_ptr<Source> source;
1125+
1126+ auto it = m_id2source.find(id);
1127+ if (it != m_id2source.end())
1128+ source = it->second;
1129+
1130+ return source;
1131+ }
1132+
1133+ std::shared_ptr<MutableModel> m_model;
1134+ std::vector<std::shared_ptr<Source>> m_sources;
1135+ std::map<Transfer::Id,std::shared_ptr<Source>> m_id2source;
1136+ std::set<core::ScopedConnection> m_connections;
1137+};
1138+
1139+/***
1140+****
1141+***/
1142+
1143+MultiSource::MultiSource():
1144+ impl(new Impl{})
1145+{
1146+}
1147+
1148+MultiSource::~MultiSource()
1149+{
1150+}
1151+
1152+void
1153+MultiSource::open(const Transfer::Id& id)
1154+{
1155+ impl->open(id);
1156+}
1157+
1158+void
1159+MultiSource::start(const Transfer::Id& id)
1160+{
1161+ impl->start(id);
1162+}
1163+
1164+void
1165+MultiSource::pause(const Transfer::Id& id)
1166+{
1167+ impl->pause(id);
1168+}
1169+
1170+void
1171+MultiSource::resume(const Transfer::Id& id)
1172+{
1173+ impl->resume(id);
1174+}
1175+
1176+void
1177+MultiSource::cancel(const Transfer::Id& id)
1178+{
1179+ impl->cancel(id);
1180+}
1181+
1182+void
1183+MultiSource::open_app(const Transfer::Id& id)
1184+{
1185+ impl->open_app(id);
1186+}
1187+
1188+std::shared_ptr<MutableModel>
1189+MultiSource::get_model()
1190+{
1191+ return impl->get_model();
1192+}
1193+
1194+void
1195+MultiSource::add_source(const std::shared_ptr<Source>& source)
1196+{
1197+ impl->add_source(source);
1198+}
1199+
1200+/***
1201+****
1202+***/
1203+
1204+} // namespace transfer
1205+} // namespace indicator
1206+} // namespace unity
1207
1208=== added file 'src/plugin-source.cpp'
1209--- src/plugin-source.cpp 1970-01-01 00:00:00 +0000
1210+++ src/plugin-source.cpp 2015-08-13 14:17:16 +0000
1211@@ -0,0 +1,108 @@
1212+/*
1213+ * Copyright 2015 Canonical Ltd.
1214+ *
1215+ * This program is free software: you can redistribute it and/or modify it
1216+ * under the terms of the GNU General Public License version 3, as published
1217+ * by the Free Software Foundation.
1218+ *
1219+ * This program is distributed in the hope that it will be useful, but
1220+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1221+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1222+ * PURPOSE. See the GNU General Public License for more details.
1223+ *
1224+ * You should have received a copy of the GNU General Public License along
1225+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1226+ *
1227+ * Authors:
1228+ * Charles Kerr <charles.kerr@canonical.com>
1229+ */
1230+
1231+#include <transfer/plugin-source.h>
1232+
1233+#include <gmodule.h>
1234+
1235+namespace unity {
1236+namespace indicator {
1237+namespace transfer {
1238+
1239+/***
1240+****
1241+***/
1242+
1243+class PluginSource::Impl
1244+{
1245+public:
1246+
1247+ Impl(PluginSource& owner, const std::string& plugin_dir):
1248+ m_owner(owner)
1249+ {
1250+ GError * error = nullptr;
1251+ g_debug("plugin_dir '%s'", plugin_dir.c_str());
1252+ GDir * dir = g_dir_open(plugin_dir.c_str(), 0, &error);
1253+ if (dir != nullptr)
1254+ {
1255+ const gchar * name;
1256+ while ((name = g_dir_read_name(dir)))
1257+ {
1258+ if (g_str_has_suffix(name, G_MODULE_SUFFIX))
1259+ {
1260+ gchar * filename = g_build_filename(plugin_dir.c_str(), name, nullptr);
1261+ GModule * mod = g_module_open(filename, G_MODULE_BIND_LOCAL);
1262+ gpointer symbol {};
1263+
1264+ if (mod == nullptr)
1265+ {
1266+ g_warning("Unable to load module '%s'", filename);
1267+ }
1268+ else if (!g_module_symbol(mod, "get_source", &symbol))
1269+ {
1270+ g_warning("Unable to use module '%s'", filename);
1271+ }
1272+ else
1273+ {
1274+ using get_source_func = Source*();
1275+ auto src = reinterpret_cast<get_source_func*>(symbol)();
1276+ if (src)
1277+ {
1278+ auto deleter = [mod,src](Source *s){
1279+ delete s;
1280+ g_module_close(mod);
1281+ };
1282+ m_owner.add_source(std::shared_ptr<Source>(src, deleter));
1283+ g_debug("Loaded plugin '%s'", filename);
1284+ mod = nullptr;
1285+ }
1286+ }
1287+ g_clear_pointer(&mod, g_module_close);
1288+ g_clear_pointer(&filename, g_free);
1289+ }
1290+ }
1291+ g_clear_pointer(&dir, g_dir_close);
1292+ }
1293+ }
1294+
1295+private:
1296+ PluginSource& m_owner;
1297+
1298+};
1299+
1300+/***
1301+****
1302+***/
1303+
1304+PluginSource::PluginSource(const std::string& plugin_dir):
1305+ impl(new Impl(*this, plugin_dir))
1306+{
1307+}
1308+
1309+PluginSource::~PluginSource()
1310+{
1311+}
1312+
1313+/***
1314+****
1315+***/
1316+
1317+} // namespace transfer
1318+} // namespace indicator
1319+} // namespace unity
1320
1321=== renamed file 'src/world.cpp' => 'src/source.cpp'
1322--- src/world.cpp 2014-06-17 01:36:16 +0000
1323+++ src/source.cpp 2015-08-13 14:17:16 +0000
1324@@ -17,7 +17,7 @@
1325 * Charles Kerr <charles.kerr@canonical.com>
1326 */
1327
1328-#include <transfer/world.h>
1329+#include <transfer/source.h>
1330
1331 namespace unity {
1332 namespace indicator {
1333@@ -27,7 +27,7 @@
1334 ****
1335 ***/
1336
1337-World::~World()
1338+Source::~Source()
1339 {
1340 }
1341
1342
1343=== modified file 'tests/CMakeLists.txt'
1344--- tests/CMakeLists.txt 2014-06-17 01:36:16 +0000
1345+++ tests/CMakeLists.txt 2015-08-13 14:17:16 +0000
1346@@ -1,37 +1,43 @@
1347 include(FindGMock)
1348+include(FindValgrind)
1349 include_directories(${CMAKE_CURRENT_SOURCE_DIR})
1350 include_directories(${GMOCK_INCLUDE_DIRS})
1351 include_directories(${GTEST_INCLUDE_DIRS})
1352
1353-# build libgtest
1354-#add_library (gtest STATIC
1355-# ${GTEST_SOURCE_DIR}/gtest-all.cc
1356-# ${GTEST_SOURCE_DIR}/gtest_main.cc)
1357-#set_target_properties (gtest PROPERTIES INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${GTEST_INCLUDE_DIR})
1358-#set_target_properties (gtest PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS} -w)
1359-
1360 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
1361 # turn off the warnings that break Google Test
1362 set (CXX_WARNING_ARGS "${CXX_WARNING_ARGS} -Wno-global-constructors -Wno-weak-vtables -Wno-undef -Wno-c++98-compat-pedantic -Wno-missing-noreturn -Wno-used-but-marked-unused -Wno-padded -Wno-deprecated -Wno-sign-compare -Wno-shift-sign-overflow")
1363 endif()
1364
1365-SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g ${CXX_WARNING_ARGS}")
1366+add_definitions(-fPIC)
1367+SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -g ${CXX_WARNING_ARGS}")
1368
1369 # look for headers in our src dir, and also in the directories where we autogenerate files...
1370 include_directories (${CMAKE_SOURCE_DIR}/src)
1371 include_directories (${CMAKE_CURRENT_BINARY_DIR})
1372 include_directories (${DBUSTEST_INCLUDE_DIRS})
1373
1374+function(add_valgrind_test_by_name name)
1375+ set (TEST_NAME ${name})
1376+ add_executable (${TEST_NAME} ${TEST_NAME}.cpp)
1377+ add_valgrind_test(${TEST_NAME} VALGRIND ./${TEST_NAME})
1378+ target_link_libraries (${TEST_NAME} indicator-transfer ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
1379+endfunction()
1380+add_valgrind_test_by_name(test-controller)
1381+add_valgrind_test_by_name(test-multisource)
1382+add_valgrind_test_by_name(test-plugin-source)
1383+set(PLUGIN_NAME "mock-source-plugin")
1384+add_library(${PLUGIN_NAME} STATIC mock-source-plugin.cpp)
1385+target_link_libraries(${PLUGIN_NAME} PRIVATE ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
1386+
1387 function(add_test_by_name name)
1388 set (TEST_NAME ${name})
1389 add_executable (${TEST_NAME} ${TEST_NAME}.cpp)
1390 add_test (${TEST_NAME} ${TEST_NAME})
1391- add_dependencies (${TEST_NAME} libindicatortransferservice)
1392- #target_link_libraries (${TEST_NAME} indicatortransferservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})
1393- target_link_libraries (${TEST_NAME} indicatortransferservice ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
1394+ target_link_libraries (${TEST_NAME} indicator-transfer ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES})
1395 endfunction()
1396-add_test_by_name(test-controller)
1397 add_test_by_name(test-view-gmenu)
1398+
1399 #add_test_by_name(test-mocks)
1400 #add_test_by_name(test-gactions)
1401 #add_test_by_name(test-actions-live)
1402
1403=== modified file 'tests/controller-mock.h'
1404--- tests/controller-mock.h 2014-06-17 01:36:16 +0000
1405+++ tests/controller-mock.h 2015-08-13 14:17:16 +0000
1406@@ -32,8 +32,8 @@
1407 {
1408 public:
1409 MockController(const std::shared_ptr<MutableModel>& model,
1410- const std::shared_ptr<World>& world):
1411- Controller(model, world) {}
1412+ const std::shared_ptr<Source>& source):
1413+ Controller(model, source) {}
1414
1415 MOCK_METHOD0(pause_all, void());
1416 MOCK_METHOD0(resume_all, void());
1417
1418=== added directory 'tests/data'
1419=== added file 'tests/data/valgrind.suppression'
1420--- tests/data/valgrind.suppression 1970-01-01 00:00:00 +0000
1421+++ tests/data/valgrind.suppression 2015-08-13 14:17:16 +0000
1422@@ -0,0 +1,2 @@
1423+
1424+
1425
1426=== modified file 'tests/glib-fixture.h'
1427--- tests/glib-fixture.h 2014-10-22 18:41:45 +0000
1428+++ tests/glib-fixture.h 2015-08-13 14:17:16 +0000
1429@@ -1,5 +1,5 @@
1430 /*
1431- * Copyright 2014 Canonical Ltd.
1432+ * Copyright 2015 Canonical Ltd.
1433 *
1434 * This program is free software: you can redistribute it and/or modify it
1435 * under the terms of the GNU General Public License version 3, as published
1436@@ -40,30 +40,13 @@
1437
1438 GLogFunc realLogHandler;
1439
1440- std::map<GLogLevelFlags,size_t> expected_log;
1441- std::map<GLogLevelFlags,std::vector<std::string>> log;
1442+ std::map<GLogLevelFlags,int> logCounts;
1443
1444- void test_log_counts()
1445+ void testLogCount(GLogLevelFlags log_level, int expected)
1446 {
1447- const GLogLevelFlags levels_to_test[] = { G_LOG_LEVEL_ERROR,
1448- G_LOG_LEVEL_CRITICAL,
1449- G_LOG_LEVEL_MESSAGE,
1450- G_LOG_LEVEL_WARNING };
1451-
1452- for(const auto& level : levels_to_test)
1453- {
1454- const auto& v = log[level];
1455- const auto n = v.size();
1456-
1457- EXPECT_EQ(expected_log[level], n);
1458-
1459- if (expected_log[level] != n)
1460- for (size_t i=0; i<n; ++i)
1461- g_message("%d %s", (n+1), v[i].c_str());
1462- }
1463-
1464- expected_log.clear();
1465- log.clear();
1466+ EXPECT_EQ(expected, logCounts[log_level]);
1467+
1468+ logCounts.erase(log_level);
1469 }
1470
1471 static void default_log_handler(const gchar * log_domain,
1472@@ -71,19 +54,13 @@
1473 const gchar * message,
1474 gpointer self)
1475 {
1476- auto tmp = g_strdup_printf ("%s:%d \"%s\"", log_domain, (int)log_level, message);
1477- static_cast<GlibFixture*>(self)->log[log_level].push_back(tmp);
1478- g_free(tmp);
1479+ g_print("%s - %d - %s\n", log_domain, (int)log_level, message);
1480+ static_cast<GlibFixture*>(self)->logCounts[log_level]++;
1481 }
1482
1483 protected:
1484
1485- void increment_expected_errors(GLogLevelFlags level, size_t n=1)
1486- {
1487- expected_log[level] += n;
1488- }
1489-
1490- virtual void SetUp()
1491+ virtual void SetUp() override
1492 {
1493 setlocale(LC_ALL, "C.UTF-8");
1494
1495@@ -91,13 +68,27 @@
1496
1497 g_log_set_default_handler(default_log_handler, this);
1498
1499+ // only use local, temporary settings
1500+#ifdef SCHEMA_DIR
1501+ g_assert(g_setenv("GSETTINGS_BACKEND", "memory", true));
1502+ g_assert(g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, true));
1503+ g_debug("SCHEMA_DIR is %s", SCHEMA_DIR);
1504+#endif
1505+
1506 g_unsetenv("DISPLAY");
1507+
1508 }
1509
1510- virtual void TearDown()
1511+ virtual void TearDown() override
1512 {
1513- test_log_counts();
1514+ // confirm there aren't any unexpected log messages
1515+ EXPECT_EQ(0, logCounts[G_LOG_LEVEL_ERROR]);
1516+ EXPECT_EQ(0, logCounts[G_LOG_LEVEL_CRITICAL]);
1517+ EXPECT_EQ(0, logCounts[G_LOG_LEVEL_WARNING]);
1518+ EXPECT_EQ(0, logCounts[G_LOG_LEVEL_MESSAGE]);
1519+ EXPECT_EQ(0, logCounts[G_LOG_LEVEL_INFO]);
1520
1521+ // revert to glib's log handler
1522 g_log_set_default_handler(realLogHandler, this);
1523
1524 g_clear_pointer(&loop, g_main_loop_unref);
1525@@ -122,7 +113,7 @@
1526 protected:
1527
1528 /* convenience func to loop while waiting for a GObject's signal */
1529- void wait_for_signal(gpointer o, const gchar * signal, const guint timeout_seconds=5)
1530+ void wait_for_signal(gpointer o, const gchar * signal, const int timeout_seconds=5)
1531 {
1532 // wait for the signal or for timeout, whichever comes first
1533 const auto handler_id = g_signal_connect_swapped(o, signal,
1534@@ -137,7 +128,7 @@
1535 }
1536
1537 /* convenience func to loop for N msec */
1538- void wait_msec(guint msec=50)
1539+ void wait_msec(int msec=50)
1540 {
1541 const auto id = g_timeout_add(msec, wait_msec__timeout, loop);
1542 g_main_loop_run(loop);
1543
1544=== added file 'tests/mock-source-plugin.cpp'
1545--- tests/mock-source-plugin.cpp 1970-01-01 00:00:00 +0000
1546+++ tests/mock-source-plugin.cpp 2015-08-13 14:17:16 +0000
1547@@ -0,0 +1,32 @@
1548+/*
1549+ * Copyright 2015 Canonical Ltd.
1550+ *
1551+ * This program is free software: you can redistribute it and/or modify it
1552+ * under the terms of the GNU General Public License version 3, as published
1553+ * by the Free Software Foundation.
1554+ *
1555+ * This program is distributed in the hope that it will be useful, but
1556+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1557+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1558+ * PURPOSE. See the GNU General Public License for more details.
1559+ *
1560+ * You should have received a copy of the GNU General Public License along
1561+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1562+ *
1563+ * Authors:
1564+ * Charles Kerr <charles.kerr@canonical.com>
1565+ */
1566+
1567+#include "source-mock.h"
1568+
1569+#include <gmodule.h>
1570+
1571+using namespace unity::indicator::transfer;
1572+
1573+extern "C"
1574+{
1575+G_MODULE_EXPORT Source* get_source()
1576+{
1577+ return new MockSource{};
1578+}
1579+}
1580
1581=== renamed file 'tests/world-mock.h' => 'tests/source-mock.h'
1582--- tests/world-mock.h 2014-06-17 01:36:16 +0000
1583+++ tests/source-mock.h 2015-08-13 14:17:16 +0000
1584@@ -17,10 +17,10 @@
1585 * Charles Kerr <charles.kerr@canonical.com>
1586 */
1587
1588-#ifndef INDICATOR_TRANSFER_WORLD_MOCK_H
1589-#define INDICATOR_TRANSFER_WORLD_MOCK_H
1590+#ifndef INDICATOR_TRANSFER_SOURCE_MOCK_H
1591+#define INDICATOR_TRANSFER_SOURCE_MOCK_H
1592
1593-#include <transfer/world.h>
1594+#include <transfer/source.h>
1595
1596 #include "gmock/gmock.h"
1597
1598@@ -29,21 +29,26 @@
1599 namespace transfer {
1600
1601 /**
1602- * \brief a World that gets its updates & events from DBus
1603+ * \brief a Source that gets its updates & events from DBus
1604 */
1605-class MockWorld: public World
1606+class MockSource: public Source
1607 {
1608 public:
1609+ MockSource(): m_model(new MutableModel) {}
1610+
1611 MOCK_METHOD1(open, void(const Transfer::Id&));
1612 MOCK_METHOD1(start, void(const Transfer::Id&));
1613 MOCK_METHOD1(pause, void(const Transfer::Id&));
1614 MOCK_METHOD1(resume, void(const Transfer::Id&));
1615 MOCK_METHOD1(cancel, void(const Transfer::Id&));
1616 MOCK_METHOD1(open_app, void(const Transfer::Id&));
1617+
1618+ std::shared_ptr<MutableModel> get_model() override {return m_model;}
1619+ std::shared_ptr<MutableModel> m_model;
1620 };
1621
1622 } // namespace transfer
1623 } // namespace indicator
1624 } // namespace unity
1625
1626-#endif // INDICATOR_TRANSFER_WORLD_MOCK_H
1627+#endif // INDICATOR_TRANSFER_SOURCE_MOCK_H
1628
1629=== modified file 'tests/test-controller.cpp'
1630--- tests/test-controller.cpp 2014-10-22 18:36:03 +0000
1631+++ tests/test-controller.cpp 2015-08-13 14:17:16 +0000
1632@@ -18,7 +18,7 @@
1633 */
1634
1635 #include "glib-fixture.h"
1636-#include "world-mock.h"
1637+#include "source-mock.h"
1638
1639 #include <transfer/controller.h>
1640
1641@@ -35,7 +35,7 @@
1642
1643 GTestDBus* bus = nullptr;
1644
1645- std::shared_ptr<MockWorld> m_world;
1646+ std::shared_ptr<MockSource> m_source;
1647 std::shared_ptr<MutableModel> m_model;
1648 std::shared_ptr<Controller> m_controller;
1649
1650@@ -43,16 +43,16 @@
1651 {
1652 super::SetUp();
1653
1654- m_world.reset(new MockWorld);
1655+ m_source.reset(new MockSource);
1656 m_model.reset(new MutableModel);
1657- m_controller.reset(new Controller(m_model, m_world));
1658+ m_controller.reset(new Controller(m_model, m_source));
1659 }
1660
1661 void TearDown()
1662 {
1663 m_controller.reset();
1664 m_model.reset();
1665- m_world.reset();
1666+ m_source.reset();
1667
1668 super::TearDown();
1669 }
1670@@ -72,7 +72,7 @@
1671 };
1672 }
1673
1674-TEST_F(ControllerFixture, HelloWorld)
1675+TEST_F(ControllerFixture, HelloSource)
1676 {
1677 // confirms that the Test DBus SetUp() and TearDown() works
1678 }
1679@@ -147,7 +147,7 @@
1680 t->id = transfer.id;
1681 m_model->add(t);
1682 EXPECT_EQ(transfer.can_pause, t->can_pause());
1683- EXPECT_CALL(*m_world, pause(transfer.id)).Times(transfer.can_pause?1:0);
1684+ EXPECT_CALL(*m_source, pause(transfer.id)).Times(transfer.can_pause?1:0);
1685 }
1686
1687 m_controller->pause_all();
1688@@ -180,7 +180,7 @@
1689 t->id = transfer.id;
1690 m_model->add(t);
1691 EXPECT_EQ(transfer.can_resume, t->can_resume());
1692- EXPECT_CALL(*m_world, resume(transfer.id)).Times(transfer.can_resume?1:0);
1693+ EXPECT_CALL(*m_source, resume(transfer.id)).Times(transfer.can_resume?1:0);
1694 }
1695
1696 m_controller->resume_all();
1697@@ -199,67 +199,67 @@
1698 m_model->add(t);
1699
1700 t->state = Transfer::QUEUED;
1701- EXPECT_CALL(*m_world, start(id)).Times(1);
1702- EXPECT_CALL(*m_world, pause(id)).Times(0);
1703- EXPECT_CALL(*m_world, resume(id)).Times(0);
1704- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1705- EXPECT_CALL(*m_world, open(id)).Times(0);
1706+ EXPECT_CALL(*m_source, start(id)).Times(1);
1707+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1708+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1709+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1710+ EXPECT_CALL(*m_source, open(id)).Times(0);
1711 m_controller->tap(id);
1712
1713 t->state = Transfer::RUNNING;
1714- EXPECT_CALL(*m_world, start(id)).Times(0);
1715- EXPECT_CALL(*m_world, pause(id)).Times(1);
1716- EXPECT_CALL(*m_world, resume(id)).Times(0);
1717- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1718- EXPECT_CALL(*m_world, open(id)).Times(0);
1719+ EXPECT_CALL(*m_source, start(id)).Times(0);
1720+ EXPECT_CALL(*m_source, pause(id)).Times(1);
1721+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1722+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1723+ EXPECT_CALL(*m_source, open(id)).Times(0);
1724 m_controller->tap(id);
1725
1726 t->state = Transfer::PAUSED;
1727- EXPECT_CALL(*m_world, start(id)).Times(0);
1728- EXPECT_CALL(*m_world, pause(id)).Times(0);
1729- EXPECT_CALL(*m_world, resume(id)).Times(1);
1730- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1731- EXPECT_CALL(*m_world, open(id)).Times(0);
1732+ EXPECT_CALL(*m_source, start(id)).Times(0);
1733+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1734+ EXPECT_CALL(*m_source, resume(id)).Times(1);
1735+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1736+ EXPECT_CALL(*m_source, open(id)).Times(0);
1737 m_controller->tap(id);
1738
1739 t->state = Transfer::CANCELED;
1740- EXPECT_CALL(*m_world, start(id)).Times(0);
1741- EXPECT_CALL(*m_world, pause(id)).Times(0);
1742- EXPECT_CALL(*m_world, resume(id)).Times(1);
1743- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1744- EXPECT_CALL(*m_world, open(id)).Times(0);
1745+ EXPECT_CALL(*m_source, start(id)).Times(0);
1746+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1747+ EXPECT_CALL(*m_source, resume(id)).Times(1);
1748+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1749+ EXPECT_CALL(*m_source, open(id)).Times(0);
1750 m_controller->tap(id);
1751
1752 t->state = Transfer::ERROR;
1753- EXPECT_CALL(*m_world, start(id)).Times(0);
1754- EXPECT_CALL(*m_world, pause(id)).Times(0);
1755- EXPECT_CALL(*m_world, resume(id)).Times(1);
1756- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1757- EXPECT_CALL(*m_world, open(id)).Times(0);
1758+ EXPECT_CALL(*m_source, start(id)).Times(0);
1759+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1760+ EXPECT_CALL(*m_source, resume(id)).Times(1);
1761+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1762+ EXPECT_CALL(*m_source, open(id)).Times(0);
1763 m_controller->tap(id);
1764
1765 t->state = Transfer::HASHING;
1766- EXPECT_CALL(*m_world, start(id)).Times(0);
1767- EXPECT_CALL(*m_world, pause(id)).Times(1);
1768- EXPECT_CALL(*m_world, resume(id)).Times(0);
1769- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1770- EXPECT_CALL(*m_world, open(id)).Times(0);
1771+ EXPECT_CALL(*m_source, start(id)).Times(0);
1772+ EXPECT_CALL(*m_source, pause(id)).Times(1);
1773+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1774+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1775+ EXPECT_CALL(*m_source, open(id)).Times(0);
1776 m_controller->tap(id);
1777
1778 t->state = Transfer::PROCESSING;
1779- EXPECT_CALL(*m_world, start(id)).Times(0);
1780- EXPECT_CALL(*m_world, pause(id)).Times(1);
1781- EXPECT_CALL(*m_world, resume(id)).Times(0);
1782- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1783- EXPECT_CALL(*m_world, open(id)).Times(0);
1784+ EXPECT_CALL(*m_source, start(id)).Times(0);
1785+ EXPECT_CALL(*m_source, pause(id)).Times(1);
1786+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1787+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1788+ EXPECT_CALL(*m_source, open(id)).Times(0);
1789 m_controller->tap(id);
1790
1791 t->state = Transfer::FINISHED;
1792- EXPECT_CALL(*m_world, start(id)).Times(0);
1793- EXPECT_CALL(*m_world, pause(id)).Times(0);
1794- EXPECT_CALL(*m_world, resume(id)).Times(0);
1795- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1796- EXPECT_CALL(*m_world, open(id)).Times(1);
1797+ EXPECT_CALL(*m_source, start(id)).Times(0);
1798+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1799+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1800+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1801+ EXPECT_CALL(*m_source, open(id)).Times(1);
1802 m_controller->tap(id);
1803 }
1804
1805@@ -274,11 +274,11 @@
1806 for (const auto& state : all_states)
1807 {
1808 t->state = state;
1809- EXPECT_CALL(*m_world, start(id)).Times(t->can_start()?1:0);
1810- EXPECT_CALL(*m_world, pause(id)).Times(0);
1811- EXPECT_CALL(*m_world, resume(id)).Times(0);
1812- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1813- EXPECT_CALL(*m_world, open(id)).Times(0);
1814+ EXPECT_CALL(*m_source, start(id)).Times(t->can_start()?1:0);
1815+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1816+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1817+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1818+ EXPECT_CALL(*m_source, open(id)).Times(0);
1819 m_controller->start(id);
1820 }
1821 }
1822@@ -294,11 +294,11 @@
1823 for (const auto& state : all_states)
1824 {
1825 t->state = state;
1826- EXPECT_CALL(*m_world, start(id)).Times(0);
1827- EXPECT_CALL(*m_world, pause(id)).Times(t->can_pause()?1:0);
1828- EXPECT_CALL(*m_world, resume(id)).Times(0);
1829- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1830- EXPECT_CALL(*m_world, open(id)).Times(0);
1831+ EXPECT_CALL(*m_source, start(id)).Times(0);
1832+ EXPECT_CALL(*m_source, pause(id)).Times(t->can_pause()?1:0);
1833+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1834+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1835+ EXPECT_CALL(*m_source, open(id)).Times(0);
1836 m_controller->pause(id);
1837 }
1838 }
1839@@ -314,11 +314,11 @@
1840 for (const auto& state : all_states)
1841 {
1842 t->state = state;
1843- EXPECT_CALL(*m_world, start(id)).Times(0);
1844- EXPECT_CALL(*m_world, pause(id)).Times(0);
1845- EXPECT_CALL(*m_world, resume(id)).Times(t->can_resume()?1:0);
1846- EXPECT_CALL(*m_world, cancel(id)).Times(0);
1847- EXPECT_CALL(*m_world, open(id)).Times(0);
1848+ EXPECT_CALL(*m_source, start(id)).Times(0);
1849+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1850+ EXPECT_CALL(*m_source, resume(id)).Times(t->can_resume()?1:0);
1851+ EXPECT_CALL(*m_source, cancel(id)).Times(0);
1852+ EXPECT_CALL(*m_source, open(id)).Times(0);
1853 m_controller->resume(id);
1854 }
1855 }
1856@@ -334,11 +334,11 @@
1857 for (const auto& state : all_states)
1858 {
1859 t->state = state;
1860- EXPECT_CALL(*m_world, start(id)).Times(0);
1861- EXPECT_CALL(*m_world, pause(id)).Times(0);
1862- EXPECT_CALL(*m_world, resume(id)).Times(0);
1863- EXPECT_CALL(*m_world, cancel(id)).Times(t->can_cancel()?1:0);
1864- EXPECT_CALL(*m_world, open(id)).Times(0);
1865+ EXPECT_CALL(*m_source, start(id)).Times(0);
1866+ EXPECT_CALL(*m_source, pause(id)).Times(0);
1867+ EXPECT_CALL(*m_source, resume(id)).Times(0);
1868+ EXPECT_CALL(*m_source, cancel(id)).Times(t->can_cancel()?1:0);
1869+ EXPECT_CALL(*m_source, open(id)).Times(0);
1870 m_controller->cancel(id);
1871 }
1872 }
1873
1874=== added file 'tests/test-multisource.cpp'
1875--- tests/test-multisource.cpp 1970-01-01 00:00:00 +0000
1876+++ tests/test-multisource.cpp 2015-08-13 14:17:16 +0000
1877@@ -0,0 +1,166 @@
1878+/*
1879+ * Copyright 2015 Canonical Ltd.
1880+ *
1881+ * This program is free software: you can redistribute it and/or modify it
1882+ * under the terms of the GNU General Public License version 3, as published
1883+ * by the Free Software Foundation.
1884+ *
1885+ * This program is distributed in the hope that it will be useful, but
1886+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1887+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1888+ * PURPOSE. See the GNU General Public License for more details.
1889+ *
1890+ * You should have received a copy of the GNU General Public License along
1891+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1892+ *
1893+ * Authors:
1894+ * Charles Kerr <charles.kerr@canonical.com>
1895+ */
1896+
1897+#include "source-mock.h"
1898+
1899+#include <gtest/gtest.h>
1900+
1901+#include <transfer/controller.h>
1902+#include <transfer/multisource.h>
1903+
1904+using ::testing::AtLeast;
1905+
1906+using namespace unity::indicator::transfer;
1907+
1908+class MultiSourceFixture: public ::testing::Test
1909+{
1910+protected:
1911+
1912+ struct Event
1913+ {
1914+ typedef enum { ADDED, CHANGED, REMOVED } Type;
1915+ Type type;
1916+ Transfer::Id id;
1917+ bool operator==(const Event& that) const { return type==that.type && id==that.id; }
1918+ };
1919+
1920+ bool model_consists_of(const std::shared_ptr<Model>& model, std::initializer_list<std::shared_ptr<Transfer>> list) const
1921+ {
1922+ // test get_all()
1923+ std::vector<std::shared_ptr<Transfer>> transfers(list);
1924+ std::sort(transfers.begin(), transfers.end());
1925+ g_return_val_if_fail(transfers == model->get_all(), false);
1926+
1927+ // test get()
1928+ for(auto& transfer : transfers)
1929+ g_return_val_if_fail(transfer == model->get(transfer->id), false);
1930+
1931+ // test get_ids()
1932+ std::set<Transfer::Id> ids;
1933+ for(auto& transfer : transfers)
1934+ ids.insert(transfer->id);
1935+ g_return_val_if_fail(ids == model->get_ids(), false);
1936+
1937+ return true;
1938+ }
1939+};
1940+
1941+TEST_F(MultiSourceFixture,MultiplexesModels)
1942+{
1943+ // set up the tributary sources, 'a' and 'b'
1944+ auto a = std::make_shared<MockSource>();
1945+ auto b = std::make_shared<MockSource>();
1946+
1947+ // set up the multisource and connect it to the tributaries
1948+ MultiSource multisource;
1949+ auto multimodel = multisource.get_model();
1950+ std::vector<Event> events;
1951+ std::vector<Event> expected_events;
1952+ multisource.get_model()->added().connect([&events](const Transfer::Id& id){events.push_back(Event{Event::ADDED,id});});
1953+ multisource.get_model()->changed().connect([&events](const Transfer::Id& id){events.push_back(Event{Event::CHANGED,id});});
1954+ multisource.get_model()->removed().connect([&events](const Transfer::Id& id){events.push_back(Event{Event::REMOVED,id});});
1955+ multisource.add_source(a);
1956+ multisource.add_source(b);
1957+
1958+ // add a transfer to the 'a' source...
1959+ const Transfer::Id aid {"aid"};
1960+ auto at = std::make_shared<Transfer>();
1961+ at->id = aid;
1962+ a->get_model()->add(at);
1963+ expected_events.push_back(Event{Event::ADDED,aid});
1964+
1965+ // confirm that the multimodel sees the new transfer
1966+ EXPECT_EQ(expected_events, events);
1967+ EXPECT_EQ(at, a->get_model()->get(aid));
1968+ EXPECT_TRUE(model_consists_of(multimodel, {at}));
1969+
1970+ // add a transfer to the 'b' source...
1971+ const Transfer::Id bid {"bid"};
1972+ auto bt = std::make_shared<Transfer>();
1973+ bt->id = bid;
1974+ b->get_model()->add(bt);
1975+ expected_events.push_back(Event{Event::ADDED,bid});
1976+
1977+ // confirm that the multimodel sees the new transfer
1978+ EXPECT_EQ(expected_events, events);
1979+ EXPECT_EQ(bt, b->get_model()->get(bid));
1980+ EXPECT_TRUE(model_consists_of(multimodel, {at, bt}));
1981+
1982+ // poke transfer 'at'...
1983+ at->progress = 50.0;
1984+ a->get_model()->emit_changed(aid);
1985+ expected_events.push_back(Event{Event::CHANGED,aid});
1986+ EXPECT_EQ(expected_events, events);
1987+ EXPECT_TRUE(model_consists_of(multimodel, {at, bt}));
1988+
1989+ // remove transfer 'at'...
1990+ a->get_model()->remove(aid);
1991+ expected_events.push_back(Event{Event::REMOVED,aid});
1992+ EXPECT_EQ(expected_events, events);
1993+ EXPECT_FALSE(a->get_model()->get(aid));
1994+ EXPECT_TRUE(model_consists_of(multimodel, {bt}));
1995+
1996+ // remove transfer 'bt'...
1997+ b->get_model()->remove(bid);
1998+ expected_events.push_back(Event{Event::REMOVED,bid});
1999+ EXPECT_EQ(expected_events, events);
2000+ EXPECT_FALSE(b->get_model()->get(aid));
2001+ EXPECT_TRUE(model_consists_of(multimodel, {}));
2002+}
2003+
2004+TEST(Multisource,MethodDelegation)
2005+{
2006+ // set up the tributary sources, 'a' and 'b'
2007+ auto a = std::make_shared<MockSource>();
2008+ auto b = std::make_shared<MockSource>();
2009+
2010+ // set up the multisource and connect it to the tributaries
2011+ MultiSource multisource;
2012+ multisource.add_source(a);
2013+ multisource.add_source(b);
2014+
2015+ // add a transfer to the 'a' source...
2016+ const Transfer::Id aid {"aid"};
2017+ auto at = std::make_shared<Transfer>();
2018+ at->id = aid;
2019+ a->get_model()->add(at);
2020+
2021+ // add a transfer to the 'b' source...
2022+ const Transfer::Id bid {"bid"};
2023+ auto bt = std::make_shared<Transfer>();
2024+ bt->id = bid;
2025+ b->get_model()->add(bt);
2026+
2027+ // confirm that multisource method calls are delegated to 'a'
2028+ EXPECT_CALL(*a, open(aid)); multisource.open(aid);
2029+ EXPECT_CALL(*a, start(aid)); multisource.start(aid);
2030+ EXPECT_CALL(*a, pause(aid)); multisource.pause(aid);
2031+ EXPECT_CALL(*a, resume(aid)); multisource.resume(aid);
2032+ EXPECT_CALL(*a, cancel(aid)); multisource.cancel(aid);
2033+ EXPECT_CALL(*a, open_app(aid)); multisource.open_app(aid);
2034+
2035+ // confirm that multisource method calls are delegated to 'a'
2036+ EXPECT_CALL(*b, open(bid)); multisource.open(bid);
2037+ EXPECT_CALL(*b, start(bid)); multisource.start(bid);
2038+ EXPECT_CALL(*b, pause(bid)); multisource.pause(bid);
2039+ EXPECT_CALL(*b, resume(bid)); multisource.resume(bid);
2040+ EXPECT_CALL(*b, cancel(bid)); multisource.cancel(bid);
2041+ EXPECT_CALL(*b, open_app(bid)); multisource.open_app(bid);
2042+}
2043+
2044
2045=== added file 'tests/test-plugin-source.cpp'
2046--- tests/test-plugin-source.cpp 1970-01-01 00:00:00 +0000
2047+++ tests/test-plugin-source.cpp 2015-08-13 14:17:16 +0000
2048@@ -0,0 +1,66 @@
2049+/*
2050+ * Copyright 2015 Canonical Ltd.
2051+ *
2052+ * This program is free software: you can redistribute it and/or modify it
2053+ * under the terms of the GNU General Public License version 3, as published
2054+ * by the Free Software Foundation.
2055+ *
2056+ * This program is distributed in the hope that it will be useful, but
2057+ * WITHOUT ANY WARRANTY; without even the implied warranties of
2058+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2059+ * PURPOSE. See the GNU General Public License for more details.
2060+ *
2061+ * You should have received a copy of the GNU General Public License along
2062+ * with this program. If not, see <http://www.gnu.org/licenses/>.
2063+ *
2064+ * Authors:
2065+ * Charles Kerr <charles.kerr@canonical.com>
2066+ */
2067+
2068+#include "glib-fixture.h"
2069+
2070+#include <transfer/controller.h>
2071+#include <transfer/plugin-source.h>
2072+
2073+using namespace unity::indicator::transfer;
2074+
2075+class PluginFixture: public GlibFixture
2076+{
2077+private:
2078+
2079+ typedef GlibFixture super;
2080+
2081+protected:
2082+
2083+ GTestDBus* bus = nullptr;
2084+
2085+ std::shared_ptr<MutableModel> m_model;
2086+ std::shared_ptr<Source> m_source;
2087+ std::shared_ptr<Controller> m_controller;
2088+
2089+ void SetUp()
2090+ {
2091+ super::SetUp();
2092+
2093+ auto plugin_dir = g_get_current_dir();
2094+ m_source.reset(new PluginSource(plugin_dir));
2095+ m_model = m_source->get_model();
2096+ m_controller.reset(new Controller(m_model, m_source));
2097+ g_clear_pointer(&plugin_dir, g_free);
2098+ }
2099+
2100+ void TearDown()
2101+ {
2102+ m_controller.reset();
2103+ m_model.reset();
2104+ m_source.reset();
2105+
2106+ super::TearDown();
2107+ }
2108+};
2109+
2110+TEST_F(PluginFixture, MockSourcePluginLoads)
2111+{
2112+ // confirms that the fixture loads MockSourcePlugin
2113+}
2114+
2115
2116=== modified file 'tests/test-view-gmenu.cpp'
2117--- tests/test-view-gmenu.cpp 2014-10-03 21:08:41 +0000
2118+++ tests/test-view-gmenu.cpp 2015-08-13 14:17:16 +0000
2119@@ -19,7 +19,7 @@
2120
2121 #include "glib-fixture.h"
2122 #include "controller-mock.h"
2123-#include "world-mock.h"
2124+#include "source-mock.h"
2125
2126 #include <transfer/dbus-shared.h>
2127 #include <transfer/view-gmenu.h>
2128@@ -36,7 +36,7 @@
2129 protected:
2130
2131 GTestDBus* bus = nullptr;
2132- std::shared_ptr<MockWorld> m_world;
2133+ std::shared_ptr<MockSource> m_source;
2134 std::shared_ptr<MutableModel> m_model;
2135 std::shared_ptr<MockController> m_controller;
2136 std::shared_ptr<GMenuView> m_view;
2137@@ -52,8 +52,8 @@
2138 g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);
2139 g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
2140
2141- // bring up the world
2142- m_world.reset(new MockWorld);
2143+ // bring up the source
2144+ m_source.reset(new MockSource);
2145 m_model.reset(new MutableModel);
2146 std::shared_ptr<Transfer> t;
2147 t.reset(new Transfer);
2148@@ -68,17 +68,17 @@
2149 t->id = "c";
2150 t->state = Transfer::FINISHED;
2151 m_model->add(t);
2152- m_controller.reset(new MockController(m_model, m_world));
2153+ m_controller.reset(new MockController(m_model, m_source));
2154 m_view.reset(new GMenuView(m_model, m_controller));
2155 }
2156
2157 void TearDown()
2158 {
2159- // empty the world
2160+ // empty the source
2161 m_view.reset();
2162 m_controller.reset();
2163 m_model.reset();
2164- m_world.reset();
2165+ m_source.reset();
2166
2167 // bring down the bus
2168 GError * error = nullptr;

Subscribers

People subscribed via source and target branches