Merge lp:~ralsina/ubuntuone-windows-installer/show_spinner into lp:ubuntuone-windows-installer

Proposed by Roberto Alsina
Status: Merged
Approved by: Roberto Alsina
Approved revision: 34
Merged at revision: 22
Proposed branch: lp:~ralsina/ubuntuone-windows-installer/show_spinner
Merge into: lp:ubuntuone-windows-installer
Diff against target: 278 lines (+149/-5)
4 files modified
data/qt/setup_account.ui (+1/-1)
ubuntuone_installer/gui/qt/forgotten.py (+34/-0)
ubuntuone_installer/gui/qt/gui.py (+34/-3)
ubuntuone_installer/gui/qt/tests/test_gui.py (+80/-1)
To merge this branch: bzr merge lp:~ralsina/ubuntuone-windows-installer/show_spinner
Reviewer Review Type Date Requested Status
Natalia Bidart (community) Approve
Review via email: mp+68145@code.launchpad.net

Commit message

Make all server-related actions show the overlay, and remove it when showing a page.

Description of the change

Make all server-related actions show the overlay, and remove it when showing a page.

To test IRL, start the wizard from this branch, and try to login, register a new acoount, reset password, etc. Whenever there is a lengthy operation, you should see the overlay being shown, and it should
disappear when the new page appears.

set PYTHONPATH=..\ubuntuone-client;..\ubuntuone-control-panel;..\ubuntu-sso-client;.
python bin\ubuntuone-installer-qt

To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Code looks good. Overlay shows up when trying to register, but it will not go away if there is any error in the form.

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

* There are 2 spaces here:

+ from ubuntu_sso.qt import controllers

* This docstring is not pep8 compliant:

+ """A custom forgotten password controller.
+
+ This controller hides the overlay as needed."""

should be:

+ """A custom forgotten password controller.
+
+ This controller hides the overlay as needed.
+ """

* Why are you passing new "extra" parameters called message_box?

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

The "extra" parameter is so that when the controller calls message_box.critical() instead of just displaying a QtGui.QMessageBox, it calls MainWindow.critical(), which hides the overlay, then shws the message box.

That way, I can ensure that the overlay is hidden when there is a popup and next() is not called.

Pushed the style fixes.

Revision history for this message
Natalia Bidart (nataliabidart) :
review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :

Attempt to merge into lp:ubuntuone-windows-installer failed due to conflicts:

text conflict in data/qt/setup_account.ui
text conflict in ubuntuone_installer/gui/qt/gui.py
text conflict in ubuntuone_installer/gui/qt/tests/test_gui.py

33. By Roberto Alsina

solve merge conflicts

34. By Roberto Alsina

use unix EOLs

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/qt/setup_account.ui'
2--- data/qt/setup_account.ui 2011-07-15 23:12:44 +0000
3+++ data/qt/setup_account.ui 2011-07-22 19:09:31 +0000
4@@ -234,7 +234,7 @@
5 <item>
6 <widget class="QPushButton" name="terms_button">
7 <property name="text">
8- <string>Shw terms</string>
9+ <string>Show terms</string>
10 </property>
11 </widget>
12 </item>
13
14=== added file 'ubuntuone_installer/gui/qt/forgotten.py'
15--- ubuntuone_installer/gui/qt/forgotten.py 1970-01-01 00:00:00 +0000
16+++ ubuntuone_installer/gui/qt/forgotten.py 2011-07-22 19:09:31 +0000
17@@ -0,0 +1,34 @@
18+# -*- coding: utf-8 -*-
19+
20+# Authors: Roberto Alsina <roberto.alsina@canonical.com>
21+#
22+# Copyright 2011 Canonical Ltd.
23+#
24+# This program is free software: you can redistribute it and/or modify it
25+# under the terms of the GNU General Public License version 3, as published
26+# by the Free Software Foundation.
27+#
28+# This program is distributed in the hope that it will be useful, but
29+# WITHOUT ANY WARRANTY; without even the implied warranties of
30+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
31+# PURPOSE. See the GNU General Public License for more details.
32+#
33+# You should have received a copy of the GNU General Public License along
34+# with this program. If not, see <http://www.gnu.org/licenses/>.
35+
36+"""Custom forgotten password controller."""
37+
38+from ubuntu_sso.qt import controllers
39+
40+
41+class ForgottenPasswordController(controllers.ForgottenPasswordController):
42+ """A custom forgotten password controller.
43+
44+ This controller hides the overlay as needed.
45+ """
46+
47+ def on_password_reset_error(self, app_name, error):
48+ """Hide the overlay, then do as the default controller does."""
49+ self.view.wizard().overlay.hide()
50+ super(ForgottenPasswordController,
51+ self).on_password_reset_error(app_name, error)
52
53=== modified file 'ubuntuone_installer/gui/qt/gui.py'
54--- ubuntuone_installer/gui/qt/gui.py 2011-07-22 16:32:35 +0000
55+++ ubuntuone_installer/gui/qt/gui.py 2011-07-22 19:09:31 +0000
56@@ -46,13 +46,14 @@
57 CurrentUserController,
58 EmailVerificationController,
59 ErrorController,
60- ForgottenPasswordController,
61 ResetPasswordController,
62 SetUpAccountController,
63 SuccessController,
64 TosController,
65 )
66
67+from ubuntuone.controlpanel.gui.qt.loadingoverlay import LoadingOverlay
68+
69 from ubuntuone.credentials import (
70 APP_NAME,
71 DESCRIPTION,
72@@ -73,6 +74,7 @@
73 # pylint: enable=W0611
74
75 from ubuntuone_installer.gui.qt.are_you_sure import AreYouSure
76+from ubuntuone_installer.gui.qt.forgotten import ForgottenPasswordController
77 from ubuntuone_installer.gui.qt.local_folders import LocalFoldersPage
78 from ubuntuone_installer.gui.qt.sync_now_or_later import SyncNowOrLaterPage
79 from ubuntuone_installer.gui.qt.setup_account import SetupAccountPage
80@@ -302,6 +304,8 @@
81 self.close_callback = close_callback
82
83 self.setSideWidget(SideWidget())
84+ self.overlay = LoadingOverlay(self)
85+ self.overlay.hide()
86
87 self.setOption(self.NoBackButtonOnStartPage, True)
88
89@@ -318,38 +322,56 @@
90 ui=choose_sign_in_ui.Ui_ChooseSignInPage(),
91 controller=self.sign_in_controller,
92 parent=self)
93- self.setup_controller = SetUpAccountController()
94+
95+ self.setup_controller = SetUpAccountController(message_box=self)
96 self.setup_account = SetupAccountPage(
97 setup_account_ui.Ui_SetUpAccountPage(),
98 self.setup_controller,
99 parent=self)
100+ self.setup_account.ui.set_up_button.clicked.connect(
101+ self.overlay.show)
102+
103 title_page = TITLE_STYLE % _("Ubuntu One Terms of Service")
104 self.tos = TosPage(Ui_TosPage(),
105 TosController(tos_url=TC_URL,
106 title=title_page),
107 parent=self)
108+
109 self.email_verification = EmailVerificationPage(
110 Ui_EmailVerificationPage(),
111 EmailVerificationController())
112+ self.email_verification.next_button.clicked.connect(
113+ self.overlay.show)
114+
115 title_page = TITLE_STYLE % SIGN_IN
116 self.current_user_controller = CurrentUserController(
117- title=title_page, subtitle=SIGN_IN_SUBTITLE)
118+ title=title_page, subtitle=SIGN_IN_SUBTITLE,
119+ message_box=self)
120 self.current_user = CurrentUserSignInPage(Ui_CurrentUserSignInPage(),
121 self.current_user_controller,
122 parent=self)
123+ self.current_user.ui.sign_in_button.clicked.connect(
124+ self.overlay.show)
125+
126 self.success_controller = SuccessController()
127 self.success = SuccessPage(Ui_SuccessPage(), self.success_controller,
128 parent=self)
129 self.error_controller = ErrorController()
130 self.error = ErrorPage(Ui_ErrorPage(), self.error_controller)
131+
132 self.forgotten_pwd_controller = ForgottenPasswordController()
133 self.forgotten = ForgottenPasswordPage(Ui_ForgottenPasswordPage(),
134 self.forgotten_pwd_controller,
135 parent=self)
136+ self.forgotten.ui.send_button.clicked.connect(
137+ self.overlay.show)
138+
139 self.reset_password_controller = ResetPasswordController()
140 self.reset_password = ResetPasswordPage(Ui_ResetPasswordPage(),
141 self.reset_password_controller,
142 parent=self)
143+ self.reset_password.ui.reset_password_button.clicked.connect(
144+ self.overlay.show)
145
146 self.SIGNIN_PAGE = self.addPage(self.sign_in_page)
147 self.setup_account_page_id = self.addPage(self.setup_account)
148@@ -376,6 +398,15 @@
149 # Invalid name "closeEvent"
150 # pylint: disable=C0103
151
152+ def critical(self, *args, **kwargs):
153+ """Wrapper for QMessageBox.critical that hides the overlay."""
154+ self.overlay.hide()
155+ QtGui.QMessageBox.critical(*args, **kwargs)
156+
157+ def next(self):
158+ self.overlay.hide()
159+ super(MainWindow, self).next()
160+
161 def nextId(self):
162 """Selects which page to display next."""
163 if self._next_id is not None:
164
165=== modified file 'ubuntuone_installer/gui/qt/tests/test_gui.py'
166--- ubuntuone_installer/gui/qt/tests/test_gui.py 2011-07-22 16:32:35 +0000
167+++ ubuntuone_installer/gui/qt/tests/test_gui.py 2011-07-22 19:09:31 +0000
168@@ -36,6 +36,7 @@
169 from ubuntuone_installer.gui.qt import gui
170 from ubuntuone_installer.gui.qt.tests import BaseTestCase
171 from ubuntuone_installer.gui.qt import embedded_sso
172+from ubuntuone_installer.gui.qt import forgotten
173 from ubuntuone_installer.gui.qt import local_folders
174 from ubuntuone_installer.gui.qt import setup_account
175 from ubuntuone_installer.gui.qt.ui import (
176@@ -80,6 +81,25 @@
177 return self.result # Means reject
178
179
180+class FakeOverlay(object):
181+
182+ """A fake delay overlay."""
183+
184+ def __init__(self, *args, **kwargs):
185+ """Initialize."""
186+ self.show_counter = 0
187+ self.hide_counter = 0
188+ self.args = (args, kwargs)
189+
190+ def show(self):
191+ """Fake show."""
192+ self.show_counter += 1
193+
194+ def hide(self):
195+ """Fake hide."""
196+ self.hide_counter += 1
197+
198+
199 class MainWindowTestCase(BaseTestCase):
200 """Test the qt main window."""
201
202@@ -97,8 +117,66 @@
203 self.patch(gui, "ForgottenPasswordController", FakeController)
204 self.patch(gui, "ResetPasswordController", FakeController)
205 self.patch(gui, "AreYouSure", FakeAreYouSure)
206+ self.patch(gui, "LoadingOverlay", FakeOverlay)
207 super(MainWindowTestCase, self).setUp()
208
209+ def test_critical(self):
210+ """Show a critical popup, but first hide the overlay."""
211+ self.assertEqual(self.ui.overlay.hide_counter, 1)
212+ self.patch(gui.QtGui.QMessageBox, "critical", self._set_called)
213+ self.ui.critical("WORRY!")
214+ self.assertEqual(self.ui.overlay.hide_counter, 2)
215+ self.assertEqual(self._called, (('WORRY!',), {}))
216+
217+ def test_forgotten_password_controller_error(self):
218+ """When there is an error, it should hide the overlay."""
219+ self.assertEqual(self.ui.overlay.hide_counter, 1)
220+ controller = forgotten.ForgottenPasswordController()
221+ controller.view = self.ui.forgotten
222+ controller.on_password_reset_error("app_name",
223+ {'errtype': 'ResetPasswordTokenError'})
224+ self.assertEqual(self.ui.overlay.hide_counter, 2)
225+
226+ def test_overlay_connection_setup_account(self):
227+ """Make sure we don't lose connections to the overlay."""
228+ self.assertEqual(self.ui.overlay.show_counter, 0)
229+ # This test is different from the ones below.
230+ # For some reason, click() doesn't trigger the connected
231+ # slot, but clicked.emit() does. The reason is unknown.
232+ self.ui.setup_account.ui.set_up_button.clicked.emit(False)
233+ self.assertEqual(self.ui.overlay.show_counter, 1)
234+
235+ def test_overlay_connection_email_verification(self):
236+ """Make sure we don't lose connections to the overlay."""
237+ self.assertEqual(self.ui.overlay.show_counter, 0)
238+ self.ui.email_verification.next_button.click()
239+ self.assertEqual(self.ui.overlay.show_counter, 1)
240+
241+ def test_overlay_connection_current_user(self):
242+ """Make sure we don't lose connections to the overlay."""
243+ self.assertEqual(self.ui.overlay.show_counter, 0)
244+ self.ui.current_user.ui.sign_in_button.click()
245+ self.assertEqual(self.ui.overlay.show_counter, 1)
246+
247+ def test_overlay_connection_forgotten_password(self):
248+ """Make sure we don't lose connections to the overlay."""
249+ self.assertEqual(self.ui.overlay.show_counter, 0)
250+ self.ui.forgotten.ui.send_button.click()
251+ self.assertEqual(self.ui.overlay.show_counter, 1)
252+
253+ def test_overlay_connection_reset_password(self):
254+ """Make sure we don't lose connections to the overlay."""
255+ self.assertEqual(self.ui.overlay.show_counter, 0)
256+ self.ui.reset_password.ui.reset_password_button.click()
257+ self.assertEqual(self.ui.overlay.show_counter, 1)
258+
259+ def test_next_hides_overlay(self):
260+ """Make sure next() hides the overlay."""
261+ self.ui.next()
262+ # This is 2 because we hide it once on __init__()
263+ # and then again on next()
264+ self.assertEqual(self.ui.overlay.hide_counter, 2)
265+
266 def test_done_calls_custom_close_callback(self):
267 """When closing the window, close_callback is called."""
268 gui.AreYouSure.result = 0
269@@ -192,7 +270,8 @@
270 def test_current_user_controller_parameters(self):
271 """Compare controller parameters with expected values."""
272 self.assertEqual(self.ui.current_user_controller.args,
273- ((), {'title': gui.TITLE_STYLE % gui.SIGN_IN,
274+ ((), {'message_box': self.ui,
275+ 'title': gui.TITLE_STYLE % gui.SIGN_IN,
276 'subtitle': gui.SIGN_IN_SUBTITLE}))
277
278 def test_stage_progression_1(self):

Subscribers

People subscribed via source and target branches