Merge lp:~dobey/ubuntuone-client/services-enablement into lp:ubuntuone-client

Proposed by dobey
Status: Merged
Approved by: Tim Cole
Approved revision: 441
Merged at revision: not available
Proposed branch: lp:~dobey/ubuntuone-client/services-enablement
Merge into: lp:ubuntuone-client
Diff against target: 396 lines (+212/-17)
8 files modified
bin/ubuntuone-preferences (+117/-17)
bin/ubuntuone-syncdaemon (+4/-0)
data/syncdaemon.conf (+5/-0)
tests/syncdaemon/test_config.py (+15/-0)
tests/test_preferences.py (+14/-0)
ubuntuone/syncdaemon/config.py (+9/-0)
ubuntuone/syncdaemon/dbus_interface.py (+16/-0)
ubuntuone/syncdaemon/tools.py (+32/-0)
To merge this branch: bzr merge lp:~dobey/ubuntuone-client/services-enablement
Reviewer Review Type Date Requested Status
Tim Cole (community) Approve
Rick McBride (community) Approve
Review via email: mp+21994@code.launchpad.net

Commit message

Hook up the files/music sync toggle buttons to work
Add the "News" checkbox for toggling sync of gwibber messages
Store the file sync enabled config in the config file
Add dbus methods and SyncDaemonTool methods to query/set the files sync config
Add the necessary code to toggle syncing of dbs in desktopcouch

To post a comment you must log in.
Revision history for this message
Rick McBride (rmcbride) wrote :

Go Go Gadget Service Tab!

review: Approve
Revision history for this message
Tim Cole (tcole) :
review: Approve
442. By dobey

Fix potential NameError when desktopcouch is not available/installed

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/ubuntuone-preferences'
2--- bin/ubuntuone-preferences 2010-03-17 21:45:23 +0000
3+++ bin/ubuntuone-preferences 2010-03-24 17:49:27 +0000
4@@ -50,10 +50,17 @@
5 handler.setLevel(logging.DEBUG)
6 logger.addHandler(handler)
7
8+_ = gettext.gettext
9+
10+dcouch = None
11+# Try importing the Ubuntu One desktopcouch enablement api
12+try:
13+ from desktopcouch.replication_services import ubuntuone as dcouch
14+except ImportError:
15+ logger.error(_("DesktopCouch replication API not found"))
16+
17 DBusGMainLoop(set_as_default=True)
18
19-_ = gettext.gettext
20-
21 DBUS_IFACE_NAME = "com.ubuntuone.SyncDaemon"
22 DBUS_IFACE_CONFIG_NAME = DBUS_IFACE_NAME + ".Config"
23 DBUS_IFACE_STATUS_NAME = DBUS_IFACE_NAME + ".Status"
24@@ -61,6 +68,9 @@
25 DBUS_IFACE_AUTH_NAME = "com.ubuntuone.Authentication"
26 DBUS_IFACE_AUTH_PATH = "/"
27
28+# This is where thy music lies
29+U1MSPATH = os.path.expanduser("~/.ubuntuone/Purchased from Ubuntu One")
30+
31 # Why thank you GTK+ for enforcing style-set and breaking API
32 RCSTYLE = """
33 style 'dialogs' {
34@@ -443,6 +453,12 @@
35 self.connect("close", self.__handle_response, gtk.RESPONSE_CLOSE)
36 self.connect("response", self.__handle_response)
37
38+ # desktopcouch ReplicationExclusion, or None
39+ self.dcouch = None
40+
41+ # folder id for dealing with the Music folder
42+ self.ums_id = None
43+
44 self.__bus = dbus.SessionBus()
45 self.keyring = keyring
46
47@@ -551,34 +567,113 @@
48 keyring=self.keyring,
49 callback=self.got_account_info)
50
51+ def connect_desktopcouch_exclusion(self):
52+ """Hook up to desktopcouch enablement API, or disable the UI."""
53+ # Hook up to desktopcouch, or die trying
54+ if dcouch:
55+ self.dcouch = dcouch.ReplicationExclusion()
56+ exclusions = self.dcouch.all_exclusions()
57+ for check in [self.bookmarks_check,
58+ self.abook_check,
59+ self.gwib_check]:
60+ if check.get_data('dbname') in exclusions:
61+ check.set_active(False)
62+ else:
63+ check.set_active(True)
64+ else:
65+ self.bookmarks_check.set_sensitive(False)
66+ self.abook_check.set_sensitive(False)
67+ self.gwib_check.set_sensitive(False)
68+
69 def toggle_db_sync(self, dbname, disable=False):
70 """
71 Toggle whether a db in desktopcouch is synchronized to the
72 Ubuntu One couchdb server.
73 """
74- # FIXME: Actually enable/disable the dbs if desktopcouch exists
75+ if self.dcouch:
76+ if disable:
77+ self.dcouch.exclude(dbname)
78+ else:
79+ self.dcouch.replicate(dbname)
80+ else:
81+ logger.error(_("Database enablement is unavailable."))
82
83 def __db_check_toggled(self, checkbutton):
84 """Handle toggling a desktopcouch service toggling."""
85 dbname = checkbutton.get_data('dbname')
86 self.toggle_db_sync(dbname, not checkbutton.get_active())
87
88- def __files_check_toggled(self, checkbutton):
89+ def files_check_toggled(self, checkbutton):
90 """Handle toggling the files service."""
91- enable = checkbutton.get_active()
92- if enable:
93- self.music_check.set_sensitive(True)
94- if self.music_check.get_active():
95- self.__music_check_toggled(self.music_check)
96+ enabled = checkbutton.get_active()
97+ self.sdtool.enable_files_sync(enabled).addCallbacks(
98+ lambda _: dbus_async,
99+ self.__sd_error)
100+ def sd_error(error):
101+ self.files_check.set_active(False)
102+ self.files_check.set_sensitive(False)
103+ self.music_check.set_sensitive(False)
104+ self.__sd_error(error)
105+
106+ if enabled:
107+ self.sdtool.start().addErrback(sd_error)
108+ if self.ums_id:
109+ self.music_check.set_sensitive(True)
110+ if self.music_check.get_active():
111+ self.__music_check_toggled(self.music_check)
112 else:
113+ self.sdtool.quit()
114 self.music_check.set_sensitive(False)
115- # FIXME: Actually stop or start ubuntuone-syncdaemon
116
117- def __music_check_toggled(self, checkbutton):
118+ def music_check_toggled(self, checkbutton):
119 """Handle toggling the music download service."""
120- if not self.files_check.get_active():
121+ if not self.files_check.get_active() or not self.ums_id:
122 return
123- # FIXME: Actually subscribe or unsubscribe to the UDF
124+ enabled = checkbutton.get_active()
125+ def got_error(error):
126+ checkbutton.set_sensitive(False)
127+ checkbutton.set_active(not enabled)
128+ self.__sd_error(error)
129+
130+ if enabled:
131+ d = self.sdtool.subscribe_folder(self.ums_id)
132+ else:
133+ d = self.sdtool.unsubscribe_folder(self.ums_id)
134+ d.addErrback(got_error)
135+
136+ def get_syncdaemon_sync_config(self):
137+ """Update the files/music sync config from syncdaemon."""
138+ def got_fs_err(error):
139+ self.files_check.set_sensitive(False)
140+ self.music_check.set_sensitive(False)
141+ self.__sd_error(error)
142+
143+ def got_ms_err(error):
144+ self.music_check.set_sensitive(False)
145+ self.__sd_error(error)
146+
147+ def got_info(info):
148+ if not info:
149+ self.music_check.set_active(False)
150+ self.music_check.set_sensitive(False)
151+ else:
152+ self.ums_id = info['volume_id']
153+ self.music_check.set_sensitive(True)
154+ if info['subscribed'] == 'True':
155+ self.music_check.set_active(True)
156+ else:
157+ self.music_check.set_active(False)
158+
159+ def got_fs(enabled):
160+ self.files_check.set_active(enabled)
161+
162+ self.sdtool.get_folder_info(U1MSPATH).addCallbacks(got_info, got_ms_err)
163+ self.sdtool.is_files_sync_enabled().addCallbacks(got_fs, got_fs_err)
164+
165+ def connect_file_sync_callbacks(self):
166+ """Connect the file sync checkbox callbacks."""
167+ self.files_check.connect('toggled', self.files_check_toggled)
168+ self.music_check.connect('toggled', self.music_check_toggled)
169
170 def __construct(self):
171 """Construct the dialog's layout."""
172@@ -679,8 +774,6 @@
173 services.set_border_width(6)
174 self.notebook.append_page(services)
175 self.notebook.set_tab_label_text(services, _("Services"))
176- # FIXME: These are all disabled for the moment
177- services.set_sensitive(False)
178 services.show()
179
180 self.bookmarks_check = gtk.CheckButton(_("_Bookmarks"))
181@@ -695,13 +788,18 @@
182 services.pack_start(self.abook_check, False, False)
183 self.abook_check.show()
184
185+ self.gwib_check = gtk.CheckButton(_("_News"))
186+ self.gwib_check.set_data('dbname', 'gwibber_messages')
187+ self.gwib_check.connect('toggled', self.__db_check_toggled)
188+ services.pack_start(self.gwib_check, False, False)
189+ self.gwib_check.show()
190+
191 fbox = gtk.VBox(spacing=6)
192 services.pack_start(fbox, False, False)
193 fbox.show()
194
195 self.files_check = gtk.CheckButton(_("_File Synchronization"))
196 self.files_check.set_active(True)
197- self.files_check.connect('toggled', self.__files_check_toggled)
198 fbox.pack_start(self.files_check, False, False)
199 self.files_check.show()
200
201@@ -712,7 +810,6 @@
202
203 self.music_check = gtk.CheckButton(_("_Music Download"))
204 self.music_check.set_active(True)
205- self.music_check.connect('toggled', self.__music_check_toggled)
206 alignment.add(self.music_check)
207 self.music_check.show()
208
209@@ -731,6 +828,9 @@
210 """Show our dialog, since we can do stuff now."""
211 self.disconnect_signal_handlers()
212 dialog = UbuntuOneDialog()
213+ dialog.connect_desktopcouch_exclusion()
214+ dialog.get_syncdaemon_sync_config()
215+ dialog.connect_file_sync_callbacks()
216 dialog.show()
217 dialog.request_quota_info()
218 dialog.request_account_info()
219
220=== modified file 'bin/ubuntuone-syncdaemon'
221--- bin/ubuntuone-syncdaemon 2010-03-19 14:28:40 +0000
222+++ bin/ubuntuone-syncdaemon 2010-03-24 17:49:27 +0000
223@@ -89,6 +89,10 @@
224 if is_already_running():
225 die('Another instance is running')
226
227+ # check if the user disabled files sync
228+ if not config.get_user_config().get_files_sync_enabled():
229+ die('Files synchronization is disabled.')
230+
231 # check if we are using xdg_data_home and it doesn't exists
232 if xdg_data_home in options.data_dir and \
233 not os.path.exists(options.data_dir):
234
235=== modified file 'data/syncdaemon.conf'
236--- data/syncdaemon.conf 2010-03-19 14:47:36 +0000
237+++ data/syncdaemon.conf 2010-03-24 17:49:27 +0000
238@@ -14,6 +14,11 @@
239 port.parser = int
240 port.help = The port on which to connect to the server
241
242+files_sync_enabled.default = True
243+files_sync_enabled.action = store_true
244+files_sync_enabled.parser = bool
245+files_sync_enabled.help = Toggles synchronization of files (False disables syncdaemon entirely)
246+
247 root_dir.default = ~/Ubuntu One
248 root_dir.parser = home_dir
249 root_dir.help = Use the specified directory as the root
250
251=== modified file 'tests/syncdaemon/test_config.py'
252--- tests/syncdaemon/test_config.py 2010-03-18 21:41:02 +0000
253+++ tests/syncdaemon/test_config.py 2010-03-24 17:49:27 +0000
254@@ -395,6 +395,21 @@
255 conf.read(config.get_user_config().config_file)
256 self.assertEquals(conf.get(config.THROTTLING, 'on'), 'False')
257
258+ def test_files_sync_enabled(self):
259+ """Test for toggling files sync."""
260+ dbus_config = self.main.dbus_iface.config
261+ enabled = dbus_config.files_sync_enabled()
262+ self.assertTrue(enabled)
263+ dbus_config.set_files_sync_enabled(False)
264+ enabled = dbus_config.files_sync_enabled()
265+ self.assertFalse(enabled)
266+ dbus_config.set_files_sync_enabled(True)
267+ enabled = dbus_config.files_sync_enabled()
268+ self.assertTrue(enabled)
269+ conf = ConfigParser()
270+ conf.read(config.get_user_config().config_file)
271+ self.assertEquals(conf.get(config.MAIN, 'files_sync_enabled'), 'True')
272+
273
274 class SyncDaemonConfigParserTests(BaseTwistedTestCase):
275 """Tests for SyncDaemonConfigParser"""
276
277=== modified file 'tests/test_preferences.py'
278--- tests/test_preferences.py 2010-03-12 16:07:24 +0000
279+++ tests/test_preferences.py 2010-03-24 17:49:27 +0000
280@@ -289,6 +289,20 @@
281 self.mocker.replay()
282 dialog = self.u1prefs.UbuntuOneDialog(keyring=self.keyring)
283 self.assertTrue(dialog is not None)
284+ def files_toggled(checkbutton):
285+ enabled = checkbutton.get_active()
286+ if enabled:
287+ dialog.music_check.set_sensitive(True)
288+ else:
289+ dialog.music_check.set_sensitive(False)
290+
291+ def music_toggled(checkbutton):
292+ pass
293+
294+ dialog.files_check_toggled = files_toggled
295+ dialog.music_check_toggled = music_toggled
296+ dialog.connect_file_sync_callbacks()
297+
298 dialog.files_check.set_active(False)
299 self.assertFalse(dialog.files_check.get_active())
300 self.assertFalse(dialog.music_check.props.sensitive)
301
302=== modified file 'ubuntuone/syncdaemon/config.py'
303--- ubuntuone/syncdaemon/config.py 2010-02-24 13:20:25 +0000
304+++ ubuntuone/syncdaemon/config.py 2010-03-24 17:49:27 +0000
305@@ -311,6 +311,15 @@
306 def get_udf_autosubscribe(self):
307 return self.get_parsed(MAIN, 'udf_autosubscribe')
308
309+ # files sync enablement get/set
310+ @requires_section(MAIN)
311+ def set_files_sync_enabled(self, enabled):
312+ self.set(MAIN, 'files_sync_enabled', str(enabled))
313+
314+ @requires_section(MAIN)
315+ def get_files_sync_enabled(self):
316+ return self.get_parsed(MAIN, 'files_sync_enabled')
317+
318
319 def configglue(fileobj, *filenames, **kwargs):
320 """Populate an OptionParser with options and defaults taken from a
321
322=== modified file 'ubuntuone/syncdaemon/dbus_interface.py'
323--- ubuntuone/syncdaemon/dbus_interface.py 2010-03-10 22:12:06 +0000
324+++ ubuntuone/syncdaemon/dbus_interface.py 2010-03-24 17:49:27 +0000
325@@ -1183,6 +1183,22 @@
326 user_config.set_udf_autosubscribe(False)
327 user_config.save()
328
329+ @dbus.service.method(DBUS_IFACE_CONFIG_NAME,
330+ in_signature='b', out_signature='')
331+ def set_files_sync_enabled(self, enabled):
332+ """Enable UDF autosubscribe."""
333+ logger.debug('called set_files_sync_enabled %d', enabled)
334+ user_config = config.get_user_config()
335+ user_config.set_files_sync_enabled(enabled)
336+ user_config.save()
337+
338+ @dbus.service.method(DBUS_IFACE_CONFIG_NAME,
339+ in_signature='', out_signature='b')
340+ def files_sync_enabled(self):
341+ logger.debug('called files_sync_enabled')
342+ """Return the udf_autosubscribe config value."""
343+ return config.get_user_config().get_files_sync_enabled()
344+
345
346 class Folders(DBusExposedObject):
347 """A dbus interface to interact with User Defined Folders"""
348
349=== modified file 'ubuntuone/syncdaemon/tools.py'
350--- ubuntuone/syncdaemon/tools.py 2010-03-09 22:13:42 +0000
351+++ ubuntuone/syncdaemon/tools.py 2010-03-24 17:49:27 +0000
352@@ -470,6 +470,16 @@
353 error_handler=d.errback)
354 return d
355
356+ def get_folder_info(self, path):
357+ """Call the get_info method for a UDF path."""
358+ self.log.debug('get_info')
359+ client = DBusClient(self.bus, '/folders', DBUS_IFACE_FOLDERS_NAME)
360+ d = defer.Deferred()
361+ client.call_method('get_info', path,
362+ reply_handler=d.callback,
363+ error_handler=d.errback)
364+ return d
365+
366 def query_by_path(self, path):
367 """requesting a query of the node idetifiend by 'path' to the server."""
368 self.log.debug('query_by_path(%s)', path)
369@@ -691,6 +701,28 @@
370 error_handler=d.errback)
371 return d
372
373+ def is_files_sync_enabled(self):
374+ """Check if files sync is enabled."""
375+ self.log.debug('is_files_sync_enabled')
376+ d = defer.Deferred()
377+ config_client = DBusClient(self.bus, '/config',
378+ DBUS_IFACE_CONFIG_NAME)
379+ config_client.call_method('files_sync_enabled',
380+ reply_handler=d.callback,
381+ error_handler=d.errback)
382+ return d
383+
384+ def enable_files_sync(self, enabled):
385+ """Enable/disable files sync."""
386+ self.log.debug('enable_files_sync %d', enabled)
387+ d = defer.Deferred()
388+ config_client = DBusClient(self.bus, '/config',
389+ DBUS_IFACE_CONFIG_NAME)
390+ config_client.call_method('set_files_sync_enabled',
391+ reply_handler=d.callback,
392+ error_handler=d.errback)
393+ return d
394+
395
396 # callbacks used by u1sdtool script
397

Subscribers

People subscribed via source and target branches