Merge lp:~ralsina/ubuntuone-control-panel/tab-tab-tab into lp:ubuntuone-control-panel

Proposed by Roberto Alsina
Status: Merged
Approved by: Roberto Alsina
Approved revision: 291
Merged at revision: 283
Proposed branch: lp:~ralsina/ubuntuone-control-panel/tab-tab-tab
Merge into: lp:ubuntuone-control-panel
Diff against target: 239 lines (+107/-16)
2 files modified
ubuntuone/controlpanel/gui/qt/folders.py (+53/-9)
ubuntuone/controlpanel/gui/qt/tests/test_folders.py (+54/-7)
To merge this branch: bzr merge lp:~ralsina/ubuntuone-control-panel/tab-tab-tab
Reviewer Review Type Date Requested Status
Diego Sarmentero (community) Approve
Natalia Bidart (community) Approve
Review via email: mp+96687@code.launchpad.net

Commit message

- Arranged Tab ordering in folders tab according to guidelines (LP: #950073).

Description of the change

- Arranged Tab ordering in folders tab according to guidelines (LP: #950073).

To post a comment you must log in.
287. By Roberto Alsina

merged trunk

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

* I think this code is a leftover from the merge with trunk, but it should be removed:

                # Operator not preceded by a space
                # pylint: disable=C0322
                cb = lambda checked, item=child: \
                    self.on_folders_itemActivated(item)
                # pylint: enable=C0322
                button.clicked.connect(cb)

* Question, why are you adding self.is_processing = True? that code triggers the showing of the loading overlay which is already being shown in load() and hidden in the line 145 of process_info.

* In test_focus_order, could you please not use literal but the value from the FAKE_VOLUMES_INFO stub data? Ideally you should iterate the FAKE_VOLUMES_INFO so if we change it to add a specific buggy entry, this test does not break.

* Any reason to use this style?

                self.assertEqual(self.ui.widget_items[button],
                item)

instead of:

                self.assertEqual(self.ui.widget_items[button], item)

since line length allows it to be like the second form.

After testing IRL, it works great! (tough because the leftover callback, the file manager is opened twice).

review: Needs Fixing
288. By Roberto Alsina

removed remnant

289. By Roberto Alsina

removed remnant, extra guard, style fix

Revision history for this message
Roberto Alsina (ralsina) wrote :

> * I think this code is a leftover from the merge with trunk, but it should be
> removed:
>
> # Operator not preceded by a space
> # pylint: disable=C0322
> cb = lambda checked, item=child: \
> self.on_folders_itemActivated(item)
> # pylint: enable=C0322
> button.clicked.connect(cb)

Yes, bad merge with no conflict warning, will remove.

> * Question, why are you adding self.is_processing = True? that code triggers
> the showing of the loading overlay which is already being shown in load() and
> hidden in the line 145 of process_info.

I was getting weird stuff when not setting that.Turns out I was missing a guard in on_folders_itemChanged instead.

> * In test_focus_order, could you please not use literal but the value from the
> FAKE_VOLUMES_INFO stub data? Ideally you should iterate the FAKE_VOLUMES_INFO
> so if we change it to add a specific buggy entry, this test does not break.

Tricky. The items are not in the same order in FAKE_VOLUMES_INFO and in the widget, so any change in FAKE_VOLUMES_INFO can change what we get in test_focus_order. I could do a loop, over a VOLUMES_INFO
that was sorted, and not use FAKE_VOLUMES_INFO.

>
> * Any reason to use this style?
>
> self.assertEqual(self.ui.widget_items[button],
> item)
>
> instead of:
>
> self.assertEqual(self.ui.widget_items[button], item)
>
> since line length allows it to be like the second form.

It used to be longer ;-)

I pushed the suggested changes (except for the FAKE_VOLUMES_INFO loop one) in revno 289.

290. By Roberto Alsina

removed commented code

291. By Roberto Alsina

removed useless line

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Looks good!

review: Approve
Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ubuntuone/controlpanel/gui/qt/folders.py'
--- ubuntuone/controlpanel/gui/qt/folders.py 2012-03-09 17:11:54 +0000
+++ ubuntuone/controlpanel/gui/qt/folders.py 2012-03-12 14:58:17 +0000
@@ -81,6 +81,7 @@
8181
82 ui_class = folders_ui82 ui_class = folders_ui
83 logger = logger83 logger = logger
84 widget_items = {}
8485
85 def _setup(self):86 def _setup(self):
86 """Do some extra setupping for the UI."""87 """Do some extra setupping for the UI."""
@@ -101,6 +102,14 @@
101 self.ui.share_publish_button.uri = MANAGE_FILES_LINK102 self.ui.share_publish_button.uri = MANAGE_FILES_LINK
102 icon = icon_from_name('external_icon_orange')103 icon = icon_from_name('external_icon_orange')
103 self.ui.share_publish_button.setIcon(icon)104 self.ui.share_publish_button.setIcon(icon)
105 QtGui.QApplication.instance().focusChanged.connect(self.focus_changed)
106
107 def focus_changed(self, old, new):
108 """When a inner widget is focused, scroll to its item."""
109 item = self.widget_items.get(new, None)
110 if item is not None:
111 self.ui.folders.scrollToItem(item)
112 self.ui.folders.setCurrentItem(item)
104113
105 @log_call(logger.info)114 @log_call(logger.info)
106 def on_folder_created(self, new_folder):115 def on_folder_created(self, new_folder):
@@ -132,6 +141,7 @@
132 # the code would be much more complicated.141 # the code would be much more complicated.
133 scrollbar_position = self.ui.folders.verticalScrollBar().value()142 scrollbar_position = self.ui.folders.verticalScrollBar().value()
134 self.ui.folders.clear()143 self.ui.folders.clear()
144 self.widget_items = {}
135 self.is_processing = False145 self.is_processing = False
136146
137 for name, _, volumes in info: # ignore free_bytes147 for name, _, volumes in info: # ignore free_bytes
@@ -177,32 +187,63 @@
177 icon_name = MUSIC_ICON_NAME187 icon_name = MUSIC_ICON_NAME
178188
179 icon = icon_from_name(icon_name)189 icon = icon_from_name(icon_name)
190 child.icon_obj = icon # hack!
191 child.setIcon(FOLDER_NAME_COL, icon)
192 item.addChild(child)
180193
181 if is_root:194 if is_root:
182 child.setText(SUBSCRIPTION_COL, ALWAYS_SUBSCRIBED)195 child.setText(SUBSCRIPTION_COL, ALWAYS_SUBSCRIBED)
183 else: # set check state196 else: # set check state
197 # We are using an embedded checkbox instead of the
198 # item's checkState, because of focus and navigation
199 # issues.
200 checkbox = QtGui.QCheckBox(parent=self.ui.folders)
201 self.widget_items[checkbox] = child
184 if bool(volume[u'subscribed']):202 if bool(volume[u'subscribed']):
185 child.setCheckState(SUBSCRIPTION_COL, CHECKED)203 checkbox.setCheckState(CHECKED)
186 else:204 else:
187 child.setCheckState(SUBSCRIPTION_COL, UNCHECKED)205 checkbox.setCheckState(UNCHECKED)
188 pixmap = icon.pixmap(24, icon.Disabled, icon.Off)206 pixmap = icon.pixmap(24, icon.Disabled, icon.Off)
189 icon = QtGui.QIcon(pixmap)207 icon = QtGui.QIcon(pixmap)
190 icon.icon_name = icon_name208 icon.icon_name = icon_name
191209 self.ui.folders.setItemWidget(child, SUBSCRIPTION_COL,
192 child.icon_obj = icon # hack!210 checkbox)
193 child.setIcon(FOLDER_NAME_COL, icon)211
194 item.addChild(child)212 # Operator not preceded by a space
213 # pylint: disable=C0322
214 cb = lambda checked, item=child: \
215 self.on_folders_itemChanged(item, SUBSCRIPTION_COL)
216 # pylint: enable=C0322
217
218 checkbox.stateChanged.connect(cb)
195219
196 # attach a third item with a button to explore the folder220 # attach a third item with a button to explore the folder
197 model_index = self.ui.folders.indexFromItem(child, EXPLORE_COL)
198 button = ExploreFolderButton(folder_path=child.volume_path,221 button = ExploreFolderButton(folder_path=child.volume_path,
199 parent=self.ui.folders)222 parent=self.ui.folders)
223 self.widget_items[button] = child
200 button.setEnabled(bool(volume[u'subscribed']))224 button.setEnabled(bool(volume[u'subscribed']))
201 self.ui.folders.setIndexWidget(model_index, button)225 self.ui.folders.setItemWidget(child, EXPLORE_COL, button)
202226
203 self.ui.folders.expandAll()227 self.ui.folders.expandAll()
204 self.ui.folders.verticalScrollBar().setValue(scrollbar_position)228 self.ui.folders.verticalScrollBar().setValue(scrollbar_position)
205229
230 # Rearrange the focus chain so that explore buttons
231 # and checkboxes are right after ui.folders, and in
232 # the displayed order.
233 previous_widget = self.ui.folders
234 it = QtGui.QTreeWidgetItemIterator(self.ui.folders)
235 while it.value():
236 item = it.value()
237 checkbox = self.ui.folders.itemWidget(item, SUBSCRIPTION_COL)
238 button = self.ui.folders.itemWidget(item, EXPLORE_COL)
239 if checkbox:
240 QtGui.QWidget.setTabOrder(previous_widget, checkbox)
241 previous_widget = checkbox
242 if button:
243 QtGui.QWidget.setTabOrder(previous_widget, button)
244 previous_widget = button
245 it += 1
246
206 # Invalid name "on_folders_itemActivated", "on_folders_itemChanged"247 # Invalid name "on_folders_itemActivated", "on_folders_itemChanged"
207 # pylint: disable=C0103248 # pylint: disable=C0103
208249
@@ -233,7 +274,10 @@
233 # ignore signals when the UI is being updated274 # ignore signals when the UI is being updated
234 return275 return
235276
236 subscribed = item.checkState(SUBSCRIPTION_COL) == CHECKED # new state277 checkbox = self.ui.folders.itemWidget(item, SUBSCRIPTION_COL)
278 if not checkbox:
279 return
280 subscribed = checkbox.checkState() == CHECKED # new state
237 logger.info('on_folders_itemChanged: processing volume id %r with '281 logger.info('on_folders_itemChanged: processing volume id %r with '
238 'path %r, new subscribed value is: %r. Path exists? %r',282 'path %r, new subscribed value is: %r. Path exists? %r',
239 volume_id, volume_path, subscribed,283 volume_id, volume_path, subscribed,
240284
=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_folders.py'
--- ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-08 20:46:13 +0000
+++ ubuntuone/controlpanel/gui/qt/tests/test_folders.py 2012-03-12 14:58:17 +0000
@@ -20,6 +20,7 @@
20import operator20import operator
21import os21import os
2222
23from PyQt4 import QtGui
23from twisted.internet import defer24from twisted.internet import defer
24from ubuntuone.devtools.handlers import MementoHandler25from ubuntuone.devtools.handlers import MementoHandler
2526
@@ -38,7 +39,6 @@
38 UbuntuOneBinTestCase,39 UbuntuOneBinTestCase,
39)40)
4041
41
42# Access to a protected member42# Access to a protected member
43# Instance of 'ControlBackend' has no '_called' member43# Instance of 'ControlBackend' has no '_called' member
44# pylint: disable=W0212, E110344# pylint: disable=W0212, E1103
@@ -171,8 +171,9 @@
171 self.assertEqual(item.text(gui.SUBSCRIPTION_COL),171 self.assertEqual(item.text(gui.SUBSCRIPTION_COL),
172 gui.ALWAYS_SUBSCRIBED)172 gui.ALWAYS_SUBSCRIBED)
173 else:173 else:
174 subscribed = item.checkState(gui.SUBSCRIPTION_COL) == \174 checkbox = self.ui.ui.folders.itemWidget(
175 gui.CHECKED175 item, gui.SUBSCRIPTION_COL)
176 subscribed = checkbox.checkState() == gui.CHECKED
176 self.assertEqual(subscribed, bool(volume['subscribed']))177 self.assertEqual(subscribed, bool(volume['subscribed']))
177178
178 icon_name = item.icon_obj.icon_name179 icon_name = item.icon_obj.icon_name
@@ -321,7 +322,8 @@
321 label = item.text(gui.FOLDER_NAME_COL)322 label = item.text(gui.FOLDER_NAME_COL)
322 self.assertEqual(label, gui.MUSIC_DISPLAY_NAME)323 self.assertEqual(label, gui.MUSIC_DISPLAY_NAME)
323324
324 subscribed = item.checkState(gui.SUBSCRIPTION_COL) == gui.CHECKED325 checkbox = self.ui.ui.folders.itemWidget(item, gui.SUBSCRIPTION_COL)
326 subscribed = checkbox.checkState() == gui.CHECKED
325 self.assertEqual(subscribed, bool(volume['subscribed']))327 self.assertEqual(subscribed, bool(volume['subscribed']))
326328
327 icon_name = item.icon_obj.icon_name329 icon_name = item.icon_obj.icon_name
@@ -335,6 +337,45 @@
335 self.assert_uri_hook_called(self.ui.ui.share_publish_button,337 self.assert_uri_hook_called(self.ui.ui.share_publish_button,
336 gui.MANAGE_FILES_LINK)338 gui.MANAGE_FILES_LINK)
337339
340 def test_focus_order(self):
341 """Ensure that the inner widgets are in the correct tab order."""
342 self.ui.process_info(FAKE_VOLUMES_INFO)
343 # First, assert we are jumping from ui.folders to an
344 # QPushButton
345 widget = self.ui.ui.folders.nextInFocusChain()
346 self.assertIsInstance(widget, QtGui.QPushButton)
347 # Then, assert it's the right one
348 self.assertEqual(unicode(
349 self.ui.widget_items[widget].text(0)), u"My Ubuntu")
350 # Next are a checkbox / pushbutton pair
351 # in the 'bar' item
352 widget = widget.nextInFocusChain()
353 self.assertIsInstance(widget, QtGui.QCheckBox)
354 self.assertEqual(unicode(
355 self.ui.widget_items[widget].text(0)), u"bar")
356 widget = widget.nextInFocusChain()
357 self.assertIsInstance(widget, QtGui.QPushButton)
358 self.assertEqual(unicode(
359 self.ui.widget_items[widget].text(0)), u"bar")
360
361 def test_widget_dict(self):
362 """Ensure the widget_items dictionary is full."""
363 self.ui.process_info(FAKE_VOLUMES_INFO)
364 it = QtGui.QTreeWidgetItemIterator(self.ui.ui.folders)
365 while it.value():
366 item = it.value()
367 checkbox = self.ui.ui.folders.itemWidget(item,
368 gui.SUBSCRIPTION_COL)
369 button = self.ui.ui.folders.itemWidget(item,
370 gui.EXPLORE_COL)
371 if checkbox:
372 self.assertEqual(self.ui.widget_items[checkbox],
373 item)
374 if button:
375 self.assertEqual(self.ui.widget_items[button],
376 item)
377 it += 1
378
338379
339class FoldersPanelAddFolderTestCase(FoldersPanelTestCase):380class FoldersPanelAddFolderTestCase(FoldersPanelTestCase):
340 """The test suite for the folder creation from a local dir."""381 """The test suite for the folder creation from a local dir."""
@@ -389,7 +430,9 @@
389 check_state = gui.CHECKED if subscribed else gui.UNCHECKED430 check_state = gui.CHECKED if subscribed else gui.UNCHECKED
390431
391 self.ui.is_processing = True432 self.ui.is_processing = True
392 self.item.setCheckState(gui.SUBSCRIPTION_COL, check_state)433 checkbox = self.ui.ui.folders.itemWidget(self.item,
434 gui.SUBSCRIPTION_COL)
435 checkbox.setCheckState(check_state)
393 self.ui.is_processing = False436 self.ui.is_processing = False
394437
395 yield self.ui.on_folders_itemChanged(self.item)438 yield self.ui.on_folders_itemChanged(self.item)
@@ -398,7 +441,9 @@
398 self.assert_backend_called('change_volume_settings',441 self.assert_backend_called('change_volume_settings',
399 fid, {'subscribed': subscribed})442 fid, {'subscribed': subscribed})
400443
401 value = self.item.checkState(gui.SUBSCRIPTION_COL) == gui.CHECKED444 checkbox = self.ui.ui.folders.itemWidget(self.item,
445 gui.SUBSCRIPTION_COL)
446 value = checkbox.checkState() == gui.CHECKED
402 self.assertEqual(value, bool(subscribed))447 self.assertEqual(value, bool(subscribed))
403448
404 # folder list was reloaded449 # folder list was reloaded
@@ -518,7 +563,9 @@
518 """The confirmation dialog is not shown if unsubscribing."""563 """The confirmation dialog is not shown if unsubscribing."""
519 # make sure the item is unsubscribed564 # make sure the item is unsubscribed
520 self.ui.is_processing = True565 self.ui.is_processing = True
521 self.item.setCheckState(gui.SUBSCRIPTION_COL, gui.UNCHECKED)566 checkbox = self.ui.ui.folders.itemWidget(
567 self.item, gui.SUBSCRIPTION_COL)
568 checkbox.setCheckState(gui.UNCHECKED)
522 self.ui.is_processing = False569 self.ui.is_processing = False
523570
524 # the confirm dialog was not called so far571 # the confirm dialog was not called so far

Subscribers

People subscribed via source and target branches