Merge lp:~nataliabidart/ubuntu/precise/ubuntuone-control-panel/ubuntuone-control-panel-2.99.2 into lp:ubuntu/precise/ubuntuone-control-panel

Proposed by Natalia Bidart on 2012-01-17
Status: Merged
Merged at revision: 38
Proposed branch: lp:~nataliabidart/ubuntu/precise/ubuntuone-control-panel/ubuntuone-control-panel-2.99.2
Merge into: lp:ubuntu/precise/ubuntuone-control-panel
Diff against target: 463 lines (+306/-13)
13 files modified
PKG-INFO (+1/-1)
debian/changelog (+9/-0)
debian/control (+6/-6)
debian/watch (+1/-1)
setup.py (+1/-1)
ubuntuone/controlpanel/gui/qt/devices.py (+1/-0)
ubuntuone/controlpanel/gui/qt/main/__init__.py (+4/-4)
ubuntuone/controlpanel/gui/qt/tests/test_devices.py (+22/-0)
ubuntuone/controlpanel/gui/qt/uniqueapp/__init__.py (+28/-0)
ubuntuone/controlpanel/gui/qt/uniqueapp/linux.py (+29/-0)
ubuntuone/controlpanel/gui/qt/uniqueapp/tests/__init__.py (+17/-0)
ubuntuone/controlpanel/gui/qt/uniqueapp/tests/test_windows.py (+135/-0)
ubuntuone/controlpanel/gui/qt/uniqueapp/windows.py (+52/-0)
To merge this branch: bzr merge lp:~nataliabidart/ubuntu/precise/ubuntuone-control-panel/ubuntuone-control-panel-2.99.2
Reviewer Review Type Date Requested Status
Ubuntu Sponsors Team 2012-01-17 Pending
Review via email: mp+88925@code.launchpad.net

Commit Message

* New upstream release.
* debian/watch: updated to latest active milestone.
* debian/control: updating ubuntu-sso-client and ubuntuone-client depends version to 2.99.2.

To post a comment you must log in.
Sebastien Bacher (seb128) wrote :

Thank you for your work, I will upload it once the new ubuntuone-client is uploaded

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'PKG-INFO'
2--- PKG-INFO 2012-01-03 19:04:19 +0000
3+++ PKG-INFO 2012-01-17 19:42:43 +0000
4@@ -1,6 +1,6 @@
5 Metadata-Version: 1.1
6 Name: ubuntuone-control-panel
7-Version: 2.99.1
8+Version: 2.99.2
9 Summary: Ubuntu One Control Panel
10 Home-page: https://launchpad.net/ubuntuone-control-panel
11 Author: Natalia Bidart
12
13=== modified file 'debian/changelog'
14--- debian/changelog 2012-01-04 12:42:44 +0000
15+++ debian/changelog 2012-01-17 19:42:43 +0000
16@@ -1,3 +1,12 @@
17+ubuntuone-control-panel (2.99.2-0ubuntu1) UNRELEASED; urgency=low
18+
19+ * New upstream release.
20+ * debian/watch: updated to latest active milestone.
21+ * debian/control: updating ubuntu-sso-client and ubuntuone-client depends
22+ version to 2.99.2.
23+
24+ -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Tue, 17 Jan 2012 16:29:03 -0300
25+
26 ubuntuone-control-panel (2.99.1-0ubuntu1) precise; urgency=low
27
28 * New upstream release.
29
30=== modified file 'debian/control'
31--- debian/control 2012-01-03 19:38:15 +0000
32+++ debian/control 2012-01-17 19:42:43 +0000
33@@ -17,7 +17,7 @@
34 ${python:Depends},
35 python,
36 python-ubuntuone-control-panel (= ${binary:Version}),
37- ubuntuone-client (>= 2.99.1),
38+ ubuntuone-client (>= 2.99.2),
39 Recommends: ubuntuone-control-panel-gui
40 Description: Ubuntu One Control Panel
41 Desktop application to manage an Ubuntu One account.
42@@ -37,8 +37,8 @@
43 python-simplejson,
44 python-twisted-core,
45 python-twisted-web,
46- python-ubuntuone-client (>= 2.99.1),
47- ubuntu-sso-client (>= 2.99.1),
48+ python-ubuntuone-client (>= 2.99.2),
49+ ubuntu-sso-client (>= 2.99.2),
50 Description: Ubuntu One Control Panel Python Libraries
51 Ubuntu One Control Panel provides a Python library to manage an Ubuntu One
52 account.
53@@ -55,9 +55,9 @@
54 python-defer | python-aptdaemon,
55 python-gobject (>= 2.21.5),
56 python-gtk2,
57- python-ubuntuone-client (>= 2.99.1),
58- ubuntu-sso-client (>= 2.99.1),
59- ubuntuone-client (>= 2.99.1),
60+ python-ubuntuone-client (>= 2.99.2),
61+ ubuntu-sso-client (>= 2.99.2),
62+ ubuntuone-client (>= 2.99.2),
63 ubuntuone-control-panel (= ${binary:Version}),
64 ubuntuone-installer (>= 2.0.0),
65 Provides: ubuntuone-control-panel-gui
66
67=== modified file 'debian/watch'
68--- debian/watch 2012-01-03 19:03:54 +0000
69+++ debian/watch 2012-01-17 19:42:43 +0000
70@@ -1,2 +1,2 @@
71 version=3
72-http://launchpad.net/ubuntuone-control-panel/stable-3-0/2.99.1 .*/ubuntuone-control-panel-([0-9.]+)\.tar\.gz
73+http://launchpad.net/ubuntuone-control-panel/stable-3-0/2.99.2 .*/ubuntuone-control-panel-([0-9.]+)\.tar\.gz
74
75=== modified file 'setup.py'
76--- setup.py 2012-01-03 19:04:19 +0000
77+++ setup.py 2012-01-17 19:42:43 +0000
78@@ -229,7 +229,7 @@
79
80 DistUtilsExtra.auto.setup(
81 name='ubuntuone-control-panel',
82- version='2.99.1',
83+ version='2.99.2',
84 license='GPL v3',
85 author='Natalia Bidart',
86 author_email='natalia.bidart@canonical.com',
87
88=== modified file 'ubuntuone/controlpanel/gui/qt/devices.py'
89--- ubuntuone/controlpanel/gui/qt/devices.py 2011-12-20 18:12:36 +0000
90+++ ubuntuone/controlpanel/gui/qt/devices.py 2012-01-17 19:42:43 +0000
91@@ -81,6 +81,7 @@
92 for i in reversed(range(children)):
93 widget = box.itemAt(i).widget()
94 box.removeWidget(widget)
95+ widget.deleteLater()
96
97 def update_device_info(self, device_info):
98 """Update one device."""
99
100=== modified file 'ubuntuone/controlpanel/gui/qt/main/__init__.py'
101--- ubuntuone/controlpanel/gui/qt/main/__init__.py 2011-12-20 18:12:36 +0000
102+++ ubuntuone/controlpanel/gui/qt/main/__init__.py 2012-01-17 19:42:43 +0000
103@@ -18,13 +18,11 @@
104
105 import sys
106
107-from PyQt4 import QtGui
108-
109 # Module used to include the resources into this file
110 # Unused import images_rc, pylint: disable=W0611
111 from ubuntuone.controlpanel.gui.qt.ui import images_rc
112 # pylint: enable=W0611
113-
114+from ubuntuone.controlpanel.gui.qt.uniqueapp import UniqueApplication
115
116 # Invalid name "source", pylint: disable=C0103
117 if sys.platform == 'win32':
118@@ -42,7 +40,7 @@
119 # because u1trial already provides a reactor.
120
121 # The main loop MUST be initialized before importing the reactor
122- app = QtGui.QApplication(sys.argv)
123+ app = UniqueApplication(sys.argv, "ubuntuone-control-panel")
124 source.main(app)
125
126 # Reimport 'qt4reactor', 'reactor', 'start', pylint: disable=W0404, F0401
127@@ -59,6 +57,8 @@
128 icon, window = start(reactor.stop,
129 minimized=minimized, with_icon=with_icon)
130 # pylint: enable=W0612
131+ if icon:
132+ app.new_instance.connect(icon.restore_window)
133
134 reactor.run()
135 # pylint: enable=E1101
136
137=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py'
138--- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-12-20 18:12:36 +0000
139+++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2012-01-17 19:42:43 +0000
140@@ -35,6 +35,7 @@
141 innerclass_ui = gui.devices_ui
142 innerclass_name = "Ui_Form"
143 class_ui = gui.DevicesPanel
144+ executed = False
145
146 @defer.inlineCallbacks
147 def setUp(self):
148@@ -88,6 +89,27 @@
149 device = self.ui.ui.list_devices.itemWidget(item)
150 self.assertEqual(device.text(), remote_device['name'])
151
152+ def test_remove_device_and_check_layout_state(self):
153+ """Test if the widget is properly removed."""
154+ self.ui.process_info(SAMPLE_DEVICES_INFO)
155+ self.ui.show()
156+
157+ self.assertEqual(self.ui.ui.local_device_box.count(), 1)
158+ local_device = self.ui.ui.local_device_box.itemAt(0).widget()
159+ self.executed = False
160+
161+ def delete_later(reference=None):
162+ """Fake delete later."""
163+ self.executed = True
164+ self.patch(local_device, "deleteLater", delete_later)
165+ self.ui.clear_device_info(self.ui.ui.local_device_box)
166+ self.ui.process_info(SAMPLE_DEVICES_INFO)
167+ self.assertEqual(self.ui.ui.local_device_box.count(), 1)
168+ local_device2 = self.ui.ui.local_device_box.itemAt(0).widget()
169+ self.assertNotEqual(local_device, local_device2)
170+ self.assertTrue(self.executed)
171+ self.assertFalse(local_device.isVisible())
172+
173 def test_process_info_twice(self):
174 """The widget is updated with the info."""
175 self.test_process_info()
176
177=== added directory 'ubuntuone/controlpanel/gui/qt/uniqueapp'
178=== added file 'ubuntuone/controlpanel/gui/qt/uniqueapp/__init__.py'
179--- ubuntuone/controlpanel/gui/qt/uniqueapp/__init__.py 1970-01-01 00:00:00 +0000
180+++ ubuntuone/controlpanel/gui/qt/uniqueapp/__init__.py 2012-01-17 19:42:43 +0000
181@@ -0,0 +1,28 @@
182+# -*- coding: utf-8 -*-
183+#
184+# Copyright 2011 Canonical Ltd.
185+#
186+# This program is free software: you can redistribute it and/or modify it
187+# under the terms of the GNU General Public License version 3, as published
188+# by the Free Software Foundation.
189+#
190+# This program is distributed in the hope that it will be useful, but
191+# WITHOUT ANY WARRANTY; without even the implied warranties of
192+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
193+# PURPOSE. See the GNU General Public License for more details.
194+#
195+# You should have received a copy of the GNU General Public License along
196+# with this program. If not, see <http://www.gnu.org/licenses/>.
197+
198+"""A QApplication that starts a single instance."""
199+
200+#pylint: disable=W0404
201+import sys
202+
203+if sys.platform == "win32":
204+ import windows as platform
205+else:
206+ import linux as platform
207+
208+#pylint: disable=C0103
209+UniqueApplication = platform.UniqueApplication
210
211=== added file 'ubuntuone/controlpanel/gui/qt/uniqueapp/linux.py'
212--- ubuntuone/controlpanel/gui/qt/uniqueapp/linux.py 1970-01-01 00:00:00 +0000
213+++ ubuntuone/controlpanel/gui/qt/uniqueapp/linux.py 2012-01-17 19:42:43 +0000
214@@ -0,0 +1,29 @@
215+# -*- coding: utf-8 -*-
216+#
217+# Copyright 2011 Canonical Ltd.
218+#
219+# This program is free software: you can redistribute it and/or modify it
220+# under the terms of the GNU General Public License version 3, as published
221+# by the Free Software Foundation.
222+#
223+# This program is distributed in the hope that it will be useful, but
224+# WITHOUT ANY WARRANTY; without even the implied warranties of
225+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
226+# PURPOSE. See the GNU General Public License for more details.
227+#
228+# You should have received a copy of the GNU General Public License along
229+# with this program. If not, see <http://www.gnu.org/licenses/>.
230+
231+"""A QApplication that starts a single instance."""
232+
233+from PyQt4 import QtGui, QtCore
234+
235+
236+class UniqueApplication(QtGui.QApplication):
237+
238+ """A dummy UniqueApplication class."""
239+
240+ new_instance = QtCore.pyqtSignal()
241+
242+ def __init__(self, argv, key):
243+ super(UniqueApplication, self).__init__(argv)
244
245=== added directory 'ubuntuone/controlpanel/gui/qt/uniqueapp/tests'
246=== added file 'ubuntuone/controlpanel/gui/qt/uniqueapp/tests/__init__.py'
247--- ubuntuone/controlpanel/gui/qt/uniqueapp/tests/__init__.py 1970-01-01 00:00:00 +0000
248+++ ubuntuone/controlpanel/gui/qt/uniqueapp/tests/__init__.py 2012-01-17 19:42:43 +0000
249@@ -0,0 +1,17 @@
250+# -*- coding: utf-8 -*-
251+#
252+# Copyright 2011-2012 Canonical Ltd.
253+#
254+# This program is free software: you can redistribute it and/or modify it
255+# under the terms of the GNU General Public License version 3, as published
256+# by the Free Software Foundation.
257+#
258+# This program is distributed in the hope that it will be useful, but
259+# WITHOUT ANY WARRANTY; without even the implied warranties of
260+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
261+# PURPOSE. See the GNU General Public License for more details.
262+#
263+# You should have received a copy of the GNU General Public License along
264+# with this program. If not, see <http://www.gnu.org/licenses/>.
265+
266+"""Tests for the UniqueApplication class."""
267
268=== added file 'ubuntuone/controlpanel/gui/qt/uniqueapp/tests/test_windows.py'
269--- ubuntuone/controlpanel/gui/qt/uniqueapp/tests/test_windows.py 1970-01-01 00:00:00 +0000
270+++ ubuntuone/controlpanel/gui/qt/uniqueapp/tests/test_windows.py 2012-01-17 19:42:43 +0000
271@@ -0,0 +1,135 @@
272+# -*- coding: utf-8 -*-
273+#
274+# Copyright 2011-2012 Canonical Ltd.
275+#
276+# This program is free software: you can redistribute it and/or modify it
277+# under the terms of the GNU General Public License version 3, as published
278+# by the Free Software Foundation.
279+#
280+# This program is distributed in the hope that it will be useful, but
281+# WITHOUT ANY WARRANTY; without even the implied warranties of
282+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
283+# PURPOSE. See the GNU General Public License for more details.
284+#
285+# You should have received a copy of the GNU General Public License along
286+# with this program. If not, see <http://www.gnu.org/licenses/>.
287+
288+"""Tests for the UniqueApplication class."""
289+
290+from PyQt4 import QtCore
291+from twisted.internet.defer import inlineCallbacks
292+
293+from ubuntuone.controlpanel.gui.qt.uniqueapp import windows as uniqueapp
294+from ubuntuone.controlpanel.tests import TestCase
295+
296+
297+#pylint: disable=C0103
298+class FakeLocalSocket(object):
299+ """A fake QLocalSocket."""
300+
301+ def __init__(self):
302+ self.connect_calls = []
303+ self.connect_timeouts = []
304+ self.connect_succeeds = True
305+
306+ def connectToServer(self, *args, **kwargs):
307+ """Fake connectToServer."""
308+ self.connect_calls.append((args, kwargs))
309+
310+ def waitForConnected(self, timeout):
311+ """Fake waitForConnected."""
312+ self.connect_timeouts.append(timeout)
313+ return self.connect_succeeds
314+
315+
316+class FakeSignal(object):
317+
318+ """A fake PyQt signal."""
319+
320+ def __init__(self, *args, **kwargs):
321+ """Initialize."""
322+ self.target = None
323+
324+ def connect(self, target):
325+ """Fake connect."""
326+ self.target = target
327+
328+ def disconnect(self, *args):
329+ """Fake disconnect."""
330+ self.target = None
331+
332+ def emit(self, *args):
333+ """Fake emit."""
334+ if self.target:
335+ self.target(*args)
336+
337+
338+class FakeLocalServer(object):
339+
340+ """A fake QLocalServer."""
341+
342+ def __init__(self):
343+ self.newConnection = FakeSignal()
344+ self.listen_args = []
345+
346+ def listen(self, *args, **kwargs):
347+ """Fake listen."""
348+ self.listen_args.append((args, kwargs))
349+
350+
351+class FakeApplication(object):
352+ """A fake QApplication."""
353+
354+
355+class UniqueAppTestCase(TestCase):
356+ """Test the UniqueAppplication class."""
357+
358+ @inlineCallbacks
359+ def setUp(self):
360+ yield super(UniqueAppTestCase, self).setUp()
361+ self.local_socket = FakeLocalSocket()
362+ self.patch(uniqueapp.QtNetwork, "QLocalSocket",
363+ lambda: self.local_socket)
364+ self.local_server = FakeLocalServer()
365+ self.patch(uniqueapp.QtNetwork, "QLocalServer",
366+ lambda parent: self.local_server)
367+ self.patch(uniqueapp.sys, "exit", self._set_called)
368+ self.fake_quit = FakeSignal()
369+ self.patch(uniqueapp.UniqueApplication, "aboutToQuit", self.fake_quit)
370+ self.patch(uniqueapp.QtGui, "QApplication", FakeApplication)
371+
372+ def test_client_socket(self):
373+ """Check that the client socket is used correctly."""
374+ self.local_socket.connect_succeeds = True
375+ uniqueapp.UniqueApplication([], "key")
376+ self.assertEqual(self.local_socket.connect_calls,
377+ [(("key", QtCore.QIODevice.WriteOnly), {})])
378+ self.assertEqual(self.local_socket.connect_timeouts,
379+ [500])
380+ # The connection succeeds, so it should stop
381+ self.assertEqual(self._called, ((), {}))
382+
383+ def test_server_socket(self):
384+ """Check that the server socket is used correctly."""
385+ self.local_socket.connect_succeeds = False
386+ uniqueapp.UniqueApplication([], "key")
387+ self.assertEqual(self.local_socket.connect_calls,
388+ [(("key", QtCore.QIODevice.WriteOnly), {})])
389+ self.assertEqual(self.local_socket.connect_timeouts,
390+ [500])
391+
392+ # Should not exit
393+ self.assertEqual(self._called, False)
394+
395+ def test_signal_connection(self):
396+ """Check that new_instance is correctly connected."""
397+ app = uniqueapp.UniqueApplication([], "key")
398+ # Yes, this is ugly. I can't find any other meaningful
399+ # way to compare them though.
400+ self.assertEqual(str(app.server.newConnection.target.__self__),
401+ str(app.new_instance))
402+
403+ def test_cleanup(self):
404+ """Check that cleanup is called with the right key."""
405+ app = uniqueapp.UniqueApplication([], "key")
406+ self.assertEqual(self.fake_quit.target, app.cleanup)
407
408=== added file 'ubuntuone/controlpanel/gui/qt/uniqueapp/windows.py'
409--- ubuntuone/controlpanel/gui/qt/uniqueapp/windows.py 1970-01-01 00:00:00 +0000
410+++ ubuntuone/controlpanel/gui/qt/uniqueapp/windows.py 2012-01-17 19:42:43 +0000
411@@ -0,0 +1,52 @@
412+# -*- coding: utf-8 -*-
413+#
414+# Copyright 2011 Canonical Ltd.
415+#
416+# This program is free software: you can redistribute it and/or modify it
417+# under the terms of the GNU General Public License version 3, as published
418+# by the Free Software Foundation.
419+#
420+# This program is distributed in the hope that it will be useful, but
421+# WITHOUT ANY WARRANTY; without even the implied warranties of
422+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
423+# PURPOSE. See the GNU General Public License for more details.
424+#
425+# You should have received a copy of the GNU General Public License along
426+# with this program. If not, see <http://www.gnu.org/licenses/>.
427+
428+"""A QApplication that starts a single instance."""
429+
430+import sys
431+
432+from PyQt4 import QtNetwork, QtGui, QtCore
433+
434+
435+class UniqueApplication(QtGui.QApplication):
436+
437+ """A QApplication that can only be started once.
438+
439+ Also, the new instance notifies the old one to show
440+ its window.
441+ """
442+
443+ new_instance = QtCore.pyqtSignal()
444+
445+ def __init__(self, argv, key):
446+ super(UniqueApplication, self).__init__(argv)
447+ self.key = key
448+ self.server = QtNetwork.QLocalServer(self)
449+ self.server.newConnection.connect(self.new_instance.emit)
450+ self.aboutToQuit.connect(self.cleanup)
451+ # Try to connect to existing app
452+ socket = QtNetwork.QLocalSocket()
453+ socket.connectToServer(key, QtCore.QIODevice.WriteOnly)
454+ if socket.waitForConnected(500):
455+ # Connected, exit
456+ sys.exit()
457+
458+ # Not connected, start server
459+ self.ready = self.server.listen(key)
460+
461+ def cleanup(self):
462+ """Remove the socket when we die."""
463+ self.server.removeServer(self.key)

Subscribers

People subscribed via source and target branches