Merge lp:~elachuni/software-center/any-language into lp:software-center

Proposed by Anthony Lenton
Status: Merged
Merged at revision: 2664
Proposed branch: lp:~elachuni/software-center/any-language
Merge into: lp:software-center
Diff against target: 189 lines (+93/-30)
2 files modified
softwarecenter/ui/gtk3/widgets/reviews.py (+25/-19)
test/gtk3/test_widgets.py (+68/-11)
To merge this branch: bzr merge lp:~elachuni/software-center/any-language
Reviewer Review Type Date Requested Status
Michael Vogt Approve
Review via email: mp+88877@code.launchpad.net

Description of the change

Overview
========
This branch adds an 'Any language' option to the review language dropdown

Details
=======
At the same time I removed the "Show reviews in English" button as it becomes redundant as users can select to display reviews in any language.

The big plan is that, once users can choose to display reviews in any language, and we always fall back to fetch reviews for older versions, the number of reported ratings and visible reviews will match.

Some tests were added for the review list widget, so I split that out into its own test case.

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) wrote :

Thanks! This looks very good, especially the tests are done in a nice and elegant way. Quite impressive.

While working at this code it would be great to extend the combobox to have not only "en" but a proper
mapping from /usr/share/xml/iso-codes/iso_639_3.xml short ids to language names (including translations
via dgettext("iso_639_3", language_name).

But that is of course not relevant to the MP at hand which looks great.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'softwarecenter/ui/gtk3/widgets/reviews.py'
--- softwarecenter/ui/gtk3/widgets/reviews.py 2011-11-25 12:10:05 +0000
+++ softwarecenter/ui/gtk3/widgets/reviews.py 2012-01-17 15:53:18 +0000
@@ -130,6 +130,7 @@
130 self.review_language = Gtk.ComboBoxText.new()130 self.review_language = Gtk.ComboBoxText.new()
131 for lang in get_languages():131 for lang in get_languages():
132 self.review_language.append_text(lang)132 self.review_language.append_text(lang)
133 self.review_language.append_text(_('Any language'))
133 self.review_language.set_active(0)134 self.review_language.set_active(0)
134 self.review_language.connect(135 self.review_language.connect(
135 "changed", self._on_different_review_language_clicked)136 "changed", self._on_different_review_language_clicked)
@@ -269,23 +270,15 @@
269 self.new_review.set_label(_("Write your own review"))270 self.new_review.set_label(_("Write your own review"))
270 else:271 else:
271 # no reviews, either offer to write one or show "none"272 # no reviews, either offer to write one or show "none"
272 if is_installed and is_connected:273 if (self.get_active_review_language() != 'any' and
274 self.global_review_stats and
275 self.global_review_stats.ratings_total > 0):
276 self.vbox.pack_start(NoReviewRelaxLanguage(), True, True, 0)
277 elif is_installed and is_connected:
273 self._be_the_first_to_review()278 self._be_the_first_to_review()
274 else:279 else:
275 self.vbox.pack_start(NoReviewYet(), True, True, 0)280 self.vbox.pack_start(NoReviewYet(), True, True, 0)
276281
277 # if there are no reviews, try english as fallback
278 language = get_language()
279 if (len(self.reviews) == 0 and
280 self.global_review_stats and
281 self.global_review_stats.ratings_total > 0 and
282 language != "en"):
283 button = Gtk.Button(_("Show reviews in english"))
284 button.connect(
285 "clicked", self._on_show_reviews_in_english_clicked)
286 button.show()
287 self.vbox.pack_start(button, True, True, 0)
288
289 # aaronp: removed check to see if the length of reviews is divisible by282 # aaronp: removed check to see if the length of reviews is divisible by
290 # the batch size to allow proper fixing of LP: #794060 as when a review283 # the batch size to allow proper fixing of LP: #794060 as when a review
291 # is submitted and appears in the list, the pagination will break this284 # is submitted and appears in the list, the pagination will break this
@@ -307,17 +300,18 @@
307 self.vbox.remove(button)300 self.vbox.remove(button)
308 self.emit("more-reviews-clicked")301 self.emit("more-reviews-clicked")
309302
310 def _on_show_reviews_in_english_clicked(self, button):
311 self.vbox.remove(button)
312 self.emit("different-review-language-clicked", "en")
313
314 def _on_different_review_language_clicked(self, combo):303 def _on_different_review_language_clicked(self, combo):
315 # and set them304 language = self.get_active_review_language()
316 language = combo.get_active_text()
317 # clean reviews so that we can show the new language305 # clean reviews so that we can show the new language
318 self.clear()306 self.clear()
319 self.emit("different-review-language-clicked", language)307 self.emit("different-review-language-clicked", language)
320308
309 def get_active_review_language(self):
310 language = self.review_language.get_active_text()
311 if language == _('Any language'):
312 language = 'any'
313 return language
314
321 def get_all_review_ids(self):315 def get_all_review_ids(self):
322 ids = []316 ids = []
323 for review in self.reviews:317 for review in self.reviews:
@@ -889,6 +883,18 @@
889 return883 return
890884
891885
886class NoReviewRelaxLanguage(EmbeddedMessage):
887 """ represents if there are no reviews yet and the app is not installed """
888 def __init__(self, *args, **kwargs):
889 # TRANSLATORS: displayed if there are no reviews for the app in
890 # the current language, but there are some in other
891 # languages
892 title = _("This app has not been reviewed yet in your language")
893 msg = _('Try selecting a different language, or even "Any language"'
894 ' in the language dropdown')
895 EmbeddedMessage.__init__(self, title, msg)
896
897
892class NoReviewYet(EmbeddedMessage):898class NoReviewYet(EmbeddedMessage):
893 """ represents if there are no reviews yet and the app is not installed """899 """ represents if there are no reviews yet and the app is not installed """
894 def __init__(self, *args, **kwargs):900 def __init__(self, *args, **kwargs):
895901
=== modified file 'test/gtk3/test_widgets.py'
--- test/gtk3/test_widgets.py 2012-01-16 14:42:49 +0000
+++ test/gtk3/test_widgets.py 2012-01-17 15:53:18 +0000
@@ -3,11 +3,13 @@
3from gi.repository import Gtk, GdkPixbuf, GObject3from gi.repository import Gtk, GdkPixbuf, GObject
4import os4import os
5import unittest5import unittest
66from gettext import gettext as _
7from mock import Mock7
88from mock import Mock, patch
9from testutils import setup_test_env9
10from testutils import setup_test_env, do_events
10setup_test_env()11setup_test_env()
12from softwarecenter.ui.gtk3.widgets.reviews import get_test_reviews_window
1113
1214
13# window destory timeout15# window destory timeout
@@ -76,12 +78,6 @@
76 GObject.timeout_add(TIMEOUT, lambda: d.destroy())78 GObject.timeout_add(TIMEOUT, lambda: d.destroy())
77 d.run()79 d.run()
7880
79 def test_reviews(self):
80 from softwarecenter.ui.gtk3.widgets.reviews import get_test_reviews_window
81 win = get_test_reviews_window()
82 GObject.timeout_add(TIMEOUT, lambda: win.destroy())
83 Gtk.main()
84
85 def test_searchentry(self):81 def test_searchentry(self):
86 from softwarecenter.ui.gtk3.widgets.searchentry import get_test_searchentry_window82 from softwarecenter.ui.gtk3.widgets.searchentry import get_test_searchentry_window
87 win = get_test_searchentry_window()83 win = get_test_searchentry_window()
@@ -127,7 +123,68 @@
127 GObject.timeout_add(TIMEOUT, lambda: win.destroy())123 GObject.timeout_add(TIMEOUT, lambda: win.destroy())
128 Gtk.main()124 Gtk.main()
129125
130 126
127class TestUIReviewsList(unittest.TestCase):
128 def setUp(self):
129 self.win = get_test_reviews_window()
130 self.rl = self.win.get_children()[0]
131
132 def tearDown(self):
133 GObject.timeout_add(TIMEOUT, lambda: self.win.destroy())
134 Gtk.main()
135
136 def assertComboBoxTextIncludes(self, combo, option):
137 store = combo.get_model()
138 self.assertTrue(option in [x[0] for x in store])
139
140 def assertEmbeddedMessageLabel(self, title, message):
141 markup = self.rl.vbox.get_children()[1].label.get_label()
142 self.assertTrue(title in markup)
143 self.assertTrue(message in markup)
144
145 def test_reviews_includes_any_language(self):
146 review_language = self.rl.review_language
147 self.assertComboBoxTextIncludes(review_language, _('Any language'))
148
149 def test_reviews_offers_to_relax_language(self):
150 # No reviews found, but there are some in other languages:
151 self.rl.clear()
152 self.rl.global_review_stats = Mock()
153 self.rl.global_review_stats.ratings_total = 4
154 self.rl.configure_reviews_ui()
155 do_events()
156
157 self.assertEmbeddedMessageLabel(
158 _("This app has not been reviewed yet in your language"),
159 _('Try selecting a different language, or even "Any language"'
160 ' in the language dropdown'))
161
162 @patch('softwarecenter.ui.gtk3.widgets.reviews.network_state_is_connected')
163 def test_reviews_no_reviews_but_app_not_installed(self, mock_connected):
164 mock_connected.return_value = True
165 # No reviews found, and the app isn't installed
166 self.rl.clear()
167 self.rl.configure_reviews_ui()
168 do_events()
169
170 self.assertEmbeddedMessageLabel(
171 _("This app has not been reviewed yet"),
172 _('You need to install this before you can review it'))
173
174 @patch('softwarecenter.ui.gtk3.widgets.reviews.network_state_is_connected')
175 def test_reviews_no_reviews_offer_to_write_one(self, mock_connected):
176 from softwarecenter.enums import PkgStates
177 mock_connected.return_value = True
178 # No reviews found, and the app is installed
179 self.rl.clear()
180 self.rl._parent.app_details.pkg_state = PkgStates.INSTALLED
181 self.rl.configure_reviews_ui()
182 do_events()
183
184 self.assertEmbeddedMessageLabel(
185 _('Got an opinion?'),
186 _('Be the first to contribute a review for this application'))
187
131188
132if __name__ == "__main__":189if __name__ == "__main__":
133 import logging190 import logging