Merge lp:~nataliabidart/ubuntu/oneiric/ubuntuone-control-panel/ubuntuone-control-panel-2.0.0 into lp:ubuntu/oneiric/ubuntuone-control-panel
- Oneiric (11.10)
- ubuntuone-control-panel-2.0.0
- Merge into oneiric
Status: | Merged |
---|---|
Merged at revision: | 33 |
Proposed branch: | lp:~nataliabidart/ubuntu/oneiric/ubuntuone-control-panel/ubuntuone-control-panel-2.0.0 |
Merge into: | lp:ubuntu/oneiric/ubuntuone-control-panel |
Diff against target: |
30030 lines (+2419/-25703) 78 files modified
MANIFEST (+0/-140) PKG-INFO (+2/-21) bin/ubuntuone-control-panel-qt (+10/-1) data/gtk/overview.ui (+4/-29) data/gtk/services.ui (+16/-86) data/qt/account.ui (+23/-2) data/qt/controlpanel.ui (+228/-191) data/qt/images.qrc (+1/-0) data/qt/preferences.ui (+3/-3) data/qt/signin.ui (+203/-0) data/qt/ubuntuone.qss (+27/-5) debian/changelog (+29/-0) debian/control (+7/-7) debian/ubuntuone-control-panel-gtk.install (+0/-1) docs/ubuntuone-control-panel-gtk.1 (+2/-2) po/POTFILES.in (+0/-1) po/ubuntuone-control-panel.pot (+0/-486) setup.py (+2/-2) ubuntuone-control-panel-gtk.desktop.in (+0/-11) ubuntuone-control-panel.in (+1/-1) ubuntuone/controlpanel/backend.py (+24/-20) ubuntuone/controlpanel/cache.py (+50/-0) ubuntuone/controlpanel/dbus_service.py (+0/-40) ubuntuone/controlpanel/dbustests/test_dbus_service.py (+3/-34) ubuntuone/controlpanel/gui/__init__.py (+5/-5) ubuntuone/controlpanel/gui/gtk/gui.py (+9/-12) ubuntuone/controlpanel/gui/gtk/tests/__init__.py (+3/-3) ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py (+9/-1) ubuntuone/controlpanel/gui/qt/__init__.py (+57/-2) ubuntuone/controlpanel/gui/qt/account.py (+3/-0) ubuntuone/controlpanel/gui/qt/addfolder.py (+11/-9) ubuntuone/controlpanel/gui/qt/controlpanel.py (+73/-30) ubuntuone/controlpanel/gui/qt/device.py (+15/-6) ubuntuone/controlpanel/gui/qt/devices.py (+12/-7) ubuntuone/controlpanel/gui/qt/filesyncstatus.py (+7/-8) ubuntuone/controlpanel/gui/qt/folders.py (+25/-11) ubuntuone/controlpanel/gui/qt/gotoweb.py (+19/-5) ubuntuone/controlpanel/gui/qt/gui.py (+28/-5) ubuntuone/controlpanel/gui/qt/loadingoverlay.py (+6/-4) ubuntuone/controlpanel/gui/qt/main/linux.py (+4/-6) ubuntuone/controlpanel/gui/qt/main/windows.py (+8/-11) ubuntuone/controlpanel/gui/qt/preferences.py (+2/-0) ubuntuone/controlpanel/gui/qt/signin.py (+89/-0) ubuntuone/controlpanel/gui/qt/systray.py (+68/-0) ubuntuone/controlpanel/gui/qt/tests/__init__.py (+93/-33) ubuntuone/controlpanel/gui/qt/tests/test_account.py (+4/-9) ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py (+24/-24) ubuntuone/controlpanel/gui/qt/tests/test_common.py (+210/-0) ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py (+129/-24) ubuntuone/controlpanel/gui/qt/tests/test_device.py (+20/-18) ubuntuone/controlpanel/gui/qt/tests/test_devices.py (+12/-7) ubuntuone/controlpanel/gui/qt/tests/test_folders.py (+27/-38) ubuntuone/controlpanel/gui/qt/tests/test_gotoweb.py (+54/-2) ubuntuone/controlpanel/gui/qt/tests/test_gui.py (+7/-0) ubuntuone/controlpanel/gui/qt/tests/test_signin.py (+168/-0) ubuntuone/controlpanel/gui/qt/tests/test_start.py (+91/-0) ubuntuone/controlpanel/gui/qt/tests/test_systray.py (+103/-0) ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py (+20/-10) ubuntuone/controlpanel/gui/qt/ubuntuonebin.py (+19/-10) ubuntuone/controlpanel/gui/qt/ui/account_ui.py (+0/-84) ubuntuone/controlpanel/gui/qt/ui/controlpanel_ui.py (+0/-208) ubuntuone/controlpanel/gui/qt/ui/device_ui.py (+0/-46) ubuntuone/controlpanel/gui/qt/ui/devices_ui.py (+0/-71) ubuntuone/controlpanel/gui/qt/ui/filesyncstatus_ui.py (+0/-48) ubuntuone/controlpanel/gui/qt/ui/folders_ui.py (+0/-90) ubuntuone/controlpanel/gui/qt/ui/images_rc.py (+0/-23506) ubuntuone/controlpanel/gui/qt/ui/loadingoverlay_ui.py (+0/-59) ubuntuone/controlpanel/gui/qt/ui/mainwindow_ui.py (+0/-54) ubuntuone/controlpanel/gui/qt/ui/preferences_ui.py (+0/-115) ubuntuone/controlpanel/gui/tests/__init__.py (+4/-2) ubuntuone/controlpanel/gui/tests/test_url_sign.py (+2/-2) ubuntuone/controlpanel/logger.py (+5/-1) ubuntuone/controlpanel/replication_client.py (+1/-2) ubuntuone/controlpanel/tests/test_backend.py (+88/-31) ubuntuone/controlpanel/tests/test_cache.py (+58/-0) ubuntuone/controlpanel/web_client/tests/__init__.py (+19/-0) ubuntuone/controlpanel/web_client/tests/test_txwebclient.py (+155/-0) ubuntuone/controlpanel/web_client/txwebclient.py (+18/-1) |
To merge this branch: | bzr merge lp:~nataliabidart/ubuntu/oneiric/ubuntuone-control-panel/ubuntuone-control-panel-2.0.0 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Sponsors | Pending | ||
Review via email:
|
Commit message
Description of the change
* New upstream release:
[ Alejandro J. Cura <email address hidden>]
- Do not throw a webclient error when closing
(LP: #845105).
[ Natalia B. Bidart <email address hidden> ]
- Removed all code related to Bookmarks (LP: #850142).
- Replaces references to "Evolution" by "Thunderbird" (LP: #849494).
[ Rodney Dawes <email address hidden> ]
- Don't install a .desktop file for control panel
(part of LP: #838778).
- Point the indicator/Unity API at the installer .desktop file
(part of LP: #838778).
- Set the WMCLASS so Unity will fall back properly
(part of LP: #838778).
- Fix a few grammar mistakes (LP: #835093).
- Don't show the "Get NGB free!" label on "Join now" button at all
(LP: #819955).
* debian/control:
- ubuntuone-
- require ubuntuone-client >= 2.0.0.
- require ubuntu-sso-client >= 1.4.0.
- no longer install a .desktop file (will be installed by ubuntuone-

Sebastien Bacher (seb128) wrote : | # |
Preview Diff
1 | === removed file 'MANIFEST' |
2 | --- MANIFEST 2011-08-12 19:12:08 +0000 |
3 | +++ MANIFEST 1970-01-01 00:00:00 +0000 |
4 | @@ -1,140 +0,0 @@ |
5 | -# file GENERATED by distutils, do NOT edit |
6 | -COPYING |
7 | -MANIFEST |
8 | -README |
9 | -com.ubuntuone.controlpanel.gui.service.in |
10 | -com.ubuntuone.controlpanel.service.in |
11 | -pylintrc |
12 | -run-tests |
13 | -run-tests.bat |
14 | -setup.py |
15 | -ubuntuone-control-panel-gtk.desktop.in |
16 | -ubuntuone-control-panel.in |
17 | -ubuntuone.controlpanel.pth |
18 | -bin/ubuntuone-control-panel-backend |
19 | -bin/ubuntuone-control-panel-gtk |
20 | -bin/ubuntuone-control-panel-qt |
21 | -data/Ubuntu-R.ttf |
22 | -data/computer.png |
23 | -data/contacts.png |
24 | -data/external_icon_orange.png |
25 | -data/external_icon_white.png |
26 | -data/facebook.png |
27 | -data/files.png |
28 | -data/folder.png |
29 | -data/music-store.png |
30 | -data/music-stream.png |
31 | -data/notes.png |
32 | -data/overview.png |
33 | -data/phone.png |
34 | -data/services-bookmarks.png |
35 | -data/services-contacts.png |
36 | -data/services-files-example.png |
37 | -data/services-files.png |
38 | -data/sync_status_alert.png |
39 | -data/sync_status_disconnected.png |
40 | -data/sync_status_sync_done.png |
41 | -data/sync_status_syncing.png |
42 | -data/twitter.png |
43 | -data/u1icon.png |
44 | -data/gtk/dashboard.ui |
45 | -data/gtk/device.ui |
46 | -data/gtk/devices.ui |
47 | -data/gtk/install.ui |
48 | -data/gtk/management.ui |
49 | -data/gtk/overview.ui |
50 | -data/gtk/services.ui |
51 | -data/gtk/volumes.ui |
52 | -data/qt/account.ui |
53 | -data/qt/controlpanel.ui |
54 | -data/qt/device.ui |
55 | -data/qt/devices.ui |
56 | -data/qt/filesyncstatus.ui |
57 | -data/qt/folders.ui |
58 | -data/qt/images.qrc |
59 | -data/qt/loadingoverlay.ui |
60 | -data/qt/mainwindow.ui |
61 | -data/qt/preferences.ui |
62 | -data/qt/ubuntuone.qss |
63 | -docs/ubuntuone-control-panel-gtk.1 |
64 | -po/POTFILES.in |
65 | -po/ubuntuone-control-panel.pot |
66 | -ubuntuone/__init__.py |
67 | -ubuntuone/controlpanel/__init__.py |
68 | -ubuntuone/controlpanel/backend.py |
69 | -ubuntuone/controlpanel/constants.py.in |
70 | -ubuntuone/controlpanel/dbus_service.py |
71 | -ubuntuone/controlpanel/logger.py |
72 | -ubuntuone/controlpanel/login_client.py |
73 | -ubuntuone/controlpanel/replication_client.py |
74 | -ubuntuone/controlpanel/utils.py |
75 | -ubuntuone/controlpanel/dbustests/__init__.py |
76 | -ubuntuone/controlpanel/dbustests/test_dbus_service.py |
77 | -ubuntuone/controlpanel/dbustests/test_gui_service.py |
78 | -ubuntuone/controlpanel/dbustests/test_sd_client/__init__.py |
79 | -ubuntuone/controlpanel/dbustests/test_sd_client/test_linux.py |
80 | -ubuntuone/controlpanel/gui/__init__.py |
81 | -ubuntuone/controlpanel/gui/gtk/__init__.py |
82 | -ubuntuone/controlpanel/gui/gtk/gui.py |
83 | -ubuntuone/controlpanel/gui/gtk/package_manager.py |
84 | -ubuntuone/controlpanel/gui/gtk/widgets.py |
85 | -ubuntuone/controlpanel/gui/gtk/tests/__init__.py |
86 | -ubuntuone/controlpanel/gui/gtk/tests/test_gui.py |
87 | -ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py |
88 | -ubuntuone/controlpanel/gui/gtk/tests/test_package_manager.py |
89 | -ubuntuone/controlpanel/gui/gtk/tests/test_widgets.py |
90 | -ubuntuone/controlpanel/gui/qt/__init__.py |
91 | -ubuntuone/controlpanel/gui/qt/account.py |
92 | -ubuntuone/controlpanel/gui/qt/addfolder.py |
93 | -ubuntuone/controlpanel/gui/qt/controlpanel.py |
94 | -ubuntuone/controlpanel/gui/qt/device.py |
95 | -ubuntuone/controlpanel/gui/qt/devices.py |
96 | -ubuntuone/controlpanel/gui/qt/filesyncstatus.py |
97 | -ubuntuone/controlpanel/gui/qt/folders.py |
98 | -ubuntuone/controlpanel/gui/qt/gotoweb.py |
99 | -ubuntuone/controlpanel/gui/qt/gui.py |
100 | -ubuntuone/controlpanel/gui/qt/loadingoverlay.py |
101 | -ubuntuone/controlpanel/gui/qt/preferences.py |
102 | -ubuntuone/controlpanel/gui/qt/ubuntuonebin.py |
103 | -ubuntuone/controlpanel/gui/qt/main/__init__.py |
104 | -ubuntuone/controlpanel/gui/qt/main/linux.py |
105 | -ubuntuone/controlpanel/gui/qt/main/windows.py |
106 | -ubuntuone/controlpanel/gui/qt/tests/__init__.py |
107 | -ubuntuone/controlpanel/gui/qt/tests/test_account.py |
108 | -ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py |
109 | -ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py |
110 | -ubuntuone/controlpanel/gui/qt/tests/test_device.py |
111 | -ubuntuone/controlpanel/gui/qt/tests/test_devices.py |
112 | -ubuntuone/controlpanel/gui/qt/tests/test_filesyncstatus.py |
113 | -ubuntuone/controlpanel/gui/qt/tests/test_folders.py |
114 | -ubuntuone/controlpanel/gui/qt/tests/test_gotoweb.py |
115 | -ubuntuone/controlpanel/gui/qt/tests/test_gui.py |
116 | -ubuntuone/controlpanel/gui/qt/tests/test_loadingoverlay.py |
117 | -ubuntuone/controlpanel/gui/qt/tests/test_preferences.py |
118 | -ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py |
119 | -ubuntuone/controlpanel/gui/qt/ui/__init__.py |
120 | -ubuntuone/controlpanel/gui/qt/ui/account_ui.py |
121 | -ubuntuone/controlpanel/gui/qt/ui/controlpanel_ui.py |
122 | -ubuntuone/controlpanel/gui/qt/ui/device_ui.py |
123 | -ubuntuone/controlpanel/gui/qt/ui/devices_ui.py |
124 | -ubuntuone/controlpanel/gui/qt/ui/filesyncstatus_ui.py |
125 | -ubuntuone/controlpanel/gui/qt/ui/folders_ui.py |
126 | -ubuntuone/controlpanel/gui/qt/ui/images_rc.py |
127 | -ubuntuone/controlpanel/gui/qt/ui/loadingoverlay_ui.py |
128 | -ubuntuone/controlpanel/gui/qt/ui/mainwindow_ui.py |
129 | -ubuntuone/controlpanel/gui/qt/ui/preferences_ui.py |
130 | -ubuntuone/controlpanel/gui/tests/__init__.py |
131 | -ubuntuone/controlpanel/gui/tests/test_humanize.py |
132 | -ubuntuone/controlpanel/gui/tests/test_url_sign.py |
133 | -ubuntuone/controlpanel/sd_client/__init__.py |
134 | -ubuntuone/controlpanel/sd_client/linux.py |
135 | -ubuntuone/controlpanel/tests/__init__.py |
136 | -ubuntuone/controlpanel/tests/test_backend.py |
137 | -ubuntuone/controlpanel/tests/test_login_client.py |
138 | -ubuntuone/controlpanel/tests/test_replication_client.py |
139 | -ubuntuone/controlpanel/tests/test_sd_client.py |
140 | -ubuntuone/controlpanel/tests/test_utils.py |
141 | -ubuntuone/controlpanel/tests/test_web_client.py |
142 | -ubuntuone/controlpanel/web_client/__init__.py |
143 | -ubuntuone/controlpanel/web_client/libsoup.py |
144 | -ubuntuone/controlpanel/web_client/txwebclient.py |
145 | |
146 | === modified file 'PKG-INFO' |
147 | --- PKG-INFO 2011-08-25 19:37:14 +0000 |
148 | +++ PKG-INFO 2011-09-26 18:38:27 +0000 |
149 | @@ -1,30 +1,11 @@ |
150 | Metadata-Version: 1.1 |
151 | Name: ubuntuone-control-panel |
152 | -Version: 1.1.3 |
153 | +Version: 2.0.0 |
154 | Summary: Ubuntu One Control Panel |
155 | Home-page: https://launchpad.net/ubuntuone-control-panel |
156 | Author: Natalia Bidart |
157 | Author-email: natalia.bidart@canonical.com |
158 | License: GPL v3 |
159 | -Description: Application to manage a Ubuntu One account. Provides a DBus service to query/modify all the Ubuntu One bits. |
160 | +Description: Application to manage an Ubuntu One account. Provides a DBus service to query/modify all the Ubuntu One bits. |
161 | Platform: UNKNOWN |
162 | -Requires: PyQt4 |
163 | -Requires: apt |
164 | -Requires: aptdaemon |
165 | -Requires: dbus |
166 | -Requires: defer |
167 | -Requires: desktopcouch.application.replication_services |
168 | -Requires: gi.repository |
169 | -Requires: gobject |
170 | -Requires: gtk |
171 | -Requires: mocker |
172 | -Requires: oauth |
173 | -Requires: pango |
174 | -Requires: simplejson |
175 | -Requires: twisted.application |
176 | -Requires: twisted.internet |
177 | -Requires: twisted.python.failure |
178 | -Requires: twisted.trial.unittest |
179 | -Requires: twisted.web |
180 | -Requires: ubuntu_sso |
181 | Provides: ubuntuone |
182 | |
183 | === modified file 'bin/ubuntuone-control-panel-qt' |
184 | --- bin/ubuntuone-control-panel-qt 2011-08-25 19:37:14 +0000 |
185 | +++ bin/ubuntuone-control-panel-qt 2011-09-26 18:38:27 +0000 |
186 | @@ -45,10 +45,19 @@ |
187 | result.add_option("-a", "--alert", dest="alert", action="store_true", |
188 | default=False, help="Start Ubuntu One " |
189 | "alerting the user to its presence.") |
190 | + result.add_option("--minimized", dest="minimized", action="store_true", |
191 | + default=False, help="Start Ubuntu One " |
192 | + "only in the notification area, with no visible window. " |
193 | + "Implies --with-icon") |
194 | + result.add_option("--with-icon", dest="with_icon", action="store_true", |
195 | + default=False, help="Start Ubuntu One " |
196 | + "with an icon in the notification area.") |
197 | return result |
198 | |
199 | |
200 | if __name__ == "__main__": |
201 | parser = parser_options() |
202 | (options, args) = parser.parse_args(sys.argv) |
203 | - main.main(switch_to=options.switch_to, alert=options.alert) |
204 | + main.main(switch_to=options.switch_to, |
205 | + alert=options.alert, minimized=options.minimized, |
206 | + with_icon=options.with_icon) |
207 | |
208 | === added file 'data/Ubuntu-B.ttf' |
209 | Binary files data/Ubuntu-B.ttf 1970-01-01 00:00:00 +0000 and data/Ubuntu-B.ttf 2011-09-26 18:38:27 +0000 differ |
210 | === modified file 'data/gtk/overview.ui' |
211 | --- data/gtk/overview.ui 2011-07-22 21:26:48 +0000 |
212 | +++ data/gtk/overview.ui 2011-09-26 18:38:27 +0000 |
213 | @@ -150,7 +150,7 @@ |
214 | <property name="can_focus">False</property> |
215 | <property name="xalign">0</property> |
216 | <property name="label" translatable="yes">Stay Productive |
217 | -<span foreground="#909090">Keep your Firefox bookmarks and Tomboy notes synced</span></property> |
218 | +<span foreground="#909090">Keep your Tomboy notes synced</span></property> |
219 | <property name="use_markup">True</property> |
220 | <property name="wrap">True</property> |
221 | </object> |
222 | @@ -251,36 +251,11 @@ |
223 | <property name="use_action_appearance">False</property> |
224 | <signal name="clicked" handler="on_join_now_button_clicked" swapped="no"/> |
225 | <child> |
226 | - <object class="GtkVBox" id="vbox4"> |
227 | + <object class="GtkLabel" id="label1"> |
228 | <property name="visible">True</property> |
229 | <property name="can_focus">False</property> |
230 | - <property name="spacing">5</property> |
231 | - <child> |
232 | - <object class="GtkLabel" id="label1"> |
233 | - <property name="visible">True</property> |
234 | - <property name="can_focus">False</property> |
235 | - <property name="label" translatable="yes"><span font_size="xx-large" foreground="#4d4d4d">Join now</span></property> |
236 | - <property name="use_markup">True</property> |
237 | - </object> |
238 | - <packing> |
239 | - <property name="expand">True</property> |
240 | - <property name="fill">True</property> |
241 | - <property name="position">0</property> |
242 | - </packing> |
243 | - </child> |
244 | - <child> |
245 | - <object class="GtkLabel" id="label2"> |
246 | - <property name="visible">True</property> |
247 | - <property name="can_focus">False</property> |
248 | - <property name="label" translatable="yes"><span foreground="#909090">2GB of free storage</span></property> |
249 | - <property name="use_markup">True</property> |
250 | - </object> |
251 | - <packing> |
252 | - <property name="expand">True</property> |
253 | - <property name="fill">True</property> |
254 | - <property name="position">1</property> |
255 | - </packing> |
256 | - </child> |
257 | + <property name="label" translatable="yes"><span font_size="xx-large" foreground="#4d4d4d">Join now</span></property> |
258 | + <property name="use_markup">True</property> |
259 | </object> |
260 | </child> |
261 | </object> |
262 | |
263 | === modified file 'data/gtk/services.ui' |
264 | --- data/gtk/services.ui 2011-07-22 21:26:48 +0000 |
265 | +++ data/gtk/services.ui 2011-09-26 18:38:27 +0000 |
266 | @@ -59,16 +59,21 @@ |
267 | <property name="use_action_appearance">False</property> |
268 | <property name="draw_indicator">True</property> |
269 | </object> |
270 | + <packing> |
271 | + <property name="x_options"></property> |
272 | + <property name="y_options"></property> |
273 | + </packing> |
274 | </child> |
275 | <child> |
276 | <object class="GtkImage" id="files_icon"> |
277 | <property name="visible">True</property> |
278 | <property name="can_focus">False</property> |
279 | - <property name="xpad">5</property> |
280 | </object> |
281 | <packing> |
282 | <property name="left_attach">1</property> |
283 | <property name="right_attach">2</property> |
284 | + <property name="x_options"></property> |
285 | + <property name="y_options"></property> |
286 | </packing> |
287 | </child> |
288 | <child> |
289 | @@ -154,8 +159,6 @@ |
290 | <object class="GtkImage" id="files_example"> |
291 | <property name="visible">True</property> |
292 | <property name="can_focus">False</property> |
293 | - <property name="xpad">5</property> |
294 | - <property name="ypad">5</property> |
295 | </object> |
296 | <packing> |
297 | <property name="expand">False</property> |
298 | @@ -188,6 +191,7 @@ |
299 | <object class="GtkAlignment" id="alignment3"> |
300 | <property name="visible">True</property> |
301 | <property name="can_focus">False</property> |
302 | + <property name="top_padding">6</property> |
303 | <child> |
304 | <object class="GtkHBox" id="hbox3"> |
305 | <property name="visible">True</property> |
306 | @@ -203,6 +207,7 @@ |
307 | <property name="can_focus">False</property> |
308 | <property name="n_rows">2</property> |
309 | <property name="n_columns">3</property> |
310 | + <property name="column_spacing">5</property> |
311 | <property name="row_spacing">5</property> |
312 | <child> |
313 | <object class="GtkCheckButton" id="contacts_check"> |
314 | @@ -212,16 +217,21 @@ |
315 | <property name="use_action_appearance">False</property> |
316 | <property name="draw_indicator">True</property> |
317 | </object> |
318 | + <packing> |
319 | + <property name="x_options"></property> |
320 | + <property name="y_options"></property> |
321 | + </packing> |
322 | </child> |
323 | <child> |
324 | <object class="GtkImage" id="contacts_icon"> |
325 | <property name="visible">True</property> |
326 | <property name="can_focus">False</property> |
327 | - <property name="xpad">5</property> |
328 | </object> |
329 | <packing> |
330 | <property name="left_attach">1</property> |
331 | <property name="right_attach">2</property> |
332 | + <property name="x_options"></property> |
333 | + <property name="y_options"></property> |
334 | </packing> |
335 | </child> |
336 | <child> |
337 | @@ -245,7 +255,6 @@ |
338 | <property name="label" translatable="yes"><span font_size="small">Once enabled, visit the <a href="https://one.ubuntu.com">Ubuntu One website</a> to manage your contacts, including Gmail and Facebook import</span></property> |
339 | <property name="use_markup">True</property> |
340 | <property name="wrap">True</property> |
341 | - <property name="width_chars">35</property> |
342 | </object> |
343 | <packing> |
344 | <property name="left_attach">2</property> |
345 | @@ -269,92 +278,13 @@ |
346 | </child> |
347 | </object> |
348 | <packing> |
349 | - <property name="expand">False</property> |
350 | + <property name="expand">True</property> |
351 | <property name="fill">True</property> |
352 | <property name="position">0</property> |
353 | </packing> |
354 | </child> |
355 | <child> |
356 | - <object class="GtkVBox" id="bookmarks"> |
357 | - <property name="visible">True</property> |
358 | - <property name="can_focus">False</property> |
359 | - <child> |
360 | - <object class="GtkTable" id="bookmarks_sync"> |
361 | - <property name="visible">True</property> |
362 | - <property name="can_focus">False</property> |
363 | - <property name="n_rows">2</property> |
364 | - <property name="n_columns">3</property> |
365 | - <property name="row_spacing">5</property> |
366 | - <child> |
367 | - <object class="GtkCheckButton" id="bookmarks_check"> |
368 | - <property name="visible">True</property> |
369 | - <property name="can_focus">True</property> |
370 | - <property name="receives_default">False</property> |
371 | - <property name="use_action_appearance">False</property> |
372 | - <property name="draw_indicator">True</property> |
373 | - </object> |
374 | - </child> |
375 | - <child> |
376 | - <object class="GtkImage" id="bookmarks_icon"> |
377 | - <property name="visible">True</property> |
378 | - <property name="can_focus">False</property> |
379 | - <property name="xpad">5</property> |
380 | - </object> |
381 | - <packing> |
382 | - <property name="left_attach">1</property> |
383 | - <property name="right_attach">2</property> |
384 | - </packing> |
385 | - </child> |
386 | - <child> |
387 | - <object class="GtkLabel" id="label6"> |
388 | - <property name="visible">True</property> |
389 | - <property name="can_focus">False</property> |
390 | - <property name="xalign">0</property> |
391 | - <property name="label" translatable="yes">Enable Bookmarks Sync</property> |
392 | - </object> |
393 | - <packing> |
394 | - <property name="left_attach">2</property> |
395 | - <property name="right_attach">3</property> |
396 | - </packing> |
397 | - </child> |
398 | - <child> |
399 | - <object class="GtkLabel" id="label7"> |
400 | - <property name="visible">True</property> |
401 | - <property name="can_focus">False</property> |
402 | - <property name="xalign">0</property> |
403 | - <property name="yalign">0</property> |
404 | - <property name="label" translatable="yes"><span font_size="small">Bookmarks sync works with Firefox</span></property> |
405 | - <property name="use_markup">True</property> |
406 | - <property name="wrap">True</property> |
407 | - <property name="width_chars">30</property> |
408 | - </object> |
409 | - <packing> |
410 | - <property name="left_attach">2</property> |
411 | - <property name="right_attach">3</property> |
412 | - <property name="top_attach">1</property> |
413 | - <property name="bottom_attach">2</property> |
414 | - </packing> |
415 | - </child> |
416 | - <child> |
417 | - <placeholder/> |
418 | - </child> |
419 | - <child> |
420 | - <placeholder/> |
421 | - </child> |
422 | - </object> |
423 | - <packing> |
424 | - <property name="expand">False</property> |
425 | - <property name="fill">True</property> |
426 | - <property name="position">0</property> |
427 | - </packing> |
428 | - </child> |
429 | - </object> |
430 | - <packing> |
431 | - <property name="expand">False</property> |
432 | - <property name="fill">True</property> |
433 | - <property name="pack_type">end</property> |
434 | - <property name="position">1</property> |
435 | - </packing> |
436 | + <placeholder/> |
437 | </child> |
438 | </object> |
439 | </child> |
440 | |
441 | === modified file 'data/qt/account.ui' |
442 | --- data/qt/account.ui 2011-08-25 19:37:14 +0000 |
443 | +++ data/qt/account.ui 2011-09-26 18:38:27 +0000 |
444 | @@ -35,7 +35,16 @@ |
445 | <string>Your services</string> |
446 | </property> |
447 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
448 | - <property name="margin"> |
449 | + <property name="leftMargin"> |
450 | + <number>10</number> |
451 | + </property> |
452 | + <property name="topMargin"> |
453 | + <number>0</number> |
454 | + </property> |
455 | + <property name="rightMargin"> |
456 | + <number>0</number> |
457 | + </property> |
458 | + <property name="bottomMargin"> |
459 | <number>0</number> |
460 | </property> |
461 | <item> |
462 | @@ -61,11 +70,23 @@ |
463 | <string>Personal details</string> |
464 | </property> |
465 | <layout class="QVBoxLayout" name="verticalLayout_4"> |
466 | - <property name="margin"> |
467 | + <property name="leftMargin"> |
468 | + <number>10</number> |
469 | + </property> |
470 | + <property name="topMargin"> |
471 | + <number>0</number> |
472 | + </property> |
473 | + <property name="rightMargin"> |
474 | + <number>0</number> |
475 | + </property> |
476 | + <property name="bottomMargin"> |
477 | <number>0</number> |
478 | </property> |
479 | <item> |
480 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
481 | + <property name="leftMargin"> |
482 | + <number>6</number> |
483 | + </property> |
484 | <item> |
485 | <widget class="QLabel" name="name_label"> |
486 | <property name="text"> |
487 | |
488 | === modified file 'data/qt/controlpanel.ui' |
489 | --- data/qt/controlpanel.ui 2011-08-25 19:37:14 +0000 |
490 | +++ data/qt/controlpanel.ui 2011-09-26 18:38:27 +0000 |
491 | @@ -6,8 +6,8 @@ |
492 | <rect> |
493 | <x>0</x> |
494 | <y>0</y> |
495 | - <width>367</width> |
496 | - <height>142</height> |
497 | + <width>387</width> |
498 | + <height>168</height> |
499 | </rect> |
500 | </property> |
501 | <property name="sizePolicy"> |
502 | @@ -20,215 +20,247 @@ |
503 | <string notr="true">Form</string> |
504 | </property> |
505 | <layout class="QVBoxLayout" name="verticalLayout"> |
506 | - <property name="spacing"> |
507 | - <number>3</number> |
508 | - </property> |
509 | <property name="margin"> |
510 | <number>0</number> |
511 | </property> |
512 | <item> |
513 | - <widget class="QFrame" name="frame_header"> |
514 | - <layout class="QHBoxLayout" name="horizontalLayout_2"> |
515 | - <property name="spacing"> |
516 | - <number>5</number> |
517 | - </property> |
518 | - <property name="margin"> |
519 | - <number>0</number> |
520 | - </property> |
521 | - <item> |
522 | - <widget class="QFrame" name="frame_greeting"> |
523 | - <layout class="QVBoxLayout" name="verticalLayout_4"> |
524 | - <property name="margin"> |
525 | - <number>0</number> |
526 | - </property> |
527 | - <item> |
528 | - <widget class="QLabel" name="greeting_label"> |
529 | - <property name="alignment"> |
530 | - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> |
531 | - </property> |
532 | - </widget> |
533 | - </item> |
534 | - </layout> |
535 | - </widget> |
536 | - </item> |
537 | - <item> |
538 | - <spacer name="horizontalSpacer"> |
539 | - <property name="orientation"> |
540 | - <enum>Qt::Horizontal</enum> |
541 | - </property> |
542 | - <property name="sizeType"> |
543 | - <enum>QSizePolicy::Fixed</enum> |
544 | - </property> |
545 | - <property name="sizeHint" stdset="0"> |
546 | - <size> |
547 | - <width>15</width> |
548 | - <height>20</height> |
549 | - </size> |
550 | - </property> |
551 | - </spacer> |
552 | - </item> |
553 | - <item> |
554 | - <widget class="QFrame" name="frame_storage"> |
555 | - <property name="sizePolicy"> |
556 | - <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
557 | - <horstretch>0</horstretch> |
558 | - <verstretch>0</verstretch> |
559 | - </sizepolicy> |
560 | - </property> |
561 | - <property name="minimumSize"> |
562 | - <size> |
563 | - <width>165</width> |
564 | - <height>0</height> |
565 | - </size> |
566 | - </property> |
567 | - <property name="maximumSize"> |
568 | - <size> |
569 | - <width>165</width> |
570 | - <height>16777215</height> |
571 | - </size> |
572 | - </property> |
573 | - <layout class="QVBoxLayout" name="vLayoutStorage"> |
574 | - <property name="spacing"> |
575 | - <number>6</number> |
576 | - </property> |
577 | - <property name="sizeConstraint"> |
578 | - <enum>QLayout::SetDefaultConstraint</enum> |
579 | - </property> |
580 | - <property name="margin"> |
581 | - <number>0</number> |
582 | - </property> |
583 | - <item> |
584 | - <widget class="QFrame" name="frame_quota"> |
585 | - <layout class="QVBoxLayout" name="verticalLayout_3"> |
586 | + <widget class="QStackedWidget" name="switcher"> |
587 | + <property name="currentIndex"> |
588 | + <number>1</number> |
589 | + </property> |
590 | + <widget class="QWidget" name="management"> |
591 | + <property name="sizePolicy"> |
592 | + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
593 | + <horstretch>0</horstretch> |
594 | + <verstretch>0</verstretch> |
595 | + </sizepolicy> |
596 | + </property> |
597 | + <layout class="QVBoxLayout" name="verticalLayout_5"> |
598 | + <property name="margin"> |
599 | + <number>0</number> |
600 | + </property> |
601 | + <item> |
602 | + <layout class="QVBoxLayout" name="verticalLayout_2"> |
603 | + <item> |
604 | + <widget class="QFrame" name="frame_header"> |
605 | + <layout class="QHBoxLayout" name="horizontalLayout_2"> |
606 | <property name="spacing"> |
607 | - <number>2</number> |
608 | + <number>5</number> |
609 | </property> |
610 | <property name="margin"> |
611 | <number>0</number> |
612 | </property> |
613 | <item> |
614 | - <widget class="QLabel" name="percentage_usage_label"> |
615 | - <property name="sizePolicy"> |
616 | - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
617 | - <horstretch>0</horstretch> |
618 | - <verstretch>0</verstretch> |
619 | - </sizepolicy> |
620 | - </property> |
621 | - <property name="text"> |
622 | - <string notr="true"/> |
623 | - </property> |
624 | - </widget> |
625 | - </item> |
626 | - <item> |
627 | - <widget class="QLabel" name="quota_usage_label"> |
628 | - <property name="font"> |
629 | - <font> |
630 | - <pointsize>8</pointsize> |
631 | - </font> |
632 | - </property> |
633 | - <property name="text"> |
634 | - <string/> |
635 | - </property> |
636 | + <widget class="QFrame" name="frame_greeting"> |
637 | + <layout class="QVBoxLayout" name="verticalLayout_4"> |
638 | + <property name="margin"> |
639 | + <number>0</number> |
640 | + </property> |
641 | + <item> |
642 | + <widget class="QLabel" name="greeting_label"> |
643 | + <property name="alignment"> |
644 | + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> |
645 | + </property> |
646 | + </widget> |
647 | + </item> |
648 | + </layout> |
649 | + </widget> |
650 | + </item> |
651 | + <item> |
652 | + <spacer name="horizontalSpacer"> |
653 | + <property name="orientation"> |
654 | + <enum>Qt::Horizontal</enum> |
655 | + </property> |
656 | + <property name="sizeType"> |
657 | + <enum>QSizePolicy::Fixed</enum> |
658 | + </property> |
659 | + <property name="sizeHint" stdset="0"> |
660 | + <size> |
661 | + <width>15</width> |
662 | + <height>20</height> |
663 | + </size> |
664 | + </property> |
665 | + </spacer> |
666 | + </item> |
667 | + <item> |
668 | + <widget class="QFrame" name="frame_storage"> |
669 | + <property name="sizePolicy"> |
670 | + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
671 | + <horstretch>0</horstretch> |
672 | + <verstretch>0</verstretch> |
673 | + </sizepolicy> |
674 | + </property> |
675 | + <property name="minimumSize"> |
676 | + <size> |
677 | + <width>165</width> |
678 | + <height>0</height> |
679 | + </size> |
680 | + </property> |
681 | + <property name="maximumSize"> |
682 | + <size> |
683 | + <width>165</width> |
684 | + <height>16777215</height> |
685 | + </size> |
686 | + </property> |
687 | + <layout class="QVBoxLayout" name="vLayoutStorage"> |
688 | + <property name="spacing"> |
689 | + <number>6</number> |
690 | + </property> |
691 | + <property name="sizeConstraint"> |
692 | + <enum>QLayout::SetFixedSize</enum> |
693 | + </property> |
694 | + <property name="margin"> |
695 | + <number>0</number> |
696 | + </property> |
697 | + <item> |
698 | + <widget class="QFrame" name="frame_quota"> |
699 | + <layout class="QVBoxLayout" name="verticalLayout_3"> |
700 | + <property name="spacing"> |
701 | + <number>2</number> |
702 | + </property> |
703 | + <property name="margin"> |
704 | + <number>0</number> |
705 | + </property> |
706 | + <item> |
707 | + <widget class="QLabel" name="percentage_usage_label"> |
708 | + <property name="sizePolicy"> |
709 | + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
710 | + <horstretch>0</horstretch> |
711 | + <verstretch>0</verstretch> |
712 | + </sizepolicy> |
713 | + </property> |
714 | + <property name="text"> |
715 | + <string notr="true"/> |
716 | + </property> |
717 | + <property name="OverQuota" stdset="0"> |
718 | + <bool>false</bool> |
719 | + </property> |
720 | + </widget> |
721 | + </item> |
722 | + <item> |
723 | + <widget class="QLabel" name="quota_usage_label"> |
724 | + <property name="font"> |
725 | + <font> |
726 | + <pointsize>8</pointsize> |
727 | + </font> |
728 | + </property> |
729 | + <property name="text"> |
730 | + <string/> |
731 | + </property> |
732 | + <property name="OverQuota" stdset="0"> |
733 | + <bool>false</bool> |
734 | + </property> |
735 | + </widget> |
736 | + </item> |
737 | + </layout> |
738 | + <zorder>quota_usage_label</zorder> |
739 | + <zorder>percentage_usage_label</zorder> |
740 | + </widget> |
741 | + </item> |
742 | + <item> |
743 | + <widget class="GoToWebButton" name="get_more_space_button"> |
744 | + <property name="text"> |
745 | + <string>Get more storage</string> |
746 | + </property> |
747 | + </widget> |
748 | + </item> |
749 | + </layout> |
750 | + </widget> |
751 | + </item> |
752 | + <item> |
753 | + <widget class="QFrame" name="frame_status"> |
754 | + <property name="sizePolicy"> |
755 | + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
756 | + <horstretch>0</horstretch> |
757 | + <verstretch>0</verstretch> |
758 | + </sizepolicy> |
759 | + </property> |
760 | + <property name="minimumSize"> |
761 | + <size> |
762 | + <width>165</width> |
763 | + <height>0</height> |
764 | + </size> |
765 | + </property> |
766 | + <property name="maximumSize"> |
767 | + <size> |
768 | + <width>165</width> |
769 | + <height>16777215</height> |
770 | + </size> |
771 | + </property> |
772 | + <layout class="QHBoxLayout" name="horizontalLayout_8"> |
773 | + <property name="sizeConstraint"> |
774 | + <enum>QLayout::SetMinimumSize</enum> |
775 | + </property> |
776 | + <property name="margin"> |
777 | + <number>0</number> |
778 | + </property> |
779 | + <item> |
780 | + <widget class="FileSyncStatus" name="file_sync_status" native="true"> |
781 | + <property name="sizePolicy"> |
782 | + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
783 | + <horstretch>0</horstretch> |
784 | + <verstretch>0</verstretch> |
785 | + </sizepolicy> |
786 | + </property> |
787 | + <property name="minimumSize"> |
788 | + <size> |
789 | + <width>0</width> |
790 | + <height>0</height> |
791 | + </size> |
792 | + </property> |
793 | + <property name="maximumSize"> |
794 | + <size> |
795 | + <width>165</width> |
796 | + <height>16777215</height> |
797 | + </size> |
798 | + </property> |
799 | + </widget> |
800 | + </item> |
801 | + </layout> |
802 | </widget> |
803 | </item> |
804 | </layout> |
805 | - <zorder>quota_usage_label</zorder> |
806 | - <zorder>percentage_usage_label</zorder> |
807 | - </widget> |
808 | - </item> |
809 | - <item> |
810 | - <widget class="GoToWebButton" name="get_more_space_button"> |
811 | - <property name="text"> |
812 | - <string>Get more storage</string> |
813 | - </property> |
814 | - </widget> |
815 | - </item> |
816 | - </layout> |
817 | - </widget> |
818 | - </item> |
819 | - <item> |
820 | - <widget class="QFrame" name="frame_status"> |
821 | - <property name="sizePolicy"> |
822 | - <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
823 | - <horstretch>0</horstretch> |
824 | - <verstretch>0</verstretch> |
825 | - </sizepolicy> |
826 | - </property> |
827 | - <property name="minimumSize"> |
828 | - <size> |
829 | - <width>165</width> |
830 | - <height>0</height> |
831 | - </size> |
832 | - </property> |
833 | - <property name="maximumSize"> |
834 | - <size> |
835 | - <width>165</width> |
836 | - <height>16777215</height> |
837 | - </size> |
838 | - </property> |
839 | - <layout class="QHBoxLayout" name="horizontalLayout_8"> |
840 | - <property name="margin"> |
841 | - <number>0</number> |
842 | - </property> |
843 | - <item> |
844 | - <widget class="FileSyncStatus" name="file_sync_status" native="true"> |
845 | + </widget> |
846 | + </item> |
847 | + <item> |
848 | + <widget class="QTabWidget" name="tab_widget"> |
849 | <property name="sizePolicy"> |
850 | - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
851 | + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> |
852 | <horstretch>0</horstretch> |
853 | <verstretch>0</verstretch> |
854 | </sizepolicy> |
855 | </property> |
856 | - <property name="minimumSize"> |
857 | - <size> |
858 | - <width>0</width> |
859 | - <height>0</height> |
860 | - </size> |
861 | - </property> |
862 | - <property name="maximumSize"> |
863 | - <size> |
864 | - <width>165</width> |
865 | - <height>16777215</height> |
866 | - </size> |
867 | - </property> |
868 | + <property name="currentIndex"> |
869 | + <number>0</number> |
870 | + </property> |
871 | + <widget class="FoldersPanel" name="folders_tab"> |
872 | + <attribute name="title"> |
873 | + <string>Folders</string> |
874 | + </attribute> |
875 | + </widget> |
876 | + <widget class="DevicesPanel" name="devices_tab"> |
877 | + <attribute name="title"> |
878 | + <string>Devices</string> |
879 | + </attribute> |
880 | + </widget> |
881 | + <widget class="PreferencesPanel" name="preferences_tab"> |
882 | + <attribute name="title"> |
883 | + <string>Settings</string> |
884 | + </attribute> |
885 | + </widget> |
886 | + <widget class="AccountPanel" name="account_tab"> |
887 | + <attribute name="title"> |
888 | + <string>Account information</string> |
889 | + </attribute> |
890 | + </widget> |
891 | </widget> |
892 | </item> |
893 | </layout> |
894 | - </widget> |
895 | - </item> |
896 | - </layout> |
897 | - </widget> |
898 | - </item> |
899 | - <item> |
900 | - <widget class="QTabWidget" name="tab_widget"> |
901 | - <property name="sizePolicy"> |
902 | - <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> |
903 | - <horstretch>0</horstretch> |
904 | - <verstretch>0</verstretch> |
905 | - </sizepolicy> |
906 | - </property> |
907 | - <property name="currentIndex"> |
908 | - <number>0</number> |
909 | - </property> |
910 | - <widget class="FoldersPanel" name="folders_tab"> |
911 | - <attribute name="title"> |
912 | - <string>Folders</string> |
913 | - </attribute> |
914 | - </widget> |
915 | - <widget class="DevicesPanel" name="devices_tab"> |
916 | - <attribute name="title"> |
917 | - <string>Devices</string> |
918 | - </attribute> |
919 | - </widget> |
920 | - <widget class="PreferencesPanel" name="preferences_tab"> |
921 | - <attribute name="title"> |
922 | - <string>Settings</string> |
923 | - </attribute> |
924 | - </widget> |
925 | - <widget class="AccountPanel" name="account_tab"> |
926 | - <attribute name="title"> |
927 | - <string>Account information</string> |
928 | - </attribute> |
929 | - </widget> |
930 | + </item> |
931 | + </layout> |
932 | + </widget> |
933 | + <widget class="QWidget" name="empty"/> |
934 | + <widget class="SignInPanel" name="signin"/> |
935 | </widget> |
936 | </item> |
937 | <item> |
938 | @@ -371,9 +403,14 @@ |
939 | <header>ubuntuone.controlpanel.gui.qt.account</header> |
940 | <container>1</container> |
941 | </customwidget> |
942 | + <customwidget> |
943 | + <class>SignInPanel</class> |
944 | + <extends>QWidget</extends> |
945 | + <header>ubuntuone.controlpanel.gui.qt.signin</header> |
946 | + <container>1</container> |
947 | + </customwidget> |
948 | </customwidgets> |
949 | <tabstops> |
950 | - <tabstop>tab_widget</tabstop> |
951 | <tabstop>help_button</tabstop> |
952 | <tabstop>twitter_button</tabstop> |
953 | <tabstop>facebook_button</tabstop> |
954 | |
955 | === modified file 'data/qt/images.qrc' |
956 | --- data/qt/images.qrc 2011-08-25 19:37:14 +0000 |
957 | +++ data/qt/images.qrc 2011-09-26 18:38:27 +0000 |
958 | @@ -15,6 +15,7 @@ |
959 | <file>../facebook.png</file> |
960 | <file>../external_icon_white.png</file> |
961 | <file>../Ubuntu-R.ttf</file> |
962 | + <file>../Ubuntu-B.ttf</file> |
963 | <file>ubuntuone.qss</file> |
964 | </qresource> |
965 | </RCC> |
966 | |
967 | === modified file 'data/qt/preferences.ui' |
968 | --- data/qt/preferences.ui 2011-08-25 19:37:14 +0000 |
969 | +++ data/qt/preferences.ui 2011-09-26 18:38:27 +0000 |
970 | @@ -6,7 +6,7 @@ |
971 | <rect> |
972 | <x>0</x> |
973 | <y>0</y> |
974 | - <width>433</width> |
975 | + <width>512</width> |
976 | <height>328</height> |
977 | </rect> |
978 | </property> |
979 | @@ -138,14 +138,14 @@ |
980 | <item> |
981 | <widget class="QCheckBox" name="udf_autosubscribe_checkbox"> |
982 | <property name="text"> |
983 | - <string>Automatically sync all selected folders on this computer to the cloud</string> |
984 | + <string>Automatically sync all new cloud folders to this computer</string> |
985 | </property> |
986 | </widget> |
987 | </item> |
988 | <item> |
989 | <widget class="QCheckBox" name="share_autosubscribe_checkbox"> |
990 | <property name="text"> |
991 | - <string>Automatically sync all folders shared with me by other to this computer</string> |
992 | + <string>Automatically sync all folders shared with me to this computer</string> |
993 | </property> |
994 | </widget> |
995 | </item> |
996 | |
997 | === added file 'data/qt/signin.ui' |
998 | --- data/qt/signin.ui 1970-01-01 00:00:00 +0000 |
999 | +++ data/qt/signin.ui 2011-09-26 18:38:27 +0000 |
1000 | @@ -0,0 +1,203 @@ |
1001 | +<?xml version="1.0" encoding="UTF-8"?> |
1002 | +<ui version="4.0"> |
1003 | + <class>Form</class> |
1004 | + <widget class="QWidget" name="Form"> |
1005 | + <property name="geometry"> |
1006 | + <rect> |
1007 | + <x>0</x> |
1008 | + <y>0</y> |
1009 | + <width>344</width> |
1010 | + <height>312</height> |
1011 | + </rect> |
1012 | + </property> |
1013 | + <property name="windowTitle"> |
1014 | + <string>Form</string> |
1015 | + </property> |
1016 | + <layout class="QHBoxLayout" name="horizontalLayout_3"> |
1017 | + <property name="margin"> |
1018 | + <number>0</number> |
1019 | + </property> |
1020 | + <item> |
1021 | + <widget class="QFrame" name="signin"> |
1022 | + <layout class="QVBoxLayout" name="sign_in"> |
1023 | + <property name="spacing"> |
1024 | + <number>15</number> |
1025 | + </property> |
1026 | + <property name="margin"> |
1027 | + <number>3</number> |
1028 | + </property> |
1029 | + <item> |
1030 | + <widget class="QLabel" name="sign_in_label"> |
1031 | + <property name="text"> |
1032 | + <string>Sign in to Ubuntu One</string> |
1033 | + </property> |
1034 | + </widget> |
1035 | + </item> |
1036 | + <item> |
1037 | + <widget class="QLabel" name="description_label"> |
1038 | + <property name="text"> |
1039 | + <string>Sign in with yur existing Ubuntu One username and password.</string> |
1040 | + </property> |
1041 | + </widget> |
1042 | + </item> |
1043 | + <item> |
1044 | + <layout class="QHBoxLayout" name="horizontalLayout"> |
1045 | + <item> |
1046 | + <layout class="QVBoxLayout" name="verticalLayout_2"> |
1047 | + <property name="spacing"> |
1048 | + <number>15</number> |
1049 | + </property> |
1050 | + <item> |
1051 | + <layout class="QVBoxLayout" name="verticalLayout_4"> |
1052 | + <property name="spacing"> |
1053 | + <number>0</number> |
1054 | + </property> |
1055 | + <item> |
1056 | + <widget class="QLabel" name="email_label"> |
1057 | + <property name="text"> |
1058 | + <string>Email address</string> |
1059 | + </property> |
1060 | + </widget> |
1061 | + </item> |
1062 | + <item> |
1063 | + <widget class="QLineEdit" name="email_entry"> |
1064 | + <property name="text"> |
1065 | + <string/> |
1066 | + </property> |
1067 | + </widget> |
1068 | + </item> |
1069 | + </layout> |
1070 | + </item> |
1071 | + <item> |
1072 | + <layout class="QVBoxLayout" name="verticalLayout_3"> |
1073 | + <property name="spacing"> |
1074 | + <number>0</number> |
1075 | + </property> |
1076 | + <item> |
1077 | + <widget class="QLabel" name="password_label"> |
1078 | + <property name="text"> |
1079 | + <string>Password</string> |
1080 | + </property> |
1081 | + </widget> |
1082 | + </item> |
1083 | + <item> |
1084 | + <widget class="QLineEdit" name="password_entry"> |
1085 | + <property name="echoMode"> |
1086 | + <enum>QLineEdit::Password</enum> |
1087 | + </property> |
1088 | + </widget> |
1089 | + </item> |
1090 | + </layout> |
1091 | + </item> |
1092 | + <item> |
1093 | + <layout class="QHBoxLayout" name="horizontalLayout_2"> |
1094 | + <item> |
1095 | + <widget class="QPushButton" name="signin_button"> |
1096 | + <property name="text"> |
1097 | + <string>Sign in</string> |
1098 | + </property> |
1099 | + <property name="default"> |
1100 | + <bool>true</bool> |
1101 | + </property> |
1102 | + </widget> |
1103 | + </item> |
1104 | + <item> |
1105 | + <widget class="QPushButton" name="cancel_button"> |
1106 | + <property name="text"> |
1107 | + <string>Cancel</string> |
1108 | + </property> |
1109 | + <property name="secondary" stdset="0"> |
1110 | + <bool>true</bool> |
1111 | + </property> |
1112 | + </widget> |
1113 | + </item> |
1114 | + <item> |
1115 | + <spacer name="horizontalSpacer"> |
1116 | + <property name="orientation"> |
1117 | + <enum>Qt::Horizontal</enum> |
1118 | + </property> |
1119 | + <property name="sizeHint" stdset="0"> |
1120 | + <size> |
1121 | + <width>40</width> |
1122 | + <height>20</height> |
1123 | + </size> |
1124 | + </property> |
1125 | + </spacer> |
1126 | + </item> |
1127 | + </layout> |
1128 | + </item> |
1129 | + <item> |
1130 | + <layout class="QHBoxLayout" name="horizontalLayout_4"> |
1131 | + <item> |
1132 | + <widget class="GoToWebButton" name="forgot_password_button"> |
1133 | + <property name="sizePolicy"> |
1134 | + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
1135 | + <horstretch>0</horstretch> |
1136 | + <verstretch>0</verstretch> |
1137 | + </sizepolicy> |
1138 | + </property> |
1139 | + <property name="text"> |
1140 | + <string>Forgot your password?</string> |
1141 | + </property> |
1142 | + </widget> |
1143 | + </item> |
1144 | + <item> |
1145 | + <spacer name="horizontalSpacer_3"> |
1146 | + <property name="orientation"> |
1147 | + <enum>Qt::Horizontal</enum> |
1148 | + </property> |
1149 | + <property name="sizeHint" stdset="0"> |
1150 | + <size> |
1151 | + <width>40</width> |
1152 | + <height>20</height> |
1153 | + </size> |
1154 | + </property> |
1155 | + </spacer> |
1156 | + </item> |
1157 | + </layout> |
1158 | + </item> |
1159 | + </layout> |
1160 | + </item> |
1161 | + <item> |
1162 | + <spacer name="horizontalSpacer_2"> |
1163 | + <property name="orientation"> |
1164 | + <enum>Qt::Horizontal</enum> |
1165 | + </property> |
1166 | + <property name="sizeHint" stdset="0"> |
1167 | + <size> |
1168 | + <width>40</width> |
1169 | + <height>20</height> |
1170 | + </size> |
1171 | + </property> |
1172 | + </spacer> |
1173 | + </item> |
1174 | + </layout> |
1175 | + </item> |
1176 | + <item> |
1177 | + <spacer name="verticalSpacer"> |
1178 | + <property name="orientation"> |
1179 | + <enum>Qt::Vertical</enum> |
1180 | + </property> |
1181 | + <property name="sizeHint" stdset="0"> |
1182 | + <size> |
1183 | + <width>20</width> |
1184 | + <height>40</height> |
1185 | + </size> |
1186 | + </property> |
1187 | + </spacer> |
1188 | + </item> |
1189 | + </layout> |
1190 | + </widget> |
1191 | + </item> |
1192 | + </layout> |
1193 | + </widget> |
1194 | + <customwidgets> |
1195 | + <customwidget> |
1196 | + <class>GoToWebButton</class> |
1197 | + <extends>QPushButton</extends> |
1198 | + <header>ubuntuone.controlpanel.gui.qt.gotoweb</header> |
1199 | + </customwidget> |
1200 | + </customwidgets> |
1201 | + <resources/> |
1202 | + <connections/> |
1203 | +</ui> |
1204 | |
1205 | === modified file 'data/qt/ubuntuone.qss' |
1206 | --- data/qt/ubuntuone.qss 2011-08-25 19:37:14 +0000 |
1207 | +++ data/qt/ubuntuone.qss 2011-09-26 18:38:27 +0000 |
1208 | @@ -1,5 +1,5 @@ |
1209 | QMainWindow { |
1210 | - background-color: #dd4814; |
1211 | + background-color: #aea79f; |
1212 | } |
1213 | |
1214 | QWidget { |
1215 | @@ -12,6 +12,7 @@ |
1216 | border: none; |
1217 | } |
1218 | |
1219 | +QFrame#signin, |
1220 | QFrame#frame_header { |
1221 | background: #ffffff; |
1222 | border-radius: 5px; |
1223 | @@ -137,6 +138,7 @@ |
1224 | border: none; |
1225 | } |
1226 | |
1227 | +GoToWebButton#forgot_password_button, |
1228 | GoToWebButton#share_publish_button { |
1229 | background: transparent; |
1230 | border: none; |
1231 | @@ -216,11 +218,8 @@ |
1232 | padding-top: 30px; |
1233 | border: none; |
1234 | margin-top: 1ex; |
1235 | -} |
1236 | - |
1237 | -QGroupBox::title { |
1238 | color: #333333; |
1239 | - font: bold 15px; |
1240 | + font: bold 14px; |
1241 | } |
1242 | |
1243 | QGroupBox#profile, |
1244 | @@ -228,6 +227,11 @@ |
1245 | padding-left: 5px; |
1246 | } |
1247 | |
1248 | +QGroupBox#bandwidth_settings, |
1249 | +QGroupBox#file_sync_settings { |
1250 | + padding-left: 20px; |
1251 | +} |
1252 | + |
1253 | QListWidget { |
1254 | background: #f7f6f5; |
1255 | alternate-background-color: #efedec; |
1256 | @@ -237,6 +241,10 @@ |
1257 | min-height: 48px; |
1258 | } |
1259 | |
1260 | +QLabel[OverQuota="false"] { |
1261 | + color: #333333; |
1262 | +} |
1263 | + |
1264 | QLabel#other_devices_label { |
1265 | font: bold 16px; |
1266 | } |
1267 | @@ -249,6 +257,20 @@ |
1268 | color: white; |
1269 | } |
1270 | |
1271 | +QLabel#sign_in_label { |
1272 | + font: 16px; |
1273 | +} |
1274 | + |
1275 | +QLabel#email_label, |
1276 | +QLabel#password_label { |
1277 | + font-size: 10px; |
1278 | +} |
1279 | + |
1280 | +QLabel[OverQuota="true"], |
1281 | +QLabel#warning_label { |
1282 | + color: #df2d1f; |
1283 | +} |
1284 | + |
1285 | QAbstractItemView { |
1286 | border-style: solid; |
1287 | border-color: #898989; |
1288 | |
1289 | === modified file 'debian/changelog' |
1290 | --- debian/changelog 2011-09-07 13:35:18 +0000 |
1291 | +++ debian/changelog 2011-09-26 18:38:27 +0000 |
1292 | @@ -1,3 +1,32 @@ |
1293 | +ubuntuone-control-panel (2.0.0-0ubuntu1) UNRELEASED; urgency=low |
1294 | + |
1295 | + * New upstream release: |
1296 | + |
1297 | + [ Alejandro J. Cura <alecu@canonical.com>] |
1298 | + - Do not throw a webclient error when closing |
1299 | + (LP: #845105). |
1300 | + [ Natalia B. Bidart <natalia.bidart@canonical.com> ] |
1301 | + - Removed all code related to Bookmarks (LP: #850142). |
1302 | + - Replaces references to "Evolution" by "Thunderbird" (LP: #849494). |
1303 | + [ Rodney Dawes <rodney.dawes@canonical.com> ] |
1304 | + - Don't install a .desktop file for control panel |
1305 | + (part of LP: #838778). |
1306 | + - Point the indicator/Unity API at the installer .desktop file |
1307 | + (part of LP: #838778). |
1308 | + - Set the WMCLASS so Unity will fall back properly |
1309 | + (part of LP: #838778). |
1310 | + - Fix a few grammar mistakes (LP: #835093). |
1311 | + - Don't show the "Get NGB free!" label on "Join now" button at all |
1312 | + (LP: #819955). |
1313 | + |
1314 | + * debian/control: |
1315 | + - ubuntuone-control-panel-gtk depends now on ubuntuone-installer >= 2.0.0. |
1316 | + - require ubuntuone-client >= 2.0.0. |
1317 | + - require ubuntu-sso-client >= 1.4.0. |
1318 | + - no longer install a .desktop file (will be installed by ubuntuone-installer). |
1319 | + |
1320 | + -- Natalia Bidart (nessita) <natalia.bidart@canonical.com> Mon, 26 Sep 2011 14:55:15 -0300 |
1321 | + |
1322 | ubuntuone-control-panel (1.1.3-0ubuntu2) UNRELEASED; urgency=low |
1323 | |
1324 | [ Paul Stewart ] |
1325 | |
1326 | === modified file 'debian/control' |
1327 | --- debian/control 2011-08-26 21:22:36 +0000 |
1328 | +++ debian/control 2011-09-26 18:38:27 +0000 |
1329 | @@ -17,7 +17,7 @@ |
1330 | ${python:Depends}, |
1331 | python, |
1332 | python-ubuntuone-control-panel (= ${binary:Version}), |
1333 | - ubuntuone-client (>= 1.7.1), |
1334 | + ubuntuone-client (>= 2.0.0), |
1335 | Recommends: ubuntuone-control-panel-gui |
1336 | Description: Ubuntu One Control Panel |
1337 | Desktop application to manage an Ubuntu One account. |
1338 | @@ -37,8 +37,8 @@ |
1339 | python-simplejson, |
1340 | python-twisted-core, |
1341 | python-twisted-web, |
1342 | - python-ubuntuone-client (>= 1.7.1), |
1343 | - ubuntu-sso-client (>= 1.2.0), |
1344 | + python-ubuntuone-client (>= 2.0.0), |
1345 | + ubuntu-sso-client (>= 1.4.0), |
1346 | Description: Ubuntu One Control Panel Python Libraries |
1347 | Ubuntu One Control Panel provides a Python library to manage an Ubuntu One |
1348 | account. |
1349 | @@ -55,11 +55,11 @@ |
1350 | python-defer | python-aptdaemon, |
1351 | python-gobject (>= 2.21.5), |
1352 | python-gtk2, |
1353 | - python-ubuntuone-client (>= 1.7.1), |
1354 | - ubuntu-sso-client (>= 1.2.0), |
1355 | - ubuntuone-client (>= 1.7.1), |
1356 | + python-ubuntuone-client (>= 2.0.0), |
1357 | + ubuntu-sso-client (>= 1.4.0), |
1358 | + ubuntuone-client (>= 2.0.0), |
1359 | ubuntuone-control-panel (= ${binary:Version}), |
1360 | + ubuntuone-installer (>= 2.0.0), |
1361 | Provides: ubuntuone-control-panel-gui |
1362 | Description: Ubuntu One Control Panel |
1363 | GTK+ desktop application to manage an Ubuntu One account. |
1364 | - |
1365 | |
1366 | === modified file 'debian/ubuntuone-control-panel-gtk.install' |
1367 | --- debian/ubuntuone-control-panel-gtk.install 2011-07-22 21:45:30 +0000 |
1368 | +++ debian/ubuntuone-control-panel-gtk.install 2011-09-26 18:38:27 +0000 |
1369 | @@ -1,7 +1,6 @@ |
1370 | debian/tmp/usr/bin/ubuntuone-control-panel-gtk |
1371 | debian/tmp/usr/share/dbus-1/services/com.ubuntuone.controlpanel.gui.service |
1372 | debian/tmp/usr/share/indicators/messages/applications/ubuntuone-control-panel |
1373 | -debian/tmp/usr/share/applications/ubuntuone-control-panel-gtk.desktop |
1374 | debian/tmp/usr/share/ubuntuone-control-panel/gtk/*.ui |
1375 | debian/tmp/usr/share/ubuntuone-control-panel/*.png |
1376 | debian/tmp/usr/share/man/man1/ubuntuone-control-panel-gtk.* |
1377 | |
1378 | === modified file 'docs/ubuntuone-control-panel-gtk.1' |
1379 | --- docs/ubuntuone-control-panel-gtk.1 2010-12-06 12:27:11 +0000 |
1380 | +++ docs/ubuntuone-control-panel-gtk.1 2011-09-26 18:38:27 +0000 |
1381 | @@ -1,7 +1,7 @@ |
1382 | .TH UBUNTUONE-CONTROL-PANEL-GTK 1 |
1383 | |
1384 | .SH NAME |
1385 | -ubuntuone-control-panel-gtk \- A GTK UI for managing a Ubuntu One account |
1386 | +ubuntuone-control-panel-gtk \- A GTK UI for managing an Ubuntu One account |
1387 | |
1388 | .SH SYNOPSYS |
1389 | .B ubutuone-control-panel-gtk |
1390 | @@ -9,7 +9,7 @@ |
1391 | .SH DESCRIPTION |
1392 | This manual page briefly documents the |
1393 | .BR ubuntuone-control-panel-gtk |
1394 | -process, which provides a desktop application to manage a Ubuntu One account. |
1395 | +process, which provides a desktop application to manage an Ubuntu One account. |
1396 | |
1397 | .SH AUTHOR |
1398 | This manual page was written by Natalia Bidart <natalia.bidart@canonical.com> |
1399 | |
1400 | === modified file 'po/POTFILES.in' |
1401 | --- po/POTFILES.in 2011-07-22 21:26:48 +0000 |
1402 | +++ po/POTFILES.in 2011-09-26 18:38:27 +0000 |
1403 | @@ -1,4 +1,3 @@ |
1404 | -ubuntuone-control-panel-gtk.desktop.in |
1405 | ubuntuone/controlpanel/gui/__init__.py |
1406 | [type: gettext/glade] data/gtk/dashboard.ui |
1407 | [type: gettext/glade] data/gtk/device.ui |
1408 | |
1409 | === removed file 'po/ubuntuone-control-panel.pot' |
1410 | --- po/ubuntuone-control-panel.pot 2011-08-25 19:37:14 +0000 |
1411 | +++ po/ubuntuone-control-panel.pot 1970-01-01 00:00:00 +0000 |
1412 | @@ -1,486 +0,0 @@ |
1413 | -# SOME DESCRIPTIVE TITLE. |
1414 | -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
1415 | -# This file is distributed under the same license as the PACKAGE package. |
1416 | -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
1417 | -# |
1418 | -#, fuzzy |
1419 | -msgid "" |
1420 | -msgstr "" |
1421 | -"Project-Id-Version: PACKAGE VERSION\n" |
1422 | -"Report-Msgid-Bugs-To: \n" |
1423 | -"POT-Creation-Date: 2011-08-25 15:26-0400\n" |
1424 | -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
1425 | -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
1426 | -"Language-Team: LANGUAGE <LL@li.org>\n" |
1427 | -"Language: \n" |
1428 | -"MIME-Version: 1.0\n" |
1429 | -"Content-Type: text/plain; charset=CHARSET\n" |
1430 | -"Content-Transfer-Encoding: 8bit\n" |
1431 | - |
1432 | -#: ../ubuntuone-control-panel-gtk.desktop.in.h:1 |
1433 | -msgid "Configure and manage your Ubuntu One account" |
1434 | -msgstr "" |
1435 | - |
1436 | -#: ../ubuntuone/controlpanel/gui/__init__.py:72 |
1437 | -msgid "Always in sync" |
1438 | -msgstr "" |
1439 | - |
1440 | -#: ../ubuntuone/controlpanel/gui/__init__.py:73 |
1441 | -msgid "Firefox extension" |
1442 | -msgstr "" |
1443 | - |
1444 | -#: ../ubuntuone/controlpanel/gui/__init__.py:74 |
1445 | -msgid "Connect to Ubuntu One" |
1446 | -msgstr "" |
1447 | - |
1448 | -#: ../ubuntuone/controlpanel/gui/__init__.py:75 |
1449 | -msgid "Evolution plug-in" |
1450 | -msgstr "" |
1451 | - |
1452 | -#: ../ubuntuone/controlpanel/gui/__init__.py:76 |
1453 | -msgid "There was a problem while retrieving the credentials." |
1454 | -msgstr "" |
1455 | - |
1456 | -#: ../ubuntuone/controlpanel/gui/__init__.py:77 |
1457 | -msgid "View your personal details and service summary" |
1458 | -msgstr "" |
1459 | - |
1460 | -#: ../ubuntuone/controlpanel/gui/__init__.py:79 |
1461 | -msgid "Welcome to Ubuntu One!" |
1462 | -msgstr "" |
1463 | - |
1464 | -#: ../ubuntuone/controlpanel/gui/__init__.py:80 |
1465 | -msgid "" |
1466 | -"The information could not be retrieved. Maybe your internet connection is " |
1467 | -"down?" |
1468 | -msgstr "" |
1469 | - |
1470 | -#: ../ubuntuone/controlpanel/gui/__init__.py:83 |
1471 | -#: ../ubuntuone/controlpanel/gui/__init__.py:156 |
1472 | -msgid "" |
1473 | -"The settings could not be changed,\n" |
1474 | -"previous values were restored." |
1475 | -msgstr "" |
1476 | - |
1477 | -#: ../ubuntuone/controlpanel/gui/__init__.py:85 |
1478 | -msgid "Are you sure you want to remove this device from Ubuntu One?" |
1479 | -msgstr "" |
1480 | - |
1481 | -#: ../ubuntuone/controlpanel/gui/__init__.py:88 |
1482 | -msgid "The device could not be removed." |
1483 | -msgstr "" |
1484 | - |
1485 | -#: ../ubuntuone/controlpanel/gui/__init__.py:89 |
1486 | -msgid "Manage devices registered with your personal cloud" |
1487 | -msgstr "" |
1488 | - |
1489 | -#: ../ubuntuone/controlpanel/gui/__init__.py:91 |
1490 | -msgid "The devices connected with your personal cloud are listed below." |
1491 | -msgstr "" |
1492 | - |
1493 | -#: ../ubuntuone/controlpanel/gui/__init__.py:93 |
1494 | -msgid "Explore" |
1495 | -msgstr "" |
1496 | - |
1497 | -#: ../ubuntuone/controlpanel/gui/__init__.py:94 |
1498 | -#, python-format |
1499 | -msgid "<i>%(package_name)s</i> could not be installed" |
1500 | -msgstr "" |
1501 | - |
1502 | -#: ../ubuntuone/controlpanel/gui/__init__.py:95 |
1503 | -msgid "Sync another folder with your cloud" |
1504 | -msgstr "" |
1505 | - |
1506 | -#: ../ubuntuone/controlpanel/gui/__init__.py:96 |
1507 | -#, python-format |
1508 | -msgid "" |
1509 | -"The chosen directory \"%(folder_path)s\" is not valid. \n" |
1510 | -"\n" |
1511 | -"Please choose a folder inside your \"%(home_folder)s\" directory, and not " |
1512 | -"overlapping with any existing cloud folder." |
1513 | -msgstr "" |
1514 | - |
1515 | -#: ../ubuntuone/controlpanel/gui/__init__.py:101 |
1516 | -msgid "My personal folders" |
1517 | -msgstr "" |
1518 | - |
1519 | -#: ../ubuntuone/controlpanel/gui/__init__.py:102 |
1520 | -#, python-format |
1521 | -msgid "Shared by %(other_user_display_name)s" |
1522 | -msgstr "" |
1523 | - |
1524 | -#: ../ubuntuone/controlpanel/gui/__init__.py:103 |
1525 | -#, python-format |
1526 | -msgid "" |
1527 | -"The contents of your cloud folder will be merged with your local folder " |
1528 | -"\"%(folder_path)s\" when subscribing.\n" |
1529 | -"Do you want to subscribe to this cloud folder?" |
1530 | -msgstr "" |
1531 | - |
1532 | -#: ../ubuntuone/controlpanel/gui/__init__.py:107 |
1533 | -msgid "Manage your cloud folders" |
1534 | -msgstr "" |
1535 | - |
1536 | -#: ../ubuntuone/controlpanel/gui/__init__.py:109 |
1537 | -msgid "" |
1538 | -"Select which folders from your cloud you want to sync with this computer" |
1539 | -msgstr "" |
1540 | - |
1541 | -#: ../ubuntuone/controlpanel/gui/__init__.py:111 |
1542 | -msgid "Connect" |
1543 | -msgstr "" |
1544 | - |
1545 | -#: ../ubuntuone/controlpanel/gui/__init__.py:112 |
1546 | -msgid "Connect the file sync service with your personal cloud" |
1547 | -msgstr "" |
1548 | - |
1549 | -#: ../ubuntuone/controlpanel/gui/__init__.py:114 |
1550 | -msgid "File Sync is disabled." |
1551 | -msgstr "" |
1552 | - |
1553 | -#: ../ubuntuone/controlpanel/gui/__init__.py:115 |
1554 | -msgid "Disconnect" |
1555 | -msgstr "" |
1556 | - |
1557 | -#: ../ubuntuone/controlpanel/gui/__init__.py:116 |
1558 | -msgid "Disconnect the file sync service from your personal cloud" |
1559 | -msgstr "" |
1560 | - |
1561 | -#: ../ubuntuone/controlpanel/gui/__init__.py:118 |
1562 | -msgid "File Sync is disconnected." |
1563 | -msgstr "" |
1564 | - |
1565 | -#: ../ubuntuone/controlpanel/gui/__init__.py:119 |
1566 | -msgid "Enable" |
1567 | -msgstr "" |
1568 | - |
1569 | -#: ../ubuntuone/controlpanel/gui/__init__.py:120 |
1570 | -msgid "Enable the file sync service" |
1571 | -msgstr "" |
1572 | - |
1573 | -#: ../ubuntuone/controlpanel/gui/__init__.py:121 |
1574 | -msgid "File Sync error." |
1575 | -msgstr "" |
1576 | - |
1577 | -#: ../ubuntuone/controlpanel/gui/__init__.py:122 |
1578 | -msgid "File Sync is up-to-date." |
1579 | -msgstr "" |
1580 | - |
1581 | -#: ../ubuntuone/controlpanel/gui/__init__.py:123 |
1582 | -msgid "Restart" |
1583 | -msgstr "" |
1584 | - |
1585 | -#: ../ubuntuone/controlpanel/gui/__init__.py:124 |
1586 | -msgid "Restart the file sync service" |
1587 | -msgstr "" |
1588 | - |
1589 | -#: ../ubuntuone/controlpanel/gui/__init__.py:125 |
1590 | -msgid "File Sync" |
1591 | -msgstr "" |
1592 | - |
1593 | -#: ../ubuntuone/controlpanel/gui/__init__.py:126 |
1594 | -msgid "Start" |
1595 | -msgstr "" |
1596 | - |
1597 | -#: ../ubuntuone/controlpanel/gui/__init__.py:127 |
1598 | -msgid "Start the file sync service" |
1599 | -msgstr "" |
1600 | - |
1601 | -#: ../ubuntuone/controlpanel/gui/__init__.py:128 |
1602 | -msgid "File Sync starting..." |
1603 | -msgstr "" |
1604 | - |
1605 | -#: ../ubuntuone/controlpanel/gui/__init__.py:129 |
1606 | -msgid "Stop" |
1607 | -msgstr "" |
1608 | - |
1609 | -#: ../ubuntuone/controlpanel/gui/__init__.py:130 |
1610 | -msgid "Stop the file sync service" |
1611 | -msgstr "" |
1612 | - |
1613 | -#: ../ubuntuone/controlpanel/gui/__init__.py:131 |
1614 | -msgid "File Sync is stopped." |
1615 | -msgstr "" |
1616 | - |
1617 | -#: ../ubuntuone/controlpanel/gui/__init__.py:132 |
1618 | -msgid "File Sync in progress..." |
1619 | -msgstr "" |
1620 | - |
1621 | -#: ../ubuntuone/controlpanel/gui/__init__.py:133 |
1622 | -#, python-format |
1623 | -msgid "%(free_space)s available storage" |
1624 | -msgstr "" |
1625 | - |
1626 | -#: ../ubuntuone/controlpanel/gui/__init__.py:134 |
1627 | -#, python-format |
1628 | -msgid "Hi %(user_display_name)s" |
1629 | -msgstr "" |
1630 | - |
1631 | -#: ../ubuntuone/controlpanel/gui/__init__.py:135 |
1632 | -#, python-format |
1633 | -msgid "" |
1634 | -"You need to install the package <i>%(package_name)s</i> in order to enable " |
1635 | -"more sync services." |
1636 | -msgstr "" |
1637 | - |
1638 | -#: ../ubuntuone/controlpanel/gui/__init__.py:137 |
1639 | -#, python-format |
1640 | -msgid "Install the %(plugin_name)s for the sync service: %(service_name)s" |
1641 | -msgstr "" |
1642 | - |
1643 | -#: ../ubuntuone/controlpanel/gui/__init__.py:139 |
1644 | -#, python-format |
1645 | -msgid "Installation of <i>%(package_name)s</i> in progress" |
1646 | -msgstr "" |
1647 | - |
1648 | -#: ../ubuntuone/controlpanel/gui/__init__.py:140 |
1649 | -msgid "Loading..." |
1650 | -msgstr "" |
1651 | - |
1652 | -#: ../ubuntuone/controlpanel/gui/__init__.py:141 |
1653 | -#, python-format |
1654 | -msgid "%(app_name)s Control Panel" |
1655 | -msgstr "" |
1656 | - |
1657 | -#: ../ubuntuone/controlpanel/gui/__init__.py:142 |
1658 | -msgid "My folders" |
1659 | -msgstr "" |
1660 | - |
1661 | -#: ../ubuntuone/controlpanel/gui/__init__.py:143 |
1662 | -msgid "[unknown user name]" |
1663 | -msgstr "" |
1664 | - |
1665 | -#: ../ubuntuone/controlpanel/gui/__init__.py:144 |
1666 | -msgid "Purchased Music" |
1667 | -msgstr "" |
1668 | - |
1669 | -#: ../ubuntuone/controlpanel/gui/__init__.py:146 |
1670 | -#, python-format |
1671 | -msgid "An internet connection is required to join or sign in to %(app_name)s." |
1672 | -msgstr "" |
1673 | - |
1674 | -#: ../ubuntuone/controlpanel/gui/__init__.py:148 |
1675 | -msgid "No devices to show." |
1676 | -msgstr "" |
1677 | - |
1678 | -#: ../ubuntuone/controlpanel/gui/__init__.py:149 |
1679 | -msgid "No folders to show." |
1680 | -msgstr "" |
1681 | - |
1682 | -#: ../ubuntuone/controlpanel/gui/__init__.py:150 |
1683 | -msgid "There is no Ubuntu One pairing record." |
1684 | -msgstr "" |
1685 | - |
1686 | -#: ../ubuntuone/controlpanel/gui/__init__.py:151 |
1687 | -#, python-format |
1688 | -msgid "%(percentage)s used" |
1689 | -msgstr "" |
1690 | - |
1691 | -#: ../ubuntuone/controlpanel/gui/__init__.py:152 |
1692 | -#, python-format |
1693 | -msgid "Using %(used)s of %(total)s (%(percentage).0f%%)" |
1694 | -msgstr "" |
1695 | - |
1696 | -#: ../ubuntuone/controlpanel/gui/__init__.py:153 |
1697 | -#, python-format |
1698 | -msgid "%(used)s of %(total)s" |
1699 | -msgstr "" |
1700 | - |
1701 | -#: ../ubuntuone/controlpanel/gui/__init__.py:154 |
1702 | -msgid "Manage the sync services" |
1703 | -msgstr "" |
1704 | - |
1705 | -#: ../ubuntuone/controlpanel/gui/__init__.py:155 |
1706 | -msgid "Enable the sync services for this computer." |
1707 | -msgstr "" |
1708 | - |
1709 | -#: ../ubuntuone/controlpanel/gui/__init__.py:158 |
1710 | -msgid "Manage the shares offered to others" |
1711 | -msgstr "" |
1712 | - |
1713 | -#: ../ubuntuone/controlpanel/gui/__init__.py:159 |
1714 | -msgid "Manage permissions for shares made to other users." |
1715 | -msgstr "" |
1716 | - |
1717 | -#: ../ubuntuone/controlpanel/gui/__init__.py:160 |
1718 | -#, python-format |
1719 | -msgid "<i>%(package_name)s</i> was successfully installed" |
1720 | -msgstr "" |
1721 | - |
1722 | -#: ../ubuntuone/controlpanel/gui/__init__.py:161 ../data/gtk/volumes.ui.h:1 |
1723 | -msgid "Sync locally?" |
1724 | -msgstr "" |
1725 | - |
1726 | -#: ../ubuntuone/controlpanel/gui/__init__.py:162 |
1727 | -msgid "Value could not be retrieved." |
1728 | -msgstr "" |
1729 | - |
1730 | -#: ../ubuntuone/controlpanel/gui/__init__.py:163 |
1731 | -msgid "Unknown error" |
1732 | -msgstr "" |
1733 | - |
1734 | -#: ../data/gtk/dashboard.ui.h:1 |
1735 | -msgid "<b>Personal details</b>" |
1736 | -msgstr "" |
1737 | - |
1738 | -#: ../data/gtk/dashboard.ui.h:2 |
1739 | -msgid "<b>Your services</b>" |
1740 | -msgstr "" |
1741 | - |
1742 | -#: ../data/gtk/dashboard.ui.h:3 |
1743 | -msgid "Buy storage and plans" |
1744 | -msgstr "" |
1745 | - |
1746 | -#: ../data/gtk/dashboard.ui.h:4 |
1747 | -msgid "Edit account details" |
1748 | -msgstr "" |
1749 | - |
1750 | -#: ../data/gtk/device.ui.h:1 |
1751 | -msgid "KiB/s" |
1752 | -msgstr "" |
1753 | - |
1754 | -#: ../data/gtk/device.ui.h:2 |
1755 | -msgid "Limit file sync bandwidth usage" |
1756 | -msgstr "" |
1757 | - |
1758 | -#: ../data/gtk/device.ui.h:3 |
1759 | -msgid "Max download speed:" |
1760 | -msgstr "" |
1761 | - |
1762 | -#: ../data/gtk/device.ui.h:4 |
1763 | -msgid "Max upload speed:" |
1764 | -msgstr "" |
1765 | - |
1766 | -#: ../data/gtk/device.ui.h:5 |
1767 | -msgid "Show activity notifications" |
1768 | -msgstr "" |
1769 | - |
1770 | -#: ../data/gtk/install.ui.h:1 |
1771 | -msgid "_Install now" |
1772 | -msgstr "" |
1773 | - |
1774 | -#: ../data/gtk/management.ui.h:1 |
1775 | -msgid "Account" |
1776 | -msgstr "" |
1777 | - |
1778 | -#: ../data/gtk/management.ui.h:2 |
1779 | -msgid "Cloud Folders" |
1780 | -msgstr "" |
1781 | - |
1782 | -#: ../data/gtk/management.ui.h:3 |
1783 | -msgid "Community Support" |
1784 | -msgstr "" |
1785 | - |
1786 | -#: ../data/gtk/management.ui.h:4 |
1787 | -msgid "Devices" |
1788 | -msgstr "" |
1789 | - |
1790 | -#: ../data/gtk/management.ui.h:5 |
1791 | -msgid "Official Support" |
1792 | -msgstr "" |
1793 | - |
1794 | -#: ../data/gtk/management.ui.h:6 |
1795 | -msgid "Services" |
1796 | -msgstr "" |
1797 | - |
1798 | -#: ../data/gtk/management.ui.h:7 |
1799 | -msgid "Shares" |
1800 | -msgstr "" |
1801 | - |
1802 | -#: ../data/gtk/management.ui.h:8 |
1803 | -msgid "Talk to us on:" |
1804 | -msgstr "" |
1805 | - |
1806 | -#: ../data/gtk/management.ui.h:9 |
1807 | -msgid "http://twitter.com/ubuntuone" |
1808 | -msgstr "" |
1809 | - |
1810 | -#: ../data/gtk/management.ui.h:10 |
1811 | -msgid "http://www.facebook.com/ubuntuone" |
1812 | -msgstr "" |
1813 | - |
1814 | -#: ../data/gtk/overview.ui.h:1 |
1815 | -msgid "" |
1816 | -"<span font=\"24\" foreground=\"#4d4d4d\">The Power of Your Personal Cloud</" |
1817 | -"span>" |
1818 | -msgstr "" |
1819 | - |
1820 | -#: ../data/gtk/overview.ui.h:2 |
1821 | -msgid "<span font_size=\"xx-large\" foreground=\"#4d4d4d\">Join now</span>" |
1822 | -msgstr "" |
1823 | - |
1824 | -#: ../data/gtk/overview.ui.h:3 |
1825 | -msgid "<span foreground=\"#909090\">2GB of free storage</span>" |
1826 | -msgstr "" |
1827 | - |
1828 | -#: ../data/gtk/overview.ui.h:4 |
1829 | -msgid "<span foreground=\"#909090\">Learn More</span>" |
1830 | -msgstr "" |
1831 | - |
1832 | -#: ../data/gtk/overview.ui.h:5 |
1833 | -msgid "" |
1834 | -"Files Anywhere\n" |
1835 | -"<span foreground=\"#909090\">Back up and access your files from Ubuntu, " |
1836 | -"Windows, Web or Mobile</span>" |
1837 | -msgstr "" |
1838 | - |
1839 | -#: ../data/gtk/overview.ui.h:7 |
1840 | -msgid "I already have an account!" |
1841 | -msgstr "" |
1842 | - |
1843 | -#: ../data/gtk/overview.ui.h:8 |
1844 | -msgid "" |
1845 | -"Keep Connected\n" |
1846 | -"<span foreground=\"#909090\">Unify your contacts across Desktop, Mobile and " |
1847 | -"Web</span>" |
1848 | -msgstr "" |
1849 | - |
1850 | -#: ../data/gtk/overview.ui.h:10 |
1851 | -msgid "" |
1852 | -"Rock Out\n" |
1853 | -"<span foreground=\"#909090\">Your entire collection follows you around with " |
1854 | -"music streaming to Android and iPhone</span>" |
1855 | -msgstr "" |
1856 | - |
1857 | -#: ../data/gtk/overview.ui.h:12 |
1858 | -msgid "" |
1859 | -"Stay Productive\n" |
1860 | -"<span foreground=\"#909090\">Keep your Firefox bookmarks and Tomboy notes " |
1861 | -"synced</span>" |
1862 | -msgstr "" |
1863 | - |
1864 | -#: ../data/gtk/services.ui.h:1 |
1865 | -msgid "<span font_size=\"small\">Bookmarks sync works with Firefox</span>" |
1866 | -msgstr "" |
1867 | - |
1868 | -#: ../data/gtk/services.ui.h:2 |
1869 | -msgid "" |
1870 | -"<span font_size=\"small\">Enable and then choose which folders you want to " |
1871 | -"access from the Web or any device you connected to Ubuntu One\n" |
1872 | -"\n" |
1873 | -"Simply drag and drop any file or folder to your Ubuntu One folder on this " |
1874 | -"computer</span>" |
1875 | -msgstr "" |
1876 | - |
1877 | -#: ../data/gtk/services.ui.h:5 |
1878 | -msgid "" |
1879 | -"<span font_size=\"small\">Once enabled, visit the <a href=\"https://one." |
1880 | -"ubuntu.com\">Ubuntu One website</a> to manage your contacts, including Gmail " |
1881 | -"and Facebook import</span>" |
1882 | -msgstr "" |
1883 | - |
1884 | -#: ../data/gtk/services.ui.h:6 |
1885 | -msgid "Enable Bookmarks Sync" |
1886 | -msgstr "" |
1887 | - |
1888 | -#: ../data/gtk/services.ui.h:7 |
1889 | -msgid "Enable Contacts Sync" |
1890 | -msgstr "" |
1891 | - |
1892 | -#: ../data/gtk/services.ui.h:8 |
1893 | -msgid "Enable File Sync" |
1894 | -msgstr "" |
1895 | - |
1896 | -#: ../data/gtk/services.ui.h:9 |
1897 | -msgid "_Show me my Ubuntu One folder" |
1898 | -msgstr "" |
1899 | |
1900 | === modified file 'setup.py' |
1901 | --- setup.py 2011-08-25 19:37:14 +0000 |
1902 | +++ setup.py 2011-09-26 18:38:27 +0000 |
1903 | @@ -229,12 +229,12 @@ |
1904 | |
1905 | DistUtilsExtra.auto.setup( |
1906 | name='ubuntuone-control-panel', |
1907 | - version='1.1.3', |
1908 | + version='2.0.0', |
1909 | license='GPL v3', |
1910 | author='Natalia Bidart', |
1911 | author_email='natalia.bidart@canonical.com', |
1912 | description='Ubuntu One Control Panel', |
1913 | - long_description='Application to manage a Ubuntu One account. Provides' \ |
1914 | + long_description='Application to manage an Ubuntu One account. Provides' \ |
1915 | ' a DBus service to query/modify all the Ubuntu One bits.', |
1916 | url='https://launchpad.net/ubuntuone-control-panel', |
1917 | packages=[ |
1918 | |
1919 | === removed file 'ubuntuone-control-panel-gtk.desktop.in' |
1920 | --- ubuntuone-control-panel-gtk.desktop.in 2011-07-22 21:26:48 +0000 |
1921 | +++ ubuntuone-control-panel-gtk.desktop.in 1970-01-01 00:00:00 +0000 |
1922 | @@ -1,11 +0,0 @@ |
1923 | -[Desktop Entry] |
1924 | -Name=Ubuntu One |
1925 | -_Comment=Configure and manage your Ubuntu One account |
1926 | -Exec=ubuntuone-control-panel-gtk |
1927 | -Icon=ubuntuone |
1928 | -Terminal=false |
1929 | -Type=Application |
1930 | -Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalSettings |
1931 | -StartupNotify=true |
1932 | -X-Ayatana-Appmenu-Show-Stubs=False |
1933 | -X-GNOME-Settings-Panel=ubuntuone |
1934 | |
1935 | === modified file 'ubuntuone-control-panel.in' |
1936 | --- ubuntuone-control-panel.in 2011-01-27 22:10:30 +0000 |
1937 | +++ ubuntuone-control-panel.in 2011-09-26 18:38:27 +0000 |
1938 | @@ -1,1 +1,1 @@ |
1939 | -@prefix@/share/applications/ubuntuone-control-panel-gtk.desktop |
1940 | +@prefix@/share/applications/ubuntuone-installer.desktop |
1941 | |
1942 | === modified file 'ubuntuone/controlpanel/backend.py' |
1943 | --- ubuntuone/controlpanel/backend.py 2011-08-25 19:37:14 +0000 |
1944 | +++ ubuntuone/controlpanel/backend.py 2011-09-26 18:38:27 +0000 |
1945 | @@ -67,8 +67,7 @@ |
1946 | MSG_KEY = 'message' |
1947 | STATUS_KEY = 'status' |
1948 | |
1949 | -BOOKMARKS_PKG = 'xul-ext-bindwood' |
1950 | -CONTACTS_PKG = 'evolution-couchdb' |
1951 | +CONTACTS_PKG = 'thunderbird-couchdb' |
1952 | |
1953 | |
1954 | def append_path_sep(path): |
1955 | @@ -99,7 +98,7 @@ |
1956 | result = yield f(instance, *args, **kwargs) |
1957 | except UnauthorizedError, e: |
1958 | logger.exception('process_unauthorized (clearing credentials):') |
1959 | - yield instance.login_client.clear_credentials() |
1960 | + yield instance.clear_credentials() |
1961 | raise e |
1962 | |
1963 | returnValue(result) |
1964 | @@ -138,6 +137,8 @@ |
1965 | self.sd_client = sd_client.SyncDaemonClient() |
1966 | self.wc = web_client_factory(self.get_credentials) |
1967 | |
1968 | + logger.info('ControlBackend: instance started.') |
1969 | + |
1970 | def _process_file_sync_status(self, status): |
1971 | """Process raw file sync status into custom format. |
1972 | |
1973 | @@ -297,16 +298,32 @@ |
1974 | @inlineCallbacks |
1975 | def get_credentials(self): |
1976 | """Find credentials.""" |
1977 | - if self._credentials is None: |
1978 | + if not self._credentials: |
1979 | self._credentials = yield self.login_client.find_credentials() |
1980 | returnValue(self._credentials) |
1981 | |
1982 | @inlineCallbacks |
1983 | + def clear_credentials(self): |
1984 | + """Clear the credentials.""" |
1985 | + self._credentials = None |
1986 | + yield self.login_client.clear_credentials() |
1987 | + |
1988 | + @inlineCallbacks |
1989 | def get_token(self): |
1990 | """Return the token from the credentials.""" |
1991 | credentials = yield self.get_credentials() |
1992 | returnValue(credentials["token"]) |
1993 | |
1994 | + @log_call(logger.debug, with_args=False) |
1995 | + @inlineCallbacks |
1996 | + def login(self, email, password): |
1997 | + """Login using 'email' and 'password'.""" |
1998 | + result = yield self.login_client.login_email_password( |
1999 | + email=email, password=password) |
2000 | + # cache credentils |
2001 | + self._credentials = result |
2002 | + returnValue(result) |
2003 | + |
2004 | @inlineCallbacks |
2005 | def device_is_local(self, device_id): |
2006 | """Return whether 'device_id' is the local devicew or not.""" |
2007 | @@ -480,7 +497,7 @@ |
2008 | if is_local: |
2009 | logger.warning('remove_device: device is local! removing and ' |
2010 | 'clearing credentials.') |
2011 | - yield self.login_client.clear_credentials() |
2012 | + yield self.clear_credentials() |
2013 | |
2014 | returnValue(device_id) |
2015 | |
2016 | @@ -580,6 +597,7 @@ |
2017 | 'list (%r).', vid, self._volumes[vid]) |
2018 | self._volumes[vid] = share |
2019 | |
2020 | + share[u'realpath'] = share[u'path'] |
2021 | nicer_path = share[u'path'].replace(shares_dir, shares_dir_link) |
2022 | share[u'path'] = nicer_path |
2023 | share[u'subscribed'] = bool(share[u'subscribed']) |
2024 | @@ -690,9 +708,7 @@ |
2025 | result = [] |
2026 | for rep in replications: |
2027 | dependency = '' |
2028 | - if rep == replication_client.BOOKMARKS: |
2029 | - dependency = BOOKMARKS_PKG |
2030 | - elif rep == replication_client.CONTACTS: |
2031 | + if rep == replication_client.CONTACTS: |
2032 | dependency = CONTACTS_PKG |
2033 | |
2034 | repd = { |
2035 | @@ -717,18 +733,6 @@ |
2036 | returnValue(replication_id) |
2037 | |
2038 | @log_call(logger.debug) |
2039 | - def query_bookmark_extension(self): |
2040 | - """True if the bookmark extension has been installed.""" |
2041 | - # still pending (LP: #673672) |
2042 | - returnValue(False) |
2043 | - |
2044 | - @log_call(logger.debug) |
2045 | - def install_bookmarks_extension(self): |
2046 | - """Install the extension to sync bookmarks.""" |
2047 | - # still pending (LP: #673673) |
2048 | - returnValue(None) |
2049 | - |
2050 | - @log_call(logger.debug) |
2051 | @inlineCallbacks |
2052 | def file_sync_settings_info(self): |
2053 | """Get the file sync settings info.""" |
2054 | |
2055 | === added file 'ubuntuone/controlpanel/cache.py' |
2056 | --- ubuntuone/controlpanel/cache.py 1970-01-01 00:00:00 +0000 |
2057 | +++ ubuntuone/controlpanel/cache.py 2011-09-26 18:38:27 +0000 |
2058 | @@ -0,0 +1,50 @@ |
2059 | +# -*- coding: utf-8 -*- |
2060 | + |
2061 | +# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
2062 | +# |
2063 | +# Copyright 2011 Canonical Ltd. |
2064 | +# |
2065 | +# This program is free software: you can redistribute it and/or modify it |
2066 | +# under the terms of the GNU General Public License version 3, as published |
2067 | +# by the Free Software Foundation. |
2068 | +# |
2069 | +# This program is distributed in the hope that it will be useful, but |
2070 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
2071 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2072 | +# PURPOSE. See the GNU General Public License for more details. |
2073 | +# |
2074 | +# You should have received a copy of the GNU General Public License along |
2075 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
2076 | + |
2077 | +"""The base object that holds a backend instance.""" |
2078 | + |
2079 | +from ubuntuone.controlpanel import backend |
2080 | + |
2081 | + |
2082 | +class Cache(object): |
2083 | + """The base object that caches stuff.""" |
2084 | + |
2085 | + logger = None |
2086 | + _shared_objects = {} |
2087 | + |
2088 | + def __init__(self, *args, **kwargs): |
2089 | + """Initialize the object using 'backend' as backend.""" |
2090 | + super(Cache, self).__init__() |
2091 | + if self.logger is not None: |
2092 | + self.logger.debug('%s: started.', self.__class__.__name__) |
2093 | + |
2094 | + def get_backend(self): |
2095 | + """A cached ControlBackend instance.""" |
2096 | + if not self._shared_objects: |
2097 | + self._shared_objects['backend'] = backend.ControlBackend() |
2098 | + return self._shared_objects['backend'] |
2099 | + |
2100 | + def set_backend(self, new_value): |
2101 | + """Set a new ControlBackend instance.""" |
2102 | + self._shared_objects['backend'] = new_value |
2103 | + |
2104 | + backend = property(fget=get_backend, fset=set_backend) |
2105 | + |
2106 | + def clear(self): |
2107 | + """Clear all cached objects.""" |
2108 | + self._shared_objects = {} |
2109 | |
2110 | === modified file 'ubuntuone/controlpanel/dbus_service.py' |
2111 | --- ubuntuone/controlpanel/dbus_service.py 2011-08-25 19:37:14 +0000 |
2112 | +++ ubuntuone/controlpanel/dbus_service.py 2011-09-26 18:38:27 +0000 |
2113 | @@ -563,46 +563,6 @@ |
2114 | |
2115 | #--- |
2116 | |
2117 | - @log_call(logger.debug) |
2118 | - @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") |
2119 | - def query_bookmark_extension(self): |
2120 | - """Check if the extension to sync bookmarks is installed.""" |
2121 | - d = self.backend.query_bookmark_extension() |
2122 | - d.addCallback(self.QueryBookmarksResult) |
2123 | - d.addErrback(self.transform(self.QueryBookmarksError)) |
2124 | - |
2125 | - @log_call(logger.debug) |
2126 | - @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="b") |
2127 | - def QueryBookmarksResult(self, enabled): |
2128 | - """The bookmark extension is or is not installed.""" |
2129 | - |
2130 | - @log_call(logger.error) |
2131 | - @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}") |
2132 | - def QueryBookmarksError(self, error): |
2133 | - """Problem getting the status of the extension.""" |
2134 | - |
2135 | - #--- |
2136 | - |
2137 | - @log_call(logger.info) |
2138 | - @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") |
2139 | - def install_bookmarks_extension(self): |
2140 | - """Install the extension to sync bookmarks.""" |
2141 | - d = self.backend.install_bookmarks_extension() |
2142 | - d.addCallback(lambda _: self.InstallBookmarksSuccess()) |
2143 | - d.addErrback(self.transform(self.InstallBookmarksError)) |
2144 | - |
2145 | - @log_call(logger.info) |
2146 | - @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="") |
2147 | - def InstallBookmarksSuccess(self): |
2148 | - """The extension to sync bookmarks has been installed.""" |
2149 | - |
2150 | - @log_call(logger.error) |
2151 | - @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}") |
2152 | - def InstallBookmarksError(self, error): |
2153 | - """Problem installing the extension to sync bookmarks.""" |
2154 | - |
2155 | - #--- |
2156 | - |
2157 | @log_call(logger.info) |
2158 | @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="") |
2159 | def shutdown(self): |
2160 | |
2161 | === modified file 'ubuntuone/controlpanel/dbustests/test_dbus_service.py' |
2162 | --- ubuntuone/controlpanel/dbustests/test_dbus_service.py 2011-08-25 19:37:14 +0000 |
2163 | +++ ubuntuone/controlpanel/dbustests/test_dbus_service.py 2011-09-26 18:38:27 +0000 |
2164 | @@ -50,7 +50,7 @@ |
2165 | "limit_bandwidth": True, |
2166 | "max_upload_speed": 12345, |
2167 | "max_download_speed": 54321, |
2168 | - "available_services": "files, contacts, music, bookmarks", |
2169 | + "available_services": "files, contacts, music", |
2170 | "enabled_services": "files, music", |
2171 | }, |
2172 | { |
2173 | @@ -59,8 +59,8 @@ |
2174 | "date_added": "2010-09-22T20:45:38.0", |
2175 | "type": "computer", |
2176 | "configurable": False, |
2177 | - "available_services": "files, contacts, bookmarks", |
2178 | - "enabled_services": "files, bookmarks", |
2179 | + "available_services": "files, contacts", |
2180 | + "enabled_services": "files", |
2181 | }, |
2182 | ] |
2183 | |
2184 | @@ -244,14 +244,6 @@ |
2185 | """Configure a given replication.""" |
2186 | return self._process(replication_id) |
2187 | |
2188 | - def query_bookmark_extension(self): |
2189 | - """True if the bookmark extension has been installed.""" |
2190 | - return self._process(False) |
2191 | - |
2192 | - def install_bookmarks_extension(self): |
2193 | - """Install the extension to sync bookmarks.""" |
2194 | - return self._process(None) |
2195 | - |
2196 | def shutdown(self): |
2197 | """Stop this service.""" |
2198 | self.shutdown_func() |
2199 | @@ -616,29 +608,6 @@ |
2200 | expected_replication_id, {'enabled': ''}) |
2201 | return self.assert_correct_method_call(*args) |
2202 | |
2203 | - def test_query_bookmarks_extension(self): |
2204 | - """The bookmarks extension is queried.""" |
2205 | - |
2206 | - def got_signal(enabled): |
2207 | - """The correct status was received.""" |
2208 | - self.assertEqual(enabled, False) |
2209 | - self.deferred.callback("success") |
2210 | - |
2211 | - args = ("QueryBookmarksResult", "QueryBookmarksError", got_signal, |
2212 | - self.backend.query_bookmark_extension) |
2213 | - return self.assert_correct_method_call(*args) |
2214 | - |
2215 | - def test_install_bookmarks_extension(self): |
2216 | - """The bookmarks extension is installed.""" |
2217 | - |
2218 | - def got_signal(): |
2219 | - """The extension was installed.""" |
2220 | - self.deferred.callback("success") |
2221 | - |
2222 | - args = ("InstallBookmarksSuccess", "InstallBookmarksError", got_signal, |
2223 | - self.backend.install_bookmarks_extension) |
2224 | - return self.assert_correct_method_call(*args) |
2225 | - |
2226 | |
2227 | class OperationsErrorTestCase(OperationsTestCase): |
2228 | """Test for the DBus service operations when there is an error.""" |
2229 | |
2230 | === modified file 'ubuntuone/controlpanel/gui/__init__.py' |
2231 | --- ubuntuone/controlpanel/gui/__init__.py 2011-08-12 19:12:08 +0000 |
2232 | +++ ubuntuone/controlpanel/gui/__init__.py 2011-09-26 18:38:27 +0000 |
2233 | @@ -51,28 +51,29 @@ |
2234 | MUSIC_STORE_ICON = 'music-store.png' |
2235 | MUSIC_STREAM_ICON = 'music-stream.png' |
2236 | NOTES_ICON = 'notes.png' |
2237 | -SERVICES_BOOKMARKS_ICON = 'services-bookmarks.png' |
2238 | SERVICES_CONTACTS_ICON = 'services-contacts.png' |
2239 | SERVICES_FILES_EXAMPLE = 'services-files-example.png' |
2240 | SERVICES_FILES_ICON = 'services-files.png' |
2241 | |
2242 | FILE_URI_PREFIX = 'file://' |
2243 | +UBUNTUONE_FROM_OAUTH = 'https://one.ubuntu.com/api/1.0/from_oauth/' |
2244 | UBUNTUONE_LINK = 'https://one.ubuntu.com/' |
2245 | |
2246 | CONTACTS_LINK = UBUNTUONE_LINK |
2247 | EDIT_ACCOUNT_LINK = UBUNTUONE_LINK + 'account/' |
2248 | EDIT_DEVICES_LINK = EDIT_ACCOUNT_LINK + 'machines/' |
2249 | EDIT_PROFILE_LINK = 'https://login.ubuntu.com/' |
2250 | +EDIT_SERVICES_LINK = UBUNTUONE_LINK + 'services' |
2251 | FACEBOOK_LINK = 'http://www.facebook.com/ubuntuone/' |
2252 | GET_SUPPORT_LINK = UBUNTUONE_LINK + 'support/' |
2253 | LEARN_MORE_LINK = UBUNTUONE_LINK |
2254 | MANAGE_FILES_LINK = UBUNTUONE_LINK + 'files/' |
2255 | +RESET_PASSWORD_LINK = EDIT_PROFILE_LINK + '+forgot_password' |
2256 | TWITTER_LINK = 'http://twitter.com/ubuntuone/' |
2257 | |
2258 | ALWAYS_SUBSCRIBED = _('Always in sync') |
2259 | -BOOKMARKS = _('Firefox extension') |
2260 | CONNECT_BUTTON_LABEL = _('Connect to Ubuntu One') |
2261 | -CONTACTS = _('Evolution plug-in') |
2262 | +CONTACTS = _('Thunderbird plug-in') |
2263 | CREDENTIALS_ERROR = _('There was a problem while retrieving the credentials.') |
2264 | DASHBOARD_BUTTON_TOOLTIP = _('View your personal details and service ' |
2265 | 'summary') |
2266 | @@ -188,9 +189,8 @@ |
2267 | credentials["consumer_secret"]) |
2268 | token = oauth.OAuthToken(credentials["token"], |
2269 | credentials["token_secret"]) |
2270 | - uri = 'https://one.ubuntu.com/api/1.0/from_oauth/' |
2271 | request = oauth.OAuthRequest.from_consumer_and_token( |
2272 | - http_url=uri, http_method='GET', |
2273 | + http_url=UBUNTUONE_FROM_OAUTH, http_method='GET', |
2274 | oauth_consumer=consumer, token=token, |
2275 | parameters={'next': url}) |
2276 | sig_method = oauth.OAuthSignatureMethod_HMAC_SHA1() |
2277 | |
2278 | === modified file 'ubuntuone/controlpanel/gui/gtk/gui.py' |
2279 | --- ubuntuone/controlpanel/gui/gtk/gui.py 2011-08-25 19:37:14 +0000 |
2280 | +++ ubuntuone/controlpanel/gui/gtk/gui.py 2011-09-26 18:38:27 +0000 |
2281 | @@ -62,7 +62,7 @@ |
2282 | try: |
2283 | from gi.repository import Unity # pylint: disable=E0611 |
2284 | USE_LIBUNITY = True |
2285 | - U1_DOTDESKTOP = "ubuntuone-control-panel-gtk.desktop" |
2286 | + U1_DOTDESKTOP = "ubuntuone-installer.desktop" |
2287 | except ImportError: |
2288 | USE_LIBUNITY = False |
2289 | |
2290 | @@ -71,6 +71,9 @@ |
2291 | |
2292 | WARNING_MARKUP = '<span foreground="%s"><b>%%s</b></span>' % ERROR_COLOR |
2293 | |
2294 | +CP_WMCLASS_NAME = 'ubuntuone-control-panel-gtk' |
2295 | +CP_WMCLASS_CLASS = 'ubuntuone-installer' |
2296 | + |
2297 | |
2298 | def error_handler(*args, **kwargs): |
2299 | """Log errors when calling D-Bus methods in a async way.""" |
2300 | @@ -1118,11 +1121,8 @@ |
2301 | self.files_icon.set_from_file(get_data_file(SERVICES_FILES_ICON)) |
2302 | self.files_example.set_from_file(get_data_file(SERVICES_FILES_EXAMPLE)) |
2303 | self.contacts_icon.set_from_file(get_data_file(SERVICES_CONTACTS_ICON)) |
2304 | - icon = get_data_file(SERVICES_BOOKMARKS_ICON) |
2305 | - self.bookmarks_icon.set_from_file(icon) |
2306 | |
2307 | - self.plugin_names = {'contacts': CONTACTS, |
2308 | - 'bookmarks': BOOKMARKS} |
2309 | + self.plugin_names = {'contacts': CONTACTS} |
2310 | |
2311 | self.package_manager = package_manager.PackageManager() |
2312 | self.install_box = None |
2313 | @@ -1161,13 +1161,6 @@ |
2314 | """ |
2315 | uri_hook(None, CONTACTS) |
2316 | |
2317 | - def on_bookmarks_button_clicked(self, *args, **kwargs): |
2318 | - """The bookmarks button was clicked. |
2319 | - |
2320 | - XXX: this should be part of the DesktopcouchService widget. |
2321 | - |
2322 | - """ |
2323 | - |
2324 | @log_call(logger.debug) |
2325 | def load(self): |
2326 | """Load info.""" |
2327 | @@ -1614,6 +1607,10 @@ |
2328 | def __init__(self, switch_to='', alert=False): |
2329 | super(ControlPanelWindow, self).__init__() |
2330 | |
2331 | + # We need to set WMCLASS so Unity falls back and we only get one |
2332 | + # launcher on the launcher panel |
2333 | + self.set_wmclass(CP_WMCLASS_NAME, CP_WMCLASS_CLASS) |
2334 | + |
2335 | self.connect('focus-in-event', self.remove_urgency) |
2336 | self.set_title(MAIN_WINDOW_TITLE % {'app_name': U1_APP_NAME}) |
2337 | self.set_position(gtk.WIN_POS_CENTER_ALWAYS) |
2338 | |
2339 | === modified file 'ubuntuone/controlpanel/gui/gtk/tests/__init__.py' |
2340 | --- ubuntuone/controlpanel/gui/gtk/tests/__init__.py 2011-08-25 19:37:14 +0000 |
2341 | +++ ubuntuone/controlpanel/gui/gtk/tests/__init__.py 2011-09-26 18:38:27 +0000 |
2342 | @@ -109,8 +109,8 @@ |
2343 | ] |
2344 | |
2345 | |
2346 | -class FakeControlPanelBackend(FakedDBusBackend): |
2347 | - """Fake a Control Panel Service, act as a dbus.Interface.""" |
2348 | +class FakedGUIBackend(FakedDBusBackend): |
2349 | + """Fake a Control Panel GUI Service, act as a dbus.Interface.""" |
2350 | |
2351 | bus_name = gui.DBUS_BUS_NAME_GUI |
2352 | object_path = gui.DBUS_PATH_GUI |
2353 | @@ -135,7 +135,7 @@ |
2354 | return FakedControlPanelBackend(obj, dbus_interface, |
2355 | *args, **kwargs) |
2356 | if dbus_interface == gui.DBUS_IFACE_GUI: |
2357 | - return FakeControlPanelBackend( |
2358 | + return FakedGUIBackend( |
2359 | obj, dbus_interface, *args, **kwargs) |
2360 | |
2361 | |
2362 | |
2363 | === modified file 'ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py' |
2364 | --- ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py 2011-08-25 19:37:14 +0000 |
2365 | +++ ubuntuone/controlpanel/gui/gtk/tests/test_gui_basic.py 2011-09-26 18:38:27 +0000 |
2366 | @@ -122,6 +122,14 @@ |
2367 | self.assertEqual( |
2368 | self._called, ((), {}), 'gtk.main_quit was not called.') |
2369 | |
2370 | + def test_wmclass_is_correct(self): |
2371 | + """Test that the WMCLASS is set.""" |
2372 | + self.patch(gui.ControlPanelWindow, 'set_wmclass', self._set_called) |
2373 | + cp = gui.ControlPanelWindow() |
2374 | + cp.destroy() |
2375 | + expected = ((gui.CP_WMCLASS_NAME, gui.CP_WMCLASS_CLASS), {}) |
2376 | + self.assertEqual(self._called, expected) |
2377 | + |
2378 | def test_title_is_correct(self): |
2379 | """The window title is correct.""" |
2380 | expected = gui.MAIN_WINDOW_TITLE % {'app_name': gui.U1_APP_NAME} |
2381 | @@ -315,7 +323,7 @@ |
2382 | |
2383 | |
2384 | class UbuntuOneBinTestCase(BaseTestCase): |
2385 | - """The test suite for a Ubuntu One panel.""" |
2386 | + """The test suite for the Ubuntu One panel.""" |
2387 | |
2388 | klass = gui.UbuntuOneBin |
2389 | kwargs = {'title': 'Something old, something new and something blue.'} |
2390 | |
2391 | === modified file 'ubuntuone/controlpanel/gui/qt/__init__.py' |
2392 | --- ubuntuone/controlpanel/gui/qt/__init__.py 2011-07-22 21:26:48 +0000 |
2393 | +++ ubuntuone/controlpanel/gui/qt/__init__.py 2011-09-26 18:38:27 +0000 |
2394 | @@ -18,13 +18,25 @@ |
2395 | |
2396 | """The Qt graphical interface for the control panel for Ubuntu One.""" |
2397 | |
2398 | +import collections |
2399 | +import logging |
2400 | + |
2401 | +from functools import wraps |
2402 | + |
2403 | from PyQt4 import QtGui, QtCore |
2404 | +from twisted.internet import defer |
2405 | + |
2406 | +from ubuntuone.controlpanel.gui import FILE_URI_PREFIX |
2407 | |
2408 | |
2409 | def uri_hook(uri): |
2410 | """Open an URI using the default browser/file manager.""" |
2411 | - url = QtCore.QString(uri) |
2412 | - QtGui.QDesktopServices.openUrl(QtCore.QUrl(url)) |
2413 | + if uri.startswith(FILE_URI_PREFIX): |
2414 | + url = QtCore.QUrl(uri) |
2415 | + else: |
2416 | + url = QtCore.QUrl() |
2417 | + url.setEncodedUrl(uri) |
2418 | + QtGui.QDesktopServices.openUrl(url) |
2419 | |
2420 | |
2421 | def pixmap_from_name(icon_name): |
2422 | @@ -52,3 +64,46 @@ |
2423 | icon.icon_name = icon_name |
2424 | |
2425 | return icon |
2426 | + |
2427 | + |
2428 | +def handle_errors(error_handler=None, logger=None): |
2429 | + """Decorator to handle errors when calling a function. |
2430 | + |
2431 | + if 'error_handler' is not None, it will be yielded on if any error happens. |
2432 | + |
2433 | + """ |
2434 | + if logger is None: |
2435 | + logger = logging.getLogger() |
2436 | + |
2437 | + def middle(f): |
2438 | + """Decorator to handle errors when calling 'f'.""" |
2439 | + |
2440 | + @defer.inlineCallbacks |
2441 | + @wraps(f) |
2442 | + def inner(*args, **kwargs): |
2443 | + """Call 'f' passing 'args' and 'kwargs'. |
2444 | + |
2445 | + Catch any error and show a error message. |
2446 | + |
2447 | + """ |
2448 | + try: |
2449 | + res = yield f(*args, **kwargs) |
2450 | + except Exception, e: # pylint: disable=W0703 |
2451 | + logger.exception(f.__name__) |
2452 | + else: |
2453 | + defer.returnValue(res) |
2454 | + |
2455 | + # this code will only be executed if there was an exception |
2456 | + if error_handler is not None: |
2457 | + yield error_handler() |
2458 | + |
2459 | + if len(e.args) > 0 and isinstance(e.args[0], collections.Mapping): |
2460 | + msgs = e.args[0].itervalues() |
2461 | + else: |
2462 | + msgs = [e.__class__.__name__] + map(repr, e.args) |
2463 | + msg = '\n'.join(msgs) |
2464 | + QtGui.QMessageBox.warning(None, '', msg, QtGui.QMessageBox.Close) |
2465 | + |
2466 | + return inner |
2467 | + |
2468 | + return middle |
2469 | |
2470 | === modified file 'ubuntuone/controlpanel/gui/qt/account.py' |
2471 | --- ubuntuone/controlpanel/gui/qt/account.py 2011-07-22 21:26:48 +0000 |
2472 | +++ ubuntuone/controlpanel/gui/qt/account.py 2011-09-26 18:38:27 +0000 |
2473 | @@ -37,12 +37,15 @@ |
2474 | """The Account Tab Panel widget""" |
2475 | |
2476 | ui_class = account_ui |
2477 | + logger = logger |
2478 | |
2479 | def _setup(self): |
2480 | """Do some extra setupping for the UI.""" |
2481 | + super(AccountPanel, self)._setup() |
2482 | self.ui.edit_profile_button.uri = EDIT_PROFILE_LINK |
2483 | self.ui.edit_services_button.uri = EDIT_ACCOUNT_LINK |
2484 | |
2485 | + # pylint: disable=E0202 |
2486 | @defer.inlineCallbacks |
2487 | def load(self): |
2488 | """Load info.""" |
2489 | |
2490 | === modified file 'ubuntuone/controlpanel/gui/qt/addfolder.py' |
2491 | --- ubuntuone/controlpanel/gui/qt/addfolder.py 2011-07-22 21:26:48 +0000 |
2492 | +++ ubuntuone/controlpanel/gui/qt/addfolder.py 2011-09-26 18:38:27 +0000 |
2493 | @@ -25,11 +25,10 @@ |
2494 | from PyQt4 import QtGui, QtCore |
2495 | from twisted.internet import defer |
2496 | |
2497 | -from ubuntuone.controlpanel import backend |
2498 | +from ubuntuone.controlpanel import cache |
2499 | from ubuntuone.controlpanel.logger import setup_logging |
2500 | -from ubuntuone.controlpanel.gui import ( |
2501 | - FOLDER_INVALID_PATH, |
2502 | -) |
2503 | +from ubuntuone.controlpanel.gui import FOLDER_INVALID_PATH |
2504 | +from ubuntuone.controlpanel.gui.qt import handle_errors |
2505 | |
2506 | |
2507 | logger = setup_logging('qt.addfolder') |
2508 | @@ -37,9 +36,11 @@ |
2509 | CLOSE = QtGui.QMessageBox.Close |
2510 | |
2511 | |
2512 | -class AddFolderButton(QtGui.QPushButton): |
2513 | +class AddFolderButton(cache.Cache, QtGui.QPushButton): |
2514 | """The AddFolderButton widget""" |
2515 | |
2516 | + logger = logger |
2517 | + |
2518 | folderCreated = QtCore.pyqtSignal(unicode) |
2519 | folderCreationCanceled = QtCore.pyqtSignal() |
2520 | |
2521 | @@ -47,16 +48,17 @@ |
2522 | """Initialize the UI of the widget.""" |
2523 | super(AddFolderButton, self).__init__(*args, **kwargs) |
2524 | self.cloud_folders = [] |
2525 | - self.backend = backend.ControlBackend() |
2526 | self.clicked.connect(self.on_clicked) |
2527 | - logger.debug('%s: started.', self.__class__.__name__) |
2528 | |
2529 | @QtCore.pyqtSlot() |
2530 | + @handle_errors(logger=logger) |
2531 | @defer.inlineCallbacks |
2532 | def on_clicked(self): |
2533 | """The 'Sync another folder' button was clicked.""" |
2534 | - folder = QtGui.QFileDialog.getExistingDirectory(parent=self) |
2535 | - folder = unicode(folder) |
2536 | + # The options argument is because of LP: #835013 |
2537 | + folder = QtGui.QFileDialog.getExistingDirectory( |
2538 | + parent=self, options=QtGui.QFileDialog.DontUseNativeDialog) |
2539 | + folder = unicode(QtCore.QDir.toNativeSeparators(folder)) |
2540 | logger.debug('on_add_folder_button_clicked: user requested folder ' |
2541 | 'creation for path %r', folder) |
2542 | if folder == '': |
2543 | |
2544 | === modified file 'ubuntuone/controlpanel/gui/qt/controlpanel.py' |
2545 | --- ubuntuone/controlpanel/gui/qt/controlpanel.py 2011-08-12 19:12:08 +0000 |
2546 | +++ ubuntuone/controlpanel/gui/qt/controlpanel.py 2011-09-26 18:38:27 +0000 |
2547 | @@ -21,62 +21,79 @@ |
2548 | |
2549 | from __future__ import division |
2550 | |
2551 | -from PyQt4 import QtGui, QtCore |
2552 | +from PyQt4 import QtCore |
2553 | from twisted.internet import defer |
2554 | |
2555 | -from ubuntuone.controlpanel import backend |
2556 | +from ubuntuone.controlpanel.backend import AUTOCONNECT_KEY |
2557 | from ubuntuone.controlpanel.logger import setup_logging, log_call |
2558 | from ubuntuone.controlpanel.gui import ( |
2559 | humanize, |
2560 | - EDIT_ACCOUNT_LINK, |
2561 | + EDIT_SERVICES_LINK, |
2562 | FACEBOOK_LINK, |
2563 | GET_SUPPORT_LINK, |
2564 | GREETING, |
2565 | PERCENTAGE_LABEL, |
2566 | + QUOTA_THRESHOLD, |
2567 | TWITTER_LINK, |
2568 | USAGE_LABEL, |
2569 | ) |
2570 | -from ubuntuone.controlpanel.gui.qt import uri_hook |
2571 | +from ubuntuone.controlpanel.gui import qt |
2572 | +from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin |
2573 | from ubuntuone.controlpanel.gui.qt.ui import controlpanel_ui |
2574 | |
2575 | |
2576 | logger = setup_logging('qt.controlpanel') |
2577 | |
2578 | -NAME_STYLE = '<br><span style=" font-size:24pt;">%s!</span>' |
2579 | +NAME_STYLE = '<br><span style=" font-size:16pt;">%s!</span>' |
2580 | PERCENTAGE_STYLE = '<span style=" font-size:16pt;">%.0f%%</span>' |
2581 | |
2582 | |
2583 | -class ControlPanel(QtGui.QWidget): |
2584 | +class ControlPanel(UbuntuOneBin): |
2585 | """The Control Panel widget""" |
2586 | |
2587 | - def __init__(self, parent=None): |
2588 | - """Initialize the UI of the widget.""" |
2589 | - QtGui.QWidget.__init__(self, parent) |
2590 | - self.ui = controlpanel_ui.Ui_Form() |
2591 | - self.ui.setupUi(self) |
2592 | - |
2593 | - self.backend = backend.ControlBackend() |
2594 | - self._setup() |
2595 | - logger.debug('%s: started.', self.__class__.__name__) |
2596 | + ui_class = controlpanel_ui |
2597 | + logger = logger |
2598 | |
2599 | def _setup(self): |
2600 | """Do some extra setupping for the UI.""" |
2601 | - self.ui.get_more_space_button.uri = EDIT_ACCOUNT_LINK |
2602 | + self.ui.get_more_space_button.uri = EDIT_SERVICES_LINK |
2603 | self.ui.help_button.uri = GET_SUPPORT_LINK |
2604 | - |
2605 | - # Invalid name "showEvent" |
2606 | - # pylint: disable=C0103 |
2607 | - |
2608 | - def showEvent(self, event): |
2609 | - """Load info.""" |
2610 | - self.load() |
2611 | - event.accept() |
2612 | - |
2613 | + self.ui.devices_tab.localDeviceRemoved.connect( |
2614 | + self.on_credentials_not_found) |
2615 | + self.ui.signin.credentialsFound.connect(lambda creds: self.load()) |
2616 | + |
2617 | + @defer.inlineCallbacks |
2618 | + def connect_file_sync(self): |
2619 | + """Connect file sync service if the setting autoconnect is enabled.""" |
2620 | + settings = yield self.backend.file_sync_settings_info() |
2621 | + if AUTOCONNECT_KEY in settings and settings[AUTOCONNECT_KEY]: |
2622 | + yield self.backend.connect_files() |
2623 | + |
2624 | + @log_call(logger.debug) |
2625 | + def on_credentials_not_found(self): |
2626 | + """Credentials are not found or were removed.""" |
2627 | + self.ui.switcher.setCurrentWidget(self.ui.signin) |
2628 | + self.is_processing = False |
2629 | + |
2630 | + @log_call(logger.debug) |
2631 | + def on_credentials_found(self): |
2632 | + """Credentials are not found or were removed.""" |
2633 | + self.ui.switcher.setCurrentWidget(self.ui.management) |
2634 | + self.connect_file_sync() |
2635 | + self.is_processing = False |
2636 | + |
2637 | + # pylint: disable=E0202 |
2638 | @defer.inlineCallbacks |
2639 | def load(self): |
2640 | """Load info.""" |
2641 | - info = yield self.backend.account_info() |
2642 | - self.process_info(info) |
2643 | + self.is_processing = True |
2644 | + credentials = yield self.backend.get_credentials() |
2645 | + if not credentials: |
2646 | + self.on_credentials_not_found() |
2647 | + else: |
2648 | + self.on_credentials_found() |
2649 | + info = yield self.backend.account_info() |
2650 | + self.process_info(info) |
2651 | |
2652 | @log_call(logger.debug) |
2653 | def process_info(self, info): |
2654 | @@ -86,17 +103,43 @@ |
2655 | |
2656 | used = int(info['quota_used']) |
2657 | total = int(info['quota_total']) |
2658 | - percentage = {'percentage': PERCENTAGE_STYLE % ((used / total) * 100)} |
2659 | + percentage_value = ((used / total) * 100) |
2660 | + percentage = {'percentage': PERCENTAGE_STYLE % percentage_value} |
2661 | data = {'used': humanize(used), 'total': humanize(total)} |
2662 | self.ui.percentage_usage_label.setText(PERCENTAGE_LABEL % percentage) |
2663 | self.ui.quota_usage_label.setText(USAGE_LABEL % data) |
2664 | + self._update_quota({'percentage': percentage_value}) |
2665 | + |
2666 | + @log_call(logger.debug) |
2667 | + def _update_quota(self, data=None): |
2668 | + """Update the quota info.""" |
2669 | + fraction = 0.0 |
2670 | + if data is not None: |
2671 | + fraction = data.get('percentage', 0.0) / 100 |
2672 | + if fraction > 0 and fraction < 0.05: |
2673 | + fraction = 0.05 |
2674 | + else: |
2675 | + fraction = round(fraction, 2) |
2676 | + |
2677 | + logger.debug('ManagementPanel: updating quota to %r.', fraction) |
2678 | + self.ui.percentage_usage_label.setProperty("OverQuota", |
2679 | + fraction >= QUOTA_THRESHOLD) |
2680 | + self.ui.quota_usage_label.setProperty("OverQuota", |
2681 | + fraction >= QUOTA_THRESHOLD) |
2682 | + self.ui.percentage_usage_label.style().unpolish( |
2683 | + self.ui.percentage_usage_label) |
2684 | + self.ui.percentage_usage_label.style().polish( |
2685 | + self.ui.percentage_usage_label) |
2686 | + self.ui.quota_usage_label.style().unpolish( |
2687 | + self.ui.quota_usage_label) |
2688 | + self.ui.quota_usage_label.style().polish(self.ui.quota_usage_label) |
2689 | |
2690 | @QtCore.pyqtSlot() |
2691 | def on_twitter_button_clicked(self): |
2692 | """The twitter button was clicked.""" |
2693 | - uri_hook(TWITTER_LINK) |
2694 | + qt.uri_hook(TWITTER_LINK) |
2695 | |
2696 | @QtCore.pyqtSlot() |
2697 | def on_facebook_button_clicked(self): |
2698 | """The facebook button was clicked.""" |
2699 | - uri_hook(FACEBOOK_LINK) |
2700 | + qt.uri_hook(FACEBOOK_LINK) |
2701 | |
2702 | === modified file 'ubuntuone/controlpanel/gui/qt/device.py' |
2703 | --- ubuntuone/controlpanel/gui/qt/device.py 2011-07-22 21:26:48 +0000 |
2704 | +++ ubuntuone/controlpanel/gui/qt/device.py 2011-09-26 18:38:27 +0000 |
2705 | @@ -25,9 +25,15 @@ |
2706 | DEVICE_TYPE_COMPUTER, |
2707 | DEVICE_TYPE_PHONE, |
2708 | ) |
2709 | +from ubuntuone.controlpanel import cache |
2710 | from ubuntuone.controlpanel.gui import DEVICE_CONFIRM_REMOVE |
2711 | -from ubuntuone.controlpanel.gui.qt import icon_from_name, pixmap_from_name |
2712 | +from ubuntuone.controlpanel.gui.qt import ( |
2713 | + handle_errors, |
2714 | + icon_from_name, |
2715 | + pixmap_from_name, |
2716 | +) |
2717 | from ubuntuone.controlpanel.gui.qt.ui import device_ui |
2718 | +from ubuntuone.controlpanel.logger import setup_logging |
2719 | |
2720 | COMPUTER_ICON = "computer" |
2721 | PHONE_ICON = "phone" |
2722 | @@ -43,25 +49,27 @@ |
2723 | YES = QtGui.QMessageBox.Yes |
2724 | |
2725 | |
2726 | +logger = setup_logging('qt.device') |
2727 | + |
2728 | + |
2729 | def icon_name_from_type(device_type): |
2730 | """Get the icon name for the device.""" |
2731 | icon_name = DEVICE_TYPE_TO_ICON_MAP.get(device_type, DEFAULT_ICON) |
2732 | return icon_name |
2733 | |
2734 | |
2735 | -class DeviceWidget(QtGui.QWidget): |
2736 | +class DeviceWidget(cache.Cache, QtGui.QWidget): |
2737 | """The widget for each device in the control panel.""" |
2738 | |
2739 | removed = QtCore.pyqtSignal() |
2740 | removeCanceled = QtCore.pyqtSignal() |
2741 | |
2742 | - def __init__(self, backend, device_id, **kwargs): |
2743 | + def __init__(self, device_id, *args, **kwargs): |
2744 | """Initialize the UI of the widget.""" |
2745 | - QtGui.QWidget.__init__(self, **kwargs) |
2746 | + super(DeviceWidget, self).__init__(*args, **kwargs) |
2747 | self.ui = device_ui.Ui_Form() |
2748 | self.ui.setupUi(self) |
2749 | self.id = device_id |
2750 | - self.backend = backend |
2751 | |
2752 | def update_device_info(self, device_info): |
2753 | """Update the device info.""" |
2754 | @@ -70,8 +78,9 @@ |
2755 | pixmap = pixmap_from_name(icon_name) |
2756 | self.ui.device_icon_label.setPixmap(pixmap) |
2757 | |
2758 | + @QtCore.pyqtSlot() |
2759 | + @handle_errors(logger=logger) |
2760 | @defer.inlineCallbacks |
2761 | - @QtCore.pyqtSlot() |
2762 | def on_remove_device_button_clicked(self): |
2763 | """The user wants to remove this device.""" |
2764 | msg = DEVICE_CONFIRM_REMOVE |
2765 | |
2766 | === modified file 'ubuntuone/controlpanel/gui/qt/devices.py' |
2767 | --- ubuntuone/controlpanel/gui/qt/devices.py 2011-07-22 21:26:48 +0000 |
2768 | +++ ubuntuone/controlpanel/gui/qt/devices.py 2011-09-26 18:38:27 +0000 |
2769 | @@ -18,8 +18,6 @@ |
2770 | |
2771 | """The user interface for the control panel for Ubuntu One.""" |
2772 | |
2773 | -from gettext import gettext as _ |
2774 | - |
2775 | # Unused import QtGui |
2776 | # pylint: disable=W0611 |
2777 | from PyQt4 import QtGui, QtCore |
2778 | @@ -39,13 +37,17 @@ |
2779 | class DevicesPanel(UbuntuOneBin): |
2780 | """The DevicesFolders Tab Panel widget""" |
2781 | |
2782 | - title = _('This device') |
2783 | ui_class = devices_ui |
2784 | + logger = logger |
2785 | + |
2786 | + localDeviceRemoved = QtCore.pyqtSignal() |
2787 | |
2788 | def _setup(self): |
2789 | """Do some extra setupping for the UI.""" |
2790 | + super(DevicesPanel, self)._setup() |
2791 | self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK |
2792 | |
2793 | + # pylint: disable=E0202 |
2794 | @defer.inlineCallbacks |
2795 | def load(self): |
2796 | """Load info.""" |
2797 | @@ -64,6 +66,11 @@ |
2798 | |
2799 | self.is_processing = False |
2800 | |
2801 | + def on_local_device_removed(self): |
2802 | + """When the local device is removed, clear the box and emit signal.""" |
2803 | + self.clear_device_info(self.ui.local_device_box) |
2804 | + self.localDeviceRemoved.emit() |
2805 | + |
2806 | def clear_device_info(self, box): |
2807 | """Clear all the device info.""" |
2808 | children = box.count() |
2809 | @@ -84,11 +91,9 @@ |
2810 | |
2811 | def update_local_device(self, device_info): |
2812 | """Update the info for the local device.""" |
2813 | - device_widget = device.DeviceWidget(backend=self.backend, |
2814 | - device_id=device_info['device_id']) |
2815 | + device_widget = device.DeviceWidget(device_id=device_info['device_id']) |
2816 | device_widget.update_device_info(device_info) |
2817 | - f = lambda: self.clear_device_info(self.ui.local_device_box) |
2818 | - device_widget.removed.connect(f) |
2819 | + device_widget.removed.connect(self.on_local_device_removed) |
2820 | |
2821 | self.ui.local_device_box.addWidget(device_widget) |
2822 | |
2823 | |
2824 | === modified file 'ubuntuone/controlpanel/gui/qt/filesyncstatus.py' |
2825 | --- ubuntuone/controlpanel/gui/qt/filesyncstatus.py 2011-08-25 19:37:14 +0000 |
2826 | +++ ubuntuone/controlpanel/gui/qt/filesyncstatus.py 2011-09-26 18:38:27 +0000 |
2827 | @@ -21,7 +21,7 @@ |
2828 | from PyQt4 import QtGui, QtCore |
2829 | from twisted.internet import defer |
2830 | |
2831 | -from ubuntuone.controlpanel import backend |
2832 | +from ubuntuone.controlpanel import backend, cache |
2833 | from ubuntuone.controlpanel.logger import setup_logging, log_call |
2834 | from ubuntuone.controlpanel.gui import ( |
2835 | ERROR_COLOR, |
2836 | @@ -108,27 +108,26 @@ |
2837 | return icon_name |
2838 | |
2839 | |
2840 | -class FileSyncStatus(QtGui.QWidget): |
2841 | +class FileSyncStatus(cache.Cache, QtGui.QWidget): |
2842 | """The FileSyncStatus widget""" |
2843 | |
2844 | - def __init__(self, parent=None): |
2845 | + def __init__(self, *args, **kwargs): |
2846 | """Initialize the UI of the widget.""" |
2847 | - QtGui.QWidget.__init__(self, parent) |
2848 | + super(FileSyncStatus, self).__init__(*args, **kwargs) |
2849 | self.ui = filesyncstatus_ui.Ui_Form() |
2850 | self.ui.setupUi(self) |
2851 | |
2852 | self._backend_method = None |
2853 | - self.backend = backend.ControlBackend() |
2854 | - |
2855 | - logger.debug('%s: started.', self.__class__.__name__) |
2856 | |
2857 | # Invalid name "showEvent" |
2858 | # pylint: disable=C0103 |
2859 | |
2860 | def showEvent(self, event): |
2861 | """Load info.""" |
2862 | + super(FileSyncStatus, self).showEvent(event) |
2863 | self.load() |
2864 | - event.accept() |
2865 | + |
2866 | + # pylint: enable=C0103 |
2867 | |
2868 | @defer.inlineCallbacks |
2869 | def load(self): |
2870 | |
2871 | === modified file 'ubuntuone/controlpanel/gui/qt/folders.py' |
2872 | --- ubuntuone/controlpanel/gui/qt/folders.py 2011-08-12 19:12:08 +0000 |
2873 | +++ ubuntuone/controlpanel/gui/qt/folders.py 2011-09-26 18:38:27 +0000 |
2874 | @@ -29,7 +29,6 @@ |
2875 | from ubuntuone.controlpanel.gui import ( |
2876 | ALWAYS_SUBSCRIBED, |
2877 | EXPLORE, |
2878 | - FILE_URI_PREFIX, |
2879 | FOLDER_ICON_NAME, |
2880 | FOLDER_OWNED_BY, |
2881 | FOLDER_SHARED_BY, |
2882 | @@ -65,11 +64,12 @@ |
2883 | """The Folders Tab Panel widget""" |
2884 | |
2885 | ui_class = folders_ui |
2886 | + logger = logger |
2887 | |
2888 | def _setup(self): |
2889 | """Do some extra setupping for the UI.""" |
2890 | - load_info = lambda *a, **kw: self.load() |
2891 | - self.ui.add_folder_button.folderCreated.connect(load_info) |
2892 | + super(FoldersPanel, self)._setup() |
2893 | + self.ui.add_folder_button.folderCreated.connect(self.on_folder_created) |
2894 | |
2895 | headers = self.ui.folders.header() |
2896 | headers.setResizeMode(FOLDER_NAME_COL, headers.Stretch) |
2897 | @@ -81,8 +81,16 @@ |
2898 | icon = icon_from_name('external_icon_orange') |
2899 | self.ui.share_publish_button.setIcon(icon) |
2900 | |
2901 | - logger.debug('%s: started.', self.__class__.__name__) |
2902 | + @log_call(logger.info) |
2903 | + def on_folder_created(self, new_folder): |
2904 | + """Reload folder info after folder creation.""" |
2905 | + self.is_processing = True |
2906 | + # hack to ensure that syncdaemon updates the folder list. |
2907 | + # pylint: disable=W0404, E1101 |
2908 | + from twisted.internet import reactor |
2909 | + reactor.callLater(2, self.load) |
2910 | |
2911 | + # pylint: disable=E0202 |
2912 | @defer.inlineCallbacks |
2913 | def load(self): |
2914 | """Load specific tab info.""" |
2915 | @@ -124,9 +132,15 @@ |
2916 | self.ui.folders.addTopLevelItem(item) |
2917 | |
2918 | for volume in volumes: |
2919 | + is_root = volume[u'type'] == self.backend.ROOT_TYPE |
2920 | + is_share = volume[u'type'] == self.backend.SHARE_TYPE |
2921 | + |
2922 | child = QtGui.QTreeWidgetItem() |
2923 | child.setSizeHint(FOLDER_NAME_COL, QtCore.QSize(-1, 35)) |
2924 | - child.volume_path = volume['path'] |
2925 | + if is_share and 'realpath' in volume: |
2926 | + child.volume_path = volume['realpath'] |
2927 | + else: |
2928 | + child.volume_path = volume['path'] |
2929 | child.volume_id = volume['volume_id'] |
2930 | |
2931 | name = self._process_name(volume[u'display_name']) |
2932 | @@ -134,9 +148,6 @@ |
2933 | child.setToolTip(FOLDER_NAME_COL, name) |
2934 | child.setToolTip(EXPLORE_COL, EXPLORE) |
2935 | |
2936 | - is_root = volume[u'type'] == self.backend.ROOT_TYPE |
2937 | - is_share = volume[u'type'] == self.backend.SHARE_TYPE |
2938 | - |
2939 | icon_name = FOLDER_ICON_NAME |
2940 | if is_share: |
2941 | icon_name = SHARE_ICON_NAME |
2942 | @@ -173,12 +184,14 @@ |
2943 | policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, |
2944 | QtGui.QSizePolicy.Fixed) |
2945 | button.setSizePolicy(policy) |
2946 | + button.setEnabled(bool(volume[u'subscribed'])) |
2947 | |
2948 | # Operator not preceded by a space |
2949 | # pylint: disable=C0322 |
2950 | - cb = lambda item=child: self.on_folders_itemActivated(item) |
2951 | + cb = lambda checked, item=child: \ |
2952 | + self.on_folders_itemActivated(item) |
2953 | # pylint: enable=C0322 |
2954 | - QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), cb) |
2955 | + button.clicked.connect(cb) |
2956 | self.ui.folders.setIndexWidget(model_index, button) |
2957 | |
2958 | self.ui.folders.expandAll() |
2959 | @@ -196,7 +209,7 @@ |
2960 | logger.warning('on_folders_itemActivated: stored path %r ' |
2961 | 'does not exist.', volume_path) |
2962 | else: |
2963 | - uri = FILE_URI_PREFIX + volume_path |
2964 | + uri = unicode(QtCore.QUrl.fromLocalFile(volume_path).toString()) |
2965 | uri_hook(uri) |
2966 | |
2967 | @defer.inlineCallbacks |
2968 | @@ -230,6 +243,7 @@ |
2969 | # user accepted, merge the folder content |
2970 | yield self.backend.change_volume_settings(volume_id, |
2971 | {'subscribed': subscribed}) |
2972 | + self.load() |
2973 | else: |
2974 | # restore old value |
2975 | old = UNCHECKED if subscribed else CHECKED |
2976 | |
2977 | === modified file 'ubuntuone/controlpanel/gui/qt/gotoweb.py' |
2978 | --- ubuntuone/controlpanel/gui/qt/gotoweb.py 2011-07-22 21:26:48 +0000 |
2979 | +++ ubuntuone/controlpanel/gui/qt/gotoweb.py 2011-09-26 18:38:27 +0000 |
2980 | @@ -20,10 +20,13 @@ |
2981 | |
2982 | from PyQt4 import QtGui, QtCore |
2983 | |
2984 | -from ubuntuone.controlpanel.gui import qt |
2985 | - |
2986 | - |
2987 | -class GoToWebButton(QtGui.QPushButton): |
2988 | +from twisted.internet import defer |
2989 | + |
2990 | +from ubuntuone.controlpanel import cache |
2991 | +from ubuntuone.controlpanel.gui import qt, sign_url, UBUNTUONE_LINK |
2992 | + |
2993 | + |
2994 | +class GoToWebButton(cache.Cache, QtGui.QPushButton): |
2995 | """The GoToWebButton widget""" |
2996 | |
2997 | def __init__(self, *args, **kwargs): |
2998 | @@ -33,9 +36,20 @@ |
2999 | self.setIcon(qt.icon_from_name('external_icon_white')) |
3000 | self.setLayoutDirection(QtCore.Qt.RightToLeft) |
3001 | self.clicked.connect(self.on_clicked) |
3002 | + self.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) |
3003 | |
3004 | + @defer.inlineCallbacks |
3005 | @QtCore.pyqtSlot() |
3006 | def on_clicked(self): |
3007 | """Open self.uri if not None, do nothing otherwise.""" |
3008 | if self.uri is not None: |
3009 | - qt.uri_hook(self.uri) |
3010 | + |
3011 | + credentials = None |
3012 | + if self.uri.startswith(UBUNTUONE_LINK): |
3013 | + credentials = yield self.backend.get_credentials() |
3014 | + |
3015 | + uri = self.uri |
3016 | + if credentials: |
3017 | + uri = sign_url(uri, credentials) |
3018 | + |
3019 | + qt.uri_hook(uri) |
3020 | |
3021 | === modified file 'ubuntuone/controlpanel/gui/qt/gui.py' |
3022 | --- ubuntuone/controlpanel/gui/qt/gui.py 2011-07-22 21:26:48 +0000 |
3023 | +++ ubuntuone/controlpanel/gui/qt/gui.py 2011-09-26 18:38:27 +0000 |
3024 | @@ -21,22 +21,24 @@ |
3025 | |
3026 | from PyQt4 import QtGui |
3027 | |
3028 | -from ubuntuone.controlpanel.logger import setup_logging |
3029 | +from ubuntuone.controlpanel.gui.qt.systray import TrayIcon |
3030 | from ubuntuone.controlpanel.gui.qt.ui import mainwindow_ui |
3031 | |
3032 | |
3033 | -logger = setup_logging('qt.gui') |
3034 | - |
3035 | - |
3036 | class MainWindow(QtGui.QMainWindow): |
3037 | """The Main Window of the Control Panel.""" |
3038 | |
3039 | def __init__(self, close_callback=None): |
3040 | """Initialize this instance with the UI layout.""" |
3041 | - QtGui.QMainWindow.__init__(self) |
3042 | + super(MainWindow, self).__init__() |
3043 | self.ui = mainwindow_ui.Ui_MainWindow() |
3044 | self.ui.setupUi(self) |
3045 | self.close_callback = close_callback |
3046 | + self._setup() |
3047 | + |
3048 | + def _setup(self): |
3049 | + """Do some extra setupping for the UI.""" |
3050 | + self.ui.control_panel.ui.signin.signinCanceled.connect(self.close) |
3051 | |
3052 | # Invalid name "closeEvent" |
3053 | # pylint: disable=C0103 |
3054 | @@ -46,3 +48,24 @@ |
3055 | if self.close_callback is not None: |
3056 | self.close_callback() |
3057 | event.accept() |
3058 | + |
3059 | + # pylint: enable=C0103 |
3060 | + |
3061 | + |
3062 | +def start(stop, minimized=False, with_icon=False): |
3063 | + """Show the UI elements.""" |
3064 | + # pylint: disable=W0404, F0401 |
3065 | + if not minimized: |
3066 | + if with_icon or minimized: |
3067 | + window = MainWindow() |
3068 | + else: |
3069 | + window = MainWindow(close_callback=stop) |
3070 | + window.show() |
3071 | + else: |
3072 | + window = None |
3073 | + if with_icon or minimized: |
3074 | + QtGui.QApplication.instance().setQuitOnLastWindowClosed(False) |
3075 | + icon = TrayIcon(window=window) |
3076 | + else: |
3077 | + icon = None |
3078 | + return icon, window |
3079 | |
3080 | === modified file 'ubuntuone/controlpanel/gui/qt/loadingoverlay.py' |
3081 | --- ubuntuone/controlpanel/gui/qt/loadingoverlay.py 2011-08-12 19:12:08 +0000 |
3082 | +++ ubuntuone/controlpanel/gui/qt/loadingoverlay.py 2011-09-26 18:38:27 +0000 |
3083 | @@ -18,8 +18,7 @@ |
3084 | |
3085 | """Loading animation over a widget.""" |
3086 | |
3087 | -from PyQt4 import QtGui |
3088 | -from PyQt4 import QtCore |
3089 | +from PyQt4 import QtGui, QtCore |
3090 | |
3091 | from ubuntuone.controlpanel.gui.qt.ui import loadingoverlay_ui |
3092 | |
3093 | @@ -29,12 +28,15 @@ |
3094 | |
3095 | In order to have this working, the Widget which is going to use this |
3096 | overlay has to reimplement the resizeEvent as follows: |
3097 | + |
3098 | def resizeEvent(self, event): |
3099 | self.overlay.resize(event.size()) |
3100 | - event.accept()""" |
3101 | + event.accept() |
3102 | + |
3103 | + """ |
3104 | |
3105 | def __init__(self, parent=None): |
3106 | - QtGui.QFrame.__init__(self, parent) |
3107 | + super(LoadingOverlay, self).__init__(parent=parent) |
3108 | self.ui = loadingoverlay_ui.Ui_Form() |
3109 | self.ui.setupUi(self) |
3110 | |
3111 | |
3112 | === modified file 'ubuntuone/controlpanel/gui/qt/main/linux.py' |
3113 | --- ubuntuone/controlpanel/gui/qt/main/linux.py 2011-07-22 21:26:48 +0000 |
3114 | +++ ubuntuone/controlpanel/gui/qt/main/linux.py 2011-09-26 18:38:27 +0000 |
3115 | @@ -29,7 +29,7 @@ |
3116 | # pylint: enable=W0611 |
3117 | |
3118 | |
3119 | -def main(switch_to='', alert=False): |
3120 | +def main(switch_to='', alert=False, minimized=False, with_icon=False): |
3121 | """Start the Qt reactor and open the main window.""" |
3122 | |
3123 | # The DBus main loop MUST be initialized before importing the reactor |
3124 | @@ -49,11 +49,9 @@ |
3125 | from qtreactor import qt4reactor |
3126 | qt4reactor.install() |
3127 | from twisted.internet import reactor |
3128 | + from ubuntuone.controlpanel.gui.qt.gui import start |
3129 | |
3130 | - # pylint believes that reactor has no run nor stop methods. Silence it. |
3131 | # pylint: disable=E1101 |
3132 | - from ubuntuone.controlpanel.gui.qt.gui import MainWindow |
3133 | - window = MainWindow(close_callback=reactor.stop) |
3134 | - window.show() |
3135 | - |
3136 | + icon, window = start(reactor.stop, |
3137 | + minimized=minimized, with_icon=with_icon) |
3138 | reactor.run() |
3139 | |
3140 | === modified file 'ubuntuone/controlpanel/gui/qt/main/windows.py' |
3141 | --- ubuntuone/controlpanel/gui/qt/main/windows.py 2011-07-22 21:26:48 +0000 |
3142 | +++ ubuntuone/controlpanel/gui/qt/main/windows.py 2011-09-26 18:38:27 +0000 |
3143 | @@ -27,7 +27,7 @@ |
3144 | # pylint: enable=W0611 |
3145 | |
3146 | |
3147 | -def main(switch_to='', alert=False): |
3148 | +def main(switch_to='', alert=False, minimized=False, with_icon=False): |
3149 | """Start the Qt reactor and open the main window.""" |
3150 | |
3151 | # The following cannot be imported outside this function |
3152 | @@ -35,25 +35,22 @@ |
3153 | # pylint: disable=F0401, W0404 |
3154 | import qtreactor.qt4reactor |
3155 | qtreactor.qt4reactor.install() |
3156 | + from twisted.internet import reactor |
3157 | + from ubuntuone.controlpanel.gui.qt.gui import start |
3158 | |
3159 | # The main loop MUST be initialized before importing the reactor |
3160 | # pylint: disable=W0612 |
3161 | app = Qt.QApplication(sys.argv) |
3162 | + # Apply font to the entire application |
3163 | + QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf') |
3164 | + QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-B.ttf') |
3165 | # Apply Style Sheet |
3166 | qss_file = QtCore.QFile(":/ubuntuone.qss") |
3167 | qss_file.open(QtCore.QFile.ReadOnly) |
3168 | stylesheet = QtCore.QLatin1String(qss_file.readAll()) |
3169 | app.setStyleSheet(stylesheet) |
3170 | |
3171 | - # Apply font to the entire application |
3172 | - QtGui.QFontDatabase.addApplicationFont(':/Ubuntu-R.ttf') |
3173 | - |
3174 | - # pylint: disable=W0404, F0401 |
3175 | - from twisted.internet import reactor |
3176 | - |
3177 | - from ubuntuone.controlpanel.gui.qt.gui import MainWindow |
3178 | - window = MainWindow(close_callback=reactor.stop) |
3179 | - window.show() |
3180 | - |
3181 | + icon, window = start(reactor.stop, |
3182 | + minimized=minimized, with_icon=with_icon) |
3183 | # pylint: disable=E1101 |
3184 | reactor.run() |
3185 | |
3186 | === modified file 'ubuntuone/controlpanel/gui/qt/preferences.py' |
3187 | --- ubuntuone/controlpanel/gui/qt/preferences.py 2011-07-22 21:26:48 +0000 |
3188 | +++ ubuntuone/controlpanel/gui/qt/preferences.py 2011-09-26 18:38:27 +0000 |
3189 | @@ -62,7 +62,9 @@ |
3190 | """The Preferences Tab Panel widget""" |
3191 | |
3192 | ui_class = preferences_ui |
3193 | + logger = logger |
3194 | |
3195 | + # pylint: disable=E0202 |
3196 | @defer.inlineCallbacks |
3197 | def load(self): |
3198 | """Load info.""" |
3199 | |
3200 | === added file 'ubuntuone/controlpanel/gui/qt/signin.py' |
3201 | --- ubuntuone/controlpanel/gui/qt/signin.py 1970-01-01 00:00:00 +0000 |
3202 | +++ ubuntuone/controlpanel/gui/qt/signin.py 2011-09-26 18:38:27 +0000 |
3203 | @@ -0,0 +1,89 @@ |
3204 | +# -*- coding: utf-8 -*- |
3205 | + |
3206 | +# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
3207 | +# |
3208 | +# Copyright 2011 Canonical Ltd. |
3209 | +# |
3210 | +# This program is free software: you can redistribute it and/or modify it |
3211 | +# under the terms of the GNU General Public License version 3, as published |
3212 | +# by the Free Software Foundation. |
3213 | +# |
3214 | +# This program is distributed in the hope that it will be useful, but |
3215 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
3216 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3217 | +# PURPOSE. See the GNU General Public License for more details. |
3218 | +# |
3219 | +# You should have received a copy of the GNU General Public License along |
3220 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
3221 | + |
3222 | +"""The signin page.""" |
3223 | + |
3224 | +from PyQt4 import QtCore |
3225 | +from twisted.internet import defer |
3226 | + |
3227 | +from ubuntuone.controlpanel.gui import RESET_PASSWORD_LINK |
3228 | +from ubuntuone.controlpanel.gui.qt import icon_from_name, handle_errors |
3229 | +from ubuntuone.controlpanel.gui.qt.ubuntuonebin import UbuntuOneBin |
3230 | +from ubuntuone.controlpanel.gui.qt.ui import signin_ui |
3231 | +from ubuntuone.controlpanel.logger import setup_logging, log_call |
3232 | + |
3233 | + |
3234 | +logger = setup_logging('qt.signin') |
3235 | + |
3236 | + |
3237 | +class SignInPanel(UbuntuOneBin): |
3238 | + """The widget for signing in.""" |
3239 | + |
3240 | + ui_class = signin_ui |
3241 | + logger = logger |
3242 | + |
3243 | + signinCanceled = QtCore.pyqtSignal() |
3244 | + credentialsFound = QtCore.pyqtSignal(dict) |
3245 | + |
3246 | + def _setup(self): |
3247 | + """Do some extra setupping for the UI.""" |
3248 | + super(SignInPanel, self)._setup() |
3249 | + |
3250 | + self.ui.forgot_password_button.uri = RESET_PASSWORD_LINK |
3251 | + icon = icon_from_name('external_icon_orange') |
3252 | + self.ui.forgot_password_button.setIcon(icon) |
3253 | + |
3254 | + self.ui.signin_button.setEnabled(False) |
3255 | + for entry in (self.ui.email_entry, self.ui.password_entry): |
3256 | + entry.textChanged.connect(self.validate) |
3257 | + entry.returnPressed.connect(self.ui.signin_button.click) |
3258 | + |
3259 | + def validate(self, *a, **kw): |
3260 | + """Enable sign in button only if email and password are non empty.""" |
3261 | + email = unicode(self.ui.email_entry.text()) |
3262 | + password = unicode(self.ui.password_entry.text()) |
3263 | + self.ui.signin_button.setEnabled(bool(email and password)) |
3264 | + self.ui.signin_button.style().unpolish(self.ui.signin_button) |
3265 | + self.ui.signin_button.style().polish(self.ui.signin_button) |
3266 | + |
3267 | + # pylint: disable=E0202 |
3268 | + @defer.inlineCallbacks |
3269 | + def load(self): |
3270 | + """Load specific tab info.""" |
3271 | + yield self.backend.get_credentials() |
3272 | + |
3273 | + @QtCore.pyqtSlot() |
3274 | + @handle_errors(logger=logger) |
3275 | + @log_call(logger.debug) |
3276 | + @defer.inlineCallbacks |
3277 | + def on_signin_button_clicked(self): |
3278 | + """The 'Sign in' button was clicked.""" |
3279 | + email = unicode(self.ui.email_entry.text()) |
3280 | + password = unicode(self.ui.password_entry.text()) |
3281 | + self.is_processing = True |
3282 | + try: |
3283 | + result = yield self.backend.login(email=email, password=password) |
3284 | + logger.info('Emitting credentialsFound for email %r.', email) |
3285 | + self.credentialsFound.emit(result) |
3286 | + finally: |
3287 | + self.is_processing = False |
3288 | + |
3289 | + @QtCore.pyqtSlot() |
3290 | + def on_cancel_button_clicked(self): |
3291 | + """The 'Cancel' button was clicked.""" |
3292 | + self.signinCanceled.emit() |
3293 | |
3294 | === added file 'ubuntuone/controlpanel/gui/qt/systray.py' |
3295 | --- ubuntuone/controlpanel/gui/qt/systray.py 1970-01-01 00:00:00 +0000 |
3296 | +++ ubuntuone/controlpanel/gui/qt/systray.py 2011-09-26 18:38:27 +0000 |
3297 | @@ -0,0 +1,68 @@ |
3298 | +# -*- coding: utf-8 -*- |
3299 | + |
3300 | +# Authors: Roberto Alsina <roberto.alsina@canonical.com> |
3301 | +# |
3302 | +# Copyright 2011 Canonical Ltd. |
3303 | +# |
3304 | +# This program is free software: you can redistribute it and/or modify it |
3305 | +# under the terms of the GNU General Public License version 3, as published |
3306 | +# by the Free Software Foundation. |
3307 | +# |
3308 | +# This program is distributed in the hope that it will be useful, but |
3309 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
3310 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3311 | +# PURPOSE. See the GNU General Public License for more details. |
3312 | +# |
3313 | +# You should have received a copy of the GNU General Public License along |
3314 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
3315 | +"""System notification area icon.""" |
3316 | + |
3317 | +from PyQt4 import QtGui |
3318 | + |
3319 | + |
3320 | +class TrayIcon(QtGui.QSystemTrayIcon): |
3321 | + |
3322 | + """System notification icon.""" |
3323 | + |
3324 | + def __init__(self, window=None): |
3325 | + super(TrayIcon, self).__init__(None) |
3326 | + self.setIcon(QtGui.QIcon(":/u1icon.png")) |
3327 | + self.setVisible(True) |
3328 | + self.window = window |
3329 | + self.activated.connect(self.on_activated) |
3330 | + self.context_menu = QtGui.QMenu() |
3331 | + self.restore = QtGui.QAction("Restore", self, |
3332 | + triggered=self.restore_window) |
3333 | + self.quit = QtGui.QAction("Quit Ubuntu One", self, |
3334 | + triggered=self.stop) |
3335 | + self.context_menu.addAction(self.restore) |
3336 | + self.context_menu.addSeparator() |
3337 | + self.context_menu.addAction(self.quit) |
3338 | + self.setContextMenu(self.context_menu) |
3339 | + |
3340 | + def on_activated(self, reason): |
3341 | + """The user activated the icon.""" |
3342 | + if reason == self.Trigger: # Left-click |
3343 | + self.restore_window() |
3344 | + |
3345 | + def restore_window(self): |
3346 | + """Show the main window.""" |
3347 | + if self.window is None: |
3348 | + # pylint: disable=W0404 |
3349 | + from ubuntuone.controlpanel.gui.qt.gui import MainWindow |
3350 | + # pylint: enable=W0404 |
3351 | + self.window = MainWindow(close_callback=self.delete_window) |
3352 | + self.window.show() |
3353 | + |
3354 | + def delete_window(self): |
3355 | + """Close and remove the main window.""" |
3356 | + if self.window is not None: |
3357 | + self.window.close() |
3358 | + self.window = None |
3359 | + |
3360 | + def stop(self): |
3361 | + """Stop the application.""" |
3362 | + # pylint: disable=W0404 |
3363 | + from twisted.internet import reactor |
3364 | + # pylint: enable=W0404 |
3365 | + reactor.stop() |
3366 | |
3367 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py' |
3368 | --- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-07-22 21:26:48 +0000 |
3369 | +++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-09-26 18:38:27 +0000 |
3370 | @@ -18,12 +18,16 @@ |
3371 | |
3372 | """The test suite for the Qt UI for the control panel for Ubuntu One.""" |
3373 | |
3374 | +import logging |
3375 | import os |
3376 | - |
3377 | -from PyQt4 import QtCore |
3378 | - |
3379 | -from ubuntuone.controlpanel import backend |
3380 | -from ubuntuone.controlpanel.tests import TestCase, EXPECTED_ACCOUNT_INFO |
3381 | +import urllib |
3382 | + |
3383 | +from PyQt4 import QtGui, QtCore |
3384 | +from ubuntuone.devtools.handlers import MementoHandler |
3385 | + |
3386 | +from ubuntuone.controlpanel import backend, cache |
3387 | +from ubuntuone.controlpanel.tests import TestCase, EXPECTED_ACCOUNT_INFO, TOKEN |
3388 | +from ubuntuone.controlpanel.gui import qt, UBUNTUONE_FROM_OAUTH |
3389 | from ubuntuone.controlpanel.gui.tests import FakedObject, USER_HOME |
3390 | |
3391 | # Attribute 'yyy' defined outside __init__, access to a protected member |
3392 | @@ -76,21 +80,6 @@ |
3393 | return folder |
3394 | |
3395 | |
3396 | -def skip_if_abstract_class(test): |
3397 | - """Decorator to skip a test if is an abstract class.""" |
3398 | - |
3399 | - def inner(instance): |
3400 | - """Skip a test if is an abstract class.""" |
3401 | - abstract = instance.class_ui is None |
3402 | - result = None |
3403 | - if not abstract: |
3404 | - result = test(instance) |
3405 | - |
3406 | - return result |
3407 | - |
3408 | - return inner |
3409 | - |
3410 | - |
3411 | class FakeUi(FakedObject): |
3412 | """A fake Ui object.""" |
3413 | |
3414 | @@ -114,7 +103,7 @@ |
3415 | backend.UPLOAD_KEY: -1, # no limit |
3416 | } |
3417 | |
3418 | - next_result = object() |
3419 | + next_result = [] |
3420 | exposed_methods = [ |
3421 | 'account_info', # account |
3422 | 'devices_info', 'device_names_info', # devices |
3423 | @@ -128,13 +117,41 @@ |
3424 | 'file_sync_settings_info', |
3425 | 'change_file_sync_settings', |
3426 | 'restore_file_sync_settings', |
3427 | - 'shutdown', |
3428 | + 'shutdown', 'login', |
3429 | ] |
3430 | |
3431 | - |
3432 | -class FakedConfirmDialog(object): |
3433 | + def get_credentials(self): |
3434 | + """Fake credentials retrieval.""" |
3435 | + self._called['get_credentials'] = ((), {}) |
3436 | + return TOKEN |
3437 | + |
3438 | + |
3439 | +class CrashyBackendException(Exception): |
3440 | + """A faked backend crash.""" |
3441 | + |
3442 | + |
3443 | +class CrashyBackend(FakedControlPanelBackend): |
3444 | + """A faked backend that crashes.""" |
3445 | + |
3446 | + def __init__(self, *args, **kwargs): |
3447 | + super(CrashyBackend, self).__init__(*args, **kwargs) |
3448 | + for i in self.exposed_methods + ['get_credentials']: |
3449 | + setattr(self, i, self._fail(i)) |
3450 | + |
3451 | + def _fail(self, f): |
3452 | + """Crash boom bang.""" |
3453 | + |
3454 | + def inner(*args, **kwargs): |
3455 | + """Raise a custom exception.""" |
3456 | + raise CrashyBackendException(f) |
3457 | + |
3458 | + return inner |
3459 | + |
3460 | + |
3461 | +class FakedDialog(object): |
3462 | """Fake a confirmation dialog.""" |
3463 | |
3464 | + Close = 0 |
3465 | response = args = kwargs = None |
3466 | |
3467 | @classmethod |
3468 | @@ -149,6 +166,7 @@ |
3469 | """Fake a file chooser dialog.""" |
3470 | |
3471 | response = args = kwargs = None |
3472 | + DontUseNativeDialog = 4 |
3473 | |
3474 | # Invalid name "getExistingDirectory" |
3475 | # pylint: disable=C0103 |
3476 | @@ -168,19 +186,43 @@ |
3477 | innerclass_name = None |
3478 | class_ui = None |
3479 | kwargs = {} |
3480 | + logger = None |
3481 | |
3482 | - @skip_if_abstract_class |
3483 | def setUp(self): |
3484 | + cache.Cache._shared_objects = {} |
3485 | super(BaseTestCase, self).setUp() |
3486 | self.patch(backend, 'ControlBackend', FakedControlPanelBackend) |
3487 | - # self.class_ui is not callable |
3488 | - # pylint: disable=E1102 |
3489 | - self.ui = self.class_ui(**self.kwargs) |
3490 | - self.addCleanup(self.ui.destroy) |
3491 | - |
3492 | - if hasattr(self.ui, 'backend'): |
3493 | - # clean backend calls |
3494 | - self.ui.backend._called.clear() |
3495 | + |
3496 | + self.ui = None |
3497 | + if self.class_ui is not None: |
3498 | + # self.class_ui is not callable |
3499 | + # pylint: disable=E1102 |
3500 | + self.ui = self.class_ui(**self.kwargs) |
3501 | + # pylint: enable=E1102 |
3502 | + self.addCleanup(self.ui.destroy) |
3503 | + |
3504 | + if getattr(self.ui, 'backend', None) is not None: |
3505 | + self.addCleanup(self.ui.backend._called.clear) |
3506 | + |
3507 | + logger = self.logger if self.logger is not None else \ |
3508 | + getattr(self.ui, 'logger', None) |
3509 | + self.memento = None |
3510 | + if logger is not None: |
3511 | + self.memento = MementoHandler() |
3512 | + self.memento.setLevel(logging.DEBUG) |
3513 | + logger.addHandler(self.memento) |
3514 | + self.addCleanup(logger.removeHandler, self.memento) |
3515 | + |
3516 | + # default response if user does nothing |
3517 | + FakedFileDialog.response = QtCore.QString('') |
3518 | + FakedFileDialog.args = None |
3519 | + FakedFileDialog.kwargs = None |
3520 | + self.patch(QtGui, 'QFileDialog', FakedFileDialog) |
3521 | + |
3522 | + FakedDialog.response = None |
3523 | + FakedDialog.args = None |
3524 | + FakedDialog.kwargs = None |
3525 | + self.patch(QtGui, 'QMessageBox', FakedDialog) |
3526 | |
3527 | def get_pixmap_data(self, pixmap): |
3528 | """Get the raw data of a QPixmap.""" |
3529 | @@ -202,6 +244,19 @@ |
3530 | self.assertIn(method_name, self.ui.backend._called) |
3531 | self.assertEqual(self.ui.backend._called[method_name], (args, kwargs)) |
3532 | |
3533 | + def assert_uri_hook_called(self, button, url): |
3534 | + """Check that uri_hook was called with 'url' when clicking 'button'.""" |
3535 | + self.patch(qt, 'uri_hook', self._set_called) |
3536 | + button.click() |
3537 | + |
3538 | + self.assertEqual(len(self._called), 2, 'uri_hook must be called.') |
3539 | + self.assertEqual(len(self._called[0]), 1, 'uri_hook must be called.') |
3540 | + actual_url = self._called[0][0] |
3541 | + if actual_url.startswith(UBUNTUONE_FROM_OAUTH): |
3542 | + self.assertIn(urllib.urlencode({'next': url}), actual_url) |
3543 | + else: |
3544 | + self.assertEqual(actual_url, url) |
3545 | + |
3546 | def test_init_loads_ui(self, expected_setup_ui=None): |
3547 | """The __init__ method loads the ui.""" |
3548 | if self.innerclass_ui is None: |
3549 | @@ -219,3 +274,8 @@ |
3550 | expected_setup_ui = expected_setup_ui(self.ui) |
3551 | self.assertEqual(self.ui.ui._called, |
3552 | {'setupUi': ((expected_setup_ui,), {})}) |
3553 | + |
3554 | + def test_backend_is_correct(self): |
3555 | + """The backend instance is correct.""" |
3556 | + if getattr(self.ui, 'backend', None) is not None: |
3557 | + self.assertIsInstance(self.ui.backend, FakedControlPanelBackend) |
3558 | |
3559 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_account.py' |
3560 | --- ubuntuone/controlpanel/gui/qt/tests/test_account.py 2011-07-22 21:26:48 +0000 |
3561 | +++ ubuntuone/controlpanel/gui/qt/tests/test_account.py 2011-09-26 18:38:27 +0000 |
3562 | @@ -20,7 +20,6 @@ |
3563 | |
3564 | from twisted.internet import defer |
3565 | |
3566 | -from ubuntuone.controlpanel.gui import qt |
3567 | from ubuntuone.controlpanel.gui.qt import account as gui |
3568 | from ubuntuone.controlpanel.gui.qt.tests import ( |
3569 | SAMPLE_ACCOUNT_INFO, SAMPLE_EMAIL, SAMPLE_NAME, SAMPLE_PLAN, |
3570 | @@ -75,14 +74,10 @@ |
3571 | |
3572 | def test_edit_account_button(self): |
3573 | """When clicking the edit account button, the proper url is opened.""" |
3574 | - self.patch(qt, 'uri_hook', self._set_called) |
3575 | - self.ui.ui.edit_profile_button.click() |
3576 | - |
3577 | - self.assertEqual(self._called, ((gui.EDIT_PROFILE_LINK,), {})) |
3578 | + self.assert_uri_hook_called(self.ui.ui.edit_profile_button, |
3579 | + gui.EDIT_PROFILE_LINK) |
3580 | |
3581 | def test_edit_services_button(self): |
3582 | """When clicking the mobile plan button, the proper url is opened.""" |
3583 | - self.patch(qt, 'uri_hook', self._set_called) |
3584 | - self.ui.ui.edit_services_button.click() |
3585 | - |
3586 | - self.assertEqual(self._called, ((gui.EDIT_ACCOUNT_LINK,), {})) |
3587 | + self.assert_uri_hook_called(self.ui.ui.edit_services_button, |
3588 | + gui.EDIT_ACCOUNT_LINK) |
3589 | |
3590 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py' |
3591 | --- ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-07-22 21:26:48 +0000 |
3592 | +++ ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-09-26 18:38:27 +0000 |
3593 | @@ -29,7 +29,9 @@ |
3594 | from ubuntuone.controlpanel.gui.qt import addfolder as gui |
3595 | from ubuntuone.controlpanel.gui.qt.tests import ( |
3596 | BaseTestCase, |
3597 | - FakedConfirmDialog, |
3598 | + CrashyBackend, |
3599 | + CrashyBackendException, |
3600 | + FakedDialog, |
3601 | FakedFileDialog, |
3602 | set_path_on_file_dialog, |
3603 | ) |
3604 | @@ -53,20 +55,6 @@ |
3605 | os.environ['HOME'] = USER_HOME |
3606 | self.addCleanup(lambda: os.environ.__setitem__('HOME', old_home)) |
3607 | |
3608 | - # default response if user does nothing |
3609 | - FakedFileDialog.response = gui.QtCore.QString('') |
3610 | - FakedFileDialog.args = None |
3611 | - FakedFileDialog.kwargs = None |
3612 | - self.patch(gui.QtGui, 'QFileDialog', FakedFileDialog) |
3613 | - |
3614 | - FakedConfirmDialog.response = None |
3615 | - FakedConfirmDialog.args = None |
3616 | - FakedConfirmDialog.kwargs = None |
3617 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
3618 | - |
3619 | - # reset backend state |
3620 | - self.ui.backend._called.clear() |
3621 | - |
3622 | @defer.inlineCallbacks |
3623 | def assert_does_nothing(self, method_call): |
3624 | """Nothing happens. |
3625 | @@ -92,7 +80,10 @@ |
3626 | yield self.ui.click() |
3627 | |
3628 | self.assertEqual(FakedFileDialog.args, ()) |
3629 | - self.assertEqual(FakedFileDialog.kwargs, {'parent': self.ui}) |
3630 | + self.assertEqual(FakedFileDialog.kwargs, { |
3631 | + 'options': gui.QtGui.QFileDialog.DontUseNativeDialog, |
3632 | + 'parent': self.ui, |
3633 | + }) |
3634 | |
3635 | @defer.inlineCallbacks |
3636 | def test_does_nothing_if_user_closes_file_chooser(self): |
3637 | @@ -100,8 +91,8 @@ |
3638 | yield self.assert_does_nothing(self.ui.click) |
3639 | |
3640 | # the warning dialog was not opened |
3641 | - self.assertEqual(FakedConfirmDialog.args, None) |
3642 | - self.assertEqual(FakedConfirmDialog.kwargs, None) |
3643 | + self.assertEqual(FakedDialog.args, None) |
3644 | + self.assertEqual(FakedDialog.kwargs, None) |
3645 | |
3646 | @defer.inlineCallbacks |
3647 | def test_opens_warning_if_folder_path_not_valid(self): |
3648 | @@ -113,9 +104,9 @@ |
3649 | |
3650 | args = {'folder_path': folder_path, 'home_folder': USER_HOME} |
3651 | msg = gui.FOLDER_INVALID_PATH % args |
3652 | - self.assertEqual(FakedConfirmDialog.args, |
3653 | + self.assertEqual(FakedDialog.args, |
3654 | (self.ui, '', msg, gui.CLOSE)) |
3655 | - self.assertEqual(FakedConfirmDialog.kwargs, {}) |
3656 | + self.assertEqual(FakedDialog.kwargs, {}) |
3657 | |
3658 | yield self.assert_does_nothing(self.ui.click) |
3659 | |
3660 | @@ -126,8 +117,8 @@ |
3661 | yield self.ui.click() |
3662 | |
3663 | # no warning |
3664 | - self.assertEqual(FakedConfirmDialog.args, None) |
3665 | - self.assertEqual(FakedConfirmDialog.kwargs, None) |
3666 | + self.assertEqual(FakedDialog.args, None) |
3667 | + self.assertEqual(FakedDialog.kwargs, None) |
3668 | # backend called |
3669 | self.assert_backend_called('create_folder', folder_path=folder) |
3670 | |
3671 | @@ -138,8 +129,8 @@ |
3672 | yield self.ui.click() |
3673 | |
3674 | # no warning |
3675 | - self.assertEqual(FakedConfirmDialog.args, None) |
3676 | - self.assertEqual(FakedConfirmDialog.kwargs, None) |
3677 | + self.assertEqual(FakedDialog.args, None) |
3678 | + self.assertEqual(FakedDialog.kwargs, None) |
3679 | # backend called |
3680 | self.assert_backend_called('create_folder', folder_path=folder) |
3681 | |
3682 | @@ -167,3 +158,12 @@ |
3683 | yield self.ui.click() |
3684 | |
3685 | self.assertEqual(self._called, ((), {})) |
3686 | + |
3687 | + @defer.inlineCallbacks |
3688 | + def test_backend_error_is_handled(self): |
3689 | + """Any error from the backend is properly handled.""" |
3690 | + set_path_on_file_dialog() |
3691 | + self.patch(self.ui, 'backend', CrashyBackend()) |
3692 | + yield self.ui.click() |
3693 | + |
3694 | + self.assertTrue(self.memento.check_exception(CrashyBackendException)) |
3695 | |
3696 | === added file 'ubuntuone/controlpanel/gui/qt/tests/test_common.py' |
3697 | --- ubuntuone/controlpanel/gui/qt/tests/test_common.py 1970-01-01 00:00:00 +0000 |
3698 | +++ ubuntuone/controlpanel/gui/qt/tests/test_common.py 2011-09-26 18:38:27 +0000 |
3699 | @@ -0,0 +1,210 @@ |
3700 | +# -*- coding: utf-8 -*- |
3701 | + |
3702 | +# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
3703 | +# |
3704 | +# Copyright 2011 Canonical Ltd. |
3705 | +# |
3706 | +# This program is free software: you can redistribute it and/or modify it |
3707 | +# under the terms of the GNU General Public License version 3, as published |
3708 | +# by the Free Software Foundation. |
3709 | +# |
3710 | +# This program is distributed in the hope that it will be useful, but |
3711 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
3712 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3713 | +# PURPOSE. See the GNU General Public License for more details. |
3714 | +# |
3715 | +# You should have received a copy of the GNU General Public License along |
3716 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
3717 | + |
3718 | +"""Tests for the uri_hook helper.""" |
3719 | + |
3720 | +import logging |
3721 | + |
3722 | +from PyQt4 import QtGui, QtCore |
3723 | +from twisted.internet import defer |
3724 | + |
3725 | +from ubuntuone.controlpanel.logger import setup_logging |
3726 | +from ubuntuone.controlpanel.gui.qt import uri_hook, handle_errors |
3727 | +from ubuntuone.controlpanel.gui.qt.tests import ( |
3728 | + BaseTestCase, |
3729 | + FakedDialog, |
3730 | +) |
3731 | + |
3732 | + |
3733 | +class UriHookTestCase(BaseTestCase): |
3734 | + """The test suite for the uri_hook.""" |
3735 | + |
3736 | + @defer.inlineCallbacks |
3737 | + def setUp(self): |
3738 | + yield super(UriHookTestCase, self).setUp() |
3739 | + self.patch(QtGui.QDesktopServices, 'openUrl', self._set_called) |
3740 | + |
3741 | + def test_opens_url(self): |
3742 | + """The url is opened properly.""" |
3743 | + expected = 'foo bar' |
3744 | + uri_hook(expected) |
3745 | + self.assertEqual(self._called, ((QtCore.QUrl(expected),), {})) |
3746 | + |
3747 | + def test_opens_url_encoded(self): |
3748 | + """The encoded url is opened properly.""" |
3749 | + expected = 'http://foo.bar/?next=https://one.ubuntu.com/' |
3750 | + uri_hook(expected) |
3751 | + self.assertEqual(self._called, ((QtCore.QUrl(expected),), {})) |
3752 | + |
3753 | + |
3754 | +class HandleErrorTestCase(BaseTestCase): |
3755 | + """Test suite for the generic error handler.""" |
3756 | + |
3757 | + error_handler = None |
3758 | + use_logger = False |
3759 | + logger = logging.getLogger() # root logger |
3760 | + |
3761 | + @defer.inlineCallbacks |
3762 | + def setUp(self): |
3763 | + yield super(HandleErrorTestCase, self).setUp() |
3764 | + self.called = None |
3765 | + self.result = None |
3766 | + self.failure = None |
3767 | + self.error_handler_called = None |
3768 | + |
3769 | + if self.use_logger: |
3770 | + logger = self.logger |
3771 | + else: |
3772 | + logger = None |
3773 | + |
3774 | + self.decorate_me = handle_errors(error_handler=self.error_handler, |
3775 | + logger=logger)(self._decorate_me) |
3776 | + |
3777 | + @defer.inlineCallbacks |
3778 | + def _decorate_me(self, *args, **kwargs): |
3779 | + """Helper to test thye decorator.""" |
3780 | + if self.failure: |
3781 | + # Raising only classes, instances or string are allowed |
3782 | + # pylint: disable=E0702 |
3783 | + raise self.failure |
3784 | + |
3785 | + yield |
3786 | + self.called = (args, kwargs) |
3787 | + defer.returnValue(self.result) |
3788 | + |
3789 | + @defer.inlineCallbacks |
3790 | + def test_is_decorator(self): |
3791 | + """Is a decorator.""" |
3792 | + yield self.decorate_me() |
3793 | + |
3794 | + @defer.inlineCallbacks |
3795 | + def test_params_are_passed(self): |
3796 | + """Named and unnamed arguments are passed.""" |
3797 | + args = ({}, object(), 'foo') |
3798 | + kwargs = {'1': 1, 'test': None, '0': ['a']} |
3799 | + yield self.decorate_me(*args, **kwargs) |
3800 | + |
3801 | + self.assertTrue(self.called, (args, kwargs)) |
3802 | + |
3803 | + @defer.inlineCallbacks |
3804 | + def test_result_is_returned(self): |
3805 | + """Result is returned.""" |
3806 | + self.result = object() |
3807 | + result = yield self.decorate_me() |
3808 | + |
3809 | + self.assertEqual(self.result, result) |
3810 | + |
3811 | + def test_name_is_preserved(self): |
3812 | + """The method name is not masqueraded.""" |
3813 | + self.assertEqual(self.decorate_me.__name__, self._decorate_me.__name__) |
3814 | + |
3815 | + @defer.inlineCallbacks |
3816 | + def test_exeptions_are_handled(self): |
3817 | + """Any exception is handled and logged in the root logger.""" |
3818 | + msg = 'This is me failing badly.' |
3819 | + self.failure = Exception(msg) |
3820 | + |
3821 | + yield self.decorate_me() |
3822 | + |
3823 | + logged = self.memento.check_exception(self.failure.__class__, msg) |
3824 | + recs = '\n'.join(rec.exc_text for rec in self.memento.records) |
3825 | + self.assertTrue(logged, 'Exception must be logged, got:\n%s' % recs) |
3826 | + |
3827 | + @defer.inlineCallbacks |
3828 | + def test_show_error_message(self): |
3829 | + """On error, show an error message.""" |
3830 | + self.failure = Exception() |
3831 | + |
3832 | + yield self.decorate_me() |
3833 | + |
3834 | + msg = self.failure.__class__.__name__ |
3835 | + self.assertEqual(FakedDialog.args, |
3836 | + (None, '', msg, QtGui.QMessageBox.Close)) |
3837 | + self.assertEqual(FakedDialog.kwargs, {}) |
3838 | + |
3839 | + @defer.inlineCallbacks |
3840 | + def test_show_error_message_if_args(self): |
3841 | + """On error, show an error message.""" |
3842 | + msg1 = 'This is me failing badly.' |
3843 | + msg2 = 'More details about what went wrong.' |
3844 | + obj = object() |
3845 | + self.failure = Exception(msg1, msg2, obj) |
3846 | + |
3847 | + yield self.decorate_me() |
3848 | + |
3849 | + msg = '\n'.join(map(repr, (msg1, msg2, obj))) |
3850 | + msg = self.failure.__class__.__name__ + '\n' + msg |
3851 | + self.assertEqual(FakedDialog.args, |
3852 | + (None, '', msg, QtGui.QMessageBox.Close)) |
3853 | + self.assertEqual(FakedDialog.kwargs, {}) |
3854 | + |
3855 | + @defer.inlineCallbacks |
3856 | + def test_show_error_message_if_mapping(self): |
3857 | + """On error, show an error message.""" |
3858 | + msg1 = 'This is me failing badly.' |
3859 | + msg2 = 'More details about what went wrong.' |
3860 | + errdict = {'foo': msg1, 'bar': msg2} |
3861 | + self.failure = Exception(errdict) |
3862 | + |
3863 | + yield self.decorate_me() |
3864 | + |
3865 | + msg = '\n'.join((msg1, msg2)) |
3866 | + self.assertEqual(FakedDialog.args, |
3867 | + (None, '', msg, QtGui.QMessageBox.Close)) |
3868 | + self.assertEqual(FakedDialog.kwargs, {}) |
3869 | + |
3870 | + @defer.inlineCallbacks |
3871 | + def test_no_error_message_if_no_exception(self): |
3872 | + """On success, do not show an error message.""" |
3873 | + yield self.decorate_me() |
3874 | + |
3875 | + self.assertEqual(FakedDialog.args, None) |
3876 | + self.assertEqual(FakedDialog.kwargs, None) |
3877 | + |
3878 | + @defer.inlineCallbacks |
3879 | + def test_call_error_handler(self): |
3880 | + """On success, do not execute error_handler.""" |
3881 | + yield self.decorate_me() |
3882 | + self.assertFalse(self.error_handler_called) |
3883 | + |
3884 | + |
3885 | +class HandleErrorWithCustomLoggerTestCase(HandleErrorTestCase): |
3886 | + """Test suite for the generic error handler.""" |
3887 | + |
3888 | + use_logger = True |
3889 | + logger = setup_logging('HandleErrorWithoutLoggerTestCase') # custom logger |
3890 | + |
3891 | + |
3892 | +class HandleErrorWithHandlerTestCase(HandleErrorTestCase): |
3893 | + """Test suite for the generic error handler when using a custom handler.""" |
3894 | + |
3895 | + @defer.inlineCallbacks |
3896 | + def error_handler(self, *a, **kw): |
3897 | + """Implement an error handler.""" |
3898 | + self.error_handler_called = (a, kw) |
3899 | + yield |
3900 | + |
3901 | + @defer.inlineCallbacks |
3902 | + def test_call_error_handler(self): |
3903 | + """On error, execute error_handler.""" |
3904 | + msg = 'This is me failing badly.' |
3905 | + self.failure = Exception(msg) |
3906 | + |
3907 | + yield self.decorate_me() |
3908 | + |
3909 | + self.assertEqual(self.error_handler_called, ((), {})) |
3910 | |
3911 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py' |
3912 | --- ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py 2011-07-22 21:26:48 +0000 |
3913 | +++ ubuntuone/controlpanel/gui/qt/tests/test_controlpanel.py 2011-09-26 18:38:27 +0000 |
3914 | @@ -22,14 +22,16 @@ |
3915 | |
3916 | from twisted.internet import defer |
3917 | |
3918 | -from ubuntuone.controlpanel.gui import qt |
3919 | from ubuntuone.controlpanel.gui.qt import controlpanel as gui |
3920 | from ubuntuone.controlpanel.gui.qt.tests import ( |
3921 | - BaseTestCase, SAMPLE_ACCOUNT_INFO, SAMPLE_NAME, |
3922 | -) |
3923 | - |
3924 | - |
3925 | -class ControlPanelTestCase(BaseTestCase): |
3926 | + SAMPLE_ACCOUNT_INFO, SAMPLE_NAME, TOKEN, |
3927 | +) |
3928 | +from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
3929 | + UbuntuOneBinTestCase, |
3930 | +) |
3931 | + |
3932 | + |
3933 | +class ControlPanelTestCase(UbuntuOneBinTestCase): |
3934 | """Test the qt control panel.""" |
3935 | |
3936 | innerclass_ui = gui.controlpanel_ui |
3937 | @@ -39,18 +41,68 @@ |
3938 | @defer.inlineCallbacks |
3939 | def setUp(self): |
3940 | yield super(ControlPanelTestCase, self).setUp() |
3941 | + self.patch(self.ui.ui.folders_tab, 'process_info', lambda info: None) |
3942 | self.ui.backend.next_result = SAMPLE_ACCOUNT_INFO |
3943 | |
3944 | - def test_backend(self): |
3945 | - """Backend is created.""" |
3946 | - self.assertIsInstance(self.ui.backend, |
3947 | - gui.backend.ControlBackend) |
3948 | + @defer.inlineCallbacks |
3949 | + def test_is_processing_while_asking_info(self): |
3950 | + """The ui is processing while the contents are loaded.""" |
3951 | + def check(): |
3952 | + """The ui must be is_processing.""" |
3953 | + self.assertTrue(self.ui.is_processing, 'ui must be processing') |
3954 | + return {} |
3955 | + |
3956 | + self.patch(self.ui.backend, 'get_credentials', check) |
3957 | + |
3958 | + yield self.ui.load() # trigger the info request |
3959 | + self.assertFalse(self.ui.is_processing, 'ui must not be processing') |
3960 | + |
3961 | + @defer.inlineCallbacks |
3962 | + def test_credentials_are_requested_on_load(self): |
3963 | + """The info is requested to the backend.""" |
3964 | + yield self.ui.load() |
3965 | + self.assert_backend_called('get_credentials') |
3966 | + |
3967 | + @defer.inlineCallbacks |
3968 | + def test_on_credentials_not_found_called(self): |
3969 | + """If no credentials, on_credentials_not_found is called.""" |
3970 | + self.patch(self.ui, 'on_credentials_not_found', self._set_called) |
3971 | + self.patch(self.ui.backend, 'get_credentials', lambda: {}) |
3972 | + yield self.ui.load() |
3973 | + |
3974 | + self.assertEqual(self._called, ((), {})) |
3975 | + |
3976 | + def test_on_credentials_not_found(self): |
3977 | + """The signin panel is shown.""" |
3978 | + self.ui.on_credentials_found() |
3979 | + self.ui.on_credentials_not_found() |
3980 | + self.assertIs(self.ui.ui.switcher.currentWidget(), self.ui.ui.signin) |
3981 | + |
3982 | + @defer.inlineCallbacks |
3983 | + def test_on_credentials_found_called(self): |
3984 | + """If credentials, on_credentials_not_found is called.""" |
3985 | + self.patch(self.ui, 'on_credentials_found', self._set_called) |
3986 | + yield self.ui.load() |
3987 | + |
3988 | + self.assertEqual(self._called, ((), {})) |
3989 | + |
3990 | + def test_on_credentials_found(self): |
3991 | + """The management panel is shown.""" |
3992 | + self.patch(self.ui, 'connect_file_sync', self._set_called) |
3993 | + self.ui.on_credentials_not_found() |
3994 | + self.ui.on_credentials_found() |
3995 | + |
3996 | + self.assertIs(self.ui.ui.switcher.currentWidget(), |
3997 | + self.ui.ui.management) |
3998 | + self.assertEqual(self._called, ((), {})) |
3999 | |
4000 | @defer.inlineCallbacks |
4001 | def test_info_is_requested_on_load(self): |
4002 | """The info is requested to the backend.""" |
4003 | + self.patch(self.ui, 'process_info', self._set_called) |
4004 | yield self.ui.load() |
4005 | self.assert_backend_called('account_info') |
4006 | + self.assertEqual(self._called, ((SAMPLE_ACCOUNT_INFO,), {})) |
4007 | |
4008 | def test_process_info(self): |
4009 | """The info is processed when ready.""" |
4010 | @@ -72,32 +124,85 @@ |
4011 | msg = gui.PERCENTAGE_LABEL % percentage_usage |
4012 | self.assertEqual(self.ui.ui.percentage_usage_label.text(), msg) |
4013 | |
4014 | + def test_update_over_quota(self): |
4015 | + """Check the labels state when the user exceed the quota.""" |
4016 | + percentage_value = 100 |
4017 | + # pylint: disable=W0212 |
4018 | + self.ui._update_quota({'percentage': percentage_value}) |
4019 | + # pylint: enable=W0212 |
4020 | + |
4021 | + self.assertTrue( |
4022 | + self.ui.ui.percentage_usage_label.property("OverQuota").toBool()) |
4023 | + self.assertTrue( |
4024 | + self.ui.ui.quota_usage_label.property("OverQuota").toBool()) |
4025 | + |
4026 | + def test_update_quota_in_range(self): |
4027 | + """Check the labels state when the quota is under the threshold.""" |
4028 | + percentage_value = 50 |
4029 | + # pylint: disable=W0212 |
4030 | + self.ui._update_quota({'percentage': percentage_value}) |
4031 | + # pylint: enable=W0212 |
4032 | + |
4033 | + self.assertFalse( |
4034 | + self.ui.ui.percentage_usage_label.property("OverQuota").toBool()) |
4035 | + self.assertFalse( |
4036 | + self.ui.ui.quota_usage_label.property("OverQuota").toBool()) |
4037 | + |
4038 | + def test_on_local_device_removed(self): |
4039 | + """On DeviesPanel's localDeviceRemoved, emit credentialsNotFound.""" |
4040 | + self.ui.ui.devices_tab.localDeviceRemoved.emit() |
4041 | + self.assertIs(self.ui.ui.switcher.currentWidget(), self.ui.ui.signin) |
4042 | + |
4043 | + def test_on_signin_credentials_found(self): |
4044 | + """On SignInPanel's credentialsFound, the management panel is shown.""" |
4045 | + self.patch(self.ui, 'load', self._set_called) |
4046 | + self.ui.ui.signin.credentialsFound.emit(TOKEN) |
4047 | + |
4048 | + self.assertEqual(self._called, ((), {})) |
4049 | + |
4050 | + @defer.inlineCallbacks |
4051 | + def test_connect_file_sync_with_autoconnect(self): |
4052 | + """Connect is called if autoconnect is enabled.""" |
4053 | + settings = {gui.AUTOCONNECT_KEY: True} |
4054 | + self.patch(self.ui.backend, 'file_sync_settings_info', |
4055 | + lambda: defer.succeed(settings)) |
4056 | + |
4057 | + yield self.ui.connect_file_sync() |
4058 | + |
4059 | + self.assert_backend_called('connect_files') |
4060 | + |
4061 | + @defer.inlineCallbacks |
4062 | + def test_connect_file_sync_without_autoconnect(self): |
4063 | + """Connect is called if autoconnect is disabled.""" |
4064 | + settings = {gui.AUTOCONNECT_KEY: False} |
4065 | + self.patch(self.ui.backend, 'file_sync_settings_info', |
4066 | + lambda: defer.succeed(settings)) |
4067 | + |
4068 | + yield self.ui.connect_file_sync() |
4069 | + |
4070 | + # pylint: disable=W0212 |
4071 | + self.assertNotIn('connect_files', self.ui.backend._called) |
4072 | + |
4073 | |
4074 | class ExternalLinkButtonsTestCase(ControlPanelTestCase): |
4075 | """The link in the go-to-web buttons are correct.""" |
4076 | |
4077 | - @defer.inlineCallbacks |
4078 | - def setUp(self): |
4079 | - self.patch(qt, 'uri_hook', self._set_called) |
4080 | - self.patch(gui, 'uri_hook', self._set_called) |
4081 | - yield super(ExternalLinkButtonsTestCase, self).setUp() |
4082 | - |
4083 | def test_get_more_space_button(self): |
4084 | """When clicking the get more GB button, the proper url is opened.""" |
4085 | - self.ui.ui.get_more_space_button.click() |
4086 | - self.assertEqual(self._called, ((gui.EDIT_ACCOUNT_LINK,), {})) |
4087 | + self.assert_uri_hook_called(self.ui.ui.get_more_space_button, |
4088 | + gui.EDIT_SERVICES_LINK) |
4089 | |
4090 | def test_help_button(self): |
4091 | """When clicking the help button, the proper url is opened.""" |
4092 | - self.ui.ui.help_button.click() |
4093 | - self.assertEqual(self._called, ((gui.GET_SUPPORT_LINK,), {})) |
4094 | + self.assert_uri_hook_called(self.ui.ui.help_button, |
4095 | + gui.GET_SUPPORT_LINK) |
4096 | |
4097 | def test_twitter_button(self): |
4098 | """When clicking the twitter button, the proper url is opened.""" |
4099 | - self.ui.ui.twitter_button.click() |
4100 | - self.assertEqual(self._called, ((gui.TWITTER_LINK,), {})) |
4101 | + self.assert_uri_hook_called(self.ui.ui.twitter_button, |
4102 | + gui.TWITTER_LINK) |
4103 | |
4104 | def test_facebook_button(self): |
4105 | """When clicking the facebook button, the proper url is opened.""" |
4106 | - self.ui.ui.facebook_button.click() |
4107 | - self.assertEqual(self._called, ((gui.FACEBOOK_LINK,), {})) |
4108 | + self.assert_uri_hook_called(self.ui.ui.facebook_button, |
4109 | + gui.FACEBOOK_LINK) |
4110 | |
4111 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_device.py' |
4112 | --- ubuntuone/controlpanel/gui/qt/tests/test_device.py 2011-07-22 21:26:48 +0000 |
4113 | +++ ubuntuone/controlpanel/gui/qt/tests/test_device.py 2011-09-26 18:38:27 +0000 |
4114 | @@ -23,8 +23,9 @@ |
4115 | from ubuntuone.controlpanel.gui.qt import device as gui |
4116 | from ubuntuone.controlpanel.gui.qt.tests import ( |
4117 | BaseTestCase, |
4118 | - FakedConfirmDialog, |
4119 | - FakedControlPanelBackend, |
4120 | + CrashyBackend, |
4121 | + CrashyBackendException, |
4122 | + FakedDialog, |
4123 | SAMPLE_COMPUTER_INFO, |
4124 | SAMPLE_PHONE_INFO, |
4125 | ) |
4126 | @@ -40,18 +41,14 @@ |
4127 | innerclass_ui = gui.device_ui |
4128 | innerclass_name = "Ui_Form" |
4129 | class_ui = gui.DeviceWidget |
4130 | - backend = FakedControlPanelBackend() |
4131 | device_id = 'zaraza' |
4132 | - kwargs = {'backend': backend, 'device_id': device_id} |
4133 | + kwargs = {'device_id': device_id} |
4134 | + logger = gui.logger |
4135 | |
4136 | def test_has_id(self): |
4137 | """The device as an id, None by default.""" |
4138 | self.assertEqual(self.ui.id, self.device_id) |
4139 | |
4140 | - def test_has_backend(self): |
4141 | - """The device as a backend, None by default.""" |
4142 | - self.assertIs(self.ui.backend, self.backend) |
4143 | - |
4144 | def test_update_device_info(self): |
4145 | """The widget is updated with the info.""" |
4146 | info = SAMPLE_COMPUTER_INFO |
4147 | @@ -104,10 +101,7 @@ |
4148 | @defer.inlineCallbacks |
4149 | def setUp(self): |
4150 | yield super(RemoveDeviceTestCase, self).setUp() |
4151 | - FakedConfirmDialog.response = gui.NO |
4152 | - FakedConfirmDialog.args = None |
4153 | - FakedConfirmDialog.kwargs = None |
4154 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
4155 | + FakedDialog.response = gui.YES |
4156 | |
4157 | def test_remove_device_opens_confirmation_dialog(self): |
4158 | """A confirmation dialog is opened when user clicks 'delete device'.""" |
4159 | @@ -115,13 +109,13 @@ |
4160 | |
4161 | msg = gui.DEVICE_CONFIRM_REMOVE |
4162 | buttons = gui.YES | gui.NO |
4163 | - self.assertEqual(FakedConfirmDialog.args, |
4164 | + self.assertEqual(FakedDialog.args, |
4165 | (self.ui, '', msg, buttons, gui.NO)) |
4166 | - self.assertEqual(FakedConfirmDialog.kwargs, {}) |
4167 | + self.assertEqual(FakedDialog.kwargs, {}) |
4168 | |
4169 | def test_remove_device_does_not_remove_if_answer_is_no(self): |
4170 | """The device is not removed is answer is No.""" |
4171 | - FakedConfirmDialog.response = gui.NO |
4172 | + FakedDialog.response = gui.NO |
4173 | self.ui.removed.connect(self._set_called) |
4174 | self.ui.ui.remove_device_button.click() |
4175 | |
4176 | @@ -130,7 +124,7 @@ |
4177 | |
4178 | def test_remove_device_does_remove_if_answer_is_yes(self): |
4179 | """The device is removed is answer is Yes.""" |
4180 | - FakedConfirmDialog.response = gui.YES |
4181 | + FakedDialog.response = gui.YES |
4182 | self.ui.ui.remove_device_button.click() |
4183 | |
4184 | self.assert_backend_called('remove_device', device_id=self.device_id) |
4185 | @@ -144,7 +138,7 @@ |
4186 | """Fire deferred when the device was removed.""" |
4187 | d.callback(device_id) |
4188 | |
4189 | - FakedConfirmDialog.response = gui.YES |
4190 | + FakedDialog.response = gui.YES |
4191 | self.ui.removed.connect(self._set_called) |
4192 | self.patch(self.ui.backend, 'remove_device', check) |
4193 | self.ui.ui.remove_device_button.click() |
4194 | @@ -154,8 +148,16 @@ |
4195 | |
4196 | def test_remove_device_emits_signal_when_not_removed(self): |
4197 | """The signal 'removeCanceled' is emitted when user cancels removal.""" |
4198 | - FakedConfirmDialog.response = gui.NO |
4199 | + FakedDialog.response = gui.NO |
4200 | self.ui.removeCanceled.connect(self._set_called) |
4201 | self.ui.ui.remove_device_button.click() |
4202 | |
4203 | self.assertEqual(self._called, ((), {})) |
4204 | + |
4205 | + @defer.inlineCallbacks |
4206 | + def test_backend_error_is_handled(self): |
4207 | + """Any error from the backend is properly handled.""" |
4208 | + self.patch(self.ui, 'backend', CrashyBackend()) |
4209 | + yield self.ui.ui.remove_device_button.click() |
4210 | + |
4211 | + self.assertTrue(self.memento.check_exception(CrashyBackendException)) |
4212 | |
4213 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py' |
4214 | --- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-07-22 21:26:48 +0000 |
4215 | +++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2011-09-26 18:38:27 +0000 |
4216 | @@ -20,10 +20,8 @@ |
4217 | |
4218 | from twisted.internet import defer |
4219 | |
4220 | -from ubuntuone.controlpanel.gui import qt |
4221 | from ubuntuone.controlpanel.gui.qt import devices as gui |
4222 | from ubuntuone.controlpanel.gui.qt.tests import ( |
4223 | - FakedConfirmDialog, |
4224 | SAMPLE_DEVICES_INFO, |
4225 | ) |
4226 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
4227 | @@ -42,7 +40,6 @@ |
4228 | def setUp(self): |
4229 | yield super(DevicesPanelTestCase, self).setUp() |
4230 | self.ui.backend.next_result = SAMPLE_DEVICES_INFO |
4231 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
4232 | |
4233 | def test_is_processing_while_asking_info(self): |
4234 | """The ui is processing while the contents are loaded.""" |
4235 | @@ -97,10 +94,8 @@ |
4236 | |
4237 | def test_manage_devices_button(self): |
4238 | """Clicking the manage devices button opens the proper url.""" |
4239 | - self.patch(qt, 'uri_hook', self._set_called) |
4240 | - self.ui.ui.manage_devices_button.click() |
4241 | - |
4242 | - self.assertEqual(self._called, ((gui.EDIT_DEVICES_LINK,), {})) |
4243 | + self.assert_uri_hook_called(self.ui.ui.manage_devices_button, |
4244 | + gui.EDIT_DEVICES_LINK) |
4245 | |
4246 | def test_remove_device_widget_after_removal(self): |
4247 | """When a device widget was deleted, remove it from the UI.""" |
4248 | @@ -110,3 +105,13 @@ |
4249 | local_device.removed.emit() |
4250 | |
4251 | self.assertTrue(self.ui.ui.local_device_box.itemAt(0) is None) |
4252 | + |
4253 | + def test_local_device_removed_signal(self): |
4254 | + """When the local device is removed, emit localDeviceRemoved signal.""" |
4255 | + self.ui.localDeviceRemoved.connect(self._set_called) |
4256 | + self.ui.process_info(SAMPLE_DEVICES_INFO) |
4257 | + |
4258 | + local_device = self.ui.ui.local_device_box.itemAt(0).widget() |
4259 | + local_device.removed.emit() |
4260 | + |
4261 | + self.assertEqual(self._called, ((), {})) |
4262 | |
4263 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py' |
4264 | --- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2011-08-12 19:12:08 +0000 |
4265 | +++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2011-09-26 18:38:27 +0000 |
4266 | @@ -31,11 +31,9 @@ |
4267 | FAKE_VOLUMES_NO_FREE_SPACE_INFO, |
4268 | MUSIC_FOLDER, ROOT, USER_HOME, |
4269 | ) |
4270 | -from ubuntuone.controlpanel.gui import qt |
4271 | from ubuntuone.controlpanel.gui.qt import folders as gui |
4272 | from ubuntuone.controlpanel.gui.qt.tests import ( |
4273 | - FakedConfirmDialog, |
4274 | - FakedFileDialog, |
4275 | + FakedDialog, |
4276 | ) |
4277 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
4278 | UbuntuOneBinTestCase, |
4279 | @@ -140,8 +138,10 @@ |
4280 | self.assertTrue(item is not None) |
4281 | |
4282 | name = volume['path'].replace(USER_HOME + os.path.sep, '') |
4283 | + expected_path = volume['path'] |
4284 | if volume['type'] == self.ui.backend.SHARE_TYPE: |
4285 | name = volume['name'] |
4286 | + expected_path = volume['realpath'] |
4287 | label = item.text(gui.FOLDER_NAME_COL) |
4288 | self.assertEqual(label, name) |
4289 | |
4290 | @@ -161,7 +161,7 @@ |
4291 | self.assertEqual(icon_name, gui.SHARE_ICON_NAME) |
4292 | |
4293 | self.assertEqual(item.volume_id, volume['volume_id']) |
4294 | - self.assertEqual(item.volume_path, volume['path']) |
4295 | + self.assertEqual(item.volume_path, expected_path) |
4296 | |
4297 | # tooltips are correct |
4298 | self.assertEqual(item.toolTip(gui.FOLDER_NAME_COL), name) |
4299 | @@ -175,6 +175,8 @@ |
4300 | gui.FOLDER_ICON_NAME) |
4301 | self.assertEqual(button.iconSize().width(), 12) |
4302 | self.assertEqual(button.iconSize().height(), 12) |
4303 | + self.assertEqual(button.isEnabled(), |
4304 | + bool(volume['subscribed'])) |
4305 | |
4306 | treeiter += 1 |
4307 | item = treeiter.value() |
4308 | @@ -245,7 +247,8 @@ |
4309 | self.ui.on_folders_itemActivated(item) |
4310 | |
4311 | self.assertEqual(self._called, |
4312 | - ((gui.FILE_URI_PREFIX + path,), {})) |
4313 | + ((unicode(gui.QtCore.QUrl.fromLocalFile(path).toString()),), {})) |
4314 | + self.assertTrue(gui.QtCore.QUrl(self._called[0][0]).isValid()) |
4315 | |
4316 | def test_clicking_on_row_handles_path_none(self): |
4317 | """None paths are properly handled.""" |
4318 | @@ -302,10 +305,8 @@ |
4319 | |
4320 | def test_share_publish_button(self): |
4321 | """When clicking the share/publish button, the proper url is opened.""" |
4322 | - self.patch(qt, 'uri_hook', self._set_called) |
4323 | - self.ui.ui.share_publish_button.click() |
4324 | - |
4325 | - self.assertEqual(self._called, ((gui.MANAGE_FILES_LINK,), {})) |
4326 | + self.assert_uri_hook_called(self.ui.ui.share_publish_button, |
4327 | + gui.MANAGE_FILES_LINK) |
4328 | |
4329 | |
4330 | class FoldersPanelAddFolderTestCase(FoldersPanelTestCase): |
4331 | @@ -322,17 +323,6 @@ |
4332 | # reset backend state |
4333 | self.ui.backend._called.clear() |
4334 | |
4335 | - # default response if user does nothing |
4336 | - FakedFileDialog.response = gui.QtCore.QString('') |
4337 | - FakedFileDialog.args = None |
4338 | - FakedFileDialog.kwargs = None |
4339 | - self.patch(gui.QtGui, 'QFileDialog', FakedFileDialog) |
4340 | - |
4341 | - FakedConfirmDialog.response = None |
4342 | - FakedConfirmDialog.args = None |
4343 | - FakedConfirmDialog.kwargs = None |
4344 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
4345 | - |
4346 | def test_not_is_processing(self): |
4347 | """Before clicking the add folder button, the UI is not processing.""" |
4348 | self.assertFalse(self.ui.is_processing, 'ui must not be processing') |
4349 | @@ -356,10 +346,7 @@ |
4350 | def setUp(self): |
4351 | yield super(FoldersPanelSubscriptionTestCase, self).setUp() |
4352 | self.patch(gui.os.path, 'exists', lambda path: True) |
4353 | - FakedConfirmDialog.response = gui.YES |
4354 | - FakedConfirmDialog.args = None |
4355 | - FakedConfirmDialog.kwargs = None |
4356 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
4357 | + FakedDialog.response = gui.YES |
4358 | |
4359 | self.ui.process_info(FAKE_VOLUMES_MINIMAL_INFO) |
4360 | # the music folder |
4361 | @@ -368,6 +355,7 @@ |
4362 | @defer.inlineCallbacks |
4363 | def test_on_folders_item_changed(self): |
4364 | """Clicking on 'subscribed' updates the folder subscription.""" |
4365 | + self.patch(self.ui, 'load', self._set_called) |
4366 | volume = MUSIC_FOLDER |
4367 | fid = volume['volume_id'] |
4368 | subscribed = not bool(volume['subscribed']) |
4369 | @@ -386,6 +374,9 @@ |
4370 | value = self.item.checkState(gui.SUBSCRIPTION_COL) == gui.CHECKED |
4371 | self.assertEqual(value, bool(subscribed)) |
4372 | |
4373 | + # folder list was reloaded |
4374 | + self.assertEqual(self._called, ((), {})) |
4375 | + |
4376 | @defer.inlineCallbacks |
4377 | def test_on_folders_item_changed_is_processing(self): |
4378 | """Clicking on 'subscribed' sets is_processing flag until done.""" |
4379 | @@ -438,9 +429,9 @@ |
4380 | volume_path = self.item.volume_path |
4381 | msg = gui.FOLDERS_CONFIRM_MERGE % {'folder_path': volume_path} |
4382 | buttons = gui.YES | gui.NO | gui.CANCEL |
4383 | - self.assertEqual(FakedConfirmDialog.args, |
4384 | + self.assertEqual(FakedDialog.args, |
4385 | (self.ui, '', msg, buttons, gui.YES)) |
4386 | - self.assertEqual(FakedConfirmDialog.kwargs, {}) |
4387 | + self.assertEqual(FakedDialog.kwargs, {}) |
4388 | |
4389 | @defer.inlineCallbacks |
4390 | def test_confirm_dialog_if_path_does_not_exist(self): |
4391 | @@ -454,14 +445,13 @@ |
4392 | |
4393 | yield self.ui.on_folders_itemChanged(self.item) |
4394 | |
4395 | - self.assertEqual(FakedConfirmDialog.args, None) |
4396 | - self.assertEqual(FakedConfirmDialog.kwargs, None) |
4397 | + self.assertEqual(FakedDialog.args, None) |
4398 | + self.assertEqual(FakedDialog.kwargs, None) |
4399 | |
4400 | @defer.inlineCallbacks |
4401 | def test_subscribe_does_not_call_backend_if_dialog_closed(self): |
4402 | """Backend is not called if users closes the confirmation dialog.""" |
4403 | - FakedConfirmDialog.response = gui.CANCEL |
4404 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
4405 | + FakedDialog.response = gui.CANCEL |
4406 | |
4407 | # make sure the item is subscribed |
4408 | self.ui.is_processing = True |
4409 | @@ -470,7 +460,7 @@ |
4410 | |
4411 | yield self.ui.on_folders_itemChanged(self.item) |
4412 | |
4413 | - self.assertFalse(FakedConfirmDialog.args is None, 'warning was called') |
4414 | + self.assertFalse(FakedDialog.args is None, 'warning was called') |
4415 | self.assertNotIn('change_volume_settings', self.ui.backend._called) |
4416 | self.assertFalse(self.ui.is_processing) |
4417 | |
4418 | @@ -480,8 +470,7 @@ |
4419 | @defer.inlineCallbacks |
4420 | def test_subscribe_does_not_call_backend_if_answer_is_no(self): |
4421 | """Backend is not called if users clicks on 'No'.""" |
4422 | - FakedConfirmDialog.response = gui.NO |
4423 | - self.patch(gui.QtGui, 'QMessageBox', FakedConfirmDialog) |
4424 | + FakedDialog.response = gui.NO |
4425 | |
4426 | # make sure the item is subscribed |
4427 | self.ui.is_processing = True |
4428 | @@ -490,7 +479,7 @@ |
4429 | |
4430 | yield self.ui.on_folders_itemChanged(self.item) |
4431 | |
4432 | - self.assertFalse(FakedConfirmDialog.args is None, 'warning was called') |
4433 | + self.assertFalse(FakedDialog.args is None, 'warning was called') |
4434 | self.assertNotIn('change_volume_settings', self.ui.backend._called) |
4435 | self.assertFalse(self.ui.is_processing) |
4436 | |
4437 | @@ -506,10 +495,10 @@ |
4438 | self.ui.is_processing = False |
4439 | |
4440 | # the confirm dialog was not called so far |
4441 | - assert FakedConfirmDialog.args is None |
4442 | - assert FakedConfirmDialog.kwargs is None |
4443 | + assert FakedDialog.args is None |
4444 | + assert FakedDialog.kwargs is None |
4445 | |
4446 | yield self.ui.on_folders_itemChanged(self.item) |
4447 | |
4448 | - self.assertTrue(FakedConfirmDialog.args is None, 'dialog was not run') |
4449 | - self.assertTrue(FakedConfirmDialog.kwargs is None, 'dialog was hid') |
4450 | + self.assertTrue(FakedDialog.args is None, 'dialog was not run') |
4451 | + self.assertTrue(FakedDialog.kwargs is None, 'dialog was hid') |
4452 | |
4453 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_gotoweb.py' |
4454 | --- ubuntuone/controlpanel/gui/qt/tests/test_gotoweb.py 2011-07-22 21:26:48 +0000 |
4455 | +++ ubuntuone/controlpanel/gui/qt/tests/test_gotoweb.py 2011-09-26 18:38:27 +0000 |
4456 | @@ -20,7 +20,7 @@ |
4457 | |
4458 | from twisted.internet import defer |
4459 | |
4460 | -from ubuntuone.controlpanel.gui import qt |
4461 | +from ubuntuone.controlpanel.gui import qt, UBUNTUONE_LINK |
4462 | from ubuntuone.controlpanel.gui.qt import gotoweb as gui |
4463 | from ubuntuone.controlpanel.gui.qt.tests import ( |
4464 | BaseTestCase, |
4465 | @@ -35,7 +35,6 @@ |
4466 | @defer.inlineCallbacks |
4467 | def setUp(self): |
4468 | yield super(GoToWebButtonTestCase, self).setUp() |
4469 | - self.patch(qt, 'uri_hook', self._set_called) |
4470 | |
4471 | def test_uri_can_be_set(self): |
4472 | """The uri can be set.""" |
4473 | @@ -47,8 +46,14 @@ |
4474 | """The layout direction is RightToLeft.""" |
4475 | self.assertEqual(self.ui.layoutDirection(), gui.QtCore.Qt.RightToLeft) |
4476 | |
4477 | + def test_cursor_pointer(self): |
4478 | + """The cursor is PointingHandCursor.""" |
4479 | + self.assertEqual(self.ui.cursor().shape(), |
4480 | + gui.QtCore.Qt.PointingHandCursor) |
4481 | + |
4482 | def test_open_uri_when_clicked(self): |
4483 | """When clicking the button, the uri is opened.""" |
4484 | + self.patch(qt, 'uri_hook', self._set_called) |
4485 | self.ui.uri = 'yadda-yadda-yoo' |
4486 | self.ui.click() |
4487 | |
4488 | @@ -56,7 +61,54 @@ |
4489 | |
4490 | def test_do_nothing_on_clicked_if_uri_is_none(self): |
4491 | """When clicking the button, if the uri is None, do nothing.""" |
4492 | + self.patch(qt, 'uri_hook', self._set_called) |
4493 | self.ui.uri = None |
4494 | self.ui.click() |
4495 | |
4496 | self.assertEqual(self._called, False) |
4497 | + |
4498 | + |
4499 | +class SignUrlTestCase(GoToWebButtonTestCase): |
4500 | + """The test suite for the sign url management.""" |
4501 | + |
4502 | + @defer.inlineCallbacks |
4503 | + def setUp(self): |
4504 | + yield super(SignUrlTestCase, self).setUp() |
4505 | + self.patch(qt, 'uri_hook', lambda url: None) |
4506 | + self.patch(gui, 'sign_url', self._set_called) |
4507 | + self.creds = yield self.ui.backend.get_credentials() |
4508 | + assert len(self.creds) > 0 |
4509 | + |
4510 | + def test_without_ubuntuone_prefix(self): |
4511 | + """If given url is not an ubuntuone url, don't sign it.""" |
4512 | + self.ui.uri = 'bad_prefix' + UBUNTUONE_LINK |
4513 | + self.ui.click() |
4514 | + |
4515 | + self.assertFalse(self._called) |
4516 | + |
4517 | + def test_with_ubuntuone_prefix(self): |
4518 | + """If given url is an ubuntuone url, sign it.""" |
4519 | + self.ui.uri = UBUNTUONE_LINK + 'foo' |
4520 | + self.ui.click() |
4521 | + |
4522 | + self.assertEqual(self._called, ((self.ui.uri, self.creds,), {})) |
4523 | + |
4524 | + |
4525 | +class SignUrlNoCredsTestCase(SignUrlTestCase): |
4526 | + """The test suite for the sign url management when there are no creds.""" |
4527 | + |
4528 | + @defer.inlineCallbacks |
4529 | + def setUp(self): |
4530 | + yield super(SignUrlNoCredsTestCase, self).setUp() |
4531 | + self.patch(self.ui.backend, 'get_credentials', lambda: {}) |
4532 | + |
4533 | + def test_with_ubuntuone_prefix(self): |
4534 | + """If given url is an ubuntuone url, don't sign it. |
4535 | + |
4536 | + Since we have no credentials, the url should not be signed. |
4537 | + |
4538 | + """ |
4539 | + self.ui.uri = UBUNTUONE_LINK + 'foo' |
4540 | + self.ui.click() |
4541 | + |
4542 | + self.assertFalse(self._called) |
4543 | |
4544 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_gui.py' |
4545 | --- ubuntuone/controlpanel/gui/qt/tests/test_gui.py 2011-07-22 21:26:48 +0000 |
4546 | +++ ubuntuone/controlpanel/gui/qt/tests/test_gui.py 2011-09-26 18:38:27 +0000 |
4547 | @@ -41,3 +41,10 @@ |
4548 | self.ui.close_callback = None |
4549 | self.ui.closeEvent(event=gui.QtGui.QCloseEvent()) |
4550 | # world did not explode |
4551 | + |
4552 | + def test_on_signin_canceled(self): |
4553 | + """On SigninPanel's signinCanceled, close.""" |
4554 | + self.patch(self.ui, 'closeEvent', self._set_called) |
4555 | + self.ui.ui.control_panel.ui.signin.signinCanceled.emit() |
4556 | + self.assertEqual(len(self._called[0]), 1) |
4557 | + self.assertIsInstance(self._called[0][0], gui.QtGui.QCloseEvent) |
4558 | |
4559 | === added file 'ubuntuone/controlpanel/gui/qt/tests/test_signin.py' |
4560 | --- ubuntuone/controlpanel/gui/qt/tests/test_signin.py 1970-01-01 00:00:00 +0000 |
4561 | +++ ubuntuone/controlpanel/gui/qt/tests/test_signin.py 2011-09-26 18:38:27 +0000 |
4562 | @@ -0,0 +1,168 @@ |
4563 | +# -*- coding: utf-8 -*- |
4564 | + |
4565 | +# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
4566 | +# |
4567 | +# Copyright 2011 Canonical Ltd. |
4568 | +# |
4569 | +# This program is free software: you can redistribute it and/or modify it |
4570 | +# under the terms of the GNU General Public License version 3, as published |
4571 | +# by the Free Software Foundation. |
4572 | +# |
4573 | +# This program is distributed in the hope that it will be useful, but |
4574 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
4575 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
4576 | +# PURPOSE. See the GNU General Public License for more details. |
4577 | +# |
4578 | +# You should have received a copy of the GNU General Public License along |
4579 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
4580 | + |
4581 | +"""Tests for the Sign In Panel.""" |
4582 | + |
4583 | +from twisted.internet import defer |
4584 | + |
4585 | +from ubuntuone.controlpanel.gui import qt |
4586 | +from ubuntuone.controlpanel.gui.qt import signin as gui |
4587 | +from ubuntuone.controlpanel.gui.qt.tests import ( |
4588 | + CrashyBackend, |
4589 | + CrashyBackendException, |
4590 | +) |
4591 | +from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
4592 | + UbuntuOneBinTestCase, |
4593 | +) |
4594 | + |
4595 | +EMAIL = 'foo@bar.com' |
4596 | +PASSWORD = 'h3ll0World' |
4597 | +TOKEN = {'yadda': 'doo'} |
4598 | + |
4599 | +MSG = {u'errtype': u'AuthenticationError', |
4600 | + u'message': u'The authentication failed.'} |
4601 | + |
4602 | + |
4603 | +def fail(*a, **kw): |
4604 | + """Emit CredentialsError.""" |
4605 | + raise TypeError(MSG) |
4606 | + |
4607 | + |
4608 | +class BaseSignInPanelTestCase(UbuntuOneBinTestCase): |
4609 | + """Test the signin panel.""" |
4610 | + |
4611 | + innerclass_ui = gui.signin_ui |
4612 | + innerclass_name = "Ui_Form" |
4613 | + class_ui = gui.SignInPanel |
4614 | + logger = gui.logger |
4615 | + |
4616 | + @defer.inlineCallbacks |
4617 | + def setUp(self): |
4618 | + yield super(BaseSignInPanelTestCase, self).setUp() |
4619 | + self.ui.backend.next_result = TOKEN |
4620 | + |
4621 | + |
4622 | +class SignInPanelTestCase(BaseSignInPanelTestCase): |
4623 | + """Test the signin panel.""" |
4624 | + |
4625 | + innerclass_ui = gui.signin_ui |
4626 | + innerclass_name = "Ui_Form" |
4627 | + class_ui = gui.SignInPanel |
4628 | + |
4629 | + @defer.inlineCallbacks |
4630 | + def setUp(self): |
4631 | + yield super(SignInPanelTestCase, self).setUp() |
4632 | + self.ui.backend.next_result = TOKEN |
4633 | + self.ui.ui.email_entry.setText(gui.QtCore.QString('')) |
4634 | + self.ui.ui.password_entry.setText(gui.QtCore.QString('')) |
4635 | + |
4636 | + @defer.inlineCallbacks |
4637 | + def test_is_processing_while_asking_info(self): |
4638 | + """The ui is processing while the contents are loaded.""" |
4639 | + def check(email, password): |
4640 | + """The ui must be is_processing.""" |
4641 | + self.assertTrue(self.ui.is_processing, 'ui must be processing') |
4642 | + return TOKEN |
4643 | + |
4644 | + self.patch(self.ui.backend, 'login', check) |
4645 | + |
4646 | + self.assertFalse(self.ui.is_processing) |
4647 | + yield self.ui.ui.signin_button.click() |
4648 | + self.assertFalse(self.ui.is_processing) |
4649 | + |
4650 | + def test_signin_disabled_at_startup(self): |
4651 | + """The signin_button is disabled at startup.""" |
4652 | + self.assertFalse(self.ui.ui.signin_button.isEnabled()) |
4653 | + |
4654 | + def test_signin_disabled_if_no_email_but_password(self): |
4655 | + """Disable signin_button if no email.""" |
4656 | + self.ui.ui.password_entry.setText(gui.QtCore.QString('doo')) |
4657 | + self.assertFalse(self.ui.ui.signin_button.isEnabled()) |
4658 | + |
4659 | + def test_signin_disabled_if_no_password_but_email(self): |
4660 | + """Disable signin_button if no password.""" |
4661 | + self.ui.ui.email_entry.setText(gui.QtCore.QString('duh')) |
4662 | + self.assertFalse(self.ui.ui.signin_button.isEnabled()) |
4663 | + |
4664 | + def test_cancel_button(self): |
4665 | + """Send a signal when the cancel button is clicked.""" |
4666 | + self.ui.signinCanceled.connect(self._set_called) |
4667 | + self.ui.ui.cancel_button.click() |
4668 | + self.assertEqual(self._called, ((), {})) |
4669 | + |
4670 | + def test_forgot_password_button(self): |
4671 | + """When clicking the forgot passsword btn, the proper url is opened.""" |
4672 | + self.patch(qt, 'uri_hook', self._set_called) |
4673 | + self.ui.ui.forgot_password_button.click() |
4674 | + |
4675 | + self.assertEqual(self._called, ((gui.RESET_PASSWORD_LINK,), {})) |
4676 | + |
4677 | + |
4678 | +class SignInButtonPanelTestCase(BaseSignInPanelTestCase): |
4679 | + """Test the signin_button widget.""" |
4680 | + |
4681 | + @defer.inlineCallbacks |
4682 | + def setUp(self): |
4683 | + yield super(SignInButtonPanelTestCase, self).setUp() |
4684 | + self.ui.ui.email_entry.setText(gui.QtCore.QString(EMAIL)) |
4685 | + self.ui.ui.password_entry.setText(gui.QtCore.QString(PASSWORD)) |
4686 | + |
4687 | + @defer.inlineCallbacks |
4688 | + def test_signin_button(self): |
4689 | + """Call the backend when the signin button is clicked.""" |
4690 | + yield self.ui.ui.signin_button.click() |
4691 | + |
4692 | + self.assert_backend_called('login', email=EMAIL, password=PASSWORD) |
4693 | + # pylint: disable=W0212 |
4694 | + for arg in self.ui.backend._called['login'][1].itervalues(): |
4695 | + self.assertIsInstance(arg, unicode) # make sure not send QString |
4696 | + |
4697 | + @defer.inlineCallbacks |
4698 | + def test_signin_success(self): |
4699 | + """Emit credentialsFound on signin success.""" |
4700 | + self.ui.credentialsFound.connect(self._set_called) |
4701 | + yield self.ui.ui.signin_button.click() |
4702 | + |
4703 | + self.assertEqual(self._called, ((TOKEN,), {})) |
4704 | + self.assertFalse(self.ui.is_processing) |
4705 | + |
4706 | + def test_signin_enabled_if_email_and_password(self): |
4707 | + """Enable signin_button if email and password are non empty.""" |
4708 | + self.assertTrue(self.ui.ui.signin_button.isEnabled()) |
4709 | + |
4710 | + def test_return_pressed(self): |
4711 | + """On return pressed, click the signin_button.""" |
4712 | + self.patch(self.ui.ui.signin_button, 'click', self._set_called) |
4713 | + |
4714 | + for entry in (self.ui.ui.email_entry, self.ui.ui.password_entry): |
4715 | + entry.returnPressed.emit() |
4716 | + |
4717 | + # This is failing, so we need to settle with counting recievers |
4718 | + #self.assertEqual(self._called, ((), {})) |
4719 | + receivers = entry.receivers(gui.QtCore.SIGNAL('returnPressed()')) |
4720 | + self.assertEqual(1, receivers) |
4721 | + |
4722 | + self._called = False |
4723 | + |
4724 | + @defer.inlineCallbacks |
4725 | + def test_backend_error_is_handled(self): |
4726 | + """Any error from the backend is properly handled.""" |
4727 | + self.patch(self.ui, 'backend', CrashyBackend()) |
4728 | + yield self.ui.ui.signin_button.click() |
4729 | + |
4730 | + self.assertTrue(self.memento.check_exception(CrashyBackendException)) |
4731 | |
4732 | === added file 'ubuntuone/controlpanel/gui/qt/tests/test_start.py' |
4733 | --- ubuntuone/controlpanel/gui/qt/tests/test_start.py 1970-01-01 00:00:00 +0000 |
4734 | +++ ubuntuone/controlpanel/gui/qt/tests/test_start.py 2011-09-26 18:38:27 +0000 |
4735 | @@ -0,0 +1,91 @@ |
4736 | +# -*- coding: utf-8 -*- |
4737 | + |
4738 | +# Author: Roberto Alsina <roberto.alsina@canonical.com> |
4739 | +# |
4740 | +# Copyright 2011 Canonical Ltd. |
4741 | +# |
4742 | +# This program is free software: you can redistribute it and/or modify it |
4743 | +# under the terms of the GNU General Public License version 3, as published |
4744 | +# by the Free Software Foundation. |
4745 | +# |
4746 | +# This program is distributed in the hope that it will be useful, but |
4747 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
4748 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
4749 | +# PURPOSE. See the GNU General Public License for more details. |
4750 | +# |
4751 | +# You should have received a copy of the GNU General Public License along |
4752 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
4753 | + |
4754 | +"""Tests for the start function.""" |
4755 | + |
4756 | +from twisted.internet import defer |
4757 | + |
4758 | +from ubuntuone.controlpanel.gui.qt import gui |
4759 | +from ubuntuone.controlpanel.gui.qt.tests import NO_OP |
4760 | +from ubuntuone.controlpanel.tests import TestCase |
4761 | + |
4762 | + |
4763 | +class FakeThing(object): |
4764 | + |
4765 | + """A fake thing.""" |
4766 | + |
4767 | + def __init__(self): |
4768 | + self.args = [] |
4769 | + self.shown = False |
4770 | + |
4771 | + def __call__(self, *args, **kwargs): |
4772 | + self.args.append((args, kwargs)) |
4773 | + return self |
4774 | + |
4775 | + def show(self): |
4776 | + """Show.""" |
4777 | + self.shown = True |
4778 | + |
4779 | + |
4780 | +class FakeReactor(object): |
4781 | + """A fake reactor.""" |
4782 | + |
4783 | + def run(self): |
4784 | + """Start.""" |
4785 | + |
4786 | + def stop(self): |
4787 | + """Stop.""" |
4788 | + |
4789 | + |
4790 | +class StartTestCase(TestCase): |
4791 | + """Test the qt control panel.""" |
4792 | + |
4793 | + @defer.inlineCallbacks |
4794 | + def setUp(self): |
4795 | + yield super(StartTestCase, self).setUp() |
4796 | + self.main_window = FakeThing() |
4797 | + self.tray_icon = FakeThing() |
4798 | + self.patch(gui, "MainWindow", self.main_window) |
4799 | + self.patch(gui, "TrayIcon", self.tray_icon) |
4800 | + |
4801 | + def test_minimized(self): |
4802 | + """Test behaviour with minimized=True.""" |
4803 | + gui.start(NO_OP, minimized=True, with_icon=True) |
4804 | + self.assertEqual(self.tray_icon.args, [((), {'window': None})]) |
4805 | + self.assertEqual(self.main_window.args, []) |
4806 | + |
4807 | + def test_with_icon(self): |
4808 | + """Test behaviour with with_icon=True.""" |
4809 | + gui.start(NO_OP, with_icon=True, minimized=False) |
4810 | + self.assertEqual(self.main_window.args, [((), {})]) |
4811 | + self.assertEqual(self.tray_icon.args, [((), |
4812 | + {'window': self.main_window})]) |
4813 | + |
4814 | + def test_both_false(self): |
4815 | + """Test behaviour when with_icon and minimized are False.""" |
4816 | + gui.start(NO_OP, with_icon=False, minimized=False) |
4817 | + # Should be called |
4818 | + self.assertNotEqual(self.main_window.args, []) |
4819 | + # Should not be called |
4820 | + self.assertEqual(self.tray_icon.args, []) |
4821 | + |
4822 | + def test_both_true(self): |
4823 | + """Test behaviour when with_icon and minimized are True.""" |
4824 | + gui.start(NO_OP, with_icon=True, minimized=True) |
4825 | + self.assertEqual(self.tray_icon.args, [((), {'window': None})]) |
4826 | + self.assertEqual(self.main_window.args, []) |
4827 | |
4828 | === added file 'ubuntuone/controlpanel/gui/qt/tests/test_systray.py' |
4829 | --- ubuntuone/controlpanel/gui/qt/tests/test_systray.py 1970-01-01 00:00:00 +0000 |
4830 | +++ ubuntuone/controlpanel/gui/qt/tests/test_systray.py 2011-09-26 18:38:27 +0000 |
4831 | @@ -0,0 +1,103 @@ |
4832 | +# -*- coding: utf-8 -*- |
4833 | + |
4834 | +# Author: Roberto Alsina <roberto.alsina@canonical.com> |
4835 | +# |
4836 | +# Copyright 2011 Canonical Ltd. |
4837 | +# |
4838 | +# This program is free software: you can redistribute it and/or modify it |
4839 | +# under the terms of the GNU General Public License version 3, as published |
4840 | +# by the Free Software Foundation. |
4841 | +# |
4842 | +# This program is distributed in the hope that it will be useful, but |
4843 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
4844 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
4845 | +# PURPOSE. See the GNU General Public License for more details. |
4846 | +# |
4847 | +# You should have received a copy of the GNU General Public License along |
4848 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
4849 | + |
4850 | +"""Tests for the notification area icon.""" |
4851 | + |
4852 | +from PyQt4 import QtGui |
4853 | + |
4854 | +from ubuntuone.controlpanel.gui.qt.systray import TrayIcon |
4855 | +from ubuntuone.controlpanel.tests import TestCase |
4856 | +import ubuntuone.controlpanel.gui.qt.gui |
4857 | + |
4858 | + |
4859 | +class FakeMainWindow(QtGui.QWidget): |
4860 | + |
4861 | + """Fake Main Window.""" |
4862 | + |
4863 | + def __init__(self, *args, **kwargs): |
4864 | + self.args = (args, kwargs) |
4865 | + super(FakeMainWindow, self).__init__() |
4866 | + |
4867 | + |
4868 | +class SystrayTestCase(TestCase): |
4869 | + |
4870 | + """Test the notification area icon.""" |
4871 | + |
4872 | + def test_quit(self): |
4873 | + """Test the quit option in the menu.""" |
4874 | + # Not done on setup, because if I patch stop |
4875 | + # after instantiation, it doesn't get called. |
4876 | + self.patch(TrayIcon, "stop", self._set_called) |
4877 | + tray = TrayIcon() |
4878 | + tray.quit.trigger() |
4879 | + self.assertEqual(self._called, ((False,), {})) |
4880 | + |
4881 | + def test_restore_no_window(self): |
4882 | + """Test the restore window option in the menu, with no window.""" |
4883 | + self.patch(ubuntuone.controlpanel.gui.qt.gui, |
4884 | + "MainWindow", FakeMainWindow) |
4885 | + tray = TrayIcon() |
4886 | + self.assertEqual(tray.window, None) |
4887 | + tray.restore.trigger() |
4888 | + self.assertIsInstance(tray.window, FakeMainWindow) |
4889 | + self.assertTrue(tray.window.isVisible()) |
4890 | + self.assertEqual(tray.window.args, ((), |
4891 | + {'close_callback': tray.delete_window})) |
4892 | + |
4893 | + def test_activate(self): |
4894 | + """Test the icon activation.""" |
4895 | + tray = TrayIcon() |
4896 | + window = FakeMainWindow() |
4897 | + tray.window = window |
4898 | + self.assertFalse(tray.window.isVisible()) |
4899 | + tray.activated.emit(tray.Trigger) |
4900 | + self.assertEqual(tray.window, window) |
4901 | + self.assertTrue(tray.window.isVisible()) |
4902 | + |
4903 | + def test_restore_window(self): |
4904 | + """Test the restore window option in the menu, with a window.""" |
4905 | + tray = TrayIcon() |
4906 | + window = FakeMainWindow() |
4907 | + tray.window = window |
4908 | + self.assertFalse(tray.window.isVisible()) |
4909 | + tray.restore.trigger() |
4910 | + self.assertEqual(tray.window, window) |
4911 | + self.assertTrue(tray.window.isVisible()) |
4912 | + |
4913 | + def test_delete_window(self): |
4914 | + """Test deleting an existing window.""" |
4915 | + tray = TrayIcon() |
4916 | + window = FakeMainWindow() |
4917 | + tray.window = window |
4918 | + tray.delete_window() |
4919 | + self.assertEqual(tray.window, None) |
4920 | + self.assertFalse(window.isVisible()) |
4921 | + |
4922 | + def test_delete_no_window(self): |
4923 | + """Test deleting without an existing window.""" |
4924 | + tray = TrayIcon() |
4925 | + tray.delete_window() |
4926 | + self.assertEqual(tray.window, None) |
4927 | + |
4928 | + def test_initialization(self): |
4929 | + """Test that everything initializes correctly.""" |
4930 | + tray = TrayIcon() |
4931 | + self.assertTrue(tray.isVisible()) |
4932 | + self.assertEqual(tray.window, None) |
4933 | + self.assertIsInstance(tray.context_menu, QtGui.QMenu) |
4934 | + self.assertFalse(tray.icon() == None) |
4935 | |
4936 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py' |
4937 | --- ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py 2011-07-22 21:26:48 +0000 |
4938 | +++ ubuntuone/controlpanel/gui/qt/tests/test_ubuntuonebin.py 2011-09-26 18:38:27 +0000 |
4939 | @@ -18,25 +18,24 @@ |
4940 | |
4941 | """Tests for the Ubuntu One Bin.""" |
4942 | |
4943 | -from ubuntuone.devtools.testcase import skipIfOS |
4944 | +from twisted.internet import defer |
4945 | |
4946 | from ubuntuone.controlpanel.gui.qt import ubuntuonebin as gui |
4947 | -from ubuntuone.controlpanel.gui.qt.tests import BaseTestCase |
4948 | +from ubuntuone.controlpanel.gui.qt.tests import ( |
4949 | + BaseTestCase, |
4950 | + CrashyBackend, |
4951 | + CrashyBackendException, |
4952 | +) |
4953 | |
4954 | # Attribute 'yyy' defined outside __init__, access to a protected member |
4955 | # pylint: disable=W0201, W0212 |
4956 | |
4957 | |
4958 | class UbuntuOneBinTestCase(BaseTestCase): |
4959 | - """Test the qt cloud folders tab.""" |
4960 | + """Test the Ubuntu One base widget.""" |
4961 | |
4962 | class_ui = gui.UbuntuOneBin |
4963 | |
4964 | - def test_backend(self): |
4965 | - """Backend is created.""" |
4966 | - self.assertIsInstance(self.ui.backend, |
4967 | - gui.backend.ControlBackend) |
4968 | - |
4969 | def test_is_not_processing_after_creation(self): |
4970 | """After creation, is not processing.""" |
4971 | self.assertFalse(self.ui.is_processing) |
4972 | @@ -46,22 +45,33 @@ |
4973 | """The animation is active.""" |
4974 | self.assertFalse(self.ui.overlay.isVisible()) |
4975 | |
4976 | - @skipIfOS('win32', 'crashes under windows, see LP: #806154') |
4977 | def test_is_enabled_if_not_processing(self): |
4978 | """If not processing, the UI is enabled.""" |
4979 | self.ui.show() # need to show to test widgets visibility |
4980 | + self.addCleanup(self.ui.hide) |
4981 | |
4982 | self.ui.is_processing = False |
4983 | |
4984 | self.assertTrue(self.ui.isEnabled()) |
4985 | self.assertFalse(self.ui.overlay.isVisible()) |
4986 | |
4987 | - @skipIfOS('win32', 'crashes under windows, see LP: #806154') |
4988 | def test_is_not_enabled_if_processing(self): |
4989 | """If processing, the UI is disabled.""" |
4990 | self.ui.show() # need to show to test widgets visibility |
4991 | + self.addCleanup(self.ui.hide) |
4992 | |
4993 | self.ui.is_processing = True |
4994 | |
4995 | self.assertFalse(self.ui.isEnabled()) |
4996 | self.assertTrue(self.ui.overlay.isVisible()) |
4997 | + |
4998 | + @defer.inlineCallbacks |
4999 | + def test_backend_error_is_handled(self): |
5000 | + """Any error from the backend is properly handled.""" |
Thank you for your work