Merge lp:~nataliabidart/ubuntuone-control-panel/focus into lp:ubuntuone-control-panel
- focus
- Merge into trunk
Proposed by
Natalia Bidart
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Natalia Bidart | ||||||||
Approved revision: | 285 | ||||||||
Merged at revision: | 279 | ||||||||
Proposed branch: | lp:~nataliabidart/ubuntuone-control-panel/focus | ||||||||
Merge into: | lp:ubuntuone-control-panel | ||||||||
Diff against target: |
1035 lines (+291/-254) 15 files modified
data/qt/controlpanel.ui (+4/-4) data/qt/device.ui (+5/-2) data/qt/device_remote.ui (+0/-50) data/qt/devices.ui (+9/-3) data/qt/preferences.ui (+40/-27) data/qt/ubuntuone.qss (+88/-41) ubuntuone/controlpanel/gui/qt/device.py (+30/-30) ubuntuone/controlpanel/gui/qt/devices.py (+6/-21) ubuntuone/controlpanel/gui/qt/folders.py (+17/-14) ubuntuone/controlpanel/gui/qt/loadingoverlay.py (+1/-5) ubuntuone/controlpanel/gui/qt/tests/__init__.py (+1/-0) ubuntuone/controlpanel/gui/qt/tests/test_device.py (+35/-18) ubuntuone/controlpanel/gui/qt/tests/test_devices.py (+15/-35) ubuntuone/controlpanel/gui/qt/tests/test_folders.py (+22/-4) ubuntuone/controlpanel/gui/tests/__init__.py (+18/-0) |
||||||||
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-control-panel/focus | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Roberto Alsina (community) | Approve | ||
Diego Sarmentero (community) | Approve | ||
Review via email: mp+96654@code.launchpad.net |
Description of the change
To post a comment you must log in.
- 283. By Natalia Bidart
-
Less changes against trunk.
- 284. By Natalia Bidart
-
Restoring hack for tabs.
- 285. By Natalia Bidart
-
No need for controlpanel help buttons to be enabled/disabled for the style.
Revision history for this message
Roberto Alsina (ralsina) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'data/qt/controlpanel.ui' |
2 | --- data/qt/controlpanel.ui 2012-03-02 13:53:24 +0000 |
3 | +++ data/qt/controlpanel.ui 2012-03-08 21:13:18 +0000 |
4 | @@ -329,8 +329,8 @@ |
5 | </property> |
6 | <property name="maximumSize"> |
7 | <size> |
8 | - <width>16</width> |
9 | - <height>16</height> |
10 | + <width>20</width> |
11 | + <height>20</height> |
12 | </size> |
13 | </property> |
14 | <property name="cursor"> |
15 | @@ -352,8 +352,8 @@ |
16 | </property> |
17 | <property name="maximumSize"> |
18 | <size> |
19 | - <width>16</width> |
20 | - <height>16</height> |
21 | + <width>20</width> |
22 | + <height>20</height> |
23 | </size> |
24 | </property> |
25 | <property name="cursor"> |
26 | |
27 | === modified file 'data/qt/device.ui' |
28 | --- data/qt/device.ui 2012-02-22 15:35:13 +0000 |
29 | +++ data/qt/device.ui 2012-03-08 21:13:18 +0000 |
30 | @@ -6,14 +6,17 @@ |
31 | <rect> |
32 | <x>0</x> |
33 | <y>0</y> |
34 | - <width>233</width> |
35 | - <height>36</height> |
36 | + <width>430</width> |
37 | + <height>27</height> |
38 | </rect> |
39 | </property> |
40 | <property name="windowTitle"> |
41 | <string notr="true">Form</string> |
42 | </property> |
43 | <layout class="QHBoxLayout" name="horizontalLayout"> |
44 | + <property name="margin"> |
45 | + <number>0</number> |
46 | + </property> |
47 | <item> |
48 | <widget class="QLabel" name="device_icon_label"> |
49 | <property name="pixmap"> |
50 | |
51 | === removed file 'data/qt/device_remote.ui' |
52 | --- data/qt/device_remote.ui 2012-02-22 14:58:25 +0000 |
53 | +++ data/qt/device_remote.ui 1970-01-01 00:00:00 +0000 |
54 | @@ -1,50 +0,0 @@ |
55 | -<?xml version="1.0" encoding="UTF-8"?> |
56 | -<ui version="4.0"> |
57 | - <class>Form</class> |
58 | - <widget class="QWidget" name="Form"> |
59 | - <property name="geometry"> |
60 | - <rect> |
61 | - <x>0</x> |
62 | - <y>0</y> |
63 | - <width>264</width> |
64 | - <height>45</height> |
65 | - </rect> |
66 | - </property> |
67 | - <property name="windowTitle"> |
68 | - <string notr="true">Form</string> |
69 | - </property> |
70 | - <layout class="QHBoxLayout" name="horizontalLayout"> |
71 | - <item> |
72 | - <widget class="QLabel" name="device_icon_label"> |
73 | - <property name="pixmap"> |
74 | - <pixmap resource="images.qrc">:/computer.png</pixmap> |
75 | - </property> |
76 | - </widget> |
77 | - </item> |
78 | - <item> |
79 | - <widget class="QLabel" name="device_name_label"> |
80 | - <property name="text"> |
81 | - <string notr="true">Non local device</string> |
82 | - </property> |
83 | - </widget> |
84 | - </item> |
85 | - <item> |
86 | - <spacer name="horizontalSpacer"> |
87 | - <property name="orientation"> |
88 | - <enum>Qt::Horizontal</enum> |
89 | - </property> |
90 | - <property name="sizeHint" stdset="0"> |
91 | - <size> |
92 | - <width>217</width> |
93 | - <height>20</height> |
94 | - </size> |
95 | - </property> |
96 | - </spacer> |
97 | - </item> |
98 | - </layout> |
99 | - </widget> |
100 | - <resources> |
101 | - <include location="images.qrc"/> |
102 | - </resources> |
103 | - <connections/> |
104 | -</ui> |
105 | |
106 | === modified file 'data/qt/devices.ui' |
107 | --- data/qt/devices.ui 2012-03-02 13:53:24 +0000 |
108 | +++ data/qt/devices.ui 2012-03-08 21:13:18 +0000 |
109 | @@ -21,16 +21,16 @@ |
110 | <number>0</number> |
111 | </property> |
112 | <item> |
113 | - <widget class="QGroupBox" name="local_device"> |
114 | + <widget class="QGroupBox" name="local_device_box"> |
115 | <property name="title"> |
116 | <string notr="true">This device</string> |
117 | </property> |
118 | - <layout class="QVBoxLayout" name="verticalLayout"> |
119 | + <layout class="QVBoxLayout" name="local_device_layout"> |
120 | <property name="margin"> |
121 | <number>0</number> |
122 | </property> |
123 | <item> |
124 | - <layout class="QVBoxLayout" name="local_device_box"/> |
125 | + <widget class="DeviceWidget" name="local_device" native="true"/> |
126 | </item> |
127 | </layout> |
128 | </widget> |
129 | @@ -120,6 +120,12 @@ |
130 | <extends>QPushButton</extends> |
131 | <header>ubuntuone.controlpanel.gui.qt.gotoweb</header> |
132 | </customwidget> |
133 | + <customwidget> |
134 | + <class>DeviceWidget</class> |
135 | + <extends>QWidget</extends> |
136 | + <header>ubuntuone.controlpanel.gui.qt.device</header> |
137 | + <container>1</container> |
138 | + </customwidget> |
139 | </customwidgets> |
140 | <resources> |
141 | <include location="images.qrc"/> |
142 | |
143 | === modified file 'data/qt/preferences.ui' |
144 | --- data/qt/preferences.ui 2012-03-02 19:42:17 +0000 |
145 | +++ data/qt/preferences.ui 2012-03-08 21:13:18 +0000 |
146 | @@ -6,8 +6,8 @@ |
147 | <rect> |
148 | <x>0</x> |
149 | <y>0</y> |
150 | - <width>512</width> |
151 | - <height>328</height> |
152 | + <width>520</width> |
153 | + <height>342</height> |
154 | </rect> |
155 | </property> |
156 | <property name="windowTitle"> |
157 | @@ -53,14 +53,27 @@ |
158 | </property> |
159 | </widget> |
160 | </item> |
161 | - <item row="2" column="0"> |
162 | + <item row="0" column="3"> |
163 | + <spacer name="horizontalSpacer_2"> |
164 | + <property name="orientation"> |
165 | + <enum>Qt::Horizontal</enum> |
166 | + </property> |
167 | + <property name="sizeHint" stdset="0"> |
168 | + <size> |
169 | + <width>40</width> |
170 | + <height>20</height> |
171 | + </size> |
172 | + </property> |
173 | + </spacer> |
174 | + </item> |
175 | + <item row="1" column="0"> |
176 | <widget class="QCheckBox" name="limit_downloads_checkbox"> |
177 | <property name="text"> |
178 | <string notr="true">Limit download speed to</string> |
179 | </property> |
180 | </widget> |
181 | </item> |
182 | - <item row="2" column="1"> |
183 | + <item row="1" column="1"> |
184 | <widget class="QSpinBox" name="download_speed_spinbox"> |
185 | <property name="minimum"> |
186 | <number>-1</number> |
187 | @@ -70,17 +83,17 @@ |
188 | </property> |
189 | </widget> |
190 | </item> |
191 | - <item row="2" column="2"> |
192 | + <item row="1" column="2"> |
193 | <widget class="QLabel" name="kbps_label_2"> |
194 | <property name="text"> |
195 | <string notr="true">Kilobits per second</string> |
196 | </property> |
197 | </widget> |
198 | </item> |
199 | - <item row="0" column="3"> |
200 | - <spacer name="horizontalSpacer_2"> |
201 | + <item row="2" column="0"> |
202 | + <spacer name="verticalSpacer_2"> |
203 | <property name="orientation"> |
204 | - <enum>Qt::Horizontal</enum> |
205 | + <enum>Qt::Vertical</enum> |
206 | </property> |
207 | <property name="sizeHint" stdset="0"> |
208 | <size> |
209 | @@ -90,7 +103,7 @@ |
210 | </property> |
211 | </spacer> |
212 | </item> |
213 | - <item row="4" column="0" colspan="3"> |
214 | + <item row="3" column="0" colspan="3"> |
215 | <widget class="QLabel" name="label_2"> |
216 | <property name="text"> |
217 | <string notr="true">Please note that your files will not sync if you set bandwidth to 0</string> |
218 | @@ -103,19 +116,6 @@ |
219 | </property> |
220 | </widget> |
221 | </item> |
222 | - <item row="3" column="0"> |
223 | - <spacer name="verticalSpacer_2"> |
224 | - <property name="orientation"> |
225 | - <enum>Qt::Vertical</enum> |
226 | - </property> |
227 | - <property name="sizeHint" stdset="0"> |
228 | - <size> |
229 | - <width>40</width> |
230 | - <height>20</height> |
231 | - </size> |
232 | - </property> |
233 | - </spacer> |
234 | - </item> |
235 | </layout> |
236 | </widget> |
237 | </item> |
238 | @@ -124,32 +124,45 @@ |
239 | <property name="title"> |
240 | <string notr="true">File Sync Settings</string> |
241 | </property> |
242 | - <layout class="QVBoxLayout" name="verticalLayout_1"> |
243 | + <layout class="QGridLayout" name="gridLayout_2"> |
244 | <property name="margin"> |
245 | <number>0</number> |
246 | </property> |
247 | - <item> |
248 | + <item row="0" column="0"> |
249 | <widget class="QCheckBox" name="autoconnect_checkbox"> |
250 | <property name="text"> |
251 | <string notr="true">Connect automatically when computer starts</string> |
252 | </property> |
253 | </widget> |
254 | </item> |
255 | - <item> |
256 | + <item row="0" column="1"> |
257 | + <spacer name="horizontalSpacer_3"> |
258 | + <property name="orientation"> |
259 | + <enum>Qt::Horizontal</enum> |
260 | + </property> |
261 | + <property name="sizeHint" stdset="0"> |
262 | + <size> |
263 | + <width>40</width> |
264 | + <height>20</height> |
265 | + </size> |
266 | + </property> |
267 | + </spacer> |
268 | + </item> |
269 | + <item row="1" column="0"> |
270 | <widget class="QCheckBox" name="udf_autosubscribe_checkbox"> |
271 | <property name="text"> |
272 | <string notr="true">Automatically sync all new cloud folders to this computer</string> |
273 | </property> |
274 | </widget> |
275 | </item> |
276 | - <item> |
277 | + <item row="2" column="0"> |
278 | <widget class="QCheckBox" name="share_autosubscribe_checkbox"> |
279 | <property name="text"> |
280 | <string notr="true">Automatically sync all folders shared with me to this computer</string> |
281 | </property> |
282 | </widget> |
283 | </item> |
284 | - <item> |
285 | + <item row="3" column="0"> |
286 | <widget class="QCheckBox" name="show_all_notifications_checkbox"> |
287 | <property name="text"> |
288 | <string notr="true">Allow all notifications to this device</string> |
289 | |
290 | === modified file 'data/qt/ubuntuone.qss' |
291 | --- data/qt/ubuntuone.qss 2012-03-02 17:33:38 +0000 |
292 | +++ data/qt/ubuntuone.qss 2012-03-08 21:13:18 +0000 |
293 | @@ -1,3 +1,11 @@ |
294 | +/* Common colours: |
295 | + |
296 | +orange: #dd4814 |
297 | +dark grey: #333333 |
298 | +light grey: #aea79f |
299 | + |
300 | +*/ |
301 | + |
302 | QMainWindow { |
303 | background-color: #aea79f; |
304 | } |
305 | @@ -77,6 +85,18 @@ |
306 | border-width: 1px; |
307 | } |
308 | |
309 | +QPushButton:focus { |
310 | + border-width: 2px; |
311 | + /* reduce the padding since we have a 2px border now */ |
312 | + padding: 5px; |
313 | + padding-left: 19px; |
314 | + padding-right: 19px; |
315 | + /* hack to make the mild-orange focused box dissapear */ |
316 | + padding-top: 20px; |
317 | + padding-bottom: 20px; |
318 | + /* end of hack */ |
319 | +} |
320 | + |
321 | QPushButton:disabled { |
322 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
323 | stop: 0 #eaeaea, stop: 1.0 #cacaca); |
324 | @@ -91,19 +111,18 @@ |
325 | border-color: #999999; |
326 | } |
327 | |
328 | -QPushButton:enabled:focus, |
329 | +QPushButton:enabled:focus { |
330 | + border-color: #dd4814; |
331 | +} |
332 | + |
333 | QPushButton:enabled:hover { |
334 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
335 | stop: 0 #ffffff,stop: 1.0 #ededed); |
336 | - color: #333333; |
337 | - border-color: #999999; |
338 | } |
339 | |
340 | QPushButton:enabled:pressed { |
341 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
342 | stop: 0 #d9d9d9,stop: 1.0 #fefefe); |
343 | - color: #333333; |
344 | - border-color: #999999; |
345 | } |
346 | |
347 | QPushButton:default:enabled { |
348 | @@ -113,55 +132,69 @@ |
349 | border-color: #999999; |
350 | } |
351 | |
352 | -QPushButton:default:enabled:focus, |
353 | +QPushButton:default:enabled:focus { |
354 | + border-color: #333333; |
355 | +} |
356 | + |
357 | QPushButton:default:enabled:hover { |
358 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
359 | stop: 0 #ffb19c,stop: 1.0 #dd4814); |
360 | - color: white; |
361 | - border-color: #999999; |
362 | } |
363 | |
364 | QPushButton:default:enabled:pressed { |
365 | background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
366 | stop: 0 #b93f14,stop: 1.0 #dd4814); |
367 | - color: white; |
368 | - border-color: #999999; |
369 | -} |
370 | - |
371 | -QPushButton#help_button { |
372 | - background: transparent; |
373 | - border: none; |
374 | - color: white; |
375 | - text-decoration: underline; |
376 | - padding: 0px; |
377 | -} |
378 | - |
379 | -QPushButton#explore_folder_button { |
380 | - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
381 | - stop: 0 #fbfbfb, stop: 1.0 #e6e6e6); |
382 | - height: 15px; |
383 | - border-radius: 7px; |
384 | - border-color: #908e8d; |
385 | - color: #595959; |
386 | - padding-left: 10px; |
387 | - padding-right: 10px; |
388 | +} |
389 | + |
390 | +ExploreFolderButton { |
391 | margin-top: 5px; |
392 | margin-bottom: 5px; |
393 | margin-right: 20px; |
394 | margin-left: 20px; |
395 | } |
396 | |
397 | +ExploreFolderButton:enabled { |
398 | + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, |
399 | + stop: 0 #fbfbfb, stop: 1.0 #e6e6e6); |
400 | + border-color: #908e8d; |
401 | + color: #595959; |
402 | +} |
403 | + |
404 | QPushButton#twitter_button, |
405 | QPushButton#facebook_button { |
406 | + background: transparent; |
407 | +} |
408 | + |
409 | +QPushButton#twitter_button:focus, |
410 | +QPushButton#facebook_button:focus { |
411 | + border: 2px solid #dd4814; |
412 | +} |
413 | + |
414 | +GoToWebButton#help_button { |
415 | + padding: 2px; |
416 | +} |
417 | + |
418 | +GoToWebButton#share_publish_button, |
419 | +GoToWebButton#help_button { |
420 | + background: transparent; |
421 | border: none; |
422 | + text-decoration: underline; |
423 | } |
424 | |
425 | -GoToWebButton#forgot_password_button, |
426 | GoToWebButton#share_publish_button { |
427 | - background: transparent; |
428 | - border: none; |
429 | color: #dd4814; |
430 | - text-decoration: underline; |
431 | +} |
432 | + |
433 | +GoToWebButton#help_button { |
434 | + color: white; |
435 | +} |
436 | + |
437 | +GoToWebButton#share_publish_button:focus { |
438 | + border: 2px solid #aea79f; |
439 | +} |
440 | + |
441 | +GoToWebButton#help_button:focus { |
442 | + border: 2px solid #dd4814; |
443 | } |
444 | |
445 | QTabBar::tab { |
446 | @@ -192,12 +225,7 @@ |
447 | border-width: 1px; |
448 | } |
449 | |
450 | -QTabBar::tab:first:!selected { |
451 | - border-left-color: #939389; |
452 | - border-left-color: #939389; |
453 | -} |
454 | - |
455 | -QTabBar::tab:first:selected { |
456 | +QTabBar::tab:first { |
457 | border-left-color: #939389; |
458 | } |
459 | |
460 | @@ -205,13 +233,21 @@ |
461 | border-left-color: #e4e0dd; |
462 | } |
463 | |
464 | +QTabBar::tab:last:!selected { |
465 | + border-left-color: #e4e0dd; |
466 | +} |
467 | + |
468 | QTabBar::tab:hover { |
469 | background: #f6f6f6; |
470 | text-decoration: underline; |
471 | } |
472 | |
473 | -QTabBar::tab:last:!selected { |
474 | - border-left-color: #e4e0dd; |
475 | +QTabBar::tab:focus { |
476 | + text-decoration: underline; |
477 | + /* hack to make the mild-orange focused box dissapear */ |
478 | + padding-left: 1000px; |
479 | + padding-right: 1000px; |
480 | + /* end of hack */ |
481 | } |
482 | |
483 | QTabWidget { |
484 | @@ -259,6 +295,12 @@ |
485 | min-height: 48px; |
486 | } |
487 | |
488 | +QGroupBox#local_device_box, |
489 | +QListWidget#list_devices::item { |
490 | + padding-left: 9px; |
491 | + padding-right: 9px; |
492 | +} |
493 | + |
494 | QLabel[OverQuota="false"] { |
495 | color: #333333; |
496 | } |
497 | @@ -301,3 +343,8 @@ |
498 | alternate-background-color: #f7f6f5; |
499 | background: #efedec; |
500 | } |
501 | + |
502 | +QCheckBox:focus { |
503 | + border-radius: 5px; |
504 | + border: 2px solid #dd4814; |
505 | +} |
506 | |
507 | === modified file 'ubuntuone/controlpanel/gui/qt/device.py' |
508 | --- ubuntuone/controlpanel/gui/qt/device.py 2012-02-22 17:04:28 +0000 |
509 | +++ ubuntuone/controlpanel/gui/qt/device.py 2012-03-08 21:13:18 +0000 |
510 | @@ -34,7 +34,7 @@ |
511 | handle_errors, |
512 | pixmap_from_name, |
513 | ) |
514 | -from ubuntuone.controlpanel.gui.qt.ui import device_ui, device_remote_ui |
515 | +from ubuntuone.controlpanel.gui.qt.ui import device_ui |
516 | from ubuntuone.controlpanel.logger import setup_logging |
517 | |
518 | COMPUTER_ICON = "computer" |
519 | @@ -61,27 +61,35 @@ |
520 | |
521 | |
522 | class DeviceWidget(cache.Cache, QtGui.QWidget): |
523 | - """The widget for each device in the control panel.""" |
524 | + """The widget for a local device in the control panel.""" |
525 | |
526 | removed = QtCore.pyqtSignal() |
527 | removeCanceled = QtCore.pyqtSignal() |
528 | |
529 | - def __init__(self, device_id, *args, **kwargs): |
530 | + def __init__(self, device_id=None, *args, **kwargs): |
531 | """Initialize the UI of the widget.""" |
532 | super(DeviceWidget, self).__init__(*args, **kwargs) |
533 | self.ui = device_ui.Ui_Form() |
534 | self.ui.setupUi(self) |
535 | |
536 | - # The following is a hack to avoid having the faked self.ui failing |
537 | - # with AttributeError in the tests. We need to improve the fake so we |
538 | - # don't leak this to the production code. |
539 | - if getattr(self.ui, 'remove_device_button', None) is not None: |
540 | - self.ui.remove_device_button.setText(REMOVE_BUTTON) |
541 | - |
542 | + self.ui.remove_device_button.setText(REMOVE_BUTTON) |
543 | + self._id = None |
544 | self.id = device_id |
545 | |
546 | + def _get_id(self): |
547 | + """Return this device's id.""" |
548 | + return self._id |
549 | + |
550 | + def _set_id(self, new_id): |
551 | + """Set this device's id.""" |
552 | + self._id = new_id |
553 | + self.ui.remove_device_button.setEnabled(self._id is not None) |
554 | + |
555 | + id = property(fget=_get_id, fset=_set_id) |
556 | + |
557 | def update_device_info(self, device_info): |
558 | """Update the device info.""" |
559 | + self.id = device_info["device_id"] |
560 | self.ui.device_name_label.setText(device_info["name"]) |
561 | icon_name = icon_name_from_type(device_info["type"]) |
562 | pixmap = pixmap_from_name(icon_name) |
563 | @@ -102,28 +110,20 @@ |
564 | else: |
565 | self.removeCanceled.emit() |
566 | |
567 | - |
568 | -class DeviceRemoteWidget(QtGui.QWidget): |
569 | - |
570 | - """Remote Device widget for Devices List.""" |
571 | - |
572 | - def __init__(self, device_info): |
573 | - super(DeviceRemoteWidget, self).__init__() |
574 | - self.ui = device_remote_ui.Ui_Form() |
575 | - self.ui.setupUi(self) |
576 | - |
577 | - text = device_info["name"] |
578 | - icon_name = icon_name_from_type(device_info["type"]) |
579 | - pixmap = pixmap_from_name(icon_name) |
580 | - self.ui.device_icon_label.setPixmap(pixmap) |
581 | - self.ui.device_name_label.setText(text) |
582 | - |
583 | def text(self): |
584 | """Return the text displayed in the Widget.""" |
585 | return self.ui.device_name_label.text() |
586 | |
587 | - |
588 | -def get_device_for_list_widget(device_info): |
589 | - """Return a DeviceRemoteWidget with device proper info.""" |
590 | - item = DeviceRemoteWidget(device_info) |
591 | - return item |
592 | + def clear(self): |
593 | + """Clear this widget's info.""" |
594 | + self.id = None |
595 | + self.ui.device_name_label.setText('') |
596 | + |
597 | + |
598 | +class RemoteDeviceWidget(DeviceWidget): |
599 | + |
600 | + """Remote device widget.""" |
601 | + |
602 | + def __init__(self, *args, **kwargs): |
603 | + super(RemoteDeviceWidget, self).__init__(*args, **kwargs) |
604 | + self.ui.remove_device_button.hide() |
605 | |
606 | === modified file 'ubuntuone/controlpanel/gui/qt/devices.py' |
607 | --- ubuntuone/controlpanel/gui/qt/devices.py 2012-02-22 15:35:13 +0000 |
608 | +++ ubuntuone/controlpanel/gui/qt/devices.py 2012-03-08 21:13:18 +0000 |
609 | @@ -50,7 +50,7 @@ |
610 | def _setup(self): |
611 | """Do some extra setupping for the UI.""" |
612 | super(DevicesPanel, self)._setup() |
613 | - self.ui.local_device.setTitle(DEVICES_LOCAL_LABEL) |
614 | + self.ui.local_device_box.setTitle(DEVICES_LOCAL_LABEL) |
615 | self.ui.other_devices.setTitle(DEVICES_REMOTE_LABEL) |
616 | self.ui.manage_devices_button.setText(DEVICES_MANAGE_LABEL) |
617 | self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK |
618 | @@ -66,7 +66,6 @@ |
619 | @log_call(logger.debug) |
620 | def process_info(self, info): |
621 | """Process and display the devices info.""" |
622 | - self.clear_device_info(self.ui.local_device_box) |
623 | self.ui.list_devices.clear() |
624 | |
625 | for device_info in info: |
626 | @@ -76,21 +75,9 @@ |
627 | |
628 | def on_local_device_removed(self): |
629 | """When the local device is removed, clear the box and emit signal.""" |
630 | - self.clear_device_info(self.ui.local_device_box) |
631 | + self.ui.local_device.clear() |
632 | self.localDeviceRemoved.emit() |
633 | |
634 | - def clear_device_info(self, box): |
635 | - """Clear all the device info.""" |
636 | - children = box.count() |
637 | - # we need to reverse the index list to remove children because: |
638 | - # "Items are numbered consecutively from 0. If an item is deleted, |
639 | - # other items will be renumbered." |
640 | - # http://doc.qt.nokia.com/latest/qlayout.html#itemAt |
641 | - for i in reversed(range(children)): |
642 | - widget = box.itemAt(i).widget() |
643 | - box.removeWidget(widget) |
644 | - widget.deleteLater() |
645 | - |
646 | def update_device_info(self, device_info): |
647 | """Update one device.""" |
648 | if device_info["is_local"]: |
649 | @@ -100,15 +87,13 @@ |
650 | |
651 | def update_local_device(self, device_info): |
652 | """Update the info for the local device.""" |
653 | - device_widget = device.DeviceWidget(device_id=device_info['device_id']) |
654 | - device_widget.update_device_info(device_info) |
655 | - device_widget.removed.connect(self.on_local_device_removed) |
656 | - |
657 | - self.ui.local_device_box.addWidget(device_widget) |
658 | + self.ui.local_device.update_device_info(device_info) |
659 | + self.ui.local_device.removed.connect(self.on_local_device_removed) |
660 | |
661 | def create_remote_device(self, device_info): |
662 | """Add a remote device to the list.""" |
663 | - widget = device.get_device_for_list_widget(device_info) |
664 | + widget = device.RemoteDeviceWidget() |
665 | + widget.update_device_info(device_info) |
666 | item = QtGui.QListWidgetItem() |
667 | |
668 | self.ui.list_devices.addItem(item) |
669 | |
670 | === modified file 'ubuntuone/controlpanel/gui/qt/folders.py' |
671 | --- ubuntuone/controlpanel/gui/qt/folders.py 2012-02-28 17:48:23 +0000 |
672 | +++ ubuntuone/controlpanel/gui/qt/folders.py 2012-03-08 21:13:18 +0000 |
673 | @@ -61,6 +61,21 @@ |
674 | YES = QtGui.QMessageBox.Yes |
675 | |
676 | |
677 | +class ExploreFolderButton(QtGui.QPushButton): |
678 | + """A specialized button for the folder listing.""" |
679 | + |
680 | + def __init__(self, folder_path, parent=None): |
681 | + super(ExploreFolderButton, self).__init__(parent=parent) |
682 | + self.folder_path = folder_path |
683 | + self.setText(FOLDERS_COLUMN_EXPLORE) |
684 | + self.clicked.connect(self.on_clicked) |
685 | + |
686 | + def on_clicked(self): |
687 | + """Open the folder_path in the default file manager.""" |
688 | + uri = unicode(QtCore.QUrl.fromLocalFile(self.folder_path).toString()) |
689 | + uri_hook(uri) |
690 | + |
691 | + |
692 | class FoldersPanel(UbuntuOneBin): |
693 | """The Folders Tab Panel widget""" |
694 | |
695 | @@ -180,21 +195,9 @@ |
696 | |
697 | # attach a third item with a button to explore the folder |
698 | model_index = self.ui.folders.indexFromItem(child, EXPLORE_COL) |
699 | - button = QtGui.QPushButton(parent=self.ui.folders) |
700 | - button.setFlat(True) |
701 | - button.setText(FOLDERS_COLUMN_EXPLORE) |
702 | - button.setObjectName('explore_folder_button') |
703 | - policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, |
704 | - QtGui.QSizePolicy.Fixed) |
705 | - button.setSizePolicy(policy) |
706 | + button = ExploreFolderButton(folder_path=child.volume_path, |
707 | + parent=self.ui.folders) |
708 | button.setEnabled(bool(volume[u'subscribed'])) |
709 | - |
710 | - # Operator not preceded by a space |
711 | - # pylint: disable=C0322 |
712 | - cb = lambda checked, item=child: \ |
713 | - self.on_folders_itemActivated(item) |
714 | - # pylint: enable=C0322 |
715 | - button.clicked.connect(cb) |
716 | self.ui.folders.setIndexWidget(model_index, button) |
717 | |
718 | self.ui.folders.expandAll() |
719 | |
720 | === modified file 'ubuntuone/controlpanel/gui/qt/loadingoverlay.py' |
721 | --- ubuntuone/controlpanel/gui/qt/loadingoverlay.py 2012-02-22 17:04:28 +0000 |
722 | +++ ubuntuone/controlpanel/gui/qt/loadingoverlay.py 2012-03-08 21:13:18 +0000 |
723 | @@ -45,11 +45,7 @@ |
724 | self.counter = 0 |
725 | self.orientation = False |
726 | |
727 | - # The following is a hack to avoid having the faked self.ui failing |
728 | - # with AttributeError in the tests. We need to improve the fake so we |
729 | - # don't leak this to the production code. |
730 | - if getattr(self.ui, 'label', None) is not None: |
731 | - self.ui.label.setText(LOADING_OVERLAY) |
732 | + self.ui.label.setText(LOADING_OVERLAY) |
733 | |
734 | # Invalid name "paintEvent" |
735 | # pylint: disable=C0103 |
736 | |
737 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py' |
738 | --- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-03-02 13:53:24 +0000 |
739 | +++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-03-08 21:13:18 +0000 |
740 | @@ -96,6 +96,7 @@ |
741 | """A fake Ui object.""" |
742 | |
743 | exposed_methods = ['setupUi'] |
744 | + raise_attr_error = False |
745 | |
746 | |
747 | class FakedControlPanelBackend(FakedObject): |
748 | |
749 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_device.py' |
750 | --- ubuntuone/controlpanel/gui/qt/tests/test_device.py 2012-03-01 22:05:51 +0000 |
751 | +++ ubuntuone/controlpanel/gui/qt/tests/test_device.py 2012-03-08 21:13:18 +0000 |
752 | @@ -1,8 +1,6 @@ |
753 | # -*- coding: utf-8 -*- |
754 | - |
755 | -# Author: Alejandro J. Cura <alecu@canonical.com> |
756 | # |
757 | -# Copyright 2011 Canonical Ltd. |
758 | +# Copyright 2011-2012 Canonical Ltd. |
759 | # |
760 | # This program is free software: you can redistribute it and/or modify it |
761 | # under the terms of the GNU General Public License version 3, as published |
762 | @@ -36,7 +34,7 @@ |
763 | |
764 | |
765 | class DeviceWidgetTestCase(BaseTestCase): |
766 | - """Test the qt control panel.""" |
767 | + """Test the DeviceWidget class.""" |
768 | |
769 | innerclass_ui = gui.device_ui |
770 | innerclass_name = "Ui_Form" |
771 | @@ -46,9 +44,28 @@ |
772 | logger = gui.logger |
773 | |
774 | def test_has_id(self): |
775 | - """The device as an id, None by default.""" |
776 | + """The device as an id accepted as creation param.""" |
777 | self.assertEqual(self.ui.id, self.device_id) |
778 | |
779 | + def test_id_can_be_none(self): |
780 | + """The device id is None by default.""" |
781 | + ui = self.class_ui() |
782 | + self.assertEqual(ui.id, None) |
783 | + |
784 | + def test_setting_id_to_none_disables_remove_button(self): |
785 | + """If the id is set to None, the remove button is disabled.""" |
786 | + self.ui.id = None |
787 | + self.assertFalse(self.ui.ui.remove_device_button.isEnabled()) |
788 | + |
789 | + def test_setting_id_to_not_none_enables_remove_button(self): |
790 | + """If the id is set to not None, the remove button is enabled.""" |
791 | + self.ui.id = 'not None' |
792 | + self.assertTrue(self.ui.ui.remove_device_button.isEnabled()) |
793 | + |
794 | + def test_remove_button(self): |
795 | + """The remove button is visible.""" |
796 | + self.assertTrue(self.ui.ui.remove_device_button.isVisible()) |
797 | + |
798 | def test_update_device_info(self): |
799 | """The widget is updated with the info.""" |
800 | info = SAMPLE_COMPUTER_INFO |
801 | @@ -68,7 +85,7 @@ |
802 | self.assertIconMatchesType(gui.DEVICE_TYPE_PHONE, gui.PHONE_ICON) |
803 | self.assertIconMatchesType("other random type", gui.COMPUTER_ICON) |
804 | |
805 | - def _test_update_device_info_sets_right_icon(self, info): |
806 | + def assert_update_device_info_sets_right_icon(self, info): |
807 | """The widget is updated with the right icon.""" |
808 | self.ui.update_device_info(info) |
809 | pixmap_name = gui.icon_name_from_type(info["type"]) |
810 | @@ -78,21 +95,11 @@ |
811 | |
812 | def test_update_device_info_sets_computer_icon(self): |
813 | """The computer icon is set.""" |
814 | - self._test_update_device_info_sets_right_icon(SAMPLE_COMPUTER_INFO) |
815 | + self.assert_update_device_info_sets_right_icon(SAMPLE_COMPUTER_INFO) |
816 | |
817 | def test_update_device_info_sets_phone_icon(self): |
818 | """The phone icon is set.""" |
819 | - self._test_update_device_info_sets_right_icon(SAMPLE_PHONE_INFO) |
820 | - |
821 | - def test_get_device_for_list_widget(self): |
822 | - """The the item list values returned.""" |
823 | - info = SAMPLE_COMPUTER_INFO |
824 | - item = gui.get_device_for_list_widget(info) |
825 | - self.assertEqual(item.text(), info["name"]) |
826 | - |
827 | - info = SAMPLE_PHONE_INFO |
828 | - item = gui.get_device_for_list_widget(info) |
829 | - self.assertEqual(item.text(), info["name"]) |
830 | + self.assert_update_device_info_sets_right_icon(SAMPLE_PHONE_INFO) |
831 | |
832 | |
833 | class RemoveDeviceTestCase(DeviceWidgetTestCase): |
834 | @@ -161,3 +168,13 @@ |
835 | yield self.ui.ui.remove_device_button.click() |
836 | |
837 | self.assertTrue(self.memento.check_exception(CrashyBackendException)) |
838 | + |
839 | + |
840 | +class RemoteDeviceWidgetTestCase(DeviceWidgetTestCase): |
841 | + """Test the RemoteDeviceWidget class.""" |
842 | + |
843 | + class_ui = gui.RemoteDeviceWidget |
844 | + |
845 | + def test_remove_button(self): |
846 | + """The remove button is hidden.""" |
847 | + self.assertFalse(self.ui.ui.remove_device_button.isVisible()) |
848 | |
849 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py' |
850 | --- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2012-03-01 22:05:51 +0000 |
851 | +++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2012-03-08 21:13:18 +0000 |
852 | @@ -1,8 +1,6 @@ |
853 | # -*- coding: utf-8 -*- |
854 | - |
855 | -# Author: Alejandro J. Cura <alecu@canonical.com> |
856 | # |
857 | -# Copyright 2011 Canonical Ltd. |
858 | +# Copyright 2011-2012 Canonical Ltd. |
859 | # |
860 | # This program is free software: you can redistribute it and/or modify it |
861 | # under the terms of the GNU General Public License version 3, as published |
862 | @@ -63,7 +61,6 @@ |
863 | def test_no_devices_at_startup(self): |
864 | """The UI is reset at startup.""" |
865 | self.assertEqual(self.ui.ui.list_devices.count(), 0) |
866 | - self.assertEqual(self.ui.ui.local_device_box.count(), 0) |
867 | |
868 | def test_process_info(self): |
869 | """The widget is updated with the info.""" |
870 | @@ -71,10 +68,8 @@ |
871 | |
872 | local, remote = SAMPLE_DEVICES_INFO[0], SAMPLE_DEVICES_INFO[1:] |
873 | |
874 | - self.assertEqual(self.ui.ui.local_device_box.count(), 1) |
875 | - local_device = self.ui.ui.local_device_box.itemAt(0).widget() |
876 | - self.assertEqual(local_device.ui.device_name_label.text(), |
877 | - local['name']) |
878 | + local_device = self.ui.ui.local_device |
879 | + self.assertEqual(local_device.text(), local['name']) |
880 | self.assertEqual(local_device.id, local['device_id']) |
881 | |
882 | self.assertEqual(self.ui.ui.list_devices.count(), |
883 | @@ -84,26 +79,12 @@ |
884 | device = self.ui.ui.list_devices.itemWidget(item) |
885 | self.assertEqual(device.text(), remote_device['name']) |
886 | |
887 | - def test_remove_device_and_check_layout_state(self): |
888 | - """Test if the widget is properly removed.""" |
889 | - self.ui.process_info(SAMPLE_DEVICES_INFO) |
890 | - self.ui.show() |
891 | - |
892 | - self.assertEqual(self.ui.ui.local_device_box.count(), 1) |
893 | - local_device = self.ui.ui.local_device_box.itemAt(0).widget() |
894 | - self.executed = False |
895 | - |
896 | - def delete_later(reference=None): |
897 | - """Fake delete later.""" |
898 | - self.executed = True |
899 | - self.patch(local_device, "deleteLater", delete_later) |
900 | - self.ui.clear_device_info(self.ui.ui.local_device_box) |
901 | - self.ui.process_info(SAMPLE_DEVICES_INFO) |
902 | - self.assertEqual(self.ui.ui.local_device_box.count(), 1) |
903 | - local_device2 = self.ui.ui.local_device_box.itemAt(0).widget() |
904 | - self.assertNotEqual(local_device, local_device2) |
905 | - self.assertTrue(self.executed) |
906 | - self.assertFalse(local_device.isVisible()) |
907 | + def test_local_device(self): |
908 | + """Test if the local_device widget is properly packed.""" |
909 | + self.ui.process_info(SAMPLE_DEVICES_INFO) |
910 | + |
911 | + local_device = self.ui.ui.local_device_layout.itemAt(0).widget() |
912 | + self.assertIs(local_device, self.ui.ui.local_device) |
913 | |
914 | def test_process_info_twice(self): |
915 | """The widget is updated with the info.""" |
916 | @@ -115,21 +96,20 @@ |
917 | self.assert_uri_hook_called(self.ui.ui.manage_devices_button, |
918 | gui.EDIT_DEVICES_LINK) |
919 | |
920 | - def test_remove_device_widget_after_removal(self): |
921 | - """When a device widget was deleted, remove it from the UI.""" |
922 | + def test_local_device_removed_clears_the_widget(self): |
923 | + """When the local device was deleted, clear it.""" |
924 | self.ui.process_info(SAMPLE_DEVICES_INFO) |
925 | |
926 | - local_device = self.ui.ui.local_device_box.itemAt(0).widget() |
927 | - local_device.removed.emit() |
928 | + self.ui.ui.local_device.removed.emit() |
929 | |
930 | - self.assertTrue(self.ui.ui.local_device_box.itemAt(0) is None) |
931 | + self.assertEqual(self.ui.ui.local_device.text(), '') |
932 | + self.assertEqual(self.ui.ui.local_device.id, None) |
933 | |
934 | def test_local_device_removed_signal(self): |
935 | """When the local device is removed, emit localDeviceRemoved signal.""" |
936 | self.ui.localDeviceRemoved.connect(self._set_called) |
937 | self.ui.process_info(SAMPLE_DEVICES_INFO) |
938 | |
939 | - local_device = self.ui.ui.local_device_box.itemAt(0).widget() |
940 | - local_device.removed.emit() |
941 | + self.ui.ui.local_device.removed.emit() |
942 | |
943 | self.assertEqual(self._called, ((), {})) |
944 | |
945 | === modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py' |
946 | --- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-02 16:56:10 +0000 |
947 | +++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-08 21:13:18 +0000 |
948 | @@ -1,8 +1,6 @@ |
949 | # -*- coding: utf-8 -*- |
950 | - |
951 | -# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
952 | # |
953 | -# Copyright 2011 Canonical Ltd. |
954 | +# Copyright 2011-2012 Canonical Ltd. |
955 | # |
956 | # This program is free software: you can redistribute it and/or modify it |
957 | # under the terms of the GNU General Public License version 3, as published |
958 | @@ -33,6 +31,7 @@ |
959 | ) |
960 | from ubuntuone.controlpanel.gui.qt import folders as gui |
961 | from ubuntuone.controlpanel.gui.qt.tests import ( |
962 | + BaseTestCase, |
963 | FakedDialog, |
964 | ) |
965 | from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import ( |
966 | @@ -54,6 +53,26 @@ |
967 | return name |
968 | |
969 | |
970 | +class ExploreFolderButtonTestCase(BaseTestCase): |
971 | + """Test the ExploreFolderButton widget.""" |
972 | + |
973 | + class_ui = gui.ExploreFolderButton |
974 | + kwargs = dict(folder_path=u'foo') |
975 | + |
976 | + def test_text(self): |
977 | + """The button text is correct.""" |
978 | + self.assertEqual(self.ui.text(), gui.FOLDERS_COLUMN_EXPLORE) |
979 | + |
980 | + def test_clicked(self): |
981 | + """Clicking the button opens the folder in the default file manager.""" |
982 | + self.patch(gui, 'uri_hook', self._set_called) |
983 | + self.ui.click() |
984 | + |
985 | + url = gui.QtCore.QUrl.fromLocalFile(self.kwargs['folder_path']) |
986 | + expected = unicode(url.toString()) |
987 | + self.assertEqual(self._called, ((expected,), {})) |
988 | + |
989 | + |
990 | class FoldersPanelTestCase(UbuntuOneBinTestCase): |
991 | """Test the qt cloud folders tab.""" |
992 | |
993 | @@ -173,7 +192,6 @@ |
994 | # explore button is in place |
995 | model_index = folders.indexFromItem(item, gui.EXPLORE_COL) |
996 | button = folders.indexWidget(model_index) |
997 | - self.assertEqual(button.isFlat(), True) |
998 | self.assertEqual(button.isEnabled(), |
999 | bool(volume['subscribed'])) |
1000 | |
1001 | |
1002 | === modified file 'ubuntuone/controlpanel/gui/tests/__init__.py' |
1003 | --- ubuntuone/controlpanel/gui/tests/__init__.py 2012-03-02 21:21:03 +0000 |
1004 | +++ ubuntuone/controlpanel/gui/tests/__init__.py 2012-03-08 21:13:18 +0000 |
1005 | @@ -134,6 +134,7 @@ |
1006 | next_result = None |
1007 | exposed_methods = [] |
1008 | exposed_results = {} |
1009 | + raise_attr_error = True |
1010 | |
1011 | def __init__(self, *args, **kwargs): |
1012 | self._args = args |
1013 | @@ -142,6 +143,23 @@ |
1014 | for i in self.exposed_methods: |
1015 | setattr(self, i, self._record_call(i)) |
1016 | |
1017 | + def __call__(self, *args, **kwargs): |
1018 | + """Skip.""" |
1019 | + |
1020 | + def __getattribute__(self, attr_name): |
1021 | + super_getattr = super(FakedObject, self).__getattribute__ |
1022 | + |
1023 | + try: |
1024 | + result = super_getattr(attr_name) |
1025 | + except AttributeError: |
1026 | + if super_getattr('raise_attr_error'): |
1027 | + raise |
1028 | + else: |
1029 | + result = FakedObject() |
1030 | + result.raise_attr_error = super_getattr('raise_attr_error') |
1031 | + |
1032 | + return result |
1033 | + |
1034 | def _record_call(self, func_name): |
1035 | """Store values when calling 'func_name'.""" |
1036 |
+1