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

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
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Diego Sarmentero (community) Approve
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

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
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
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
=== modified file 'data/qt/controlpanel.ui'
--- data/qt/controlpanel.ui 2012-03-02 13:53:24 +0000
+++ data/qt/controlpanel.ui 2012-03-08 21:13:18 +0000
@@ -329,8 +329,8 @@
329 </property>329 </property>
330 <property name="maximumSize">330 <property name="maximumSize">
331 <size>331 <size>
332 <width>16</width>332 <width>20</width>
333 <height>16</height>333 <height>20</height>
334 </size>334 </size>
335 </property>335 </property>
336 <property name="cursor">336 <property name="cursor">
@@ -352,8 +352,8 @@
352 </property>352 </property>
353 <property name="maximumSize">353 <property name="maximumSize">
354 <size>354 <size>
355 <width>16</width>355 <width>20</width>
356 <height>16</height>356 <height>20</height>
357 </size>357 </size>
358 </property>358 </property>
359 <property name="cursor">359 <property name="cursor">
360360
=== modified file 'data/qt/device.ui'
--- data/qt/device.ui 2012-02-22 15:35:13 +0000
+++ data/qt/device.ui 2012-03-08 21:13:18 +0000
@@ -6,14 +6,17 @@
6 <rect>6 <rect>
7 <x>0</x>7 <x>0</x>
8 <y>0</y>8 <y>0</y>
9 <width>233</width>9 <width>430</width>
10 <height>36</height>10 <height>27</height>
11 </rect>11 </rect>
12 </property>12 </property>
13 <property name="windowTitle">13 <property name="windowTitle">
14 <string notr="true">Form</string>14 <string notr="true">Form</string>
15 </property>15 </property>
16 <layout class="QHBoxLayout" name="horizontalLayout">16 <layout class="QHBoxLayout" name="horizontalLayout">
17 <property name="margin">
18 <number>0</number>
19 </property>
17 <item>20 <item>
18 <widget class="QLabel" name="device_icon_label">21 <widget class="QLabel" name="device_icon_label">
19 <property name="pixmap">22 <property name="pixmap">
2023
=== removed file 'data/qt/device_remote.ui'
--- data/qt/device_remote.ui 2012-02-22 14:58:25 +0000
+++ data/qt/device_remote.ui 1970-01-01 00:00:00 +0000
@@ -1,50 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>Form</class>
4 <widget class="QWidget" name="Form">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>264</width>
10 <height>45</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string notr="true">Form</string>
15 </property>
16 <layout class="QHBoxLayout" name="horizontalLayout">
17 <item>
18 <widget class="QLabel" name="device_icon_label">
19 <property name="pixmap">
20 <pixmap resource="images.qrc">:/computer.png</pixmap>
21 </property>
22 </widget>
23 </item>
24 <item>
25 <widget class="QLabel" name="device_name_label">
26 <property name="text">
27 <string notr="true">Non local device</string>
28 </property>
29 </widget>
30 </item>
31 <item>
32 <spacer name="horizontalSpacer">
33 <property name="orientation">
34 <enum>Qt::Horizontal</enum>
35 </property>
36 <property name="sizeHint" stdset="0">
37 <size>
38 <width>217</width>
39 <height>20</height>
40 </size>
41 </property>
42 </spacer>
43 </item>
44 </layout>
45 </widget>
46 <resources>
47 <include location="images.qrc"/>
48 </resources>
49 <connections/>
50</ui>
510
=== modified file 'data/qt/devices.ui'
--- data/qt/devices.ui 2012-03-02 13:53:24 +0000
+++ data/qt/devices.ui 2012-03-08 21:13:18 +0000
@@ -21,16 +21,16 @@
21 <number>0</number>21 <number>0</number>
22 </property>22 </property>
23 <item>23 <item>
24 <widget class="QGroupBox" name="local_device">24 <widget class="QGroupBox" name="local_device_box">
25 <property name="title">25 <property name="title">
26 <string notr="true">This device</string>26 <string notr="true">This device</string>
27 </property>27 </property>
28 <layout class="QVBoxLayout" name="verticalLayout">28 <layout class="QVBoxLayout" name="local_device_layout">
29 <property name="margin">29 <property name="margin">
30 <number>0</number>30 <number>0</number>
31 </property>31 </property>
32 <item>32 <item>
33 <layout class="QVBoxLayout" name="local_device_box"/>33 <widget class="DeviceWidget" name="local_device" native="true"/>
34 </item>34 </item>
35 </layout>35 </layout>
36 </widget>36 </widget>
@@ -120,6 +120,12 @@
120 <extends>QPushButton</extends>120 <extends>QPushButton</extends>
121 <header>ubuntuone.controlpanel.gui.qt.gotoweb</header>121 <header>ubuntuone.controlpanel.gui.qt.gotoweb</header>
122 </customwidget>122 </customwidget>
123 <customwidget>
124 <class>DeviceWidget</class>
125 <extends>QWidget</extends>
126 <header>ubuntuone.controlpanel.gui.qt.device</header>
127 <container>1</container>
128 </customwidget>
123 </customwidgets>129 </customwidgets>
124 <resources>130 <resources>
125 <include location="images.qrc"/>131 <include location="images.qrc"/>
126132
=== modified file 'data/qt/preferences.ui'
--- data/qt/preferences.ui 2012-03-02 19:42:17 +0000
+++ data/qt/preferences.ui 2012-03-08 21:13:18 +0000
@@ -6,8 +6,8 @@
6 <rect>6 <rect>
7 <x>0</x>7 <x>0</x>
8 <y>0</y>8 <y>0</y>
9 <width>512</width>9 <width>520</width>
10 <height>328</height>10 <height>342</height>
11 </rect>11 </rect>
12 </property>12 </property>
13 <property name="windowTitle">13 <property name="windowTitle">
@@ -53,14 +53,27 @@
53 </property>53 </property>
54 </widget>54 </widget>
55 </item>55 </item>
56 <item row="2" column="0">56 <item row="0" column="3">
57 <spacer name="horizontalSpacer_2">
58 <property name="orientation">
59 <enum>Qt::Horizontal</enum>
60 </property>
61 <property name="sizeHint" stdset="0">
62 <size>
63 <width>40</width>
64 <height>20</height>
65 </size>
66 </property>
67 </spacer>
68 </item>
69 <item row="1" column="0">
57 <widget class="QCheckBox" name="limit_downloads_checkbox">70 <widget class="QCheckBox" name="limit_downloads_checkbox">
58 <property name="text">71 <property name="text">
59 <string notr="true">Limit download speed to</string>72 <string notr="true">Limit download speed to</string>
60 </property>73 </property>
61 </widget>74 </widget>
62 </item>75 </item>
63 <item row="2" column="1">76 <item row="1" column="1">
64 <widget class="QSpinBox" name="download_speed_spinbox">77 <widget class="QSpinBox" name="download_speed_spinbox">
65 <property name="minimum">78 <property name="minimum">
66 <number>-1</number>79 <number>-1</number>
@@ -70,17 +83,17 @@
70 </property>83 </property>
71 </widget>84 </widget>
72 </item>85 </item>
73 <item row="2" column="2">86 <item row="1" column="2">
74 <widget class="QLabel" name="kbps_label_2">87 <widget class="QLabel" name="kbps_label_2">
75 <property name="text">88 <property name="text">
76 <string notr="true">Kilobits per second</string>89 <string notr="true">Kilobits per second</string>
77 </property>90 </property>
78 </widget>91 </widget>
79 </item>92 </item>
80 <item row="0" column="3">93 <item row="2" column="0">
81 <spacer name="horizontalSpacer_2">94 <spacer name="verticalSpacer_2">
82 <property name="orientation">95 <property name="orientation">
83 <enum>Qt::Horizontal</enum>96 <enum>Qt::Vertical</enum>
84 </property>97 </property>
85 <property name="sizeHint" stdset="0">98 <property name="sizeHint" stdset="0">
86 <size>99 <size>
@@ -90,7 +103,7 @@
90 </property>103 </property>
91 </spacer>104 </spacer>
92 </item>105 </item>
93 <item row="4" column="0" colspan="3">106 <item row="3" column="0" colspan="3">
94 <widget class="QLabel" name="label_2">107 <widget class="QLabel" name="label_2">
95 <property name="text">108 <property name="text">
96 <string notr="true">Please note that your files will not sync if you set bandwidth to 0</string>109 <string notr="true">Please note that your files will not sync if you set bandwidth to 0</string>
@@ -103,19 +116,6 @@
103 </property>116 </property>
104 </widget>117 </widget>
105 </item>118 </item>
106 <item row="3" column="0">
107 <spacer name="verticalSpacer_2">
108 <property name="orientation">
109 <enum>Qt::Vertical</enum>
110 </property>
111 <property name="sizeHint" stdset="0">
112 <size>
113 <width>40</width>
114 <height>20</height>
115 </size>
116 </property>
117 </spacer>
118 </item>
119 </layout>119 </layout>
120 </widget>120 </widget>
121 </item>121 </item>
@@ -124,32 +124,45 @@
124 <property name="title">124 <property name="title">
125 <string notr="true">File Sync Settings</string>125 <string notr="true">File Sync Settings</string>
126 </property>126 </property>
127 <layout class="QVBoxLayout" name="verticalLayout_1">127 <layout class="QGridLayout" name="gridLayout_2">
128 <property name="margin">128 <property name="margin">
129 <number>0</number>129 <number>0</number>
130 </property>130 </property>
131 <item>131 <item row="0" column="0">
132 <widget class="QCheckBox" name="autoconnect_checkbox">132 <widget class="QCheckBox" name="autoconnect_checkbox">
133 <property name="text">133 <property name="text">
134 <string notr="true">Connect automatically when computer starts</string>134 <string notr="true">Connect automatically when computer starts</string>
135 </property>135 </property>
136 </widget>136 </widget>
137 </item>137 </item>
138 <item>138 <item row="0" column="1">
139 <spacer name="horizontalSpacer_3">
140 <property name="orientation">
141 <enum>Qt::Horizontal</enum>
142 </property>
143 <property name="sizeHint" stdset="0">
144 <size>
145 <width>40</width>
146 <height>20</height>
147 </size>
148 </property>
149 </spacer>
150 </item>
151 <item row="1" column="0">
139 <widget class="QCheckBox" name="udf_autosubscribe_checkbox">152 <widget class="QCheckBox" name="udf_autosubscribe_checkbox">
140 <property name="text">153 <property name="text">
141 <string notr="true">Automatically sync all new cloud folders to this computer</string>154 <string notr="true">Automatically sync all new cloud folders to this computer</string>
142 </property>155 </property>
143 </widget>156 </widget>
144 </item>157 </item>
145 <item>158 <item row="2" column="0">
146 <widget class="QCheckBox" name="share_autosubscribe_checkbox">159 <widget class="QCheckBox" name="share_autosubscribe_checkbox">
147 <property name="text">160 <property name="text">
148 <string notr="true">Automatically sync all folders shared with me to this computer</string>161 <string notr="true">Automatically sync all folders shared with me to this computer</string>
149 </property>162 </property>
150 </widget>163 </widget>
151 </item>164 </item>
152 <item>165 <item row="3" column="0">
153 <widget class="QCheckBox" name="show_all_notifications_checkbox">166 <widget class="QCheckBox" name="show_all_notifications_checkbox">
154 <property name="text">167 <property name="text">
155 <string notr="true">Allow all notifications to this device</string>168 <string notr="true">Allow all notifications to this device</string>
156169
=== modified file 'data/qt/ubuntuone.qss'
--- data/qt/ubuntuone.qss 2012-03-02 17:33:38 +0000
+++ data/qt/ubuntuone.qss 2012-03-08 21:13:18 +0000
@@ -1,3 +1,11 @@
1/* Common colours:
2
3orange: #dd4814
4dark grey: #333333
5light grey: #aea79f
6
7*/
8
1QMainWindow {9QMainWindow {
2 background-color: #aea79f;10 background-color: #aea79f;
3}11}
@@ -77,6 +85,18 @@
77 border-width: 1px;85 border-width: 1px;
78}86}
7987
88QPushButton:focus {
89 border-width: 2px;
90 /* reduce the padding since we have a 2px border now */
91 padding: 5px;
92 padding-left: 19px;
93 padding-right: 19px;
94 /* hack to make the mild-orange focused box dissapear */
95 padding-top: 20px;
96 padding-bottom: 20px;
97 /* end of hack */
98}
99
80QPushButton:disabled {100QPushButton:disabled {
81 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,101 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
82 stop: 0 #eaeaea, stop: 1.0 #cacaca);102 stop: 0 #eaeaea, stop: 1.0 #cacaca);
@@ -91,19 +111,18 @@
91 border-color: #999999;111 border-color: #999999;
92}112}
93113
94QPushButton:enabled:focus,114QPushButton:enabled:focus {
115 border-color: #dd4814;
116}
117
95QPushButton:enabled:hover {118QPushButton:enabled:hover {
96 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,119 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
97 stop: 0 #ffffff,stop: 1.0 #ededed);120 stop: 0 #ffffff,stop: 1.0 #ededed);
98 color: #333333;
99 border-color: #999999;
100}121}
101122
102QPushButton:enabled:pressed {123QPushButton:enabled:pressed {
103 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,124 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
104 stop: 0 #d9d9d9,stop: 1.0 #fefefe);125 stop: 0 #d9d9d9,stop: 1.0 #fefefe);
105 color: #333333;
106 border-color: #999999;
107}126}
108127
109QPushButton:default:enabled {128QPushButton:default:enabled {
@@ -113,55 +132,69 @@
113 border-color: #999999;132 border-color: #999999;
114}133}
115134
116QPushButton:default:enabled:focus,135QPushButton:default:enabled:focus {
136 border-color: #333333;
137}
138
117QPushButton:default:enabled:hover {139QPushButton:default:enabled:hover {
118 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,140 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
119 stop: 0 #ffb19c,stop: 1.0 #dd4814);141 stop: 0 #ffb19c,stop: 1.0 #dd4814);
120 color: white;
121 border-color: #999999;
122}142}
123143
124QPushButton:default:enabled:pressed {144QPushButton:default:enabled:pressed {
125 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,145 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
126 stop: 0 #b93f14,stop: 1.0 #dd4814);146 stop: 0 #b93f14,stop: 1.0 #dd4814);
127 color: white;147}
128 border-color: #999999;148
129}149ExploreFolderButton {
130
131QPushButton#help_button {
132 background: transparent;
133 border: none;
134 color: white;
135 text-decoration: underline;
136 padding: 0px;
137}
138
139QPushButton#explore_folder_button {
140 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
141 stop: 0 #fbfbfb, stop: 1.0 #e6e6e6);
142 height: 15px;
143 border-radius: 7px;
144 border-color: #908e8d;
145 color: #595959;
146 padding-left: 10px;
147 padding-right: 10px;
148 margin-top: 5px;150 margin-top: 5px;
149 margin-bottom: 5px;151 margin-bottom: 5px;
150 margin-right: 20px;152 margin-right: 20px;
151 margin-left: 20px;153 margin-left: 20px;
152}154}
153155
156ExploreFolderButton:enabled {
157 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
158 stop: 0 #fbfbfb, stop: 1.0 #e6e6e6);
159 border-color: #908e8d;
160 color: #595959;
161}
162
154QPushButton#twitter_button,163QPushButton#twitter_button,
155QPushButton#facebook_button {164QPushButton#facebook_button {
165 background: transparent;
166}
167
168QPushButton#twitter_button:focus,
169QPushButton#facebook_button:focus {
170 border: 2px solid #dd4814;
171}
172
173GoToWebButton#help_button {
174 padding: 2px;
175}
176
177GoToWebButton#share_publish_button,
178GoToWebButton#help_button {
179 background: transparent;
156 border: none;180 border: none;
181 text-decoration: underline;
157}182}
158183
159GoToWebButton#forgot_password_button,
160GoToWebButton#share_publish_button {184GoToWebButton#share_publish_button {
161 background: transparent;
162 border: none;
163 color: #dd4814;185 color: #dd4814;
164 text-decoration: underline;186}
187
188GoToWebButton#help_button {
189 color: white;
190}
191
192GoToWebButton#share_publish_button:focus {
193 border: 2px solid #aea79f;
194}
195
196GoToWebButton#help_button:focus {
197 border: 2px solid #dd4814;
165}198}
166199
167QTabBar::tab {200QTabBar::tab {
@@ -192,12 +225,7 @@
192 border-width: 1px;225 border-width: 1px;
193}226}
194227
195QTabBar::tab:first:!selected {228QTabBar::tab:first {
196 border-left-color: #939389;
197 border-left-color: #939389;
198}
199
200QTabBar::tab:first:selected {
201 border-left-color: #939389;229 border-left-color: #939389;
202}230}
203231
@@ -205,13 +233,21 @@
205 border-left-color: #e4e0dd;233 border-left-color: #e4e0dd;
206}234}
207235
236QTabBar::tab:last:!selected {
237 border-left-color: #e4e0dd;
238}
239
208QTabBar::tab:hover {240QTabBar::tab:hover {
209 background: #f6f6f6;241 background: #f6f6f6;
210 text-decoration: underline;242 text-decoration: underline;
211}243}
212244
213QTabBar::tab:last:!selected {245QTabBar::tab:focus {
214 border-left-color: #e4e0dd;246 text-decoration: underline;
247 /* hack to make the mild-orange focused box dissapear */
248 padding-left: 1000px;
249 padding-right: 1000px;
250 /* end of hack */
215}251}
216252
217QTabWidget {253QTabWidget {
@@ -259,6 +295,12 @@
259 min-height: 48px;295 min-height: 48px;
260}296}
261297
298QGroupBox#local_device_box,
299QListWidget#list_devices::item {
300 padding-left: 9px;
301 padding-right: 9px;
302}
303
262QLabel[OverQuota="false"] {304QLabel[OverQuota="false"] {
263 color: #333333;305 color: #333333;
264}306}
@@ -301,3 +343,8 @@
301 alternate-background-color: #f7f6f5;343 alternate-background-color: #f7f6f5;
302 background: #efedec;344 background: #efedec;
303}345}
346
347QCheckBox:focus {
348 border-radius: 5px;
349 border: 2px solid #dd4814;
350}
304351
=== modified file 'ubuntuone/controlpanel/gui/qt/device.py'
--- ubuntuone/controlpanel/gui/qt/device.py 2012-02-22 17:04:28 +0000
+++ ubuntuone/controlpanel/gui/qt/device.py 2012-03-08 21:13:18 +0000
@@ -34,7 +34,7 @@
34 handle_errors,34 handle_errors,
35 pixmap_from_name,35 pixmap_from_name,
36)36)
37from ubuntuone.controlpanel.gui.qt.ui import device_ui, device_remote_ui37from ubuntuone.controlpanel.gui.qt.ui import device_ui
38from ubuntuone.controlpanel.logger import setup_logging38from ubuntuone.controlpanel.logger import setup_logging
3939
40COMPUTER_ICON = "computer"40COMPUTER_ICON = "computer"
@@ -61,27 +61,35 @@
6161
6262
63class DeviceWidget(cache.Cache, QtGui.QWidget):63class DeviceWidget(cache.Cache, QtGui.QWidget):
64 """The widget for each device in the control panel."""64 """The widget for a local device in the control panel."""
6565
66 removed = QtCore.pyqtSignal()66 removed = QtCore.pyqtSignal()
67 removeCanceled = QtCore.pyqtSignal()67 removeCanceled = QtCore.pyqtSignal()
6868
69 def __init__(self, device_id, *args, **kwargs):69 def __init__(self, device_id=None, *args, **kwargs):
70 """Initialize the UI of the widget."""70 """Initialize the UI of the widget."""
71 super(DeviceWidget, self).__init__(*args, **kwargs)71 super(DeviceWidget, self).__init__(*args, **kwargs)
72 self.ui = device_ui.Ui_Form()72 self.ui = device_ui.Ui_Form()
73 self.ui.setupUi(self)73 self.ui.setupUi(self)
7474
75 # The following is a hack to avoid having the faked self.ui failing75 self.ui.remove_device_button.setText(REMOVE_BUTTON)
76 # with AttributeError in the tests. We need to improve the fake so we76 self._id = None
77 # don't leak this to the production code.
78 if getattr(self.ui, 'remove_device_button', None) is not None:
79 self.ui.remove_device_button.setText(REMOVE_BUTTON)
80
81 self.id = device_id77 self.id = device_id
8278
79 def _get_id(self):
80 """Return this device's id."""
81 return self._id
82
83 def _set_id(self, new_id):
84 """Set this device's id."""
85 self._id = new_id
86 self.ui.remove_device_button.setEnabled(self._id is not None)
87
88 id = property(fget=_get_id, fset=_set_id)
89
83 def update_device_info(self, device_info):90 def update_device_info(self, device_info):
84 """Update the device info."""91 """Update the device info."""
92 self.id = device_info["device_id"]
85 self.ui.device_name_label.setText(device_info["name"])93 self.ui.device_name_label.setText(device_info["name"])
86 icon_name = icon_name_from_type(device_info["type"])94 icon_name = icon_name_from_type(device_info["type"])
87 pixmap = pixmap_from_name(icon_name)95 pixmap = pixmap_from_name(icon_name)
@@ -102,28 +110,20 @@
102 else:110 else:
103 self.removeCanceled.emit()111 self.removeCanceled.emit()
104112
105
106class DeviceRemoteWidget(QtGui.QWidget):
107
108 """Remote Device widget for Devices List."""
109
110 def __init__(self, device_info):
111 super(DeviceRemoteWidget, self).__init__()
112 self.ui = device_remote_ui.Ui_Form()
113 self.ui.setupUi(self)
114
115 text = device_info["name"]
116 icon_name = icon_name_from_type(device_info["type"])
117 pixmap = pixmap_from_name(icon_name)
118 self.ui.device_icon_label.setPixmap(pixmap)
119 self.ui.device_name_label.setText(text)
120
121 def text(self):113 def text(self):
122 """Return the text displayed in the Widget."""114 """Return the text displayed in the Widget."""
123 return self.ui.device_name_label.text()115 return self.ui.device_name_label.text()
124116
125117 def clear(self):
126def get_device_for_list_widget(device_info):118 """Clear this widget's info."""
127 """Return a DeviceRemoteWidget with device proper info."""119 self.id = None
128 item = DeviceRemoteWidget(device_info)120 self.ui.device_name_label.setText('')
129 return item121
122
123class RemoteDeviceWidget(DeviceWidget):
124
125 """Remote device widget."""
126
127 def __init__(self, *args, **kwargs):
128 super(RemoteDeviceWidget, self).__init__(*args, **kwargs)
129 self.ui.remove_device_button.hide()
130130
=== modified file 'ubuntuone/controlpanel/gui/qt/devices.py'
--- ubuntuone/controlpanel/gui/qt/devices.py 2012-02-22 15:35:13 +0000
+++ ubuntuone/controlpanel/gui/qt/devices.py 2012-03-08 21:13:18 +0000
@@ -50,7 +50,7 @@
50 def _setup(self):50 def _setup(self):
51 """Do some extra setupping for the UI."""51 """Do some extra setupping for the UI."""
52 super(DevicesPanel, self)._setup()52 super(DevicesPanel, self)._setup()
53 self.ui.local_device.setTitle(DEVICES_LOCAL_LABEL)53 self.ui.local_device_box.setTitle(DEVICES_LOCAL_LABEL)
54 self.ui.other_devices.setTitle(DEVICES_REMOTE_LABEL)54 self.ui.other_devices.setTitle(DEVICES_REMOTE_LABEL)
55 self.ui.manage_devices_button.setText(DEVICES_MANAGE_LABEL)55 self.ui.manage_devices_button.setText(DEVICES_MANAGE_LABEL)
56 self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK56 self.ui.manage_devices_button.uri = EDIT_DEVICES_LINK
@@ -66,7 +66,6 @@
66 @log_call(logger.debug)66 @log_call(logger.debug)
67 def process_info(self, info):67 def process_info(self, info):
68 """Process and display the devices info."""68 """Process and display the devices info."""
69 self.clear_device_info(self.ui.local_device_box)
70 self.ui.list_devices.clear()69 self.ui.list_devices.clear()
7170
72 for device_info in info:71 for device_info in info:
@@ -76,21 +75,9 @@
7675
77 def on_local_device_removed(self):76 def on_local_device_removed(self):
78 """When the local device is removed, clear the box and emit signal."""77 """When the local device is removed, clear the box and emit signal."""
79 self.clear_device_info(self.ui.local_device_box)78 self.ui.local_device.clear()
80 self.localDeviceRemoved.emit()79 self.localDeviceRemoved.emit()
8180
82 def clear_device_info(self, box):
83 """Clear all the device info."""
84 children = box.count()
85 # we need to reverse the index list to remove children because:
86 # "Items are numbered consecutively from 0. If an item is deleted,
87 # other items will be renumbered."
88 # http://doc.qt.nokia.com/latest/qlayout.html#itemAt
89 for i in reversed(range(children)):
90 widget = box.itemAt(i).widget()
91 box.removeWidget(widget)
92 widget.deleteLater()
93
94 def update_device_info(self, device_info):81 def update_device_info(self, device_info):
95 """Update one device."""82 """Update one device."""
96 if device_info["is_local"]:83 if device_info["is_local"]:
@@ -100,15 +87,13 @@
10087
101 def update_local_device(self, device_info):88 def update_local_device(self, device_info):
102 """Update the info for the local device."""89 """Update the info for the local device."""
103 device_widget = device.DeviceWidget(device_id=device_info['device_id'])90 self.ui.local_device.update_device_info(device_info)
104 device_widget.update_device_info(device_info)91 self.ui.local_device.removed.connect(self.on_local_device_removed)
105 device_widget.removed.connect(self.on_local_device_removed)
106
107 self.ui.local_device_box.addWidget(device_widget)
10892
109 def create_remote_device(self, device_info):93 def create_remote_device(self, device_info):
110 """Add a remote device to the list."""94 """Add a remote device to the list."""
111 widget = device.get_device_for_list_widget(device_info)95 widget = device.RemoteDeviceWidget()
96 widget.update_device_info(device_info)
112 item = QtGui.QListWidgetItem()97 item = QtGui.QListWidgetItem()
11398
114 self.ui.list_devices.addItem(item)99 self.ui.list_devices.addItem(item)
115100
=== modified file 'ubuntuone/controlpanel/gui/qt/folders.py'
--- ubuntuone/controlpanel/gui/qt/folders.py 2012-02-28 17:48:23 +0000
+++ ubuntuone/controlpanel/gui/qt/folders.py 2012-03-08 21:13:18 +0000
@@ -61,6 +61,21 @@
61YES = QtGui.QMessageBox.Yes61YES = QtGui.QMessageBox.Yes
6262
6363
64class ExploreFolderButton(QtGui.QPushButton):
65 """A specialized button for the folder listing."""
66
67 def __init__(self, folder_path, parent=None):
68 super(ExploreFolderButton, self).__init__(parent=parent)
69 self.folder_path = folder_path
70 self.setText(FOLDERS_COLUMN_EXPLORE)
71 self.clicked.connect(self.on_clicked)
72
73 def on_clicked(self):
74 """Open the folder_path in the default file manager."""
75 uri = unicode(QtCore.QUrl.fromLocalFile(self.folder_path).toString())
76 uri_hook(uri)
77
78
64class FoldersPanel(UbuntuOneBin):79class FoldersPanel(UbuntuOneBin):
65 """The Folders Tab Panel widget"""80 """The Folders Tab Panel widget"""
6681
@@ -180,21 +195,9 @@
180195
181 # attach a third item with a button to explore the folder196 # attach a third item with a button to explore the folder
182 model_index = self.ui.folders.indexFromItem(child, EXPLORE_COL)197 model_index = self.ui.folders.indexFromItem(child, EXPLORE_COL)
183 button = QtGui.QPushButton(parent=self.ui.folders)198 button = ExploreFolderButton(folder_path=child.volume_path,
184 button.setFlat(True)199 parent=self.ui.folders)
185 button.setText(FOLDERS_COLUMN_EXPLORE)
186 button.setObjectName('explore_folder_button')
187 policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
188 QtGui.QSizePolicy.Fixed)
189 button.setSizePolicy(policy)
190 button.setEnabled(bool(volume[u'subscribed']))200 button.setEnabled(bool(volume[u'subscribed']))
191
192 # Operator not preceded by a space
193 # pylint: disable=C0322
194 cb = lambda checked, item=child: \
195 self.on_folders_itemActivated(item)
196 # pylint: enable=C0322
197 button.clicked.connect(cb)
198 self.ui.folders.setIndexWidget(model_index, button)201 self.ui.folders.setIndexWidget(model_index, button)
199202
200 self.ui.folders.expandAll()203 self.ui.folders.expandAll()
201204
=== modified file 'ubuntuone/controlpanel/gui/qt/loadingoverlay.py'
--- ubuntuone/controlpanel/gui/qt/loadingoverlay.py 2012-02-22 17:04:28 +0000
+++ ubuntuone/controlpanel/gui/qt/loadingoverlay.py 2012-03-08 21:13:18 +0000
@@ -45,11 +45,7 @@
45 self.counter = 045 self.counter = 0
46 self.orientation = False46 self.orientation = False
4747
48 # The following is a hack to avoid having the faked self.ui failing48 self.ui.label.setText(LOADING_OVERLAY)
49 # with AttributeError in the tests. We need to improve the fake so we
50 # don't leak this to the production code.
51 if getattr(self.ui, 'label', None) is not None:
52 self.ui.label.setText(LOADING_OVERLAY)
5349
54 # Invalid name "paintEvent"50 # Invalid name "paintEvent"
55 # pylint: disable=C010351 # pylint: disable=C0103
5652
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py'
--- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-03-02 13:53:24 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-03-08 21:13:18 +0000
@@ -96,6 +96,7 @@
96 """A fake Ui object."""96 """A fake Ui object."""
9797
98 exposed_methods = ['setupUi']98 exposed_methods = ['setupUi']
99 raise_attr_error = False
99100
100101
101class FakedControlPanelBackend(FakedObject):102class FakedControlPanelBackend(FakedObject):
102103
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_device.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_device.py 2012-03-01 22:05:51 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_device.py 2012-03-08 21:13:18 +0000
@@ -1,8 +1,6 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2
3# Author: Alejandro J. Cura <alecu@canonical.com>
4#2#
5# Copyright 2011 Canonical Ltd.3# Copyright 2011-2012 Canonical Ltd.
6#4#
7# This program is free software: you can redistribute it and/or modify it5# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published6# under the terms of the GNU General Public License version 3, as published
@@ -36,7 +34,7 @@
3634
3735
38class DeviceWidgetTestCase(BaseTestCase):36class DeviceWidgetTestCase(BaseTestCase):
39 """Test the qt control panel."""37 """Test the DeviceWidget class."""
4038
41 innerclass_ui = gui.device_ui39 innerclass_ui = gui.device_ui
42 innerclass_name = "Ui_Form"40 innerclass_name = "Ui_Form"
@@ -46,9 +44,28 @@
46 logger = gui.logger44 logger = gui.logger
4745
48 def test_has_id(self):46 def test_has_id(self):
49 """The device as an id, None by default."""47 """The device as an id accepted as creation param."""
50 self.assertEqual(self.ui.id, self.device_id)48 self.assertEqual(self.ui.id, self.device_id)
5149
50 def test_id_can_be_none(self):
51 """The device id is None by default."""
52 ui = self.class_ui()
53 self.assertEqual(ui.id, None)
54
55 def test_setting_id_to_none_disables_remove_button(self):
56 """If the id is set to None, the remove button is disabled."""
57 self.ui.id = None
58 self.assertFalse(self.ui.ui.remove_device_button.isEnabled())
59
60 def test_setting_id_to_not_none_enables_remove_button(self):
61 """If the id is set to not None, the remove button is enabled."""
62 self.ui.id = 'not None'
63 self.assertTrue(self.ui.ui.remove_device_button.isEnabled())
64
65 def test_remove_button(self):
66 """The remove button is visible."""
67 self.assertTrue(self.ui.ui.remove_device_button.isVisible())
68
52 def test_update_device_info(self):69 def test_update_device_info(self):
53 """The widget is updated with the info."""70 """The widget is updated with the info."""
54 info = SAMPLE_COMPUTER_INFO71 info = SAMPLE_COMPUTER_INFO
@@ -68,7 +85,7 @@
68 self.assertIconMatchesType(gui.DEVICE_TYPE_PHONE, gui.PHONE_ICON)85 self.assertIconMatchesType(gui.DEVICE_TYPE_PHONE, gui.PHONE_ICON)
69 self.assertIconMatchesType("other random type", gui.COMPUTER_ICON)86 self.assertIconMatchesType("other random type", gui.COMPUTER_ICON)
7087
71 def _test_update_device_info_sets_right_icon(self, info):88 def assert_update_device_info_sets_right_icon(self, info):
72 """The widget is updated with the right icon."""89 """The widget is updated with the right icon."""
73 self.ui.update_device_info(info)90 self.ui.update_device_info(info)
74 pixmap_name = gui.icon_name_from_type(info["type"])91 pixmap_name = gui.icon_name_from_type(info["type"])
@@ -78,21 +95,11 @@
7895
79 def test_update_device_info_sets_computer_icon(self):96 def test_update_device_info_sets_computer_icon(self):
80 """The computer icon is set."""97 """The computer icon is set."""
81 self._test_update_device_info_sets_right_icon(SAMPLE_COMPUTER_INFO)98 self.assert_update_device_info_sets_right_icon(SAMPLE_COMPUTER_INFO)
8299
83 def test_update_device_info_sets_phone_icon(self):100 def test_update_device_info_sets_phone_icon(self):
84 """The phone icon is set."""101 """The phone icon is set."""
85 self._test_update_device_info_sets_right_icon(SAMPLE_PHONE_INFO)102 self.assert_update_device_info_sets_right_icon(SAMPLE_PHONE_INFO)
86
87 def test_get_device_for_list_widget(self):
88 """The the item list values returned."""
89 info = SAMPLE_COMPUTER_INFO
90 item = gui.get_device_for_list_widget(info)
91 self.assertEqual(item.text(), info["name"])
92
93 info = SAMPLE_PHONE_INFO
94 item = gui.get_device_for_list_widget(info)
95 self.assertEqual(item.text(), info["name"])
96103
97104
98class RemoveDeviceTestCase(DeviceWidgetTestCase):105class RemoveDeviceTestCase(DeviceWidgetTestCase):
@@ -161,3 +168,13 @@
161 yield self.ui.ui.remove_device_button.click()168 yield self.ui.ui.remove_device_button.click()
162169
163 self.assertTrue(self.memento.check_exception(CrashyBackendException))170 self.assertTrue(self.memento.check_exception(CrashyBackendException))
171
172
173class RemoteDeviceWidgetTestCase(DeviceWidgetTestCase):
174 """Test the RemoteDeviceWidget class."""
175
176 class_ui = gui.RemoteDeviceWidget
177
178 def test_remove_button(self):
179 """The remove button is hidden."""
180 self.assertFalse(self.ui.ui.remove_device_button.isVisible())
164181
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_devices.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2012-03-01 22:05:51 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_devices.py 2012-03-08 21:13:18 +0000
@@ -1,8 +1,6 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2
3# Author: Alejandro J. Cura <alecu@canonical.com>
4#2#
5# Copyright 2011 Canonical Ltd.3# Copyright 2011-2012 Canonical Ltd.
6#4#
7# This program is free software: you can redistribute it and/or modify it5# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published6# under the terms of the GNU General Public License version 3, as published
@@ -63,7 +61,6 @@
63 def test_no_devices_at_startup(self):61 def test_no_devices_at_startup(self):
64 """The UI is reset at startup."""62 """The UI is reset at startup."""
65 self.assertEqual(self.ui.ui.list_devices.count(), 0)63 self.assertEqual(self.ui.ui.list_devices.count(), 0)
66 self.assertEqual(self.ui.ui.local_device_box.count(), 0)
6764
68 def test_process_info(self):65 def test_process_info(self):
69 """The widget is updated with the info."""66 """The widget is updated with the info."""
@@ -71,10 +68,8 @@
7168
72 local, remote = SAMPLE_DEVICES_INFO[0], SAMPLE_DEVICES_INFO[1:]69 local, remote = SAMPLE_DEVICES_INFO[0], SAMPLE_DEVICES_INFO[1:]
7370
74 self.assertEqual(self.ui.ui.local_device_box.count(), 1)71 local_device = self.ui.ui.local_device
75 local_device = self.ui.ui.local_device_box.itemAt(0).widget()72 self.assertEqual(local_device.text(), local['name'])
76 self.assertEqual(local_device.ui.device_name_label.text(),
77 local['name'])
78 self.assertEqual(local_device.id, local['device_id'])73 self.assertEqual(local_device.id, local['device_id'])
7974
80 self.assertEqual(self.ui.ui.list_devices.count(),75 self.assertEqual(self.ui.ui.list_devices.count(),
@@ -84,26 +79,12 @@
84 device = self.ui.ui.list_devices.itemWidget(item)79 device = self.ui.ui.list_devices.itemWidget(item)
85 self.assertEqual(device.text(), remote_device['name'])80 self.assertEqual(device.text(), remote_device['name'])
8681
87 def test_remove_device_and_check_layout_state(self):82 def test_local_device(self):
88 """Test if the widget is properly removed."""83 """Test if the local_device widget is properly packed."""
89 self.ui.process_info(SAMPLE_DEVICES_INFO)84 self.ui.process_info(SAMPLE_DEVICES_INFO)
90 self.ui.show()85
9186 local_device = self.ui.ui.local_device_layout.itemAt(0).widget()
92 self.assertEqual(self.ui.ui.local_device_box.count(), 1)87 self.assertIs(local_device, self.ui.ui.local_device)
93 local_device = self.ui.ui.local_device_box.itemAt(0).widget()
94 self.executed = False
95
96 def delete_later(reference=None):
97 """Fake delete later."""
98 self.executed = True
99 self.patch(local_device, "deleteLater", delete_later)
100 self.ui.clear_device_info(self.ui.ui.local_device_box)
101 self.ui.process_info(SAMPLE_DEVICES_INFO)
102 self.assertEqual(self.ui.ui.local_device_box.count(), 1)
103 local_device2 = self.ui.ui.local_device_box.itemAt(0).widget()
104 self.assertNotEqual(local_device, local_device2)
105 self.assertTrue(self.executed)
106 self.assertFalse(local_device.isVisible())
10788
108 def test_process_info_twice(self):89 def test_process_info_twice(self):
109 """The widget is updated with the info."""90 """The widget is updated with the info."""
@@ -115,21 +96,20 @@
115 self.assert_uri_hook_called(self.ui.ui.manage_devices_button,96 self.assert_uri_hook_called(self.ui.ui.manage_devices_button,
116 gui.EDIT_DEVICES_LINK)97 gui.EDIT_DEVICES_LINK)
11798
118 def test_remove_device_widget_after_removal(self):99 def test_local_device_removed_clears_the_widget(self):
119 """When a device widget was deleted, remove it from the UI."""100 """When the local device was deleted, clear it."""
120 self.ui.process_info(SAMPLE_DEVICES_INFO)101 self.ui.process_info(SAMPLE_DEVICES_INFO)
121102
122 local_device = self.ui.ui.local_device_box.itemAt(0).widget()103 self.ui.ui.local_device.removed.emit()
123 local_device.removed.emit()
124104
125 self.assertTrue(self.ui.ui.local_device_box.itemAt(0) is None)105 self.assertEqual(self.ui.ui.local_device.text(), '')
106 self.assertEqual(self.ui.ui.local_device.id, None)
126107
127 def test_local_device_removed_signal(self):108 def test_local_device_removed_signal(self):
128 """When the local device is removed, emit localDeviceRemoved signal."""109 """When the local device is removed, emit localDeviceRemoved signal."""
129 self.ui.localDeviceRemoved.connect(self._set_called)110 self.ui.localDeviceRemoved.connect(self._set_called)
130 self.ui.process_info(SAMPLE_DEVICES_INFO)111 self.ui.process_info(SAMPLE_DEVICES_INFO)
131112
132 local_device = self.ui.ui.local_device_box.itemAt(0).widget()113 self.ui.ui.local_device.removed.emit()
133 local_device.removed.emit()
134114
135 self.assertEqual(self._called, ((), {}))115 self.assertEqual(self._called, ((), {}))
136116
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-02 16:56:10 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-08 21:13:18 +0000
@@ -1,8 +1,6 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2
3# Authors: Natalia B Bidart <natalia.bidart@canonical.com>
4#2#
5# Copyright 2011 Canonical Ltd.3# Copyright 2011-2012 Canonical Ltd.
6#4#
7# This program is free software: you can redistribute it and/or modify it5# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published6# under the terms of the GNU General Public License version 3, as published
@@ -33,6 +31,7 @@
33)31)
34from ubuntuone.controlpanel.gui.qt import folders as gui32from ubuntuone.controlpanel.gui.qt import folders as gui
35from ubuntuone.controlpanel.gui.qt.tests import (33from ubuntuone.controlpanel.gui.qt.tests import (
34 BaseTestCase,
36 FakedDialog,35 FakedDialog,
37)36)
38from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (37from ubuntuone.controlpanel.gui.qt.tests.test_ubuntuonebin import (
@@ -54,6 +53,26 @@
54 return name53 return name
5554
5655
56class ExploreFolderButtonTestCase(BaseTestCase):
57 """Test the ExploreFolderButton widget."""
58
59 class_ui = gui.ExploreFolderButton
60 kwargs = dict(folder_path=u'foo')
61
62 def test_text(self):
63 """The button text is correct."""
64 self.assertEqual(self.ui.text(), gui.FOLDERS_COLUMN_EXPLORE)
65
66 def test_clicked(self):
67 """Clicking the button opens the folder in the default file manager."""
68 self.patch(gui, 'uri_hook', self._set_called)
69 self.ui.click()
70
71 url = gui.QtCore.QUrl.fromLocalFile(self.kwargs['folder_path'])
72 expected = unicode(url.toString())
73 self.assertEqual(self._called, ((expected,), {}))
74
75
57class FoldersPanelTestCase(UbuntuOneBinTestCase):76class FoldersPanelTestCase(UbuntuOneBinTestCase):
58 """Test the qt cloud folders tab."""77 """Test the qt cloud folders tab."""
5978
@@ -173,7 +192,6 @@
173 # explore button is in place192 # explore button is in place
174 model_index = folders.indexFromItem(item, gui.EXPLORE_COL)193 model_index = folders.indexFromItem(item, gui.EXPLORE_COL)
175 button = folders.indexWidget(model_index)194 button = folders.indexWidget(model_index)
176 self.assertEqual(button.isFlat(), True)
177 self.assertEqual(button.isEnabled(),195 self.assertEqual(button.isEnabled(),
178 bool(volume['subscribed']))196 bool(volume['subscribed']))
179197
180198
=== modified file 'ubuntuone/controlpanel/gui/tests/__init__.py'
--- ubuntuone/controlpanel/gui/tests/__init__.py 2012-03-02 21:21:03 +0000
+++ ubuntuone/controlpanel/gui/tests/__init__.py 2012-03-08 21:13:18 +0000
@@ -134,6 +134,7 @@
134 next_result = None134 next_result = None
135 exposed_methods = []135 exposed_methods = []
136 exposed_results = {}136 exposed_results = {}
137 raise_attr_error = True
137138
138 def __init__(self, *args, **kwargs):139 def __init__(self, *args, **kwargs):
139 self._args = args140 self._args = args
@@ -142,6 +143,23 @@
142 for i in self.exposed_methods:143 for i in self.exposed_methods:
143 setattr(self, i, self._record_call(i))144 setattr(self, i, self._record_call(i))
144145
146 def __call__(self, *args, **kwargs):
147 """Skip."""
148
149 def __getattribute__(self, attr_name):
150 super_getattr = super(FakedObject, self).__getattribute__
151
152 try:
153 result = super_getattr(attr_name)
154 except AttributeError:
155 if super_getattr('raise_attr_error'):
156 raise
157 else:
158 result = FakedObject()
159 result.raise_attr_error = super_getattr('raise_attr_error')
160
161 return result
162
145 def _record_call(self, func_name):163 def _record_call(self, func_name):
146 """Store values when calling 'func_name'."""164 """Store values when calling 'func_name'."""
147165

Subscribers

People subscribed via source and target branches