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

Proposed by Anthony Lenton on 2012-01-17
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 2012-01-17 Approve on 2012-01-17
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.
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
1=== modified file 'softwarecenter/ui/gtk3/widgets/reviews.py'
2--- softwarecenter/ui/gtk3/widgets/reviews.py 2011-11-25 12:10:05 +0000
3+++ softwarecenter/ui/gtk3/widgets/reviews.py 2012-01-17 15:53:18 +0000
4@@ -130,6 +130,7 @@
5 self.review_language = Gtk.ComboBoxText.new()
6 for lang in get_languages():
7 self.review_language.append_text(lang)
8+ self.review_language.append_text(_('Any language'))
9 self.review_language.set_active(0)
10 self.review_language.connect(
11 "changed", self._on_different_review_language_clicked)
12@@ -269,23 +270,15 @@
13 self.new_review.set_label(_("Write your own review"))
14 else:
15 # no reviews, either offer to write one or show "none"
16- if is_installed and is_connected:
17+ if (self.get_active_review_language() != 'any' and
18+ self.global_review_stats and
19+ self.global_review_stats.ratings_total > 0):
20+ self.vbox.pack_start(NoReviewRelaxLanguage(), True, True, 0)
21+ elif is_installed and is_connected:
22 self._be_the_first_to_review()
23 else:
24 self.vbox.pack_start(NoReviewYet(), True, True, 0)
25
26- # if there are no reviews, try english as fallback
27- language = get_language()
28- if (len(self.reviews) == 0 and
29- self.global_review_stats and
30- self.global_review_stats.ratings_total > 0 and
31- language != "en"):
32- button = Gtk.Button(_("Show reviews in english"))
33- button.connect(
34- "clicked", self._on_show_reviews_in_english_clicked)
35- button.show()
36- self.vbox.pack_start(button, True, True, 0)
37-
38 # aaronp: removed check to see if the length of reviews is divisible by
39 # the batch size to allow proper fixing of LP: #794060 as when a review
40 # is submitted and appears in the list, the pagination will break this
41@@ -307,17 +300,18 @@
42 self.vbox.remove(button)
43 self.emit("more-reviews-clicked")
44
45- def _on_show_reviews_in_english_clicked(self, button):
46- self.vbox.remove(button)
47- self.emit("different-review-language-clicked", "en")
48-
49 def _on_different_review_language_clicked(self, combo):
50- # and set them
51- language = combo.get_active_text()
52+ language = self.get_active_review_language()
53 # clean reviews so that we can show the new language
54 self.clear()
55 self.emit("different-review-language-clicked", language)
56
57+ def get_active_review_language(self):
58+ language = self.review_language.get_active_text()
59+ if language == _('Any language'):
60+ language = 'any'
61+ return language
62+
63 def get_all_review_ids(self):
64 ids = []
65 for review in self.reviews:
66@@ -889,6 +883,18 @@
67 return
68
69
70+class NoReviewRelaxLanguage(EmbeddedMessage):
71+ """ represents if there are no reviews yet and the app is not installed """
72+ def __init__(self, *args, **kwargs):
73+ # TRANSLATORS: displayed if there are no reviews for the app in
74+ # the current language, but there are some in other
75+ # languages
76+ title = _("This app has not been reviewed yet in your language")
77+ msg = _('Try selecting a different language, or even "Any language"'
78+ ' in the language dropdown')
79+ EmbeddedMessage.__init__(self, title, msg)
80+
81+
82 class NoReviewYet(EmbeddedMessage):
83 """ represents if there are no reviews yet and the app is not installed """
84 def __init__(self, *args, **kwargs):
85
86=== modified file 'test/gtk3/test_widgets.py'
87--- test/gtk3/test_widgets.py 2012-01-16 14:42:49 +0000
88+++ test/gtk3/test_widgets.py 2012-01-17 15:53:18 +0000
89@@ -3,11 +3,13 @@
90 from gi.repository import Gtk, GdkPixbuf, GObject
91 import os
92 import unittest
93-
94-from mock import Mock
95-
96-from testutils import setup_test_env
97+from gettext import gettext as _
98+
99+from mock import Mock, patch
100+
101+from testutils import setup_test_env, do_events
102 setup_test_env()
103+from softwarecenter.ui.gtk3.widgets.reviews import get_test_reviews_window
104
105
106 # window destory timeout
107@@ -76,12 +78,6 @@
108 GObject.timeout_add(TIMEOUT, lambda: d.destroy())
109 d.run()
110
111- def test_reviews(self):
112- from softwarecenter.ui.gtk3.widgets.reviews import get_test_reviews_window
113- win = get_test_reviews_window()
114- GObject.timeout_add(TIMEOUT, lambda: win.destroy())
115- Gtk.main()
116-
117 def test_searchentry(self):
118 from softwarecenter.ui.gtk3.widgets.searchentry import get_test_searchentry_window
119 win = get_test_searchentry_window()
120@@ -127,7 +123,68 @@
121 GObject.timeout_add(TIMEOUT, lambda: win.destroy())
122 Gtk.main()
123
124-
125+
126+class TestUIReviewsList(unittest.TestCase):
127+ def setUp(self):
128+ self.win = get_test_reviews_window()
129+ self.rl = self.win.get_children()[0]
130+
131+ def tearDown(self):
132+ GObject.timeout_add(TIMEOUT, lambda: self.win.destroy())
133+ Gtk.main()
134+
135+ def assertComboBoxTextIncludes(self, combo, option):
136+ store = combo.get_model()
137+ self.assertTrue(option in [x[0] for x in store])
138+
139+ def assertEmbeddedMessageLabel(self, title, message):
140+ markup = self.rl.vbox.get_children()[1].label.get_label()
141+ self.assertTrue(title in markup)
142+ self.assertTrue(message in markup)
143+
144+ def test_reviews_includes_any_language(self):
145+ review_language = self.rl.review_language
146+ self.assertComboBoxTextIncludes(review_language, _('Any language'))
147+
148+ def test_reviews_offers_to_relax_language(self):
149+ # No reviews found, but there are some in other languages:
150+ self.rl.clear()
151+ self.rl.global_review_stats = Mock()
152+ self.rl.global_review_stats.ratings_total = 4
153+ self.rl.configure_reviews_ui()
154+ do_events()
155+
156+ self.assertEmbeddedMessageLabel(
157+ _("This app has not been reviewed yet in your language"),
158+ _('Try selecting a different language, or even "Any language"'
159+ ' in the language dropdown'))
160+
161+ @patch('softwarecenter.ui.gtk3.widgets.reviews.network_state_is_connected')
162+ def test_reviews_no_reviews_but_app_not_installed(self, mock_connected):
163+ mock_connected.return_value = True
164+ # No reviews found, and the app isn't installed
165+ self.rl.clear()
166+ self.rl.configure_reviews_ui()
167+ do_events()
168+
169+ self.assertEmbeddedMessageLabel(
170+ _("This app has not been reviewed yet"),
171+ _('You need to install this before you can review it'))
172+
173+ @patch('softwarecenter.ui.gtk3.widgets.reviews.network_state_is_connected')
174+ def test_reviews_no_reviews_offer_to_write_one(self, mock_connected):
175+ from softwarecenter.enums import PkgStates
176+ mock_connected.return_value = True
177+ # No reviews found, and the app is installed
178+ self.rl.clear()
179+ self.rl._parent.app_details.pkg_state = PkgStates.INSTALLED
180+ self.rl.configure_reviews_ui()
181+ do_events()
182+
183+ self.assertEmbeddedMessageLabel(
184+ _('Got an opinion?'),
185+ _('Be the first to contribute a review for this application'))
186+
187
188 if __name__ == "__main__":
189 import logging