Merge lp:~nataliabidart/ubuntu-sso-client/gtk-gi into lp:ubuntu-sso-client

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 862
Merged at revision: 843
Proposed branch: lp:~nataliabidart/ubuntu-sso-client/gtk-gi
Merge into: lp:ubuntu-sso-client
Prerequisite: lp:~alecu/ubuntu-sso-client/use-restful-client
Diff against target: 2630 lines (+720/-500)
32 files modified
data/gtk/ui.glade (+314/-180)
run-tests (+13/-15)
ubuntu_sso/account.py (+7/-3)
ubuntu_sso/gtk/__init__.py (+1/-3)
ubuntu_sso/gtk/gui.py (+90/-60)
ubuntu_sso/gtk/main.py (+5/-3)
ubuntu_sso/gtk/tests/__init__.py (+1/-3)
ubuntu_sso/gtk/tests/test_gui.py (+76/-56)
ubuntu_sso/gtk/tests/test_main.py (+4/-4)
ubuntu_sso/keyring/__init__.py (+17/-9)
ubuntu_sso/keyring/tests/test_common.py (+4/-5)
ubuntu_sso/keyring/tests/test_linux.py (+1/-1)
ubuntu_sso/logger.py (+20/-4)
ubuntu_sso/main/__init__.py (+2/-2)
ubuntu_sso/main/glib.py (+45/-0)
ubuntu_sso/main/linux.py (+27/-22)
ubuntu_sso/main/qt.py (+49/-0)
ubuntu_sso/main/windows.py (+1/-1)
ubuntu_sso/qt/gui.py (+2/-1)
ubuntu_sso/qt/tests/login_u_p.py (+16/-5)
ubuntu_sso/qt/tests/show_gui.py (+5/-6)
ubuntu_sso/qt/tests/test_controllers.py (+4/-3)
ubuntu_sso/qt/tests/test_enchanced_line_edit.py (+3/-2)
ubuntu_sso/qt/tests/test_reset_password.py (+2/-1)
ubuntu_sso/tests/__init__.py (+2/-2)
ubuntu_sso/tests/bin/show_gui (+0/-58)
ubuntu_sso/tests/bin/show_nm_state (+0/-41)
ubuntu_sso/tests/test_account.py (+1/-1)
ubuntu_sso/utils/tests/test_txsecrets.py (+3/-0)
ubuntu_sso/utils/webclient/__init__.py (+2/-4)
ubuntu_sso/utils/webclient/qtnetwork.py (+2/-0)
ubuntu_sso/utils/webclient/tests/test_webclient.py (+1/-5)
To merge this branch: bzr merge lp:~nataliabidart/ubuntu-sso-client/gtk-gi
Reviewer Review Type Date Requested Status
dobey (community) Approve
Roberto Alsina (community) Approve
Review via email: mp+90134@code.launchpad.net

Commit message

- Added a dedicated logger for the gui module.
- Migrated the GTK UI to use GI bindings (LP: #801111).
- Enabled libsoup backend for webclient so the GTK UI will work.
- Enabled the running of all the tests using the single command ./run-tests.
- Added an initial version of GLib and Qt mainloop integration (needed to run all the tests).

Description of the change

You need to be running latest Ubuntu One nightlies in order this branch to work.

Also, if testing IRL, please note that the captcha image will not load because of bug #921822 (the rest of the remote calls works perfectly).

Another thing to note is that the change in the .glade file is caused by the upgrade of the syntax to latest Glade version (the changes were the result of opening the file in Glade @ precise, adding the activate-link signal handler to the 2 LinkButton we have, saving, and closing the file).

To post a comment you must log in.
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Revision history for this message
dobey (dobey) wrote :

I'm seeing a lot of the following error, in the GTK+ tests, though the tests still pass:

Gtk-WARNING **: Unable to show 'foo': Operation not supported

Do you know why this is happening?

Revision history for this message
dobey (dobey) wrote :

There also seem to be some differences from the currently shipped version, in terms of size/layout. Is there a way to test all of the pieces without actually creating a new account? I'm not really sure how to test this IRL, beyond the simple "i already have an account" piece, without making real accounts.

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

> I'm seeing a lot of the following error, in the GTK+ tests, though the tests
> still pass:
>
> Gtk-WARNING **: Unable to show 'foo': Operation not supported
>
> Do you know why this is happening?

Yes. In the UI we have a couple of LinkButton's that are not meant to open any link in any browser. I added a dummy callback (on_activate_link) and I connected it with those buttons to the activate-link signal. According to the doc, if I define a handler for the activate-signal and return True, http://developer.gnome.org/gtk3/stable/GtkLinkButton.html#GtkLinkButton-activate-link, the default handler gtk_show_uri will not be called, but in practice it's called. I would guess this is a bug... the warning complains about the "uri" property being invalid (which is intended, since we don't want any link to be opened in any browser).

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

> There also seem to be some differences from the currently shipped version, in
> terms of size/layout. Is there a way to test all of the pieces without
> actually creating a new account? I'm not really sure how to test this IRL,
> beyond the simple "i already have an account" piece, without making real
> accounts.

Yes, there are some size differences, but shouldn't be layout differences.

The way of test is actually creating SSO accounts... but you can do it for dummy applications and not for Ubuntu One (so your U1 metadata does not get messed up). To do so:

* in a terminal pointing to this branch run:

DEBUG=True PYTHONPATH=. bin/ubuntu-sso-login

* open d-feet and connect to the session bus, look for the com.ubuntu.sso service, and go to the CredentialsManagement interface. Choose the "login" or "register" method, and pass arguments like:

'Foo', {}

or:

'Foo Bar', {'help_text': 'something for test here'}

When you execute one of the methods above, you should get a GTK window with the login or register screen in it, and you should be able to login or create a kinda dummy account.

Revision history for this message
dobey (dobey) wrote :

https://launchpadlibrarian.net/91640946/sso-gtk3-nowrap.png shows what I meant about layout. It looks like the description label is not getting wrapped. I don't know if this is due to a change in this branch to the glade data, or if it's introduced by changes in gtk3 itself. I suspect the latter though.

Revision history for this message
dobey (dobey) wrote :

Looks OK to me. I think we'll need a bug against python-gi for breaking ^C. I'll file it shortly. I have filed bug #925042 against ubuntu-sso-client for the label wrapping issue.

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

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (38.4 KiB)

The attempt to merge lp:~nataliabidart/ubuntu-sso-client/gtk-gi into lp:ubuntu-sso-client failed. Below is the output from the failed tests.

*** Running test suite for ubuntu_sso ***
ubuntu_sso.tests.test_account
  AccountTestCase
    test_generate_captcha ... [OK]
    test_is_not_validated ... [OK]
    test_is_not_validated_empty_result ... [OK]
    test_is_validated ... [OK]
    test_login_if_http_error ... [OK]
    test_login_if_no_error ... [OK]
    test_register_user_checks_valid_email ... [OK]
    test_register_user_checks_valid_password ... [OK]
    test_register_user_if_status_error ... [OK]
    test_register_user_if_status_error_with_string_message ... [OK]
    test_register_user_if_status_ok ... [OK]
    test_register_user_if_status_unknown ... [OK]
    test_request_password_reset_token_if_http_error ... [OK]
    test_request_password_reset_token_if_status_ok ... [OK]
    test_request_password_reset_token_if_status_unknown ... [OK]
    test_set_new_password_if_http_error ... [OK]
    test_set_new_password_if_status_ok ... [OK]
    test_set_new_password_if_status_unknown ... [OK]
    test_validate_email_if_status_error ... [OK]
    test_validate_email_if_status_error_with_string_message ... [OK]
    test_validate_email_if_status_ok ... [OK]
    test_validate_email_if_status_unknown ... [OK]
  EnvironOverridesTestCase
    test_no_override_service_url ... [OK]
    test_override_service_url ... [OK]
    test_service_url_as_parameter ... [OK]
twisted.trial.unittest
  TestCase
    runTest ... [OK]
ubuntu_sso.tests.test_account
  TimestampedAuthorizerTestCase
    test_authorize_request_includes_timestamp ... [OK]
ubuntu_sso.tests.test_credentials
  BasicTestCase
    runTest ... [OK]
  ClearCredentialsTestCase
    test_clear_credentials ... [OK]
    test_keyring_failure ... [OK]
  CredentialsAuthDeniedTestCase
    test_auth_denial_cb ... [OK]
  CredentialsCallbacksTestCase
    test_callbacks_are_stored ... [OK]
    test_callbacks_default_to_no_op ... [OK]
    test_creation_parameters_are_stored ... ...

Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (38.5 KiB)

The attempt to merge lp:~nataliabidart/ubuntu-sso-client/gtk-gi into lp:ubuntu-sso-client failed. Below is the output from the failed tests.

*** Running test suite for ubuntu_sso ***
ubuntu_sso.tests.test_account
  AccountTestCase
    test_generate_captcha ... [OK]
    test_is_not_validated ... [OK]
    test_is_not_validated_empty_result ... [OK]
    test_is_validated ... [OK]
    test_login_if_http_error ... [OK]
    test_login_if_no_error ... [OK]
    test_register_user_checks_valid_email ... [OK]
    test_register_user_checks_valid_password ... [OK]
    test_register_user_if_status_error ... [OK]
    test_register_user_if_status_error_with_string_message ... [OK]
    test_register_user_if_status_ok ... [OK]
    test_register_user_if_status_unknown ... [OK]
    test_request_password_reset_token_if_http_error ... [OK]
    test_request_password_reset_token_if_status_ok ... [OK]
    test_request_password_reset_token_if_status_unknown ... [OK]
    test_set_new_password_if_http_error ... [OK]
    test_set_new_password_if_status_ok ... [OK]
    test_set_new_password_if_status_unknown ... [OK]
    test_validate_email_if_status_error ... [OK]
    test_validate_email_if_status_error_with_string_message ... [OK]
    test_validate_email_if_status_ok ... [OK]
    test_validate_email_if_status_unknown ... [OK]
  EnvironOverridesTestCase
    test_no_override_service_url ... [OK]
    test_override_service_url ... [OK]
    test_service_url_as_parameter ... [OK]
twisted.trial.unittest
  TestCase
    runTest ... [OK]
ubuntu_sso.tests.test_account
  TimestampedAuthorizerTestCase
    test_authorize_request_includes_timestamp ... [OK]
ubuntu_sso.tests.test_credentials
  BasicTestCase
    runTest ... [OK]
  ClearCredentialsTestCase
    test_clear_credentials ... [OK]
    test_keyring_failure ... [OK]
  CredentialsAuthDeniedTestCase
    test_auth_denial_cb ... [OK]
  CredentialsCallbacksTestCase
    test_callbacks_are_stored ... [OK]
    test_callbacks_default_to_no_op ... [OK]
    test_creation_parameters_are_stored ... ...

Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :

The attempt to merge lp:~nataliabidart/ubuntu-sso-client/gtk-gi into lp:ubuntu-sso-client failed. Below is the output from the failed tests.

*** Running test suite for ubuntu_sso ***

xvfb-run: error: Xvfb failed to start

859. By Natalia Bidart

- Adding proper cleanup for GTK windows created during tests.

860. By Natalia Bidart

- Add cleanups calls to every created UI.

861. By Natalia Bidart

Attaching new bug number.

862. By Natalia Bidart

Merged trunk in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/gtk/ui.glade'
--- data/gtk/ui.glade 2011-09-19 13:09:46 +0000
+++ data/gtk/ui.glade 2012-02-02 18:14:19 +0000
@@ -1,72 +1,14 @@
1<?xml version="1.0" encoding="UTF-8"?>1<?xml version="1.0" encoding="UTF-8"?>
2<interface>2<interface>
3 <requires lib="gtk+" version="2.16"/>3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-naming-policy project-wide -->
5 <object class="GtkWindow" id="window">
6 <property name="border_width">10</property>
7 <property name="window_position">center</property>
8 <signal name="delete_event" handler="on_close_clicked"/>
9 <child>
10 <object class="GtkVBox" id="window_vbox">
11 <property name="visible">True</property>
12 <property name="spacing">5</property>
13 <child>
14 <object class="GtkLabel" id="header_label">
15 <property name="visible">True</property>
16 <property name="xalign">0</property>
17 <property name="label" translatable="yes">Header Label </property>
18 <property name="wrap">True</property>
19 </object>
20 <packing>
21 <property name="expand">False</property>
22 <property name="padding">5</property>
23 <property name="position">0</property>
24 </packing>
25 </child>
26 <child>
27 <object class="GtkLabel" id="help_label">
28 <property name="visible">True</property>
29 <property name="xalign">0</property>
30 <property name="label" translatable="yes">help label</property>
31 <property name="wrap">True</property>
32 </object>
33 <packing>
34 <property name="expand">False</property>
35 <property name="position">1</property>
36 </packing>
37 </child>
38 <child>
39 <object class="GtkLabel" id="warning_label">
40 <property name="visible">True</property>
41 <property name="xalign">0</property>
42 <property name="label" translatable="yes">warning label</property>
43 <property name="wrap">True</property>
44 </object>
45 <packing>
46 <property name="expand">False</property>
47 <property name="position">2</property>
48 </packing>
49 </child>
50 <child>
51 <object class="GtkNotebook" id="content">
52 <property name="visible">True</property>
53 <property name="can_focus">True</property>
54 <property name="show_tabs">False</property>
55 <property name="show_border">False</property>
56 </object>
57 <packing>
58 <property name="position">3</property>
59 </packing>
60 </child>
61 </object>
62 </child>
63 </object>
64 <object class="GtkVBox" id="enter_details_vbox">4 <object class="GtkVBox" id="enter_details_vbox">
65 <property name="visible">True</property>5 <property name="visible">True</property>
6 <property name="can_focus">False</property>
66 <property name="spacing">5</property>7 <property name="spacing">5</property>
67 <child>8 <child>
68 <object class="GtkHBox" id="emails_hbox">9 <object class="GtkHBox" id="emails_hbox">
69 <property name="visible">True</property>10 <property name="visible">True</property>
11 <property name="can_focus">False</property>
70 <property name="spacing">5</property>12 <property name="spacing">5</property>
71 <property name="homogeneous">True</property>13 <property name="homogeneous">True</property>
72 <child>14 <child>
@@ -78,12 +20,14 @@
78 </object>20 </object>
79 <packing>21 <packing>
80 <property name="expand">False</property>22 <property name="expand">False</property>
23 <property name="fill">True</property>
81 <property name="position">0</property>24 <property name="position">0</property>
82 </packing>25 </packing>
83 </child>26 </child>
84 <child>27 <child>
85 <object class="GtkHBox" id="passwords_hbox">28 <object class="GtkHBox" id="passwords_hbox">
86 <property name="visible">True</property>29 <property name="visible">True</property>
30 <property name="can_focus">False</property>
87 <property name="spacing">5</property>31 <property name="spacing">5</property>
88 <property name="homogeneous">True</property>32 <property name="homogeneous">True</property>
89 <child>33 <child>
@@ -95,38 +39,45 @@
95 </object>39 </object>
96 <packing>40 <packing>
97 <property name="expand">False</property>41 <property name="expand">False</property>
42 <property name="fill">True</property>
98 <property name="position">1</property>43 <property name="position">1</property>
99 </packing>44 </packing>
100 </child>45 </child>
101 <child>46 <child>
102 <object class="GtkLabel" id="password_help_label">47 <object class="GtkLabel" id="password_help_label">
103 <property name="visible">True</property>48 <property name="visible">True</property>
49 <property name="can_focus">False</property>
104 <property name="label">password help</property>50 <property name="label">password help</property>
105 <property name="wrap">True</property>51 <property name="wrap">True</property>
106 </object>52 </object>
107 <packing>53 <packing>
108 <property name="expand">False</property>54 <property name="expand">False</property>
55 <property name="fill">True</property>
109 <property name="position">2</property>56 <property name="position">2</property>
110 </packing>57 </packing>
111 </child>58 </child>
112 <child>59 <child>
113 <object class="GtkAlignment" id="alignment5">60 <object class="GtkAlignment" id="alignment5">
114 <property name="visible">True</property>61 <property name="visible">True</property>
62 <property name="can_focus">False</property>
115 <property name="xscale">0</property>63 <property name="xscale">0</property>
116 <property name="yscale">0</property>64 <property name="yscale">0</property>
117 <child>65 <child>
118 <object class="GtkHBox" id="hbox1">66 <object class="GtkHBox" id="hbox1">
119 <property name="visible">True</property>67 <property name="visible">True</property>
68 <property name="can_focus">False</property>
120 <child>69 <child>
121 <object class="GtkVBox" id="captcha_vbox">70 <object class="GtkVBox" id="captcha_vbox">
122 <property name="width_request">300</property>71 <property name="width_request">300</property>
123 <property name="height_request">60</property>72 <property name="height_request">60</property>
124 <property name="visible">True</property>73 <property name="visible">True</property>
74 <property name="can_focus">False</property>
125 <child>75 <child>
126 <object class="GtkEventBox" id="captcha_loading">76 <object class="GtkEventBox" id="captcha_loading">
127 <property name="width_request">300</property>77 <property name="width_request">300</property>
128 <property name="height_request">60</property>78 <property name="height_request">60</property>
129 <property name="visible">True</property>79 <property name="visible">True</property>
80 <property name="can_focus">False</property>
130 <child>81 <child>
131 <placeholder/>82 <placeholder/>
132 </child>83 </child>
@@ -141,9 +92,12 @@
141 <object class="GtkImage" id="captcha_image">92 <object class="GtkImage" id="captcha_image">
142 <property name="width_request">300</property>93 <property name="width_request">300</property>
143 <property name="visible">True</property>94 <property name="visible">True</property>
95 <property name="can_focus">False</property>
144 <property name="stock">gtk-missing-image</property>96 <property name="stock">gtk-missing-image</property>
145 </object>97 </object>
146 <packing>98 <packing>
99 <property name="expand">True</property>
100 <property name="fill">True</property>
147 <property name="position">1</property>101 <property name="position">1</property>
148 </packing>102 </packing>
149 </child>103 </child>
@@ -157,23 +111,28 @@
157 <child>111 <child>
158 <object class="GtkVBox" id="vbox1">112 <object class="GtkVBox" id="vbox1">
159 <property name="visible">True</property>113 <property name="visible">True</property>
114 <property name="can_focus">False</property>
160 <child>115 <child>
161 <object class="GtkButton" id="captcha_reload_button">116 <object class="GtkButton" id="captcha_reload_button">
117 <property name="use_action_appearance">False</property>
162 <property name="visible">True</property>118 <property name="visible">True</property>
163 <property name="can_focus">True</property>119 <property name="can_focus">True</property>
164 <property name="receives_default">True</property>120 <property name="receives_default">True</property>
121 <property name="use_action_appearance">False</property>
165 <property name="relief">none</property>122 <property name="relief">none</property>
166 <property name="focus_on_click">False</property>123 <property name="focus_on_click">False</property>
167 <signal name="clicked" handler="on_captcha_reload_button_clicked"/>124 <signal name="clicked" handler="on_captcha_reload_button_clicked" swapped="no"/>
168 <child>125 <child>
169 <object class="GtkImage" id="image1">126 <object class="GtkImage" id="image1">
170 <property name="visible">True</property>127 <property name="visible">True</property>
128 <property name="can_focus">False</property>
171 <property name="icon_name">reload</property>129 <property name="icon_name">reload</property>
172 </object>130 </object>
173 </child>131 </child>
174 </object>132 </object>
175 <packing>133 <packing>
176 <property name="expand">False</property>134 <property name="expand">False</property>
135 <property name="fill">True</property>
177 <property name="position">0</property>136 <property name="position">0</property>
178 </packing>137 </packing>
179 </child>138 </child>
@@ -186,6 +145,7 @@
186 </object>145 </object>
187 <packing>146 <packing>
188 <property name="expand">False</property>147 <property name="expand">False</property>
148 <property name="fill">True</property>
189 <property name="position">1</property>149 <property name="position">1</property>
190 </packing>150 </packing>
191 </child>151 </child>
@@ -194,64 +154,76 @@
194 </object>154 </object>
195 <packing>155 <packing>
196 <property name="expand">False</property>156 <property name="expand">False</property>
157 <property name="fill">True</property>
197 <property name="position">3</property>158 <property name="position">3</property>
198 </packing>159 </packing>
199 </child>160 </child>
200 <child>161 <child>
201 <object class="GtkVBox" id="captcha_solution_vbox">162 <object class="GtkVBox" id="captcha_solution_vbox">
202 <property name="visible">True</property>163 <property name="visible">True</property>
164 <property name="can_focus">False</property>
203 <child>165 <child>
204 <placeholder/>166 <placeholder/>
205 </child>167 </child>
206 </object>168 </object>
207 <packing>169 <packing>
208 <property name="expand">False</property>170 <property name="expand">False</property>
171 <property name="fill">True</property>
209 <property name="position">4</property>172 <property name="position">4</property>
210 </packing>173 </packing>
211 </child>174 </child>
212 <child>175 <child>
213 <object class="GtkCheckButton" id="yes_to_updates_checkbutton">176 <object class="GtkCheckButton" id="yes_to_updates_checkbutton">
214 <property name="label" translatable="yes">yes to updates</property>177 <property name="label" translatable="yes">yes to updates</property>
178 <property name="use_action_appearance">False</property>
215 <property name="visible">True</property>179 <property name="visible">True</property>
216 <property name="can_focus">True</property>180 <property name="can_focus">True</property>
217 <property name="receives_default">False</property>181 <property name="receives_default">False</property>
182 <property name="use_action_appearance">False</property>
218 <property name="active">True</property>183 <property name="active">True</property>
219 <property name="draw_indicator">True</property>184 <property name="draw_indicator">True</property>
220 </object>185 </object>
221 <packing>186 <packing>
222 <property name="expand">False</property>187 <property name="expand">False</property>
188 <property name="fill">True</property>
223 <property name="position">5</property>189 <property name="position">5</property>
224 </packing>190 </packing>
225 </child>191 </child>
226 <child>192 <child>
227 <object class="GtkVBox" id="tc_vbox">193 <object class="GtkVBox" id="tc_vbox">
228 <property name="visible">True</property>194 <property name="visible">True</property>
195 <property name="can_focus">False</property>
229 <property name="spacing">5</property>196 <property name="spacing">5</property>
230 <child>197 <child>
231 <object class="GtkCheckButton" id="yes_to_tc_checkbutton">198 <object class="GtkCheckButton" id="yes_to_tc_checkbutton">
232 <property name="label" translatable="yes">yes to tc</property>199 <property name="label" translatable="yes">yes to tc</property>
200 <property name="use_action_appearance">False</property>
233 <property name="visible">True</property>201 <property name="visible">True</property>
234 <property name="can_focus">True</property>202 <property name="can_focus">True</property>
235 <property name="receives_default">False</property>203 <property name="receives_default">False</property>
236 <property name="active">False</property>204 <property name="use_action_appearance">False</property>
237 <property name="draw_indicator">True</property>205 <property name="draw_indicator">True</property>
238 </object>206 </object>
239 <packing>207 <packing>
240 <property name="expand">False</property>208 <property name="expand">False</property>
209 <property name="fill">True</property>
241 <property name="position">0</property>210 <property name="position">0</property>
242 </packing>211 </packing>
243 </child>212 </child>
244 <child>213 <child>
245 <object class="GtkHButtonBox" id="hbuttonbox3">214 <object class="GtkHButtonBox" id="hbuttonbox3">
246 <property name="visible">True</property>215 <property name="visible">True</property>
216 <property name="can_focus">False</property>
247 <property name="layout_style">start</property>217 <property name="layout_style">start</property>
248 <child>218 <child>
249 <object class="GtkButton" id="tc_button">219 <object class="GtkButton" id="tc_button">
250 <property name="label">show tc</property>220 <property name="label">show tc</property>
221 <property name="use_action_appearance">False</property>
251 <property name="visible">True</property>222 <property name="visible">True</property>
252 <property name="can_focus">True</property>223 <property name="can_focus">True</property>
253 <property name="receives_default">True</property>224 <property name="receives_default">True</property>
254 <signal name="clicked" handler="on_tc_button_clicked"/>225 <property name="use_action_appearance">False</property>
226 <signal name="clicked" handler="on_tc_button_clicked" swapped="no"/>
255 </object>227 </object>
256 <packing>228 <packing>
257 <property name="expand">False</property>229 <property name="expand">False</property>
@@ -262,42 +234,53 @@
262 </object>234 </object>
263 <packing>235 <packing>
264 <property name="expand">False</property>236 <property name="expand">False</property>
237 <property name="fill">True</property>
265 <property name="position">1</property>238 <property name="position">1</property>
266 </packing>239 </packing>
267 </child>240 </child>
268 <child>241 <child>
269 <object class="GtkLabel" id="tc_warning_label">242 <object class="GtkLabel" id="tc_warning_label">
270 <property name="visible">True</property>243 <property name="visible">True</property>
244 <property name="can_focus">False</property>
271 <property name="xalign">0</property>245 <property name="xalign">0</property>
272 <property name="label">tc warning</property>246 <property name="label">tc warning</property>
273 <property name="wrap">True</property>247 <property name="wrap">True</property>
274 </object>248 </object>
275 <packing>249 <packing>
250 <property name="expand">True</property>
251 <property name="fill">True</property>
276 <property name="position">2</property>252 <property name="position">2</property>
277 </packing>253 </packing>
278 </child>254 </child>
279 </object>255 </object>
280 <packing>256 <packing>
281 <property name="expand">False</property>257 <property name="expand">False</property>
258 <property name="fill">True</property>
282 <property name="position">6</property>259 <property name="position">6</property>
283 </packing>260 </packing>
284 </child>261 </child>
285 <child>262 <child>
286 <object class="GtkHBox" id="hbox2">263 <object class="GtkHBox" id="hbox2">
287 <property name="visible">True</property>264 <property name="visible">True</property>
265 <property name="can_focus">False</property>
288 <property name="spacing">5</property>266 <property name="spacing">5</property>
289 <child>267 <child>
290 <object class="GtkHButtonBox" id="hbuttonbox9">268 <object class="GtkHButtonBox" id="hbuttonbox9">
291 <property name="visible">True</property>269 <property name="visible">True</property>
270 <property name="can_focus">False</property>
292 <property name="layout_style">start</property>271 <property name="layout_style">start</property>
293 <child>272 <child>
294 <object class="GtkLinkButton" id="login_button">273 <object class="GtkLinkButton" id="login_button">
295 <property name="label">login button</property>274 <property name="label">login button</property>
275 <property name="use_action_appearance">False</property>
296 <property name="visible">True</property>276 <property name="visible">True</property>
297 <property name="can_focus">True</property>277 <property name="can_focus">True</property>
298 <property name="receives_default">True</property>278 <property name="receives_default">True</property>
279 <property name="use_action_appearance">False</property>
299 <property name="relief">none</property>280 <property name="relief">none</property>
300 <signal name="clicked" handler="on_sign_in_button_clicked"/>281 <property name="uri">foo</property>
282 <signal name="activate-link" handler="on_activate_link" swapped="no"/>
283 <signal name="clicked" handler="on_sign_in_button_clicked" swapped="no"/>
301 </object>284 </object>
302 <packing>285 <packing>
303 <property name="expand">False</property>286 <property name="expand">False</property>
@@ -308,20 +291,24 @@
308 </object>291 </object>
309 <packing>292 <packing>
310 <property name="expand">False</property>293 <property name="expand">False</property>
294 <property name="fill">True</property>
311 <property name="position">0</property>295 <property name="position">0</property>
312 </packing>296 </packing>
313 </child>297 </child>
314 <child>298 <child>
315 <object class="GtkHButtonBox" id="hbuttonbox1">299 <object class="GtkHButtonBox" id="hbuttonbox1">
316 <property name="visible">True</property>300 <property name="visible">True</property>
301 <property name="can_focus">False</property>
317 <property name="spacing">5</property>302 <property name="spacing">5</property>
318 <property name="layout_style">end</property>303 <property name="layout_style">end</property>
319 <child>304 <child>
320 <object class="GtkButton" id="join_cancel_button">305 <object class="GtkButton" id="join_cancel_button">
321 <property name="label">gtk-cancel</property>306 <property name="label">gtk-cancel</property>
307 <property name="use_action_appearance">False</property>
322 <property name="visible">True</property>308 <property name="visible">True</property>
323 <property name="can_focus">True</property>309 <property name="can_focus">True</property>
324 <property name="receives_default">True</property>310 <property name="receives_default">True</property>
311 <property name="use_action_appearance">False</property>
325 <property name="use_stock">True</property>312 <property name="use_stock">True</property>
326 </object>313 </object>
327 <packing>314 <packing>
@@ -333,11 +320,13 @@
333 <child>320 <child>
334 <object class="GtkButton" id="join_ok_button">321 <object class="GtkButton" id="join_ok_button">
335 <property name="label">gtk-go-forward</property>322 <property name="label">gtk-go-forward</property>
323 <property name="use_action_appearance">False</property>
336 <property name="visible">True</property>324 <property name="visible">True</property>
337 <property name="can_focus">True</property>325 <property name="can_focus">True</property>
338 <property name="receives_default">True</property>326 <property name="receives_default">True</property>
327 <property name="use_action_appearance">False</property>
339 <property name="use_stock">True</property>328 <property name="use_stock">True</property>
340 <signal name="clicked" handler="on_join_ok_button_clicked"/>329 <signal name="clicked" handler="on_join_ok_button_clicked" swapped="no"/>
341 </object>330 </object>
342 <packing>331 <packing>
343 <property name="expand">False</property>332 <property name="expand">False</property>
@@ -348,6 +337,7 @@
348 </object>337 </object>
349 <packing>338 <packing>
350 <property name="expand">False</property>339 <property name="expand">False</property>
340 <property name="fill">True</property>
351 <property name="pack_type">end</property>341 <property name="pack_type">end</property>
352 <property name="position">1</property>342 <property name="position">1</property>
353 </packing>343 </packing>
@@ -355,122 +345,72 @@
355 </object>345 </object>
356 <packing>346 <packing>
357 <property name="expand">False</property>347 <property name="expand">False</property>
348 <property name="fill">True</property>
358 <property name="pack_type">end</property>349 <property name="pack_type">end</property>
359 <property name="position">7</property>350 <property name="position">7</property>
360 </packing>351 </packing>
361 </child>352 </child>
362 </object>353 </object>
363 <object class="GtkVBox" id="processing_vbox">354 <object class="GtkVBox" id="finish_vbox">
364 <property name="visible">True</property>355 <property name="visible">True</property>
365 <property name="spacing">10</property>356 <property name="can_focus">False</property>
366 <child>357 <property name="spacing">10</property>
367 <placeholder/>358 <child>
368 </child>359 <object class="GtkLabel" id="finish_label">
369 </object>360 <property name="visible">True</property>
370 <object class="GtkVBox" id="verify_email_vbox">361 <property name="can_focus">False</property>
371 <property name="visible">True</property>362 <property name="wrap">True</property>
372 <property name="spacing">10</property>363 </object>
373 <child>364 <packing>
374 <object class="GtkAlignment" id="alignment4">365 <property name="expand">True</property>
375 <property name="visible">True</property>366 <property name="fill">True</property>
376 <property name="xscale">0</property>367 <property name="position">0</property>
377 <property name="yscale">0</property>368 </packing>
378 <child>369 </child>
379 <object class="GtkVBox" id="verify_email_details_vbox">370 <child>
380 <property name="visible">True</property>371 <object class="GtkHButtonBox" id="hbuttonbox8">
381 <child>372 <property name="visible">True</property>
382 <placeholder/>373 <property name="can_focus">False</property>
383 </child>374 <property name="layout_style">end</property>
384 </object>375 <child>
385 </child>376 <object class="GtkButton" id="finish_close_button">
386 </object>377 <property name="label">gtk-close</property>
387 <packing>378 <property name="use_action_appearance">False</property>
388 <property name="position">0</property>379 <property name="visible">True</property>
389 </packing>380 <property name="can_focus">True</property>
390 </child>381 <property name="receives_default">True</property>
391 <child>382 <property name="use_action_appearance">False</property>
392 <object class="GtkHButtonBox" id="hbuttonbox2">383 <property name="use_stock">True</property>
393 <property name="visible">True</property>384 <signal name="clicked" handler="on_close_clicked" swapped="no"/>
394 <property name="spacing">5</property>385 </object>
395 <property name="layout_style">end</property>386 <packing>
396 <child>387 <property name="expand">False</property>
397 <object class="GtkButton" id="verify_token_button">388 <property name="fill">False</property>
398 <property name="label">gtk-ok</property>389 <property name="position">0</property>
399 <property name="visible">True</property>390 </packing>
400 <property name="can_focus">True</property>391 </child>
401 <property name="receives_default">True</property>392 </object>
402 <property name="use_stock">True</property>393 <packing>
403 <signal name="clicked" handler="on_verify_token_button_clicked"/>394 <property name="expand">False</property>
404 </object>395 <property name="fill">True</property>
405 <packing>
406 <property name="expand">False</property>
407 <property name="fill">False</property>
408 <property name="position">0</property>
409 </packing>
410 </child>
411 </object>
412 <packing>
413 <property name="expand">False</property>
414 <property name="position">1</property>
415 </packing>
416 </child>
417 </object>
418 <object class="GtkVBox" id="tc_browser_vbox">
419 <property name="visible">True</property>
420 <signal name="hide" handler="on_tc_browser_vbox_hide"/>
421 <child>
422 <object class="GtkScrolledWindow" id="tc_browser_window">
423 <property name="visible">True</property>
424 <property name="can_focus">True</property>
425 <property name="border_width">10</property>
426 <property name="hscrollbar_policy">never</property>
427 <property name="vscrollbar_policy">automatic</property>
428 <property name="shadow_type">in</property>
429 <child>
430 <placeholder/>
431 </child>
432 </object>
433 <packing>
434 <property name="position">0</property>
435 </packing>
436 </child>
437 <child>
438 <object class="GtkHButtonBox" id="hbuttonbox4">
439 <property name="visible">True</property>
440 <property name="layout_style">end</property>
441 <child>
442 <object class="GtkButton" id="tc_back_button">
443 <property name="label">gtk-go-back</property>
444 <property name="visible">True</property>
445 <property name="can_focus">True</property>
446 <property name="receives_default">True</property>
447 <property name="use_stock">True</property>
448 <signal name="clicked" handler="on_tc_back_button_clicked"/>
449 </object>
450 <packing>
451 <property name="expand">False</property>
452 <property name="fill">False</property>
453 <property name="position">0</property>
454 </packing>
455 </child>
456 </object>
457 <packing>
458 <property name="expand">False</property>
459 <property name="position">1</property>396 <property name="position">1</property>
460 </packing>397 </packing>
461 </child>398 </child>
462 </object>399 </object>
463 <object class="GtkVBox" id="login_vbox">400 <object class="GtkVBox" id="login_vbox">
464 <property name="visible">True</property>401 <property name="visible">True</property>
402 <property name="can_focus">False</property>
465 <property name="spacing">10</property>403 <property name="spacing">10</property>
466 <child>404 <child>
467 <object class="GtkAlignment" id="alignment3">405 <object class="GtkAlignment" id="alignment3">
468 <property name="visible">True</property>406 <property name="visible">True</property>
407 <property name="can_focus">False</property>
469 <property name="xscale">0</property>408 <property name="xscale">0</property>
470 <property name="yscale">0</property>409 <property name="yscale">0</property>
471 <child>410 <child>
472 <object class="GtkVBox" id="login_details_vbox">411 <object class="GtkVBox" id="login_details_vbox">
473 <property name="visible">True</property>412 <property name="visible">True</property>
413 <property name="can_focus">False</property>
474 <property name="spacing">5</property>414 <property name="spacing">5</property>
475 <child>415 <child>
476 <placeholder/>416 <placeholder/>
@@ -482,26 +422,34 @@
482 </child>422 </child>
483 </object>423 </object>
484 <packing>424 <packing>
425 <property name="expand">True</property>
426 <property name="fill">True</property>
485 <property name="position">0</property>427 <property name="position">0</property>
486 </packing>428 </packing>
487 </child>429 </child>
488 <child>430 <child>
489 <object class="GtkHBox" id="hbox3">431 <object class="GtkHBox" id="hbox3">
490 <property name="visible">True</property>432 <property name="visible">True</property>
433 <property name="can_focus">False</property>
491 <property name="spacing">5</property>434 <property name="spacing">5</property>
492 <child>435 <child>
493 <object class="GtkHButtonBox" id="hbuttonbox10">436 <object class="GtkHButtonBox" id="hbuttonbox10">
494 <property name="visible">True</property>437 <property name="visible">True</property>
438 <property name="can_focus">False</property>
495 <property name="layout_style">start</property>439 <property name="layout_style">start</property>
496 <child>440 <child>
497 <object class="GtkLinkButton" id="forgotten_password_button">441 <object class="GtkLinkButton" id="forgotten_password_button">
498 <property name="label" translatable="yes">button</property>442 <property name="label" translatable="yes">forgot password button</property>
443 <property name="use_action_appearance">False</property>
499 <property name="visible">True</property>444 <property name="visible">True</property>
500 <property name="can_focus">True</property>445 <property name="can_focus">True</property>
501 <property name="receives_default">True</property>446 <property name="receives_default">True</property>
502 <property name="has_tooltip">True</property>447 <property name="has_tooltip">True</property>
448 <property name="use_action_appearance">False</property>
503 <property name="relief">none</property>449 <property name="relief">none</property>
504 <signal name="clicked" handler="on_forgotten_password_button_clicked"/>450 <property name="uri">foo</property>
451 <signal name="activate-link" handler="on_activate_link" swapped="no"/>
452 <signal name="clicked" handler="on_forgotten_password_button_clicked" swapped="no"/>
505 </object>453 </object>
506 <packing>454 <packing>
507 <property name="expand">False</property>455 <property name="expand">False</property>
@@ -513,20 +461,24 @@
513 </object>461 </object>
514 <packing>462 <packing>
515 <property name="expand">False</property>463 <property name="expand">False</property>
464 <property name="fill">True</property>
516 <property name="position">0</property>465 <property name="position">0</property>
517 </packing>466 </packing>
518 </child>467 </child>
519 <child>468 <child>
520 <object class="GtkHButtonBox" id="hbuttonbox5">469 <object class="GtkHButtonBox" id="hbuttonbox5">
521 <property name="visible">True</property>470 <property name="visible">True</property>
471 <property name="can_focus">False</property>
522 <property name="spacing">5</property>472 <property name="spacing">5</property>
523 <property name="layout_style">end</property>473 <property name="layout_style">end</property>
524 <child>474 <child>
525 <object class="GtkButton" id="login_cancel_button">475 <object class="GtkButton" id="login_cancel_button">
526 <property name="label">gtk-cancel</property>476 <property name="label">gtk-cancel</property>
477 <property name="use_action_appearance">False</property>
527 <property name="visible">True</property>478 <property name="visible">True</property>
528 <property name="can_focus">True</property>479 <property name="can_focus">True</property>
529 <property name="receives_default">True</property>480 <property name="receives_default">True</property>
481 <property name="use_action_appearance">False</property>
530 <property name="use_stock">True</property>482 <property name="use_stock">True</property>
531 </object>483 </object>
532 <packing>484 <packing>
@@ -538,11 +490,13 @@
538 <child>490 <child>
539 <object class="GtkButton" id="login_back_button">491 <object class="GtkButton" id="login_back_button">
540 <property name="label">gtk-go-back</property>492 <property name="label">gtk-go-back</property>
493 <property name="use_action_appearance">False</property>
541 <property name="visible">True</property>494 <property name="visible">True</property>
542 <property name="can_focus">True</property>495 <property name="can_focus">True</property>
543 <property name="receives_default">True</property>496 <property name="receives_default">True</property>
497 <property name="use_action_appearance">False</property>
544 <property name="use_stock">True</property>498 <property name="use_stock">True</property>
545 <signal name="clicked" handler="on_login_back_button_clicked"/>499 <signal name="clicked" handler="on_login_back_button_clicked" swapped="no"/>
546 </object>500 </object>
547 <packing>501 <packing>
548 <property name="expand">False</property>502 <property name="expand">False</property>
@@ -553,11 +507,13 @@
553 <child>507 <child>
554 <object class="GtkButton" id="login_ok_button">508 <object class="GtkButton" id="login_ok_button">
555 <property name="label">gtk-connect</property>509 <property name="label">gtk-connect</property>
510 <property name="use_action_appearance">False</property>
556 <property name="visible">True</property>511 <property name="visible">True</property>
557 <property name="can_focus">True</property>512 <property name="can_focus">True</property>
558 <property name="receives_default">True</property>513 <property name="receives_default">True</property>
514 <property name="use_action_appearance">False</property>
559 <property name="use_stock">True</property>515 <property name="use_stock">True</property>
560 <signal name="clicked" handler="on_login_connect_button_clicked"/>516 <signal name="clicked" handler="on_login_connect_button_clicked" swapped="no"/>
561 </object>517 </object>
562 <packing>518 <packing>
563 <property name="expand">False</property>519 <property name="expand">False</property>
@@ -568,6 +524,7 @@
568 </object>524 </object>
569 <packing>525 <packing>
570 <property name="expand">False</property>526 <property name="expand">False</property>
527 <property name="fill">True</property>
571 <property name="pack_type">end</property>528 <property name="pack_type">end</property>
572 <property name="position">1</property>529 <property name="position">1</property>
573 </packing>530 </packing>
@@ -575,21 +532,33 @@
575 </object>532 </object>
576 <packing>533 <packing>
577 <property name="expand">False</property>534 <property name="expand">False</property>
535 <property name="fill">True</property>
578 <property name="position">1</property>536 <property name="position">1</property>
579 </packing>537 </packing>
580 </child>538 </child>
581 </object>539 </object>
540 <object class="GtkVBox" id="processing_vbox">
541 <property name="visible">True</property>
542 <property name="can_focus">False</property>
543 <property name="spacing">10</property>
544 <child>
545 <placeholder/>
546 </child>
547 </object>
582 <object class="GtkVBox" id="request_password_token_vbox">548 <object class="GtkVBox" id="request_password_token_vbox">
583 <property name="visible">True</property>549 <property name="visible">True</property>
550 <property name="can_focus">False</property>
584 <property name="spacing">10</property>551 <property name="spacing">10</property>
585 <child>552 <child>
586 <object class="GtkAlignment" id="alignment2">553 <object class="GtkAlignment" id="alignment2">
587 <property name="visible">True</property>554 <property name="visible">True</property>
555 <property name="can_focus">False</property>
588 <property name="xscale">0</property>556 <property name="xscale">0</property>
589 <property name="yscale">0</property>557 <property name="yscale">0</property>
590 <child>558 <child>
591 <object class="GtkVBox" id="request_password_token_details_vbox">559 <object class="GtkVBox" id="request_password_token_details_vbox">
592 <property name="visible">True</property>560 <property name="visible">True</property>
561 <property name="can_focus">False</property>
593 <property name="spacing">5</property>562 <property name="spacing">5</property>
594 <child>563 <child>
595 <placeholder/>564 <placeholder/>
@@ -598,20 +567,25 @@
598 </child>567 </child>
599 </object>568 </object>
600 <packing>569 <packing>
570 <property name="expand">True</property>
571 <property name="fill">True</property>
601 <property name="position">0</property>572 <property name="position">0</property>
602 </packing>573 </packing>
603 </child>574 </child>
604 <child>575 <child>
605 <object class="GtkHButtonBox" id="hbuttonbox7">576 <object class="GtkHButtonBox" id="hbuttonbox7">
606 <property name="visible">True</property>577 <property name="visible">True</property>
578 <property name="can_focus">False</property>
607 <property name="spacing">5</property>579 <property name="spacing">5</property>
608 <property name="layout_style">end</property>580 <property name="layout_style">end</property>
609 <child>581 <child>
610 <object class="GtkButton" id="request_password_token_cancel_button">582 <object class="GtkButton" id="request_password_token_cancel_button">
611 <property name="label">gtk-cancel</property>583 <property name="label">gtk-cancel</property>
584 <property name="use_action_appearance">False</property>
612 <property name="visible">True</property>585 <property name="visible">True</property>
613 <property name="can_focus">True</property>586 <property name="can_focus">True</property>
614 <property name="receives_default">True</property>587 <property name="receives_default">True</property>
588 <property name="use_action_appearance">False</property>
615 <property name="use_stock">True</property>589 <property name="use_stock">True</property>
616 </object>590 </object>
617 <packing>591 <packing>
@@ -623,11 +597,13 @@
623 <child>597 <child>
624 <object class="GtkButton" id="request_password_token_back_button">598 <object class="GtkButton" id="request_password_token_back_button">
625 <property name="label">gtk-go-back</property>599 <property name="label">gtk-go-back</property>
600 <property name="use_action_appearance">False</property>
626 <property name="visible">True</property>601 <property name="visible">True</property>
627 <property name="can_focus">True</property>602 <property name="can_focus">True</property>
628 <property name="receives_default">True</property>603 <property name="receives_default">True</property>
604 <property name="use_action_appearance">False</property>
629 <property name="use_stock">True</property>605 <property name="use_stock">True</property>
630 <signal name="clicked" handler="on_request_password_token_back_button_clicked"/>606 <signal name="clicked" handler="on_request_password_token_back_button_clicked" swapped="no"/>
631 </object>607 </object>
632 <packing>608 <packing>
633 <property name="expand">False</property>609 <property name="expand">False</property>
@@ -638,11 +614,13 @@
638 <child>614 <child>
639 <object class="GtkButton" id="request_password_token_ok_button">615 <object class="GtkButton" id="request_password_token_ok_button">
640 <property name="label">gtk-ok</property>616 <property name="label">gtk-ok</property>
617 <property name="use_action_appearance">False</property>
641 <property name="visible">True</property>618 <property name="visible">True</property>
642 <property name="can_focus">True</property>619 <property name="can_focus">True</property>
643 <property name="receives_default">True</property>620 <property name="receives_default">True</property>
621 <property name="use_action_appearance">False</property>
644 <property name="use_stock">True</property>622 <property name="use_stock">True</property>
645 <signal name="clicked" handler="on_request_password_token_ok_button_clicked"/>623 <signal name="clicked" handler="on_request_password_token_ok_button_clicked" swapped="no"/>
646 </object>624 </object>
647 <packing>625 <packing>
648 <property name="expand">False</property>626 <property name="expand">False</property>
@@ -653,35 +631,42 @@
653 </object>631 </object>
654 <packing>632 <packing>
655 <property name="expand">False</property>633 <property name="expand">False</property>
634 <property name="fill">True</property>
656 <property name="position">1</property>635 <property name="position">1</property>
657 </packing>636 </packing>
658 </child>637 </child>
659 </object>638 </object>
660 <object class="GtkVBox" id="set_new_password_vbox">639 <object class="GtkVBox" id="set_new_password_vbox">
661 <property name="visible">True</property>640 <property name="visible">True</property>
641 <property name="can_focus">False</property>
662 <property name="spacing">10</property>642 <property name="spacing">10</property>
663 <child>643 <child>
664 <object class="GtkVBox" id="vbox2">644 <object class="GtkVBox" id="vbox2">
665 <property name="visible">True</property>645 <property name="visible">True</property>
646 <property name="can_focus">False</property>
666 <child>647 <child>
667 <object class="GtkLabel" id="reset_password_help_label">648 <object class="GtkLabel" id="reset_password_help_label">
668 <property name="visible">True</property>649 <property name="visible">True</property>
650 <property name="can_focus">False</property>
669 <property name="label">label</property>651 <property name="label">label</property>
670 <property name="wrap">True</property>652 <property name="wrap">True</property>
671 </object>653 </object>
672 <packing>654 <packing>
673 <property name="expand">False</property>655 <property name="expand">False</property>
656 <property name="fill">True</property>
674 <property name="position">0</property>657 <property name="position">0</property>
675 </packing>658 </packing>
676 </child>659 </child>
677 <child>660 <child>
678 <object class="GtkAlignment" id="alignment1">661 <object class="GtkAlignment" id="alignment1">
679 <property name="visible">True</property>662 <property name="visible">True</property>
663 <property name="can_focus">False</property>
680 <property name="xscale">0</property>664 <property name="xscale">0</property>
681 <property name="yscale">0</property>665 <property name="yscale">0</property>
682 <child>666 <child>
683 <object class="GtkVBox" id="set_new_password_details_vbox">667 <object class="GtkVBox" id="set_new_password_details_vbox">
684 <property name="visible">True</property>668 <property name="visible">True</property>
669 <property name="can_focus">False</property>
685 <property name="spacing">5</property>670 <property name="spacing">5</property>
686 <child>671 <child>
687 <placeholder/>672 <placeholder/>
@@ -696,25 +681,32 @@
696 </child>681 </child>
697 </object>682 </object>
698 <packing>683 <packing>
684 <property name="expand">True</property>
685 <property name="fill">True</property>
699 <property name="position">1</property>686 <property name="position">1</property>
700 </packing>687 </packing>
701 </child>688 </child>
702 </object>689 </object>
703 <packing>690 <packing>
691 <property name="expand">True</property>
692 <property name="fill">True</property>
704 <property name="position">0</property>693 <property name="position">0</property>
705 </packing>694 </packing>
706 </child>695 </child>
707 <child>696 <child>
708 <object class="GtkHButtonBox" id="hbuttonbox6">697 <object class="GtkHButtonBox" id="hbuttonbox6">
709 <property name="visible">True</property>698 <property name="visible">True</property>
699 <property name="can_focus">False</property>
710 <property name="spacing">5</property>700 <property name="spacing">5</property>
711 <property name="layout_style">end</property>701 <property name="layout_style">end</property>
712 <child>702 <child>
713 <object class="GtkButton" id="set_new_password_cancel_button">703 <object class="GtkButton" id="set_new_password_cancel_button">
714 <property name="label">gtk-cancel</property>704 <property name="label">gtk-cancel</property>
705 <property name="use_action_appearance">False</property>
715 <property name="visible">True</property>706 <property name="visible">True</property>
716 <property name="can_focus">True</property>707 <property name="can_focus">True</property>
717 <property name="receives_default">True</property>708 <property name="receives_default">True</property>
709 <property name="use_action_appearance">False</property>
718 <property name="use_stock">True</property>710 <property name="use_stock">True</property>
719 </object>711 </object>
720 <packing>712 <packing>
@@ -726,11 +718,13 @@
726 <child>718 <child>
727 <object class="GtkButton" id="set_new_password_ok_button">719 <object class="GtkButton" id="set_new_password_ok_button">
728 <property name="label">gtk-ok</property>720 <property name="label">gtk-ok</property>
721 <property name="use_action_appearance">False</property>
729 <property name="visible">True</property>722 <property name="visible">True</property>
730 <property name="can_focus">True</property>723 <property name="can_focus">True</property>
731 <property name="receives_default">True</property>724 <property name="receives_default">True</property>
725 <property name="use_action_appearance">False</property>
732 <property name="use_stock">True</property>726 <property name="use_stock">True</property>
733 <signal name="clicked" handler="on_set_new_password_ok_button_clicked"/>727 <signal name="clicked" handler="on_set_new_password_ok_button_clicked" swapped="no"/>
734 </object>728 </object>
735 <packing>729 <packing>
736 <property name="expand">False</property>730 <property name="expand">False</property>
@@ -741,34 +735,104 @@
741 </object>735 </object>
742 <packing>736 <packing>
743 <property name="expand">False</property>737 <property name="expand">False</property>
744 <property name="position">1</property>738 <property name="fill">True</property>
745 </packing>739 <property name="position">1</property>
746 </child>740 </packing>
747 </object>741 </child>
748 <object class="GtkVBox" id="finish_vbox">742 </object>
749 <property name="visible">True</property>743 <object class="GtkVBox" id="tc_browser_vbox">
744 <property name="visible">True</property>
745 <property name="can_focus">False</property>
746 <signal name="hide" handler="on_tc_browser_vbox_hide" swapped="no"/>
747 <child>
748 <object class="GtkScrolledWindow" id="tc_browser_window">
749 <property name="visible">True</property>
750 <property name="can_focus">True</property>
751 <property name="border_width">10</property>
752 <property name="hscrollbar_policy">never</property>
753 <property name="shadow_type">in</property>
754 <child>
755 <placeholder/>
756 </child>
757 </object>
758 <packing>
759 <property name="expand">True</property>
760 <property name="fill">True</property>
761 <property name="position">0</property>
762 </packing>
763 </child>
764 <child>
765 <object class="GtkHButtonBox" id="hbuttonbox4">
766 <property name="visible">True</property>
767 <property name="can_focus">False</property>
768 <property name="layout_style">end</property>
769 <child>
770 <object class="GtkButton" id="tc_back_button">
771 <property name="label">gtk-go-back</property>
772 <property name="use_action_appearance">False</property>
773 <property name="visible">True</property>
774 <property name="can_focus">True</property>
775 <property name="receives_default">True</property>
776 <property name="use_action_appearance">False</property>
777 <property name="use_stock">True</property>
778 <signal name="clicked" handler="on_tc_back_button_clicked" swapped="no"/>
779 </object>
780 <packing>
781 <property name="expand">False</property>
782 <property name="fill">False</property>
783 <property name="position">0</property>
784 </packing>
785 </child>
786 </object>
787 <packing>
788 <property name="expand">False</property>
789 <property name="fill">True</property>
790 <property name="position">1</property>
791 </packing>
792 </child>
793 </object>
794 <object class="GtkVBox" id="verify_email_vbox">
795 <property name="visible">True</property>
796 <property name="can_focus">False</property>
750 <property name="spacing">10</property>797 <property name="spacing">10</property>
751 <child>798 <child>
752 <object class="GtkLabel" id="finish_label">799 <object class="GtkAlignment" id="alignment4">
753 <property name="visible">True</property>800 <property name="visible">True</property>
754 <property name="wrap">True</property>801 <property name="can_focus">False</property>
802 <property name="xscale">0</property>
803 <property name="yscale">0</property>
804 <child>
805 <object class="GtkVBox" id="verify_email_details_vbox">
806 <property name="visible">True</property>
807 <property name="can_focus">False</property>
808 <child>
809 <placeholder/>
810 </child>
811 </object>
812 </child>
755 </object>813 </object>
756 <packing>814 <packing>
815 <property name="expand">True</property>
816 <property name="fill">True</property>
757 <property name="position">0</property>817 <property name="position">0</property>
758 </packing>818 </packing>
759 </child>819 </child>
760 <child>820 <child>
761 <object class="GtkHButtonBox" id="hbuttonbox8">821 <object class="GtkHButtonBox" id="hbuttonbox2">
762 <property name="visible">True</property>822 <property name="visible">True</property>
823 <property name="can_focus">False</property>
824 <property name="spacing">5</property>
763 <property name="layout_style">end</property>825 <property name="layout_style">end</property>
764 <child>826 <child>
765 <object class="GtkButton" id="finish_close_button">827 <object class="GtkButton" id="verify_token_button">
766 <property name="label">gtk-close</property>828 <property name="label">gtk-ok</property>
829 <property name="use_action_appearance">False</property>
767 <property name="visible">True</property>830 <property name="visible">True</property>
768 <property name="can_focus">True</property>831 <property name="can_focus">True</property>
769 <property name="receives_default">True</property>832 <property name="receives_default">True</property>
833 <property name="use_action_appearance">False</property>
770 <property name="use_stock">True</property>834 <property name="use_stock">True</property>
771 <signal name="clicked" handler="on_close_clicked"/>835 <signal name="clicked" handler="on_verify_token_button_clicked" swapped="no"/>
772 </object>836 </object>
773 <packing>837 <packing>
774 <property name="expand">False</property>838 <property name="expand">False</property>
@@ -779,8 +843,78 @@
779 </object>843 </object>
780 <packing>844 <packing>
781 <property name="expand">False</property>845 <property name="expand">False</property>
846 <property name="fill">True</property>
782 <property name="position">1</property>847 <property name="position">1</property>
783 </packing>848 </packing>
784 </child>849 </child>
785 </object>850 </object>
851 <object class="GtkWindow" id="window">
852 <property name="can_focus">False</property>
853 <property name="border_width">10</property>
854 <property name="window_position">center</property>
855 <signal name="delete-event" handler="on_close_clicked" swapped="no"/>
856 <child>
857 <object class="GtkVBox" id="window_vbox">
858 <property name="visible">True</property>
859 <property name="can_focus">False</property>
860 <property name="spacing">5</property>
861 <child>
862 <object class="GtkLabel" id="header_label">
863 <property name="visible">True</property>
864 <property name="can_focus">False</property>
865 <property name="xalign">0</property>
866 <property name="label" translatable="yes">Header Label </property>
867 <property name="wrap">True</property>
868 </object>
869 <packing>
870 <property name="expand">False</property>
871 <property name="fill">True</property>
872 <property name="padding">5</property>
873 <property name="position">0</property>
874 </packing>
875 </child>
876 <child>
877 <object class="GtkLabel" id="help_label">
878 <property name="visible">True</property>
879 <property name="can_focus">False</property>
880 <property name="xalign">0</property>
881 <property name="label" translatable="yes">help label</property>
882 <property name="wrap">True</property>
883 </object>
884 <packing>
885 <property name="expand">False</property>
886 <property name="fill">True</property>
887 <property name="position">1</property>
888 </packing>
889 </child>
890 <child>
891 <object class="GtkLabel" id="warning_label">
892 <property name="visible">True</property>
893 <property name="can_focus">False</property>
894 <property name="xalign">0</property>
895 <property name="label" translatable="yes">warning label</property>
896 <property name="wrap">True</property>
897 </object>
898 <packing>
899 <property name="expand">False</property>
900 <property name="fill">True</property>
901 <property name="position">2</property>
902 </packing>
903 </child>
904 <child>
905 <object class="GtkNotebook" id="content">
906 <property name="visible">True</property>
907 <property name="can_focus">True</property>
908 <property name="show_tabs">False</property>
909 <property name="show_border">False</property>
910 </object>
911 <packing>
912 <property name="expand">True</property>
913 <property name="fill">True</property>
914 <property name="position">3</property>
915 </packing>
916 </child>
917 </object>
918 </child>
919 </object>
786</interface>920</interface>
787921
=== modified file 'run-tests'
--- run-tests 2012-02-01 19:19:32 +0000
+++ run-tests 2012-02-02 18:14:19 +0000
@@ -22,13 +22,6 @@
2222
23set -e23set -e
2424
25if [ "$1" == "-qt" ]; then
26 USE_QT=1
27 shift
28else
29 USE_QT=0
30fi
31
32if [ $# -ne 0 ]; then25if [ $# -ne 0 ]; then
33 # run specific module given by the caller26 # run specific module given by the caller
34 MODULE="$@"27 MODULE="$@"
@@ -48,13 +41,18 @@
4841
49unset GTK_MODULES42unset GTK_MODULES
5043
44echo "*** Running test suite for ""$MODULE"" ***"
45`which xvfb-run` u1trial --reactor=gi -p "$QT_TESTS_PATH, $GTK_TESTS_PATH" -i "test_windows.py" "$MODULE"
46rm -rf _trial_temp
47
48echo "*** Running GTK test suite ***"
49`which xvfb-run` u1trial --reactor=gi --gui "$GTK_TESTS_PATH"
50rm -rf _trial_temp
51
52echo "*** Running QT test suite ***"
51./setup.py build53./setup.py build
52echo "Running test suite for ""$MODULE"54USE_QT_MAINLOOP=True `which xvfb-run` u1trial --reactor=qt4 --gui "$QT_TESTS_PATH"
53if [ "$USE_QT" -eq 0 ]; then55rm -rf _trial_temp
54 `which xvfb-run` u1trial --ignore-paths "$QT_TESTS_PATH" -i "$WINDOWS_TESTS" "$MODULE"56rm -rf build
55else57
56 `which xvfb-run` u1trial --ignore-paths "$GTK_TESTS_PATH" -i "$WINDOWS_TESTS" --reactor=qt4 --gui "$MODULE"
57fi
58style_check58style_check
59rm -rf _trial_temp
60rm -rf build
6159
=== modified file 'ubuntu_sso/account.py'
--- ubuntu_sso/account.py 2012-01-26 13:25:13 +0000
+++ ubuntu_sso/account.py 2012-02-02 18:14:19 +0000
@@ -16,7 +16,11 @@
16#16#
17# You should have received a copy of the GNU General Public License along17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.18# with this program. If not, see <http://www.gnu.org/licenses/>.
19"""Single Sign On account management."""19"""Single Sign On account management.
20
21All the methods in Account expect unicode as parameters.
22
23"""
2024
21import os25import os
22import re26import re
@@ -188,7 +192,7 @@
188 try:192 try:
189 credentials = yield restful_client.restcall(193 credentials = yield restful_client.restcall(
190 u"authentications.authenticate",194 u"authentications.authenticate",
191 token_name=token_name.decode("utf-8"))195 token_name=token_name)
192 except WebClientError:196 except WebClientError:
193 logger.exception('login failed with:')197 logger.exception('login failed with:')
194 raise AuthenticationError()198 raise AuthenticationError()
@@ -218,7 +222,7 @@
218 'email_token: %r, token_name: %r.',222 'email_token: %r, token_name: %r.',
219 email, email_token, token_name)223 email, email_token, token_name)
220 credentials = yield self.login(email=email, password=password,224 credentials = yield self.login(email=email, password=password,
221 token_name=token_name.decode("utf-8"))225 token_name=token_name)
222 restful_client = restful.RestfulClient(self.service_url,226 restful_client = restful.RestfulClient(self.service_url,
223 oauth_credentials=credentials)227 oauth_credentials=credentials)
224 result = yield restful_client.restcall(u"accounts.validate_email",228 result = yield restful_client.restcall(u"accounts.validate_email",
225229
=== modified file 'ubuntu_sso/gtk/__init__.py'
--- ubuntu_sso/gtk/__init__.py 2010-11-19 19:53:22 +0000
+++ ubuntu_sso/gtk/__init__.py 2012-02-02 18:14:19 +0000
@@ -1,8 +1,6 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2#2#
3# Author: Natalia Bidart <natalia.bidart@canonical.com>3# Copyright 2009-2012 Canonical Ltd.
4#
5# Copyright 2009-2010 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
97
=== modified file 'ubuntu_sso/gtk/gui.py'
--- ubuntu_sso/gtk/gui.py 2012-01-17 21:18:24 +0000
+++ ubuntu_sso/gtk/gui.py 2012-02-02 18:14:19 +0000
@@ -1,6 +1,6 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2#2#
3# Copyright 2010 Canonical Ltd.3# Copyright 2010-2012 Canonical Ltd.
4#4#
5# 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
6# 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
@@ -24,8 +24,10 @@
2424
25from functools import wraps25from functools import wraps
2626
27import gtk27# pylint: disable=E0611,F0401
2828from gi.repository import Gdk, Gtk
29from gi.repository.GdkX11 import X11Window
30# pylint: enable=E0611,F0401
29from twisted.internet import defer31from twisted.internet import defer
3032
31from ubuntu_sso import (33from ubuntu_sso import (
@@ -33,7 +35,7 @@
33 NO_OP,35 NO_OP,
34 utils,36 utils,
35)37)
36from ubuntu_sso.logger import setup_logging38from ubuntu_sso.logger import setup_gui_logging
37from ubuntu_sso.utils.ui import (39from ubuntu_sso.utils.ui import (
38 CAPTCHA_LOAD_ERROR,40 CAPTCHA_LOAD_ERROR,
39 CAPTCHA_RELOAD_TOOLTIP,41 CAPTCHA_RELOAD_TOOLTIP,
@@ -72,7 +74,19 @@
72# pylint: disable=E110174# pylint: disable=E1101
7375
7476
75logger = setup_logging('ubuntu_sso.gui')77logger = setup_gui_logging('ubuntu_sso.gui.gtk')
78
79
80# pylint: disable=C0103
81def parse_color(color):
82 """Parse a string color into Gdk.Color."""
83 c = Gdk.RGBA()
84 result = c.parse(color)
85 if not result:
86 logger.warning('Could not parse color %r.', color)
87 return c
88# pylint: enable=C0103
89
7690
77# To be removed when Python bindings provide these constants91# To be removed when Python bindings provide these constants
78# as per http://code.google.com/p/pywebkitgtk/issues/detail?id=4492# as per http://code.google.com/p/pywebkitgtk/issues/detail?id=44
@@ -92,8 +106,8 @@
92106
93DEFAULT_WIDTH = 30107DEFAULT_WIDTH = 30
94# To be replaced by values from the theme (LP: #616526)108# To be replaced by values from the theme (LP: #616526)
95HELP_TEXT_COLOR = gtk.gdk.Color("#bfbfbf")109HELP_TEXT_COLOR = parse_color("#bfbfbf")
96WARNING_TEXT_COLOR = gtk.gdk.Color("red")110WARNING_TEXT_COLOR = parse_color("red")
97111
98USER_CANCELLATION = 10112USER_CANCELLATION = 10
99LOGIN_SUCCESS = REGISTRATION_SUCCESS = 0113LOGIN_SUCCESS = REGISTRATION_SUCCESS = 0
@@ -111,9 +125,12 @@
111 return inner125 return inner
112126
113127
114class LabeledEntry(gtk.Entry):128class LabeledEntry(Gtk.Entry):
115 """An entry that displays the label within itself ina grey color."""129 """An entry that displays the label within itself ina grey color."""
116130
131 # Use of super on an old style class
132 # pylint: disable=E1002
133
117 def __init__(self, label, is_password=False, *args, **kwargs):134 def __init__(self, label, is_password=False, *args, **kwargs):
118 self.label = label135 self.label = label
119 self.is_password = is_password136 self.is_password = is_password
@@ -133,7 +150,8 @@
133 """Clear text and restore text color."""150 """Clear text and restore text color."""
134 self.set_text(self.get_text())151 self.set_text(self.get_text())
135152
136 self.modify_text(gtk.STATE_NORMAL, None) # restore to theme's default153 # restore to theme's default
154 self.override_color(Gtk.StateFlags.NORMAL, None)
137155
138 if self.is_password:156 if self.is_password:
139 self.set_visibility(False)157 self.set_visibility(False)
@@ -146,7 +164,7 @@
146 return164 return
147165
148 self.set_text(self.label)166 self.set_text(self.label)
149 self.modify_text(gtk.STATE_NORMAL, HELP_TEXT_COLOR)167 self.override_color(Gtk.StateFlags.NORMAL, HELP_TEXT_COLOR)
150168
151 if self.is_password:169 if self.is_password:
152 self.set_visibility(True)170 self.set_visibility(True)
@@ -163,7 +181,7 @@
163 def set_warning(self, warning_msg):181 def set_warning(self, warning_msg):
164 """Display warning as secondary icon, set 'warning_msg' as tooltip."""182 """Display warning as secondary icon, set 'warning_msg' as tooltip."""
165 self.warning = warning_msg183 self.warning = warning_msg
166 self.set_property('secondary-icon-stock', gtk.STOCK_DIALOG_WARNING)184 self.set_property('secondary-icon-stock', Gtk.STOCK_DIALOG_WARNING)
167 self.set_property('secondary-icon-sensitive', True)185 self.set_property('secondary-icon-sensitive', True)
168 self.set_property('secondary-icon-activatable', False)186 self.set_property('secondary-icon-activatable', False)
169 self.set_property('secondary-icon-tooltip-text', warning_msg)187 self.set_property('secondary-icon-tooltip-text', warning_msg)
@@ -185,8 +203,6 @@
185 logger.debug('UbuntuSSOClientGUI: app_name %r, kwargs %r.',203 logger.debug('UbuntuSSOClientGUI: app_name %r, kwargs %r.',
186 app_name, kwargs)204 app_name, kwargs)
187205
188 gtk.link_button_set_uri_hook(NO_OP)
189
190 self._captcha_filename = tempfile.mktemp()206 self._captcha_filename = tempfile.mktemp()
191 self._captcha_id = None207 self._captcha_id = None
192 self._signals_receivers = {}208 self._signals_receivers = {}
@@ -211,19 +227,18 @@
211 self.user_password = None227 self.user_password = None
212228
213 ui_filename = get_data_file('gtk', 'ui.glade')229 ui_filename = get_data_file('gtk', 'ui.glade')
214 builder = gtk.Builder()230 builder = Gtk.Builder()
215 builder.add_from_file(ui_filename)231 builder.add_from_file(ui_filename)
216 builder.connect_signals(self)232 builder.connect_signals(self)
217233
218 self.widgets = []234 self.widgets = []
219 self.warnings = []235 self.warnings = []
220 self.cancels = []236 self.cancels = []
221 self.labels = []
222 for obj in builder.get_objects():237 for obj in builder.get_objects():
223 name = getattr(obj, 'name', None)238 name = getattr(obj, 'name', None)
224 if name is None and isinstance(obj, gtk.Buildable):239 if name is None and isinstance(obj, Gtk.Buildable):
225 # work around bug lp:507739240 # work around bug lp:507739
226 name = gtk.Buildable.get_name(obj)241 name = Gtk.Buildable.get_name(obj)
227 if name is None:242 if name is None:
228 logging.warn("%s has no name (??)", obj)243 logging.warn("%s has no name (??)", obj)
229 else:244 else:
@@ -235,9 +250,6 @@
235 if 'cancel_button' in name:250 if 'cancel_button' in name:
236 obj.connect('clicked', self.on_close_clicked)251 obj.connect('clicked', self.on_close_clicked)
237 self.cancels.append(obj)252 self.cancels.append(obj)
238 if 'label' in name:
239 obj.connect('size-allocate', self.on_size_allocate)
240 self.labels.append(obj)
241253
242 self.entries = (u'name_entry', u'email1_entry', u'email2_entry',254 self.entries = (u'name_entry', u'email1_entry', u'email2_entry',
243 u'password1_entry', u'password2_entry',255 u'password1_entry', u'password2_entry',
@@ -297,7 +309,10 @@
297 # still do everything as a standalone window. Also,309 # still do everything as a standalone window. Also,
298 # window_foreign_new may return None breaking set_transient_for.310 # window_foreign_new may return None breaking set_transient_for.
299 try:311 try:
300 win = gtk.gdk.window_foreign_new(window_id)312 display = Gdk.Display.get_default()
313 # this is not working, we need to create a XLib.window
314 # as a second parameter to foreign_new_for_display
315 win = X11Window.foreign_new_for_display(display, None)
301 self.window.realize()316 self.window.realize()
302 self.window.window.set_transient_for(win)317 self.window.window.set_transient_for(win)
303 except: # pylint: disable=W0702318 except: # pylint: disable=W0702
@@ -366,20 +381,21 @@
366381
367 def _add_spinner_to_container(self, container, legend=None):382 def _add_spinner_to_container(self, container, legend=None):
368 """Add a spinner to 'container'."""383 """Add a spinner to 'container'."""
369 spinner = gtk.Spinner()384 spinner = Gtk.Spinner()
370 spinner.start()385 spinner.start()
371386
372 label = gtk.Label()387 label = Gtk.Label()
373 if legend:388 if legend:
374 label.set_text(legend)389 label.set_text(legend)
375 else:390 else:
376 label.set_text(LOADING)391 label.set_text(LOADING)
377392
378 hbox = gtk.HBox(spacing=5)393 hbox = Gtk.HBox(spacing=5)
379 hbox.pack_start(spinner, expand=False)394 hbox.pack_start(spinner, expand=False, fill=True, padding=0)
380 hbox.pack_start(label, expand=False)395 hbox.pack_start(label, expand=False, fill=True, padding=0)
381396
382 alignment = gtk.Alignment(xalign=0.5, yalign=0.5)397 alignment = Gtk.Alignment(xalign=0.5, yalign=0.5,
398 xscale=0, yscale=0)
383 alignment.add(hbox)399 alignment.add(hbox)
384 alignment.show_all()400 alignment.show_all()
385401
@@ -394,7 +410,7 @@
394 def _set_warning_message(self, widget, message):410 def _set_warning_message(self, widget, message):
395 """Set 'message' as text for 'widget'."""411 """Set 'message' as text for 'widget'."""
396 widget.set_text(message)412 widget.set_text(message)
397 widget.modify_fg(gtk.STATE_NORMAL, WARNING_TEXT_COLOR)413 widget.override_color(Gtk.StateFlags.NORMAL, WARNING_TEXT_COLOR)
398 widget.show()414 widget.show()
399415
400 def _clear_warnings(self):416 def _clear_warnings(self):
@@ -433,7 +449,7 @@
433449
434 def _append_page(self, page):450 def _append_page(self, page):
435 """Append 'page' to the 'window'."""451 """Append 'page' to the 'window'."""
436 self.content.append_page(page)452 self.content.append_page(page, None)
437453
438 def _set_header(self, header):454 def _set_header(self, header):
439 """Set 'header' as the window title and header."""455 """Set 'header' as the window title and header."""
@@ -472,8 +488,8 @@
472 """Present a spinner to the user while the captcha is downloaded."""488 """Present a spinner to the user while the captcha is downloaded."""
473 self.captcha_image.hide()489 self.captcha_image.hide()
474 self._add_spinner_to_container(self.captcha_loading)490 self._add_spinner_to_container(self.captcha_loading)
475 white = gtk.gdk.Color('white')491 self.captcha_loading.override_background_color(Gtk.StateFlags.NORMAL,
476 self.captcha_loading.modify_bg(gtk.STATE_NORMAL, white)492 parse_color('white'))
477 self.captcha_loading.show_all()493 self.captcha_loading.show_all()
478 self.join_ok_button.set_sensitive(False)494 self.join_ok_button.set_sensitive(False)
479495
@@ -490,20 +506,26 @@
490 self.enter_details_vbox.header = JOIN_HEADER_LABEL % d506 self.enter_details_vbox.header = JOIN_HEADER_LABEL % d
491 self.enter_details_vbox.help_text = self.help_text507 self.enter_details_vbox.help_text = self.help_text
492 self.enter_details_vbox.default_widget = self.join_ok_button508 self.enter_details_vbox.default_widget = self.join_ok_button
493 self.join_ok_button.set_flags(gtk.CAN_DEFAULT)509 self.join_ok_button.set_can_default(True)
494510
495 self.enter_details_vbox.pack_start(self.name_entry, expand=False)511 self.enter_details_vbox.pack_start(self.name_entry,
512 expand=False, fill=True, padding=0)
496 self.enter_details_vbox.reorder_child(self.name_entry, 0)513 self.enter_details_vbox.reorder_child(self.name_entry, 0)
497 entry = self.captcha_solution_entry514 entry = self.captcha_solution_entry
498 self.captcha_solution_vbox.pack_start(entry, expand=False)515 self.captcha_solution_vbox.pack_start(entry,
516 expand=False, fill=True, padding=0)
499 msg = CAPTCHA_RELOAD_TOOLTIP517 msg = CAPTCHA_RELOAD_TOOLTIP
500 self.captcha_reload_button.set_tooltip_text(msg)518 self.captcha_reload_button.set_tooltip_text(msg)
501519
502 self.emails_hbox.pack_start(self.email1_entry, expand=False)520 self.emails_hbox.pack_start(self.email1_entry,
503 self.emails_hbox.pack_start(self.email2_entry, expand=False)521 expand=False, fill=True, padding=0)
522 self.emails_hbox.pack_start(self.email2_entry,
523 expand=False, fill=True, padding=0)
504524
505 self.passwords_hbox.pack_start(self.password1_entry, expand=False)525 self.passwords_hbox.pack_start(self.password1_entry,
506 self.passwords_hbox.pack_start(self.password2_entry, expand=False)526 expand=False, fill=True, padding=0)
527 self.passwords_hbox.pack_start(self.password2_entry,
528 expand=False, fill=True, padding=0)
507 help_msg = '<small>%s</small>' % PASSWORD_HELP529 help_msg = '<small>%s</small>' % PASSWORD_HELP
508 self.password_help_label.set_markup(help_msg)530 self.password_help_label.set_markup(help_msg)
509531
@@ -519,7 +541,7 @@
519 self.yes_to_tc_checkbutton.set_label(msg)541 self.yes_to_tc_checkbutton.set_label(msg)
520 self.tc_button.set_label(TC_BUTTON)542 self.tc_button.set_label(TC_BUTTON)
521 else:543 else:
522 self.tc_vbox.hide_all()544 self.tc_vbox.hide()
523 self.login_button.set_label(LOGIN_BUTTON_LABEL)545 self.login_button.set_label(LOGIN_BUTTON_LABEL)
524546
525 return self.enter_details_vbox547 return self.enter_details_vbox
@@ -528,7 +550,7 @@
528 """Build the Terms & Conditions page."""550 """Build the Terms & Conditions page."""
529 self.tc_browser_vbox.help_text = ''551 self.tc_browser_vbox.help_text = ''
530 self.tc_browser_vbox.default_widget = self.tc_back_button552 self.tc_browser_vbox.default_widget = self.tc_back_button
531 self.tc_browser_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)553 self.tc_browser_vbox.default_widget.set_can_default(True)
532 return self.tc_browser_vbox554 return self.tc_browser_vbox
533555
534 def _build_processing_page(self):556 def _build_processing_page(self):
@@ -541,17 +563,16 @@
541 def _build_verify_email_page(self):563 def _build_verify_email_page(self):
542 """Build the verify email page."""564 """Build the verify email page."""
543 self.verify_email_vbox.default_widget = self.verify_token_button565 self.verify_email_vbox.default_widget = self.verify_token_button
544 self.verify_email_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)566 self.verify_email_vbox.default_widget.set_can_default(True)
545567
546 self.verify_email_details_vbox.pack_start(self.email_token_entry,568 self.verify_email_details_vbox.pack_start(self.email_token_entry,
547 expand=False)569 expand=False, fill=True, padding=0)
548
549 return self.verify_email_vbox570 return self.verify_email_vbox
550571
551 def _build_finish_page(self):572 def _build_finish_page(self):
552 """Build the success page."""573 """Build the success page."""
553 self.finish_vbox.default_widget = self.finish_close_button574 self.finish_vbox.default_widget = self.finish_close_button
554 self.finish_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)575 self.finish_vbox.default_widget.set_can_default(True)
555 self.finish_vbox.label = self.finish_label576 self.finish_vbox.label = self.finish_label
556 return self.finish_vbox577 return self.finish_vbox
557578
@@ -561,11 +582,13 @@
561 self.login_vbox.header = LOGIN_HEADER_LABEL % d582 self.login_vbox.header = LOGIN_HEADER_LABEL % d
562 self.login_vbox.help_text = CONNECT_HELP_LABEL % d583 self.login_vbox.help_text = CONNECT_HELP_LABEL % d
563 self.login_vbox.default_widget = self.login_ok_button584 self.login_vbox.default_widget = self.login_ok_button
564 self.login_vbox.default_widget.set_flags(gtk.CAN_DEFAULT)585 self.login_vbox.default_widget.set_can_default(True)
565586
566 self.login_details_vbox.pack_start(self.login_email_entry)587 self.login_details_vbox.pack_start(self.login_email_entry,
588 expand=True, fill=True, padding=0)
567 self.login_details_vbox.reorder_child(self.login_email_entry, 0)589 self.login_details_vbox.reorder_child(self.login_email_entry, 0)
568 self.login_details_vbox.pack_start(self.login_password_entry)590 self.login_details_vbox.pack_start(self.login_password_entry,
591 expand=True, fill=True, padding=0)
569 self.login_details_vbox.reorder_child(self.login_password_entry, 1)592 self.login_details_vbox.reorder_child(self.login_password_entry, 1)
570593
571 msg = FORGOTTEN_PASSWORD_BUTTON594 msg = FORGOTTEN_PASSWORD_BUTTON
@@ -580,12 +603,12 @@
580 text = REQUEST_PASSWORD_TOKEN_LABEL % {'app_name': self.app_label}603 text = REQUEST_PASSWORD_TOKEN_LABEL % {'app_name': self.app_label}
581 self.request_password_token_vbox.help_text = text604 self.request_password_token_vbox.help_text = text
582 btn = self.request_password_token_ok_button605 btn = self.request_password_token_ok_button
583 btn.set_flags(gtk.CAN_DEFAULT)606 btn.set_can_default(True)
584 self.request_password_token_vbox.default_widget = btn607 self.request_password_token_vbox.default_widget = btn
585608
586 entry = self.reset_email_entry609 entry = self.reset_email_entry
587 self.request_password_token_details_vbox.pack_start(entry,610 self.request_password_token_details_vbox.pack_start(entry,
588 expand=False)611 expand=False, fill=True, padding=0)
589 cb = self.on_reset_email_entry_changed612 cb = self.on_reset_email_entry_changed
590 self.reset_email_entry.connect('changed', cb)613 self.reset_email_entry.connect('changed', cb)
591 self.request_password_token_ok_button.set_label(NEXT)614 self.request_password_token_ok_button.set_label(NEXT)
@@ -598,13 +621,14 @@
598 self.set_new_password_vbox.header = RESET_PASSWORD621 self.set_new_password_vbox.header = RESET_PASSWORD
599 self.set_new_password_vbox.help_text = SET_NEW_PASSWORD_LABEL622 self.set_new_password_vbox.help_text = SET_NEW_PASSWORD_LABEL
600 btn = self.set_new_password_ok_button623 btn = self.set_new_password_ok_button
601 btn.set_flags(gtk.CAN_DEFAULT)624 btn.set_can_default(True)
602 self.set_new_password_vbox.default_widget = btn625 self.set_new_password_vbox.default_widget = btn
603626
604 for entry in (self.reset_code_entry,627 for entry in (self.reset_code_entry,
605 self.reset_password1_entry,628 self.reset_password1_entry,
606 self.reset_password2_entry):629 self.reset_password2_entry):
607 self.set_new_password_details_vbox.pack_start(entry, expand=False)630 self.set_new_password_details_vbox.pack_start(entry,
631 expand=False, fill=True, padding=0)
608632
609 cb = self.on_set_new_password_entries_changed633 cb = self.on_set_new_password_entries_changed
610 self.reset_code_entry.connect('changed', cb)634 self.reset_code_entry.connect('changed', cb)
@@ -645,6 +669,11 @@
645669
646 # GTK callbacks670 # GTK callbacks
647671
672 def destroy(self):
673 """Destroy this UI."""
674 self.window.hide()
675 self.window.destroy()
676
648 def connect(self, signal_name, handler, *args, **kwargs):677 def connect(self, signal_name, handler, *args, **kwargs):
649 """Connect 'signal_name' with 'handler'."""678 """Connect 'signal_name' with 'handler'."""
650 logger.debug('connect: signal %r, handler %r, args %r, kwargs, %r',679 logger.debug('connect: signal %r, handler %r, args %r, kwargs, %r',
@@ -661,9 +690,9 @@
661 self._done = True690 self._done = True
662 self._set_current_page(self.error_vbox)691 self._set_current_page(self.error_vbox)
663692
664 def on_size_allocate(self, widget, allocation):693 def on_activate_link(self, button):
665 """The widget can re rezised, embrase it!."""694 """Do nothing, used for LinkButtons that are used as regular ones."""
666 widget.set_size_request(allocation.width - 2, -1)695 return True
667696
668 def on_close_clicked(self, *args, **kwargs):697 def on_close_clicked(self, *args, **kwargs):
669 """Call self.close_callback if defined."""698 """Call self.close_callback if defined."""
@@ -678,8 +707,8 @@
678 self.window.hide()707 self.window.hide()
679708
680 # process any pending events before callbacking with result709 # process any pending events before callbacking with result
681 while gtk.events_pending():710 while Gtk.events_pending():
682 gtk.main_iteration()711 Gtk.main_iteration()
683712
684 return_code = LOGIN_SUCCESS713 return_code = LOGIN_SUCCESS
685 if not self._done:714 if not self._done:
@@ -751,8 +780,9 @@
751 ' name %r, captcha_id %r and captcha_solution %r.', email1,780 ' name %r, captcha_id %r and captcha_solution %r.', email1,
752 name, self._captcha_id, captcha_solution)781 name, self._captcha_id, captcha_solution)
753 f = self.backend.register_user782 f = self.backend.register_user
754 f(self.app_name, email1, password1, name,783 f(unicode(self.app_name), email1.decode('utf8'),
755 self._captcha_id, captcha_solution,784 password1.decode('utf8'), name.decode('utf8'),
785 unicode(self._captcha_id), captcha_solution.decode('utf8'),
756 reply_handler=NO_OP, error_handler=NO_OP)786 reply_handler=NO_OP, error_handler=NO_OP)
757787
758 def on_verify_token_button_clicked(self, *args, **kwargs):788 def on_verify_token_button_clicked(self, *args, **kwargs):
@@ -902,8 +932,8 @@
902 def on_tc_button_clicked(self, *args, **kwargs):932 def on_tc_button_clicked(self, *args, **kwargs):
903 """The T&C button was clicked, create the browser and load terms."""933 """The T&C button was clicked, create the browser and load terms."""
904 # delay the import of webkit to be able to build without it934 # delay the import of webkit to be able to build without it
905 import webkit935 from gi.repository import WebKit # pylint: disable=E0611
906 browser = webkit.WebView()936 browser = WebKit.WebView()
907937
908 # The signal WebKitWebView::load-finished is deprecated and should not938 # The signal WebKitWebView::load-finished is deprecated and should not
909 # be used in newly-written code. Use the "load-status" property939 # be used in newly-written code. Use the "load-status" property
910940
=== modified file 'ubuntu_sso/gtk/main.py'
--- ubuntu_sso/gtk/main.py 2012-01-16 21:10:12 +0000
+++ ubuntu_sso/gtk/main.py 2012-02-02 18:14:19 +0000
@@ -18,7 +18,9 @@
1818
19import argparse19import argparse
2020
21import gtk21# pylint: disable=E0611
22from gi.repository import Gtk
23# pylint: enable=E0611
2224
23from ubuntu_sso.gtk.gui import UbuntuSSOClientGUI25from ubuntu_sso.gtk.gui import UbuntuSSOClientGUI
2426
@@ -45,5 +47,5 @@
4547
46def main(**kwargs):48def main(**kwargs):
47 """Start the GTK mainloop and open the main window."""49 """Start the GTK mainloop and open the main window."""
48 UbuntuSSOClientGUI(close_callback=gtk.main_quit, **kwargs)50 UbuntuSSOClientGUI(close_callback=Gtk.main_quit, **kwargs)
49 gtk.main()51 Gtk.main()
5052
=== modified file 'ubuntu_sso/gtk/tests/__init__.py'
--- ubuntu_sso/gtk/tests/__init__.py 2010-11-19 19:53:22 +0000
+++ ubuntu_sso/gtk/tests/__init__.py 2012-02-02 18:14:19 +0000
@@ -1,8 +1,6 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2#2#
3# Author: Natalia Bidart <natalia.bidart@canonical.com>3# Copyright 2009-2012 Canonical Ltd.
4#
5# Copyright 2009 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
97
=== modified file 'ubuntu_sso/gtk/tests/test_gui.py'
--- ubuntu_sso/gtk/tests/test_gui.py 2012-01-17 21:18:24 +0000
+++ ubuntu_sso/gtk/tests/test_gui.py 2012-02-02 18:14:19 +0000
@@ -21,8 +21,9 @@
2121
22from collections import defaultdict22from collections import defaultdict
2323
24import gtk24# pylint: disable=E0611
25import webkit25from gi.repository import Gdk, Gtk, WebKit
26# pylint: enable=E0611
2627
27from twisted.internet import defer28from twisted.internet import defer
28from twisted.trial.unittest import TestCase29from twisted.trial.unittest import TestCase
@@ -42,6 +43,9 @@
42# Instance of 'UbuntuSSOClientGUI' has no 'yyy' member43# Instance of 'UbuntuSSOClientGUI' has no 'yyy' member
43# pylint: disable=E1101,E110344# pylint: disable=E1101,E1103
4445
46# Use of super on an old style class
47# pylint: disable=E1002
48
4549
46class FakedSSOBackend(object):50class FakedSSOBackend(object):
47 """Fake a SSO Backend."""51 """Fake a SSO Backend."""
@@ -99,7 +103,7 @@
99 self[prop_name] = newval103 self[prop_name] = newval
100104
101105
102class FakedEmbeddedBrowser(gtk.TextView):106class FakedEmbeddedBrowser(Gtk.TextView):
103 """Faked an embedded browser."""107 """Faked an embedded browser."""
104108
105 def __init__(self):109 def __init__(self):
@@ -156,6 +160,14 @@
156 """Set _called to True."""160 """Set _called to True."""
157 self._called = (args, kwargs)161 self._called = (args, kwargs)
158162
163 def assert_color_equal(self, rgba_color, gdk_color):
164 """Check that 'rgba_color' is the same as 'gdk_color'."""
165 tmp = Gdk.RGBA()
166 assert tmp.parse(gdk_color.to_string())
167
168 msg = 'Text color must be "%s" (got "%s" instead).'
169 self.assertEqual(rgba_color, tmp, msg % (rgba_color, tmp))
170
159171
160class LabeledEntryTestCase(BasicTestCase):172class LabeledEntryTestCase(BasicTestCase):
161 """Test suite for the labeled entry."""173 """Test suite for the labeled entry."""
@@ -168,9 +180,11 @@
168 self.entry = gui.LabeledEntry(label=self.label)180 self.entry = gui.LabeledEntry(label=self.label)
169181
170 # we need a window to be able to realize ourselves182 # we need a window to be able to realize ourselves
171 window = gtk.Window()183 window = Gtk.Window()
172 window.add(self.entry)184 window.add(self.entry)
173 window.show_all()185 window.show_all()
186 self.addCleanup(window.hide)
187 self.addCleanup(window.destroy)
174188
175 def grab_focus(self, focus_in=True):189 def grab_focus(self, focus_in=True):
176 """Grab focus on widget, if None use self.entry."""190 """Grab focus on widget, if None use self.entry."""
@@ -188,10 +202,9 @@
188 self.assertEqual(expected, actual, msg % (expected, actual))202 self.assertEqual(expected, actual, msg % (expected, actual))
189203
190 # text color is correct204 # text color is correct
191 msg = 'Text color must be "%s" (got "%s" instead).'
192 expected = gui.HELP_TEXT_COLOR205 expected = gui.HELP_TEXT_COLOR
193 actual = self.entry.style.text[gtk.STATE_NORMAL]206 actual = self.entry.get_style().text[Gtk.StateFlags.NORMAL]
194 self.assertEqual(expected, actual, msg % (expected, actual))207 self.assert_color_equal(expected, actual)
195208
196 def test_initial_text(self):209 def test_initial_text(self):
197 """Entry have the correct text at startup."""210 """Entry have the correct text at startup."""
@@ -218,11 +231,11 @@
218231
219 def test_text_defaults_to_theme_color_when_focus_in(self):232 def test_text_defaults_to_theme_color_when_focus_in(self):
220 """Entry restore its text color when focused in."""233 """Entry restore its text color when focused in."""
221 self.patch(self.entry, 'modify_text', self._set_called)234 self.patch(self.entry, 'override_color', self._set_called)
222235
223 self.grab_focus()236 self.grab_focus()
224237
225 self.assertEqual(((gtk.STATE_NORMAL, None), {}), self._called,238 self.assertEqual(((Gtk.StateFlags.NORMAL, None), {}), self._called,
226 'Entry text color must be restore on focus in.')239 'Entry text color must be restore on focus in.')
227240
228 def test_refill_entry_on_focus_out_if_no_input(self):241 def test_refill_entry_on_focus_out_if_no_input(self):
@@ -305,7 +318,7 @@
305 self.entry.set_warning(msg)318 self.entry.set_warning(msg)
306 self.assertEqual(self.entry.warning, msg)319 self.assertEqual(self.entry.warning, msg)
307 self.assertEqual(self.entry.get_property('secondary-icon-stock'),320 self.assertEqual(self.entry.get_property('secondary-icon-stock'),
308 gtk.STOCK_DIALOG_WARNING)321 Gtk.STOCK_DIALOG_WARNING)
309 self.assertEqual(self.entry.get_property('secondary-icon-sensitive'),322 self.assertEqual(self.entry.get_property('secondary-icon-sensitive'),
310 True)323 True)
311 self.assertEqual(self.entry.get_property('secondary-icon-activatable'),324 self.assertEqual(self.entry.get_property('secondary-icon-activatable'),
@@ -371,6 +384,7 @@
371 'tc_browser', 'login', 'request_password_token',384 'tc_browser', 'login', 'request_password_token',
372 'set_new_password')385 'set_new_password')
373 self.ui = self.gui_class(**self.kwargs)386 self.ui = self.gui_class(**self.kwargs)
387 self.addCleanup(self.ui.destroy)
374 self.error = {'message': UNKNOWN_ERROR}388 self.error = {'message': UNKNOWN_ERROR}
375389
376 def assert_entries_are_packed_to_ui(self, container_name, entries):390 def assert_entries_are_packed_to_ui(self, container_name, entries):
@@ -405,8 +419,8 @@
405419
406 # content color is correct420 # content color is correct
407 expected = gui.WARNING_TEXT_COLOR421 expected = gui.WARNING_TEXT_COLOR
408 actual = label.style.fg[gtk.STATE_NORMAL]422 actual = label.get_style().fg[Gtk.StateFlags.NORMAL]
409 self.assertEqual(expected, actual) # until realized this will fail423 self.assert_color_equal(expected, actual)
410424
411 def assert_correct_entry_warning(self, entry, message):425 def assert_correct_entry_warning(self, entry, message):
412 """Check that a warning is shown displaying 'message'."""426 """Check that a warning is shown displaying 'message'."""
@@ -533,16 +547,6 @@
533 entry = getattr(self.ui, name)547 entry = getattr(self.ui, name)
534 self.assertTrue(entry.get_activates_default(), msg % (name,))548 self.assertTrue(entry.get_activates_default(), msg % (name,))
535549
536 def test_label_size_allocated_is_connected(self):
537 """Labels have the size-allocate signal connected."""
538 msg = 'Label %r must have size-allocate connected.'
539 labels = [i for i in self.ui.widgets if 'label' in i]
540 for label in labels:
541 widget = getattr(self.ui, label)
542 widget.emit('size-allocate', gtk.gdk.Rectangle(1, 2, 3, 4))
543 self.assertEqual(widget.get_size_request(), (3 - 2, -1),
544 msg % (label,))
545
546 def test_password_fields_are_password(self):550 def test_password_fields_are_password(self):
547 """Password fields have the is_password flag set."""551 """Password fields have the is_password flag set."""
548 msg = '"%s" should be a password LabeledEntry instance.'552 msg = '"%s" should be a password LabeledEntry instance.'
@@ -573,28 +577,6 @@
573 """Main window has the proper icon."""577 """Main window has the proper icon."""
574 self.assertEqual('ubuntu-logo', self.ui.window.get_icon_name())578 self.assertEqual('ubuntu-logo', self.ui.window.get_icon_name())
575579
576 def test_transient_window_is_none_if_window_id_is_zero(self):
577 """The transient window is correct."""
578 self.patch(gtk.gdk, 'window_foreign_new', self._set_called)
579 self.gui_class(window_id=0, **self.kwargs)
580 self.assertFalse(self._called, 'set_transient_for must not be called.')
581
582 def test_transient_window_is_correct(self):
583 """The transient window is correct."""
584 xid = 5
585 self.patch(gtk.gdk, 'window_foreign_new', self._set_called)
586 self.gui_class(window_id=xid, **self.kwargs)
587 self.assertTrue(self.memento.check(logging.ERROR, 'set_transient_for'))
588 self.assertTrue(self.memento.check(logging.ERROR, str(xid)))
589 self.assertEqual(self._called, ((xid,), {}))
590
591 def test_transient_window_accepts_negative_id(self):
592 """The transient window accepts a negative window id."""
593 xid = -5
594 self.patch(gtk.gdk, 'window_foreign_new', self._set_called)
595 self.gui_class(window_id=xid, **self.kwargs)
596 self.assertEqual(self._called, ((xid,), {}))
597
598 def test_finish_success_shows_success_page(self):580 def test_finish_success_shows_success_page(self):
599 """When calling 'finish_success' the success page is shown."""581 """When calling 'finish_success' the success page is shown."""
600 self.ui.finish_success()582 self.ui.finish_success()
@@ -611,6 +593,42 @@
611 self.assertEqual(gui.ERROR, self.ui.finish_vbox.label.get_text())593 self.assertEqual(gui.ERROR, self.ui.finish_vbox.label.get_text())
612594
613595
596class SetTransientForTestCase(UbuntuSSOClientTestCase):
597 """Test suite for setting the window as transient for another one."""
598
599 def test_transient_window_is_none_if_window_id_is_zero(self):
600 """The transient window is correct."""
601 self.patch(gui.X11Window, 'foreign_new_for_display', self._set_called)
602 ui = self.gui_class(window_id=0, **self.kwargs)
603 self.addCleanup(ui.destroy)
604
605 self.assertFalse(self._called, 'set_transient_for must not be called.')
606
607 def test_transient_window_is_correct(self):
608 """The transient window is correct."""
609 xid = 5
610 self.patch(gui.X11Window, 'foreign_new_for_display', self._set_called)
611 ui = self.gui_class(window_id=xid, **self.kwargs)
612 self.addCleanup(ui.destroy)
613
614 self.assertTrue(self.memento.check(logging.ERROR, 'set_transient_for'))
615 self.assertTrue(self.memento.check(logging.ERROR, str(xid)))
616 self.assertEqual(self._called, ((xid,), {}))
617
618 def test_transient_window_accepts_negative_id(self):
619 """The transient window accepts a negative window id."""
620 xid = -5
621 self.patch(gui.X11Window, 'foreign_new_for_display', self._set_called)
622 ui = self.gui_class(window_id=xid, **self.kwargs)
623 self.addCleanup(ui.destroy)
624
625 self.assertEqual(self._called, ((xid,), {}))
626
627
628SetTransientForTestCase.skip = "Apparently, so far we can't use XLib " \
629"dynamic bindings to complete the call to X11Window.foreign_new_for_display."
630
631
614class EnterDetailsTestCase(UbuntuSSOClientTestCase):632class EnterDetailsTestCase(UbuntuSSOClientTestCase):
615 """Test suite for the user registration (enter details page)."""633 """Test suite for the user registration (enter details page)."""
616634
@@ -695,8 +713,8 @@
695 'processing_vbox must have two children.')713 'processing_vbox must have two children.')
696714
697 spinner, label = box.get_children()715 spinner, label = box.get_children()
698 self.assertIsInstance(spinner, gtk.Spinner)716 self.assertIsInstance(spinner, Gtk.Spinner)
699 self.assertIsInstance(label, gtk.Label)717 self.assertIsInstance(label, Gtk.Label)
700718
701 self.assertTrue(spinner.get_property('visible'),719 self.assertTrue(spinner.get_property('visible'),
702 'the processing spinner should be visible.')720 'the processing spinner should be visible.')
@@ -715,6 +733,8 @@
715 def test_captcha_filename_is_different_each_time(self):733 def test_captcha_filename_is_different_each_time(self):
716 """The captcha image is different each time."""734 """The captcha image is different each time."""
717 ui = self.gui_class(**self.kwargs)735 ui = self.gui_class(**self.kwargs)
736 self.addCleanup(ui.destroy)
737
718 self.assertNotEqual(self.ui._captcha_filename, ui._captcha_filename)738 self.assertNotEqual(self.ui._captcha_filename, ui._captcha_filename)
719739
720 def test_captcha_image_is_removed_when_exiting(self):740 def test_captcha_image_is_removed_when_exiting(self):
@@ -736,8 +756,8 @@
736 'captcha_loading must have two children.')756 'captcha_loading must have two children.')
737757
738 spinner, label = box.get_children()758 spinner, label = box.get_children()
739 self.assertIsInstance(spinner, gtk.Spinner)759 self.assertIsInstance(spinner, Gtk.Spinner)
740 self.assertIsInstance(label, gtk.Label)760 self.assertIsInstance(label, Gtk.Label)
741761
742 self.assertTrue(spinner.get_property('visible'),762 self.assertTrue(spinner.get_property('visible'),
743 'the captcha_loading spinner should be visible.')763 'the captcha_loading spinner should be visible.')
@@ -872,7 +892,7 @@
872 @defer.inlineCallbacks892 @defer.inlineCallbacks
873 def setUp(self):893 def setUp(self):
874 yield super(TermsAndConditionsBrowserTestCase, self).setUp()894 yield super(TermsAndConditionsBrowserTestCase, self).setUp()
875 self.patch(webkit, 'WebView', FakedEmbeddedBrowser)895 self.patch(WebKit, 'WebView', FakedEmbeddedBrowser)
876896
877 self.ui.tc_button.clicked()897 self.ui.tc_button.clicked()
878 self.addCleanup(self.ui.tc_browser_vbox.hide)898 self.addCleanup(self.ui.tc_browser_vbox.hide)
@@ -968,10 +988,10 @@
968988
969 def test_navigation_requested_succeeds_for_no_clicking(self):989 def test_navigation_requested_succeeds_for_no_clicking(self):
970 """The navigation request succeeds when user hasn't clicked a link."""990 """The navigation request succeeds when user hasn't clicked a link."""
971 action = webkit.WebNavigationAction()991 action = WebKit.WebNavigationAction()
972 action.set_reason(gui.WEBKIT_WEB_NAVIGATION_REASON_OTHER)992 action.set_reason(gui.WEBKIT_WEB_NAVIGATION_REASON_OTHER)
973993
974 decision = webkit.WebPolicyDecision()994 decision = WebKit.WebPolicyDecision()
975 decision.use = self._set_called995 decision.use = self._set_called
976996
977 kwargs = dict(browser=self.browser, frame=None, request=None,997 kwargs = dict(browser=self.browser, frame=None, request=None,
@@ -981,10 +1001,10 @@
9811001
982 def test_navigation_requested_ignores_clicked_links(self):1002 def test_navigation_requested_ignores_clicked_links(self):
983 """The navigation request is ignored if a link was clicked."""1003 """The navigation request is ignored if a link was clicked."""
984 action = webkit.WebNavigationAction()1004 action = WebKit.WebNavigationAction()
985 action.set_reason(gui.WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED)1005 action.set_reason(gui.WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED)
9861006
987 decision = webkit.WebPolicyDecision()1007 decision = WebKit.WebPolicyDecision()
988 decision.ignore = self._set_called1008 decision.ignore = self._set_called
9891009
990 self.patch(gui.webbrowser, 'open', lambda *args, **kwargs: None)1010 self.patch(gui.webbrowser, 'open', lambda *args, **kwargs: None)
@@ -1007,11 +1027,11 @@
10071027
1008 """1028 """
1009 url = 'http://something.com/yadda'1029 url = 'http://something.com/yadda'
1010 action = webkit.WebNavigationAction()1030 action = WebKit.WebNavigationAction()
1011 action.set_reason(gui.WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED)1031 action.set_reason(gui.WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED)
1012 action.set_original_uri(url)1032 action.set_original_uri(url)
10131033
1014 decision = webkit.WebPolicyDecision()1034 decision = WebKit.WebPolicyDecision()
1015 decision.ignore = gui.NO_OP1035 decision.ignore = gui.NO_OP
10161036
1017 self.patch(gui.webbrowser, 'open', self._set_called)1037 self.patch(gui.webbrowser, 'open', self._set_called)
@@ -2081,7 +2101,7 @@
20812101
2082 def test_closing_main_window(self):2102 def test_closing_main_window(self):
2083 """When closing the main window, USER_CANCELLATION is called."""2103 """When closing the main window, USER_CANCELLATION is called."""
2084 self.ui.window.emit('delete-event', gtk.gdk.Event(gtk.gdk.DELETE))2104 self.ui.window.emit('delete-event', Gdk.Event())
2085 self.assertEqual(self._called, ((gui.USER_CANCELLATION,), {}))2105 self.assertEqual(self._called, ((gui.USER_CANCELLATION,), {}))
20862106
2087 def test_every_cancel_calls_proper_callback(self):2107 def test_every_cancel_calls_proper_callback(self):
20882108
=== modified file 'ubuntu_sso/gtk/tests/test_main.py'
--- ubuntu_sso/gtk/tests/test_main.py 2012-01-18 12:37:00 +0000
+++ ubuntu_sso/gtk/tests/test_main.py 2012-02-02 18:14:19 +0000
@@ -73,14 +73,14 @@
73 called = []73 called = []
74 self.patch(main, 'UbuntuSSOClientGUI',74 self.patch(main, 'UbuntuSSOClientGUI',
75 lambda **kw: called.append(('GUI', kw)))75 lambda **kw: called.append(('GUI', kw)))
76 self.patch(main.gtk, 'main',76 self.patch(main.Gtk, 'main',
77 lambda: called.append('gtk.main'))77 lambda: called.append('main'))
7878
79 kwargs = dict(foo='foo', bar='bar', baz='yadda', yadda=0)79 kwargs = dict(foo='foo', bar='bar', baz='yadda', yadda=0)
80 main.main(**kwargs)80 main.main(**kwargs)
8181
82 kwargs['close_callback'] = main.gtk.main_quit82 kwargs['close_callback'] = main.Gtk.main_quit
83 self.assertEqual(called, [('GUI', kwargs), 'gtk.main'])83 self.assertEqual(called, [('GUI', kwargs), 'main'])
8484
85 def test_parse_args_app_name_is_required(self):85 def test_parse_args_app_name_is_required(self):
86 """If no app_name, show help and exit."""86 """If no app_name, show help and exit."""
8787
=== modified file 'ubuntu_sso/keyring/__init__.py'
--- ubuntu_sso/keyring/__init__.py 2011-10-17 18:24:55 +0000
+++ ubuntu_sso/keyring/__init__.py 2012-02-02 18:14:19 +0000
@@ -29,8 +29,8 @@
2929
30logger = setup_logging("ubuntu_sso.keyring")30logger = setup_logging("ubuntu_sso.keyring")
3131
32TOKEN_SEPARATOR = ' @ '32TOKEN_SEPARATOR = u' @ '
33SEPARATOR_REPLACEMENT = ' AT '33SEPARATOR_REPLACEMENT = u' AT '
3434
35U1_APP_NAME = "Ubuntu One"35U1_APP_NAME = "Ubuntu One"
36U1_KEY_NAME = "UbuntuOne token for https://ubuntuone.com"36U1_KEY_NAME = "UbuntuOne token for https://ubuntuone.com"
@@ -41,26 +41,34 @@
4141
4242
43def gethostname():43def gethostname():
44 """Get the hostname, encoded in utf-8."""44 """Get the hostname, return the name as unicode."""
45 sys_encoding = sys.getfilesystemencoding()45 sys_encoding = sys.getfilesystemencoding()
46 hostname = socket.gethostname().decode(sys_encoding)46 hostname = socket.gethostname().decode(sys_encoding)
47 return hostname.encode("utf-8")47 return hostname
4848
4949
50def get_old_token_name(app_name):50def get_old_token_name(app_name):
51 """Build the token name (old style)."""51 """Build the token name (old style). Return an unicode."""
52 quoted_app_name = urllib.quote(app_name)52 quoted_app_name = urllib.quote(app_name)
53 computer_name = gethostname()53 computer_name = gethostname()
54 quoted_computer_name = urllib.quote(computer_name)54 quoted_computer_name = urllib.quote(computer_name)
55 return "%s - %s" % (quoted_app_name, quoted_computer_name)55
56 assert isinstance(computer_name, unicode)
57 assert isinstance(quoted_computer_name, unicode)
58
59 return u"%s - %s" % (quoted_app_name, quoted_computer_name)
5660
5761
58def get_token_name(app_name):62def get_token_name(app_name):
59 """Build the token name."""63 """Build the token name.. Return an unicode."""
60 computer_name = gethostname().decode("utf-8")64 computer_name = gethostname()
61 computer_name = computer_name.replace(TOKEN_SEPARATOR,65 computer_name = computer_name.replace(TOKEN_SEPARATOR,
62 SEPARATOR_REPLACEMENT)66 SEPARATOR_REPLACEMENT)
63 return TOKEN_SEPARATOR.join((app_name, computer_name)).encode("utf-8")67
68 assert isinstance(computer_name, unicode)
69 assert isinstance(computer_name, unicode)
70
71 return TOKEN_SEPARATOR.join((app_name, computer_name))
6472
6573
66@inlineCallbacks74@inlineCallbacks
6775
=== modified file 'ubuntu_sso/keyring/tests/test_common.py'
--- ubuntu_sso/keyring/tests/test_common.py 2011-10-28 10:41:18 +0000
+++ ubuntu_sso/keyring/tests/test_common.py 2012-02-02 18:14:19 +0000
@@ -38,10 +38,9 @@
38 """The fs encoding is used to decode the name returned by socket."""38 """The fs encoding is used to decode the name returned by socket."""
39 fake_hostname = u"Привет-ПК"39 fake_hostname = u"Привет-ПК"
40 hostname_koi8r = fake_hostname.encode("koi8-r")40 hostname_koi8r = fake_hostname.encode("koi8-r")
41 hostname_utf8 = fake_hostname.encode("utf-8")
42 self.patch(keyring.socket, "gethostname", lambda: hostname_koi8r)41 self.patch(keyring.socket, "gethostname", lambda: hostname_koi8r)
43 self.patch(keyring.sys, "getfilesystemencoding", lambda: "koi8-r")42 self.patch(keyring.sys, "getfilesystemencoding", lambda: "koi8-r")
44 self.assertEqual(keyring.gethostname(), hostname_utf8)43 self.assertEqual(keyring.gethostname(), fake_hostname)
4544
4645
47class TestTokenNameBuilder(TestCase):46class TestTokenNameBuilder(TestCase):
@@ -78,12 +77,12 @@
78 """A token name with unicode in the app name."""77 """A token name with unicode in the app name."""
79 sample_app_name = u"Ubuntu 四百六十九"78 sample_app_name = u"Ubuntu 四百六十九"
80 sample_hostname = "Darkstar"79 sample_hostname = "Darkstar"
81 expected_result = u"Ubuntu 四百六十九 @ Darkstar".encode("utf-8")80 expected_result = u"Ubuntu 四百六十九 @ Darkstar"
82 self.check_build(sample_app_name, sample_hostname, expected_result)81 self.check_build(sample_app_name, sample_hostname, expected_result)
8382
84 def test_get_utf8_hostname_token_name(self):83 def test_get_utf8_hostname_token_name(self):
85 """A token name with utf8 in the host name."""84 """A token name with utf8 in the host name."""
86 sample_app_name = u"Ubuntu Eleven"85 sample_app_name = u"Ubuntu Eleven"
87 sample_hostname = u"Привет-ПК".encode("utf-8")86 sample_hostname = u"Привет-ПК"
88 expected_result = u"Ubuntu Eleven @ Привет-ПК".encode("utf-8")87 expected_result = u"Ubuntu Eleven @ Привет-ПК"
89 self.check_build(sample_app_name, sample_hostname, expected_result)88 self.check_build(sample_app_name, sample_hostname, expected_result)
9089
=== modified file 'ubuntu_sso/keyring/tests/test_linux.py'
--- ubuntu_sso/keyring/tests/test_linux.py 2011-10-28 10:41:18 +0000
+++ ubuntu_sso/keyring/tests/test_linux.py 2012-02-02 18:14:19 +0000
@@ -121,7 +121,7 @@
121 self.mock_service = None121 self.mock_service = None
122 self.service = self.patch(keyring, "SecretService",122 self.service = self.patch(keyring, "SecretService",
123 self.get_mock_service)123 self.get_mock_service)
124 self.patch(common_keyring, "gethostname", lambda: "darkstar")124 self.patch(common_keyring, "gethostname", lambda: u"darkstar")
125125
126 def get_mock_service(self):126 def get_mock_service(self):
127 """Create only one instance of the mock service per test."""127 """Create only one instance of the mock service per test."""
128128
=== modified file 'ubuntu_sso/logger.py'
--- ubuntu_sso/logger.py 2012-01-10 18:25:01 +0000
+++ ubuntu_sso/logger.py 2012-02-02 18:14:19 +0000
@@ -42,20 +42,31 @@
42 LOG_LEVEL = logging.INFO42 LOG_LEVEL = logging.INFO
4343
44LOG_PATH = os.path.join(LOGFOLDER, 'sso-client.log')44LOG_PATH = os.path.join(LOGFOLDER, 'sso-client.log')
45FMT = "%(asctime)s:%(msecs)s - %(name)s - %(levelname)s - %(message)s"
46
45MAIN_HANDLER = RotatingFileHandler(unicode_path(LOG_PATH),47MAIN_HANDLER = RotatingFileHandler(unicode_path(LOG_PATH),
46 maxBytes=1048576,48 maxBytes=1048576,
47 backupCount=5)49 backupCount=5)
48MAIN_HANDLER.setLevel(LOG_LEVEL)50MAIN_HANDLER.setLevel(LOG_LEVEL)
49FMT = "%(asctime)s:%(msecs)s - %(name)s - %(levelname)s - %(message)s"
50MAIN_HANDLER.setFormatter(logging.Formatter(fmt=FMT))51MAIN_HANDLER.setFormatter(logging.Formatter(fmt=FMT))
5152
5253GUI_LOG_PATH = os.path.join(LOGFOLDER, 'sso-client-gui.log')
53def setup_logging(log_domain):54GUI_HANDLER = RotatingFileHandler(unicode_path(GUI_LOG_PATH),
55 maxBytes=1048576,
56 backupCount=5)
57GUI_HANDLER.setLevel(LOG_LEVEL)
58GUI_HANDLER.setFormatter(logging.Formatter(fmt=FMT))
59
60
61def setup_logging(log_domain, handler=None):
54 """Create basic logger to set filename."""62 """Create basic logger to set filename."""
63 if handler is None:
64 handler = MAIN_HANDLER
65
55 logger = logging.getLogger(log_domain)66 logger = logging.getLogger(log_domain)
56 logger.propagate = False67 logger.propagate = False
57 logger.setLevel(LOG_LEVEL)68 logger.setLevel(LOG_LEVEL)
58 logger.addHandler(MAIN_HANDLER)69 logger.addHandler(handler)
59 if os.environ.get('DEBUG'):70 if os.environ.get('DEBUG'):
60 debug_handler = logging.StreamHandler(sys.stderr)71 debug_handler = logging.StreamHandler(sys.stderr)
61 debug_handler.setFormatter(logging.Formatter(fmt=FMT))72 debug_handler.setFormatter(logging.Formatter(fmt=FMT))
@@ -64,6 +75,11 @@
64 return logger75 return logger
6576
6677
78def setup_gui_logging(log_domain):
79 """Create basic logger to set filename."""
80 return setup_logging(log_domain, GUI_HANDLER)
81
82
67def log_call(log_func):83def log_call(log_func):
68 """Decorator to log, using 'log_func', calls to functions."""84 """Decorator to log, using 'log_func', calls to functions."""
6985
7086
=== modified file 'ubuntu_sso/main/__init__.py'
--- ubuntu_sso/main/__init__.py 2012-01-20 18:08:04 +0000
+++ ubuntu_sso/main/__init__.py 2012-02-02 18:14:19 +0000
@@ -486,8 +486,8 @@
486def main():486def main():
487 """Run the backend service."""487 """Run the backend service."""
488 logger.info('Setting up Ubuntu SSO service.')488 logger.info('Setting up Ubuntu SSO service.')
489 source.start_setup()489 loop = source.start_setup()
490 service = UbuntuSSOService()490 service = UbuntuSSOService()
491 d = service.start()491 d = service.start()
492 d.addBoth(source.finish_setup)492 d.addBoth(source.finish_setup, loop)
493 source.main()493 source.main()
494494
=== added file 'ubuntu_sso/main/glib.py'
--- ubuntu_sso/main/glib.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/main/glib.py 2012-02-02 18:14:19 +0000
@@ -0,0 +1,45 @@
1# -*- coding: utf-8 -*-
2#
3# Copyright 2012 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranties of
11# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12# PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""GLib main loop runner."""
18
19# pylint: disable=E0611,F0401
20
21from gi.repository import GLib, Gdk, Gtk
22
23
24def timeout_func(*a, **kw):
25 """Delay import of dynamic bindings to avoid crashes."""
26 return GLib.timeout_add(*a, **kw)
27
28
29def shutdown_func(*a, **kw):
30 """Delay import of dynamic bindings to avoid crashes."""
31 Gtk.main_quit()
32
33
34def run_func(loop):
35 """Delay import of dynamic bindings to avoid crashes."""
36 Gtk.main()
37
38
39def start_setup():
40 """Setup the env to run the service."""
41 import dbus.mainloop.glib # pylint: disable=W0621
42
43 dbus.mainloop.glib.threads_init()
44 Gdk.threads_init()
45 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
046
=== modified file 'ubuntu_sso/main/linux.py'
--- ubuntu_sso/main/linux.py 2012-01-26 17:21:32 +0000
+++ ubuntu_sso/main/linux.py 2012-02-02 18:14:19 +0000
@@ -25,12 +25,12 @@
2525
26"""26"""
2727
28import os
29import signal
28import threading30import threading
29import signal
3031
31import dbus.mainloop.glib32import dbus
32import dbus.service33import dbus.service
33import gtk
3434
35from twisted.internet import defer35from twisted.internet import defer
3636
@@ -68,8 +68,8 @@
68class SSOLoginProxy(dbus.service.Object):68class SSOLoginProxy(dbus.service.Object):
69 """Login thru the Single Sign On service."""69 """Login thru the Single Sign On service."""
7070
71 # Operator not preceded by a space (fails with dbus decorators)71 # Use of super on an old style class
72 # pylint: disable=C032272 # pylint: disable=E1002
7373
74 def __init__(self, root, *args, **kwargs):74 def __init__(self, root, *args, **kwargs):
75 """Initiate the Login object."""75 """Initiate the Login object."""
@@ -77,6 +77,9 @@
77 super(SSOLoginProxy, self).__init__(*args, **kwargs)77 super(SSOLoginProxy, self).__init__(*args, **kwargs)
78 self.root = root78 self.root = root
7979
80 # Operator not preceded by a space (fails with dbus decorators)
81 # pylint: disable=C0322
82
80 # generate_capcha signals83 # generate_capcha signals
81 @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss")84 @dbus.service.signal(DBUS_IFACE_USER_NAME, signature="ss")
82 def CaptchaGenerated(self, app_name, result):85 def CaptchaGenerated(self, app_name, result):
@@ -202,6 +205,9 @@
202205
203 """206 """
204207
208 # Use of super on an old style class
209 # pylint: disable=E1002
210
205 def __init__(self, root, *args, **kwargs):211 def __init__(self, root, *args, **kwargs):
206 # pylint: disable=E1002212 # pylint: disable=E1002
207 super(CredentialsManagementProxy, self).__init__(*args, **kwargs)213 super(CredentialsManagementProxy, self).__init__(*args, **kwargs)
@@ -433,39 +439,38 @@
433 return defer.succeed(result)439 return defer.succeed(result)
434440
435441
442if os.environ.get('USE_QT_MAINLOOP'):
443 from ubuntu_sso.main import qt
444 source = qt
445else:
446 from ubuntu_sso.main import glib
447 source = glib
448
449
450timeout_func = source.timeout_func
451shutdown_func = source.shutdown_func
452start_setup = source.start_setup
453
454
436def sighup_handler(*a, **kw):455def sighup_handler(*a, **kw):
437 """Stop the service."""456 """Stop the service."""
438 # This handler may be called in any thread, so is not thread safe.457 # This handler may be called in any thread, so is not thread safe.
439 # See the link below for info:458 # See the link below for info:
440 # www.listware.net/201004/gtk-devel-list/115067-unix-signals-in-glib.html459 # www.listware.net/201004/gtk-devel-list/115067-unix-signals-in-glib.html
441 #
442 # gtk.main_quit and the logger methods are safe to be called from any
443 # thread. Just don't call other random stuff here.
444 logger.info("Stoping Ubuntu SSO service since SIGHUP was received.")460 logger.info("Stoping Ubuntu SSO service since SIGHUP was received.")
445 gtk.main_quit()461 shutdown_func()
446462
447463
448class AlreadyStartedError(Exception):464class AlreadyStartedError(Exception):
449 """The backend service has already been started."""465 """The backend service has already been started."""
450466
451467
452timeout_func = gtk.timeout_add468def finish_setup(result, loop):
453shutdown_func = gtk.main_quit
454
455
456def start_setup():
457 """Setup the env to run the service."""
458 dbus.mainloop.glib.threads_init()
459 gtk.gdk.threads_init()
460 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
461
462
463def finish_setup(result):
464 """Run the specific mainloop only if no failure ocurred."""469 """Run the specific mainloop only if no failure ocurred."""
465 if result is None: # no failure ocurred, start the service470 if result is None: # no failure ocurred, start the service
466 logger.debug("Hooking up SIGHUP with handler %r.", sighup_handler)471 logger.debug("Hooking up SIGHUP with handler %r.", sighup_handler)
467 signal.signal(signal.SIGHUP, sighup_handler)472 signal.signal(signal.SIGHUP, sighup_handler)
468 gtk.main()473 source.run_func(loop)
469474
470475
471def main():476def main():
472477
=== added file 'ubuntu_sso/main/qt.py'
--- ubuntu_sso/main/qt.py 1970-01-01 00:00:00 +0000
+++ ubuntu_sso/main/qt.py 2012-02-02 18:14:19 +0000
@@ -0,0 +1,49 @@
1# -*- coding: utf-8 -*-
2#
3# Copyright 2012 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranties of
11# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12# PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program. If not, see <http://www.gnu.org/licenses/>.
16
17"""Qt main loop runner."""
18
19# pylint: disable=E0611,F0401
20
21import sys
22
23from PyQt4 import QtCore
24
25
26def timeout_func(*a, **kw):
27 """Delay import of dynamic bindings to avoid crashes."""
28 # use a QTimer to simulate a looping call
29
30
31def shutdown_func(*a, **kw):
32 """Delay import of dynamic bindings to avoid crashes."""
33 QtCore.QCoreApplication.instance().exit()
34
35
36def start_setup():
37 """Setup the env to run the service."""
38 import dbus.mainloop.qt # pylint: disable=W0621
39
40 # this has to be created before calling dbus.mainloop.qt.DBusQtMainLoop
41 loop = QtCore.QCoreApplication(sys.argv)
42 dbus.mainloop.qt.DBusQtMainLoop(set_as_default=True)
43
44 return loop
45
46
47def run_func(loop):
48 """Delay import of dynamic bindings to avoid crashes."""
49 loop.exec_()
050
=== modified file 'ubuntu_sso/main/windows.py'
--- ubuntu_sso/main/windows.py 2012-01-10 20:47:06 +0000
+++ ubuntu_sso/main/windows.py 2012-02-02 18:14:19 +0000
@@ -411,7 +411,7 @@
411# pylint: disable=E1101411# pylint: disable=E1101
412412
413413
414def finish_setup(result):414def finish_setup(result, loop):
415 """Stop the reactor if a failure ocurred."""415 """Stop the reactor if a failure ocurred."""
416 if isinstance(result, Failure):416 if isinstance(result, Failure):
417 reactor.stop()417 reactor.stop()
418418
=== modified file 'ubuntu_sso/qt/gui.py'
--- ubuntu_sso/qt/gui.py 2012-02-01 19:19:32 +0000
+++ ubuntu_sso/qt/gui.py 2012-02-02 18:14:19 +0000
@@ -1,5 +1,4 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2# Author: Manuel de la Pena <manuel@canonical.com>
3#2#
4# Copyright 2011 Canonical Ltd.3# Copyright 2011 Canonical Ltd.
5#4#
@@ -18,6 +17,8 @@
1817
19import gettext18import gettext
2019
20# pylint: disable=F0401,E0611
21
21from PyQt4.QtCore import pyqtSignal, Qt, SIGNAL22from PyQt4.QtCore import pyqtSignal, Qt, SIGNAL
22from PyQt4.QtGui import (23from PyQt4.QtGui import (
23 QApplication,24 QApplication,
2425
=== modified file 'ubuntu_sso/qt/tests/login_u_p.py'
--- ubuntu_sso/qt/tests/login_u_p.py 2012-01-10 18:14:09 +0000
+++ ubuntu_sso/qt/tests/login_u_p.py 2012-02-02 18:14:19 +0000
@@ -17,10 +17,11 @@
1717
18import sys18import sys
1919
20# pylint: disable=E1101,F0401,E0611
21
20if sys.platform != 'win32':22if sys.platform != 'win32':
21 # pylint: disable=F040123 from twisted.internet import gireactor
22 from twisted.internet import glib2reactor24 gireactor.install()
23 glib2reactor.install()
2425
25 from dbus.mainloop.glib import DBusGMainLoop26 from dbus.mainloop.glib import DBusGMainLoop
26 DBusGMainLoop(set_as_default=True)27 DBusGMainLoop(set_as_default=True)
@@ -29,8 +30,6 @@
2930
30from ubuntu_sso.main import get_sso_client31from ubuntu_sso.main import get_sso_client
3132
32# pylint: disable=E1101
33
3433
35@defer.inlineCallbacks34@defer.inlineCallbacks
36def main():35def main():
@@ -48,7 +47,19 @@
48 client.cred_manager.connect_to_signal('AuthorizationDenied', found)47 client.cred_manager.connect_to_signal('AuthorizationDenied', found)
49 client.cred_manager.connect_to_signal('CredentialsError', found)48 client.cred_manager.connect_to_signal('CredentialsError', found)
5049
50 # use the following to trigger a CredentialsError (AuthenticationError)
51 args = dict(email='xyz@canonical.com', password='ABC')51 args = dict(email='xyz@canonical.com', password='ABC')
52
53 # use the following to trigger a CredentialsError (UserNotValidated)
54 args = dict(email='a@example.com', password='1234567U')
55
56 # remove prior credentials
57 cleared = defer.Deferred()
58 client.cred_manager.connect_to_signal('CredentialsCleared',
59 cleared.callback)
60 yield client.cred_manager.clear_credentials('SUPER', {})
61 yield cleared
62
52 yield client.cred_manager.login_email_password('SUPER', args)63 yield client.cred_manager.login_email_password('SUPER', args)
53 print "called ok"64 print "called ok"
54 yield d65 yield d
5566
=== modified file 'ubuntu_sso/qt/tests/show_gui.py'
--- ubuntu_sso/qt/tests/show_gui.py 2012-01-10 18:14:09 +0000
+++ ubuntu_sso/qt/tests/show_gui.py 2012-02-02 18:14:19 +0000
@@ -17,10 +17,11 @@
1717
18import sys18import sys
1919
20# pylint: disable=E1101,F0401,E0611
21
20if sys.platform != 'win32':22if sys.platform != 'win32':
21 # pylint: disable=F040123 from twisted.internet import gireactor
22 from twisted.internet import glib2reactor24 gireactor.install()
23 glib2reactor.install()
2425
25 from dbus.mainloop.glib import DBusGMainLoop26 from dbus.mainloop.glib import DBusGMainLoop
26 DBusGMainLoop(set_as_default=True)27 DBusGMainLoop(set_as_default=True)
@@ -35,8 +36,6 @@
35 UI_MODULE_KEY,36 UI_MODULE_KEY,
36)37)
3738
38# pylint: disable=E1101
39
4039
41@defer.inlineCallbacks40@defer.inlineCallbacks
42def main():41def main():
@@ -54,7 +53,7 @@
54 client.cred_manager.connect_to_signal('AuthorizationDenied', found)53 client.cred_manager.connect_to_signal('AuthorizationDenied', found)
55 client.cred_manager.connect_to_signal('CredentialsError', found)54 client.cred_manager.connect_to_signal('CredentialsError', found)
5655
57 yield client.cred_manager.login('Ubuntu One',56 yield client.cred_manager.login('Ubuntu Two',
58 {57 {
59 TC_URL_KEY: 'http://www.google.com',58 TC_URL_KEY: 'http://www.google.com',
60 HELP_TEXT_KEY: 'This is a test.',59 HELP_TEXT_KEY: 'This is a test.',
6160
=== modified file 'ubuntu_sso/qt/tests/test_controllers.py'
--- ubuntu_sso/qt/tests/test_controllers.py 2012-02-01 19:19:32 +0000
+++ ubuntu_sso/qt/tests/test_controllers.py 2012-02-02 18:14:19 +0000
@@ -23,15 +23,16 @@
2323
24from twisted.internet import defer24from twisted.internet import defer
2525
26# pylint: disable=F0401,E0611
27
28from PyQt4.QtCore import QString, SIGNAL
26from PyQt4.QtGui import QCheckBox, QLabel, QLineEdit, QWizard29from PyQt4.QtGui import QCheckBox, QLabel, QLineEdit, QWizard
27from PyQt4.QtCore import QString, SIGNAL
2830
29# pylint: disable=F0401
30try:31try:
31 from PIL import Image32 from PIL import Image
32except ImportError:33except ImportError:
33 import Image34 import Image
34# pylint: enable=F040135# pylint: enable=F0401,E0611
3536
36from ubuntu_sso.qt.controllers import (37from ubuntu_sso.qt.controllers import (
37 BackendController,38 BackendController,
3839
=== modified file 'ubuntu_sso/qt/tests/test_enchanced_line_edit.py'
--- ubuntu_sso/qt/tests/test_enchanced_line_edit.py 2011-10-28 10:41:18 +0000
+++ ubuntu_sso/qt/tests/test_enchanced_line_edit.py 2012-02-02 18:14:19 +0000
@@ -20,8 +20,9 @@
2020
21from twisted.trial.unittest import TestCase21from twisted.trial.unittest import TestCase
2222
23from PyQt4 import QtGui23# pylint: disable=E1101
24from PyQt4 import QtCore24
25from PyQt4 import QtGui, QtCore
2526
26from ubuntu_sso.qt.gui import EnhancedLineEdit27from ubuntu_sso.qt.gui import EnhancedLineEdit
2728
2829
=== modified file 'ubuntu_sso/qt/tests/test_reset_password.py'
--- ubuntu_sso/qt/tests/test_reset_password.py 2012-02-01 19:19:32 +0000
+++ ubuntu_sso/qt/tests/test_reset_password.py 2012-02-02 18:14:19 +0000
@@ -1,5 +1,4 @@
1# -*- coding: utf-8 -*-1# -*- coding: utf-8 -*-
2# Author: Manuel de la Pena <manuel@canonical.com>
3#2#
4# Copyright 2011 Canonical Ltd.3# Copyright 2011 Canonical Ltd.
5#4#
@@ -16,6 +15,8 @@
16# with this program. If not, see <http://www.gnu.org/licenses/>.15# with this program. If not, see <http://www.gnu.org/licenses/>.
17"""Test the Reset Password Page."""16"""Test the Reset Password Page."""
1817
18# pylint: disable=F0401,E0611,E1101
19
19from PyQt4 import QtGui, QtCore20from PyQt4 import QtGui, QtCore
20from twisted.internet import defer21from twisted.internet import defer
21from twisted.trial.unittest import TestCase22from twisted.trial.unittest import TestCase
2223
=== modified file 'ubuntu_sso/tests/__init__.py'
--- ubuntu_sso/tests/__init__.py 2012-01-10 18:14:09 +0000
+++ ubuntu_sso/tests/__init__.py 2012-02-02 18:14:19 +0000
@@ -27,10 +27,10 @@
27from ubuntu_sso.keyring import get_token_name27from ubuntu_sso.keyring import get_token_name
2828
29APP_NAME = u'The Super App!'29APP_NAME = u'The Super App!'
30CAPTCHA_ID = u'test'30CAPTCHA_ID = u'test ñiña'
31CAPTCHA_PATH = os.path.abspath(os.path.join(os.curdir, 'ubuntu_sso', 'tests',31CAPTCHA_PATH = os.path.abspath(os.path.join(os.curdir, 'ubuntu_sso', 'tests',
32 'files', 'captcha.png'))32 'files', 'captcha.png'))
33CAPTCHA_SOLUTION = u'william Byrd'33CAPTCHA_SOLUTION = u'william Byrd ñandú'
34EMAIL = u'test@example.com'34EMAIL = u'test@example.com'
35EMAIL_TOKEN = u'B2Pgtf'35EMAIL_TOKEN = u'B2Pgtf'
36GTK_GUI_CLASS = 'UbuntuSSOClientGUI'36GTK_GUI_CLASS = 'UbuntuSSOClientGUI'
3737
=== removed directory 'ubuntu_sso/tests/bin'
=== removed file 'ubuntu_sso/tests/bin/show_gui'
--- ubuntu_sso/tests/bin/show_gui 2010-12-20 14:29:18 +0000
+++ ubuntu_sso/tests/bin/show_gui 1970-01-01 00:00:00 +0000
@@ -1,58 +0,0 @@
1#!/usr/bin/python
2
3# ubuntu-sso-login-gui - GUI for registration and login for Ubuntu SSO
4#
5# Author: Natalia Bidart <natalia.bidart@canonical.com>
6#
7# Copyright 2010 Canonical Ltd.
8#
9# This program is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License version 3, as published
11# by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranties of
15# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16# PURPOSE. See the GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program. If not, see <http://www.gnu.org/licenses/>.
20"""Script to run the Ubuntu SSO client GUI."""
21
22import gtk
23import sys
24
25from ubuntu_sso.gtk.gui import UbuntuSSOClientGUI
26
27
28APP_NAME = 'Ubuntu'
29TC_URL = 'http://one.ubuntu.com/terms'
30HELP_TEXT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' \
31 'Nam sed lorem nibh. Suspendisse gravida nulla non nunc suscipit' \
32 ' pulvinar tempus ut augue.'
33
34
35if __name__ == '__main__':
36
37 # pylint: disable=C0103, E1101
38
39 tc_url = TC_URL
40 login_only = False
41 xid = 0
42
43 if '--login' in sys.argv:
44 login_only = True
45 tc_url = None
46
47 if '--with-parent-window' in sys.argv:
48 win = gtk.Window()
49 win.set_title(APP_NAME)
50 win.set_position(gtk.WIN_POS_CENTER)
51 win.set_size_request(800, 600)
52 win.show()
53 xid = win.window.xid
54
55 UbuntuSSOClientGUI(close_callback=lambda *args, **kwargs: gtk.main_quit(),
56 app_name=APP_NAME, tc_url=tc_url, help_text=HELP_TEXT,
57 window_id=xid, login_only=login_only)
58 gtk.main()
590
=== removed file 'ubuntu_sso/tests/bin/show_nm_state'
--- ubuntu_sso/tests/bin/show_nm_state 2011-02-24 02:46:19 +0000
+++ ubuntu_sso/tests/bin/show_nm_state 1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
1#!/usr/bin/python
2
3# show_nm_state - Show the state of the NetworkManager daemon
4#
5# Author: Alejandro J. Cura <alecu@canonical.com>
6#
7# Copyright 2010 Canonical Ltd.
8#
9# This program is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License version 3, as published
11# by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranties of
15# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16# PURPOSE. See the GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program. If not, see <http://www.gnu.org/licenses/>.
20"""A test program that just shows the network state."""
21
22import gobject
23
24from dbus.mainloop.glib import DBusGMainLoop
25
26from ubuntu_sso.networkstate.linux import NetworkManagerState, NM_STATE_NAMES
27
28DBusGMainLoop(set_as_default=True)
29
30
31def got_state(state):
32 """Called when the network state is found."""
33 try:
34 print NM_STATE_NAMES[state]
35 finally:
36 gobject.MainLoop().quit()
37
38# pylint: disable=C0103
39nms = NetworkManagerState(got_state)
40nms.find_online_state()
41gobject.MainLoop().run()
420
=== modified file 'ubuntu_sso/tests/test_account.py'
--- ubuntu_sso/tests/test_account.py 2012-01-26 13:25:13 +0000
+++ ubuntu_sso/tests/test_account.py 2012-02-02 18:14:19 +0000
@@ -325,7 +325,7 @@
325 def test_login_if_http_error(self):325 def test_login_if_http_error(self):
326 """Proper error is raised if authentication fails."""326 """Proper error is raised if authentication fails."""
327 # use an invalid token name327 # use an invalid token name
328 self.login_kwargs['token_name'] = (APP_NAME * 2).encode("utf-8")328 self.login_kwargs['token_name'] = APP_NAME * 2
329 d = self.processor.login(**self.login_kwargs)329 d = self.processor.login(**self.login_kwargs)
330 yield self.assertFailure(d, AuthenticationError)330 yield self.assertFailure(d, AuthenticationError)
331331
332332
=== modified file 'ubuntu_sso/utils/tests/test_txsecrets.py'
--- ubuntu_sso/utils/tests/test_txsecrets.py 2012-01-26 17:21:32 +0000
+++ ubuntu_sso/utils/tests/test_txsecrets.py 2012-02-02 18:14:19 +0000
@@ -36,6 +36,9 @@
36# pylint complains when things are a little too dynamic36# pylint complains when things are a little too dynamic
37# pylint: disable=E110137# pylint: disable=E1101
3838
39# Use of super on an old style class
40# pylint: disable=E1002
41
3942
40ERROR_CREATE_BUT_LOCKED = "Cannot create an item in a locked collection"43ERROR_CREATE_BUT_LOCKED = "Cannot create an item in a locked collection"
41PROMPT_BASE_PATH = "/org/freedesktop/secrets/prompt"44PROMPT_BASE_PATH = "/org/freedesktop/secrets/prompt"
4245
=== modified file 'ubuntu_sso/utils/webclient/__init__.py'
--- ubuntu_sso/utils/webclient/__init__.py 2012-01-19 21:41:43 +0000
+++ ubuntu_sso/utils/webclient/__init__.py 2012-02-02 18:14:19 +0000
@@ -35,10 +35,8 @@
35 if is_qt4reactor_installed():35 if is_qt4reactor_installed():
36 from ubuntu_sso.utils.webclient import qtnetwork as web_module36 from ubuntu_sso.utils.webclient import qtnetwork as web_module
37 else:37 else:
38 # the libsoup backend depends on the twisted + GI bug38 from ubuntu_sso.utils.webclient import libsoup as web_module
39 # meanwhile, use the txweb sample client39 #from ubuntu_sso.utils.webclient import txweb as web_module
40 #from ubuntu_sso.utils.webclient import libsoup as web_module
41 from ubuntu_sso.utils.webclient import txweb as web_module
42 return web_module40 return web_module
4341
4442
4543
=== modified file 'ubuntu_sso/utils/webclient/qtnetwork.py'
--- ubuntu_sso/utils/webclient/qtnetwork.py 2012-01-25 15:02:50 +0000
+++ ubuntu_sso/utils/webclient/qtnetwork.py 2012-02-02 18:14:19 +0000
@@ -17,11 +17,13 @@
1717
18import sys18import sys
1919
20# pylint: disable=E0611
20from PyQt4.QtCore import (21from PyQt4.QtCore import (
21 QBuffer,22 QBuffer,
22 QCoreApplication,23 QCoreApplication,
23 QUrl,24 QUrl,
24)25)
26# pylint: enable=E0611
25from PyQt4.QtNetwork import (27from PyQt4.QtNetwork import (
26 QNetworkAccessManager,28 QNetworkAccessManager,
27 QNetworkProxy,29 QNetworkProxy,
2830
=== modified file 'ubuntu_sso/utils/webclient/tests/test_webclient.py'
--- ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-01-27 20:12:10 +0000
+++ ubuntu_sso/utils/webclient/tests/test_webclient.py 2012-02-02 18:14:19 +0000
@@ -255,11 +255,7 @@
255 """Test the module name for the libsoup case."""255 """Test the module name for the libsoup case."""
256 self.patch(webclient, "is_qt4reactor_installed", lambda: False)256 self.patch(webclient, "is_qt4reactor_installed", lambda: False)
257 module = webclient.webclient_module()257 module = webclient.webclient_module()
258 # pylint: disable=W0511258 self.assert_module_name(module, "libsoup")
259 # TODO: the libsoup backend depends on the twisted + GI bug
260 # meanwhile, use the test txweb client
261 #self.assert_module_name(module, "libsoup")
262 self.assert_module_name(module, "txweb")
263259
264260
265class WebClientTestCase(TestCase):261class WebClientTestCase(TestCase):

Subscribers

People subscribed via source and target branches