Merge lp:~nataliabidart/ubuntuone-control-panel/focus into lp:ubuntuone-control-panel

Proposed by Natalia Bidart on 2012-03-08
Status: Merged
Approved by: Natalia Bidart on 2012-03-09
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
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve on 2012-03-09
Diego Sarmentero (community) 2012-03-08 Approve on 2012-03-09
Review via email: mp+96654@code.launchpad.net

Commit message

- Apply new specification for tabbing navigation and tabbing style
  (LP: #942020).
- Make the "Explore" buttons for folders be disabled (style-wise) when the folder
  is not synched (LP: #949035).

To post a comment you must log in.
283. By Natalia Bidart on 2012-03-08

Less changes against trunk.

284. By Natalia Bidart on 2012-03-08

Restoring hack for tabs.

285. By Natalia Bidart on 2012-03-08

No need for controlpanel help buttons to be enabled/disabled for the style.

Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
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

Subscribers

People subscribed via source and target branches