Merge lp:~ralsina/ubuntuone-windows-installer/fix_800383 into lp:ubuntuone-windows-installer
- fix_800383
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Roberto Alsina | ||||
Approved revision: | 30 | ||||
Merged at revision: | 7 | ||||
Proposed branch: | lp:~ralsina/ubuntuone-windows-installer/fix_800383 | ||||
Merge into: | lp:ubuntuone-windows-installer | ||||
Diff against target: |
827 lines (+674/-21) 10 files modified
data/qt/congratulations.ui (+103/-0) pylintrc (+305/-0) run-tests (+1/-1) ubuntuone_installer/__init__.py (+1/-1) ubuntuone_installer/gui/qt/__init__.py (+0/-1) ubuntuone_installer/gui/qt/gui.py (+52/-18) ubuntuone_installer/gui/qt/tests/__init__.py (+68/-0) ubuntuone_installer/gui/qt/tests/test_gui.py (+61/-0) ubuntuone_installer/gui/tests/__init__.py (+45/-0) ubuntuone_installer/tests/__init__.py (+38/-0) |
||||
To merge this branch: | bzr merge lp:~ralsina/ubuntuone-windows-installer/fix_800383 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Approve | ||
Natalia Bidart (community) | Approve | ||
Review via email: mp+65416@code.launchpad.net |
Commit message
Beginning of the implementation of the congratulations page.
Description of the change
Beginning of the implementation of this page.
Even after this branch lands:
* Need correct artwork from design
* The optional "syncing" message depends on a previous page
To test (on Linux):
PYTHONPATH=. python bin/ubuntuone-
You should have two pages on the wizard.
The "Open Ubuntu One Dashboard" button on the final page should open the control panel.
Natalia Bidart (nataliabidart) wrote : | # |
I'm marking this as needs fixing so we have can have at least a minimal test suite for this widgets that are now starting to have some logic.
Thanks!
- 12. By Roberto Alsina
-
style fixes
- 13. By Roberto Alsina
-
Basic testing stuff copied from control panel, with 4 tests which fail
- 14. By Roberto Alsina
-
The main UI is not loaded using loadUI
- 15. By Roberto Alsina
-
Re-add some things that should not have been removed
- 16. By Roberto Alsina
-
closer to making testing itself work
- 17. By Roberto Alsina
-
use done() instead of closeEvent()
- 18. By Roberto Alsina
-
This is as far as I managed to monkeypatch, and I have a problem. I will ask for help now.
- 19. By Roberto Alsina
-
Make tests work using the reactor as mandel said
- 20. By Roberto Alsina
-
style fixes
- 21. By Roberto Alsina
-
Don't start the control panel on the tests
- 22. By Roberto Alsina
-
whitespace fixes, pylintrc
- 23. By Roberto Alsina
-
added tests for the 'start control panel' logic
- 24. By Roberto Alsina
-
add build step to run-tests
- 25. By Roberto Alsina
-
Style fix
- 26. By Roberto Alsina
-
use .ui instead of .page_ui for consistency
- 27. By Roberto Alsina
-
changed method name to be PEP8-alike
- 28. By Roberto Alsina
-
style issues
- 29. By Roberto Alsina
-
Make it more like control panel's
Natalia Bidart (nataliabidart) : | # |
- 30. By Roberto Alsina
-
switch t the -qt version of control panel
dobey (dobey) : | # |
Preview Diff
1 | === added file 'data/qt/congratulations.ui' |
2 | --- data/qt/congratulations.ui 1970-01-01 00:00:00 +0000 |
3 | +++ data/qt/congratulations.ui 2011-06-22 14:18:49 +0000 |
4 | @@ -0,0 +1,103 @@ |
5 | +<?xml version="1.0" encoding="UTF-8"?> |
6 | +<ui version="4.0"> |
7 | + <class>Form</class> |
8 | + <widget class="QWidget" name="Form"> |
9 | + <property name="geometry"> |
10 | + <rect> |
11 | + <x>0</x> |
12 | + <y>0</y> |
13 | + <width>426</width> |
14 | + <height>387</height> |
15 | + </rect> |
16 | + </property> |
17 | + <property name="windowTitle"> |
18 | + <string>Form</string> |
19 | + </property> |
20 | + <layout class="QVBoxLayout" name="verticalLayout_2"> |
21 | + <property name="spacing"> |
22 | + <number>24</number> |
23 | + </property> |
24 | + <item> |
25 | + <widget class="QLabel" name="label"> |
26 | + <property name="font"> |
27 | + <font> |
28 | + <pointsize>14</pointsize> |
29 | + <weight>75</weight> |
30 | + <bold>true</bold> |
31 | + </font> |
32 | + </property> |
33 | + <property name="text"> |
34 | + <string>Congratulation!</string> |
35 | + </property> |
36 | + </widget> |
37 | + </item> |
38 | + <item> |
39 | + <widget class="QLabel" name="label_2"> |
40 | + <property name="text"> |
41 | + <string>Nice picture goes here</string> |
42 | + </property> |
43 | + </widget> |
44 | + </item> |
45 | + <item> |
46 | + <widget class="QLabel" name="label_3"> |
47 | + <property name="text"> |
48 | + <string>Ubuntu One is installed, set up and is ready to go!</string> |
49 | + </property> |
50 | + </widget> |
51 | + </item> |
52 | + <item> |
53 | + <layout class="QHBoxLayout" name="horizontalLayout"> |
54 | + <item> |
55 | + <widget class="QLabel" name="label_4"> |
56 | + <property name="text"> |
57 | + <string>IMAGE GOES HERE?</string> |
58 | + </property> |
59 | + </widget> |
60 | + </item> |
61 | + <item> |
62 | + <layout class="QVBoxLayout" name="verticalLayout"> |
63 | + <item> |
64 | + <widget class="QLabel" name="label_5"> |
65 | + <property name="font"> |
66 | + <font> |
67 | + <weight>75</weight> |
68 | + <bold>true</bold> |
69 | + </font> |
70 | + </property> |
71 | + <property name="text"> |
72 | + <string>Sync in progress...</string> |
73 | + </property> |
74 | + </widget> |
75 | + </item> |
76 | + <item> |
77 | + <widget class="QLabel" name="label_6"> |
78 | + <property name="text"> |
79 | + <string>Your folders have started to sync in the background, launch the dahboard to get more information about the sync in progress</string> |
80 | + </property> |
81 | + <property name="wordWrap"> |
82 | + <bool>true</bool> |
83 | + </property> |
84 | + </widget> |
85 | + </item> |
86 | + </layout> |
87 | + </item> |
88 | + </layout> |
89 | + </item> |
90 | + <item> |
91 | + <spacer name="verticalSpacer"> |
92 | + <property name="orientation"> |
93 | + <enum>Qt::Vertical</enum> |
94 | + </property> |
95 | + <property name="sizeHint" stdset="0"> |
96 | + <size> |
97 | + <width>20</width> |
98 | + <height>40</height> |
99 | + </size> |
100 | + </property> |
101 | + </spacer> |
102 | + </item> |
103 | + </layout> |
104 | + </widget> |
105 | + <resources/> |
106 | + <connections/> |
107 | +</ui> |
108 | |
109 | === added file 'pylintrc' |
110 | --- pylintrc 1970-01-01 00:00:00 +0000 |
111 | +++ pylintrc 2011-06-22 14:18:49 +0000 |
112 | @@ -0,0 +1,305 @@ |
113 | +# lint Python modules using external checkers. |
114 | +# |
115 | +# This is the main checker controlling the other ones and the reports |
116 | +# generation. It is itself both a raw checker and an astng checker in order |
117 | +# to: |
118 | +# * handle message activation / deactivation at the module level |
119 | +# * handle some basic but necessary stats'data (number of classes, methods...) |
120 | +# |
121 | +[MASTER] |
122 | + |
123 | +# Specify a configuration file. |
124 | +#rcfile= |
125 | + |
126 | +# Python code to execute, usually for sys.path manipulation such as |
127 | +# pygtk.require(). |
128 | +#init-hook= |
129 | + |
130 | +# Profiled execution. |
131 | +profile=no |
132 | + |
133 | +# Add <file or directory> to the black list. It should be a base name, not a |
134 | +# path. You may set this option multiple times. |
135 | +ignore=ui,qtreactor |
136 | + |
137 | +# Pickle collected data for later comparisons. |
138 | +persistent=no |
139 | + |
140 | +# List of plugins (as comma separated values of python modules names) to load, |
141 | +# usually to register additional checkers. |
142 | +load-plugins= |
143 | + |
144 | + |
145 | +[MESSAGES CONTROL] |
146 | + |
147 | +# Enable only checker(s) with the given id(s). This option conflicts with the |
148 | +# disable-checker option |
149 | +#enable-checker= |
150 | + |
151 | +# Enable all checker(s) except those with the given id(s). This option |
152 | +# conflicts with the enable-checker option |
153 | +#disable-checker= |
154 | + |
155 | +# Enable all messages in the listed categories. |
156 | +#enable-cat= |
157 | + |
158 | +# Disable all messages in the listed categories. |
159 | +#disable-cat= |
160 | + |
161 | +# Disable the message(s) with the given id(s) or categories |
162 | +# W0142: Used * or ** magic |
163 | +# W0613: Unused argument 'yyy' |
164 | +disable=R,I,W0142,W0613,W0511 |
165 | + |
166 | + |
167 | +[REPORTS] |
168 | + |
169 | +# Set the output format. Available formats are text, parseable, colorized, msvs |
170 | +# (visual studio) and html |
171 | +output-format=colorized |
172 | + |
173 | +# Include message's id in output |
174 | +include-ids=yes |
175 | + |
176 | +# Put messages in a separate file for each module / package specified on the |
177 | +# command line instead of printing them on stdout. Reports (if any) will be |
178 | +# written in a file name "pylint_global.[txt|html]". |
179 | +files-output=no |
180 | + |
181 | +# Tells whether to display a full report or only the messages |
182 | +reports=no |
183 | + |
184 | +# Python expression which should return a note less than 10 (10 is the highest |
185 | +# note). You have access to the variables errors warning, statement which |
186 | +# respectively contain the number of errors / warnings messages and the total |
187 | +# number of statements analyzed. This is used by the global evaluation report |
188 | +# (R0004). |
189 | +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) |
190 | + |
191 | +# Add a comment according to your evaluation note. This is used by the global |
192 | +# evaluation report (R0004). |
193 | +comment=no |
194 | + |
195 | +# Enable the report(s) with the given id(s). |
196 | +#enable-report= |
197 | + |
198 | +# Disable the report(s) with the given id(s). |
199 | +#disable-report= |
200 | + |
201 | + |
202 | +# try to find bugs in the code using type inference |
203 | +# |
204 | +[TYPECHECK] |
205 | + |
206 | +# Tells whether missing members accessed in mixin class should be ignored. A |
207 | +# mixin class is detected if its name ends with "mixin" (case insensitive). |
208 | +ignore-mixin-members=yes |
209 | + |
210 | +# List of classes names for which member attributes should not be checked |
211 | +# (useful for classes with attributes dynamically set). |
212 | +ignored-classes= |
213 | + |
214 | +# When zope mode is activated, add a predefined set of Zope acquired attributes |
215 | +# to generated-members. |
216 | +zope=no |
217 | + |
218 | +# List of members which are set dynamically and missed by pylint inference |
219 | +# system, and so shouldn't trigger E0201 when accessed. |
220 | +generated-members=REQUEST,acl_users,aq_parent |
221 | + |
222 | + |
223 | +# checks for |
224 | +# * unused variables / imports |
225 | +# * undefined variables |
226 | +# * redefinition of variable from builtins or from an outer scope |
227 | +# * use of variable before assignment |
228 | +# |
229 | +[VARIABLES] |
230 | + |
231 | +# Tells whether we should check for unused import in __init__ files. |
232 | +init-import=yes |
233 | + |
234 | +# A regular expression matching names used for dummy variables (i.e. not used). |
235 | +dummy-variables-rgx=_|dummy |
236 | + |
237 | +# List of additional names supposed to be defined in builtins. Remember that |
238 | +# you should avoid to define new builtins when possible. |
239 | +additional-builtins= |
240 | + |
241 | + |
242 | +# checks for : |
243 | +# * doc strings |
244 | +# * modules / classes / functions / methods / arguments / variables name |
245 | +# * number of arguments, local variables, branches, returns and statements in |
246 | +# functions, methods |
247 | +# * required module attributes |
248 | +# * dangerous default values as arguments |
249 | +# * redefinition of function / method / class |
250 | +# * uses of the global statement |
251 | +# |
252 | +[BASIC] |
253 | + |
254 | +# Required attributes for module, separated by a comma |
255 | +required-attributes= |
256 | + |
257 | +# Regular expression which should only match functions or classes name which do |
258 | +# not require a docstring |
259 | +no-docstring-rgx=(__.*__|setUp|tearDown) |
260 | + |
261 | +# Regular expression which should only match correct module names |
262 | +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ |
263 | + |
264 | +# Regular expression which should only match correct module level names |
265 | +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ |
266 | + |
267 | +# Regular expression which should only match correct class names |
268 | +class-rgx=[A-Z_][a-zA-Z0-9]+$ |
269 | + |
270 | +# Regular expression which should only match correct function names |
271 | +function-rgx=[a-z_][a-z0-9_]{2,79}$ |
272 | + |
273 | +# Regular expression which should only match correct method names |
274 | +method-rgx=([a-z_][a-z0-9_]{2,79}$|setUp|tearDown) |
275 | + |
276 | +# Regular expression which should only match correct instance attribute names |
277 | +attr-rgx=[a-z_][a-z0-9_]{1,30}$ |
278 | + |
279 | +# Regular expression which should only match correct argument names |
280 | +argument-rgx=[a-z_][a-z0-9_]{1,30}$ |
281 | + |
282 | +# Regular expression which should only match correct variable names |
283 | +variable-rgx=[a-z_][a-z0-9_]{1,30}$ |
284 | + |
285 | +# Regular expression which should only match correct list comprehension / |
286 | +# generator expression variable names |
287 | +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ |
288 | + |
289 | +# Good variable names which should always be accepted, separated by a comma |
290 | +good-names=d,e,f,g,i,j,k,ex,logger,Run,_ |
291 | + |
292 | +# Bad variable names which should always be refused, separated by a comma |
293 | +bad-names=foo,bar,baz,toto,tutu,tata |
294 | + |
295 | +# List of builtins function names that should not be used, separated by a comma |
296 | +bad-functions=apply,input,reduce |
297 | + |
298 | + |
299 | +# checks for sign of poor/misdesign: |
300 | +# * number of methods, attributes, local variables... |
301 | +# * size, complexity of functions, methods |
302 | +# |
303 | +[DESIGN] |
304 | + |
305 | +# Maximum number of arguments for function / method |
306 | +max-args=5 |
307 | + |
308 | +# Maximum number of locals for function / method body |
309 | +max-locals=15 |
310 | + |
311 | +# Maximum number of return / yield for function / method body |
312 | +max-returns=6 |
313 | + |
314 | +# Maximum number of branch for function / method body |
315 | +max-branchs=12 |
316 | + |
317 | +# Maximum number of statements in function / method body |
318 | +max-statements=50 |
319 | + |
320 | +# Maximum number of parents for a class (see R0901). |
321 | +max-parents=7 |
322 | + |
323 | +# Maximum number of attributes for a class (see R0902). |
324 | +max-attributes=7 |
325 | + |
326 | +# Minimum number of public methods for a class (see R0903). |
327 | +min-public-methods=2 |
328 | + |
329 | +# Maximum number of public methods for a class (see R0904). |
330 | +max-public-methods=20 |
331 | + |
332 | + |
333 | +# checks for : |
334 | +# * methods without self as first argument |
335 | +# * overridden methods signature |
336 | +# * access only to existent members via self |
337 | +# * attributes not defined in the __init__ method |
338 | +# * supported interfaces implementation |
339 | +# * unreachable code |
340 | +# |
341 | +[CLASSES] |
342 | + |
343 | +# List of interface methods to ignore, separated by a comma. This is used for |
344 | +# instance to not check methods defines in Zopes Interface base class. |
345 | +#ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by,providedBy |
346 | + |
347 | +# List of method names used to declare (i.e. assign) instance attributes. |
348 | +defining-attr-methods=__init__,__new__,setUp |
349 | + |
350 | + |
351 | +# checks for |
352 | +# * external modules dependencies |
353 | +# * relative / wildcard imports |
354 | +# * cyclic imports |
355 | +# * uses of deprecated modules |
356 | +# |
357 | +[IMPORTS] |
358 | + |
359 | +# Deprecated modules which should not be used, separated by a comma |
360 | +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec |
361 | + |
362 | +# Create a graph of every (i.e. internal and external) dependencies in the |
363 | +# given file (report RP0402 must not be disabled) |
364 | +import-graph= |
365 | + |
366 | +# Create a graph of external dependencies in the given file (report RP0402 must |
367 | +# not be disabled) |
368 | +ext-import-graph= |
369 | + |
370 | +# Create a graph of internal dependencies in the given file (report RP0402 must |
371 | +# not be disabled) |
372 | +int-import-graph= |
373 | + |
374 | + |
375 | +# checks for : |
376 | +# * unauthorized constructions |
377 | +# * strict indentation |
378 | +# * line length |
379 | +# * use of <> instead of != |
380 | +# |
381 | +[FORMAT] |
382 | + |
383 | +# Maximum number of characters on a single line. |
384 | +max-line-length=79 |
385 | + |
386 | +# Maximum number of lines in a module |
387 | +max-module-lines=2500 |
388 | + |
389 | +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 |
390 | +# tab). |
391 | +indent-string=' ' |
392 | + |
393 | + |
394 | +# checks for similarities and duplicated code. This computation may be |
395 | +# memory / CPU intensive, so you should disable it if you experiments some |
396 | +# problems. |
397 | +# |
398 | +[SIMILARITIES] |
399 | + |
400 | +# Minimum lines number of a similarity. |
401 | +min-similarity-lines=4 |
402 | + |
403 | +# Ignore comments when computing similarities. |
404 | +ignore-comments=yes |
405 | + |
406 | +# Ignore docstrings when computing similarities. |
407 | +ignore-docstrings=yes |
408 | + |
409 | + |
410 | +# checks for: |
411 | +# * warning notes in the code like FIXME, XXX |
412 | +# * PEP 263: source code with non ascii character but no encoding declaration |
413 | +# |
414 | +[MISCELLANEOUS] |
415 | + |
416 | +# List of note tags to take in consideration, separated by a comma. |
417 | +notes=FIXME,XXX,TODO,fixme,xxx,todo |
418 | |
419 | === modified file 'run-tests' |
420 | --- run-tests 2011-06-21 20:01:26 +0000 |
421 | +++ run-tests 2011-06-22 14:18:49 +0000 |
422 | @@ -37,7 +37,7 @@ |
423 | |
424 | ./setup.py build |
425 | echo "Running test suite for ""$MODULE" |
426 | -`which xvfb-run` u1trial "$MODULE" |
427 | +`which xvfb-run` u1trial --reactor=qt4 --gui "$MODULE" |
428 | style_check |
429 | rm -rf _trial_temp |
430 | rm -rf build |
431 | |
432 | === modified file 'ubuntuone_installer/__init__.py' |
433 | --- ubuntuone_installer/__init__.py 2011-06-21 15:41:55 +0000 |
434 | +++ ubuntuone_installer/__init__.py 2011-06-22 14:18:49 +0000 |
435 | @@ -19,7 +19,7 @@ |
436 | |
437 | """The windows installer for Ubuntu One. |
438 | |
439 | -The installer is a wizard that sets up the basic account and configuration for |
440 | +The installer is a wizard that sets up the basic account and configuration for |
441 | a Ubuntu One user on windows. |
442 | """ |
443 | |
444 | |
445 | === modified file 'ubuntuone_installer/gui/qt/__init__.py' |
446 | --- ubuntuone_installer/gui/qt/__init__.py 2011-06-21 18:18:33 +0000 |
447 | +++ ubuntuone_installer/gui/qt/__init__.py 2011-06-22 14:18:49 +0000 |
448 | @@ -17,4 +17,3 @@ |
449 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
450 | |
451 | """The Qt graphical interface for the Ubuntu One Installer.""" |
452 | - |
453 | |
454 | === modified file 'ubuntuone_installer/gui/qt/gui.py' |
455 | --- ubuntuone_installer/gui/qt/gui.py 2011-06-21 19:46:39 +0000 |
456 | +++ ubuntuone_installer/gui/qt/gui.py 2011-06-22 14:18:49 +0000 |
457 | @@ -19,32 +19,37 @@ |
458 | |
459 | """The user interface for the Ubuntu One Installer.""" |
460 | |
461 | +import subprocess |
462 | |
463 | from PyQt4 import QtGui |
464 | |
465 | from ubuntuone_installer.logger import setup_logging |
466 | -from ubuntuone_installer.gui.qt.ui import license_ui |
467 | +from ubuntuone_installer.gui.qt.ui import ( |
468 | + license_ui, |
469 | + congratulations_ui, |
470 | +) |
471 | |
472 | import gettext |
473 | |
474 | _ = gettext.gettext |
475 | |
476 | +# Invalid name logger |
477 | +# pylint: disable=C0103 |
478 | logger = setup_logging('qt.gui') |
479 | +# pylint: enable=C0103 |
480 | |
481 | |
482 | class LicensePage(QtGui.QWizardPage): |
483 | """Wizard Page that displays the license info and links to the GPL""" |
484 | |
485 | - # Invalid constant names and Qt-inherited methods |
486 | - # pylint: disable=C0103 |
487 | - |
488 | - LICENSE_PAGE = 0 |
489 | - |
490 | def __init__(self, parent=None): |
491 | QtGui.QWizardPage.__init__(self, parent) |
492 | self.ui = license_ui.Ui_Form() |
493 | self.ui.setupUi(self) |
494 | |
495 | + # Invalid names of Qt-inherited methods |
496 | + # pylint: disable=C0103 |
497 | + |
498 | def initializePage(self): |
499 | """Setup UI details""" |
500 | |
501 | @@ -55,50 +60,79 @@ |
502 | # Set the right texts and connections for buttons |
503 | self.setButtonText(QtGui.QWizard.NextButton, _("Agree && Install")) |
504 | self.setButtonText(QtGui.QWizard.CancelButton, |
505 | - _("Disagree && Cancel")) |
506 | - self.setButtonText(QtGui.QWizard.CustomButton1, _("&Print")) |
507 | - self.wizard().customButtonClicked.connect(self.printDocument) |
508 | - |
509 | - def printDocument(self, button_id): |
510 | + _("Disagree && Cancel")) |
511 | + self.setButtonText(QtGui.QWizard.CustomButton1, _("&Print")) |
512 | + self.wizard().customButtonClicked.connect(self.print_document) |
513 | + |
514 | + def print_document(self, button_id): |
515 | """Print the document displayed in textBrowser""" |
516 | - |
517 | + |
518 | if button_id == QtGui.QWizard.CustomButton1: |
519 | document = self.ui.textBrowser.document() |
520 | printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) |
521 | |
522 | dialog = QtGui.QPrintDialog(printer, self) |
523 | - |
524 | + |
525 | dialog.setWindowTitle(_("Send to printer")) |
526 | if dialog.exec_() != QtGui.QDialog.Accepted: |
527 | return |
528 | printer.setFullPage(True) |
529 | printer.setPageSize(QtGui.QPrinter.A4) |
530 | document.print_(printer) |
531 | - |
532 | + |
533 | + |
534 | +class CongratulationsPage(QtGui.QWizardPage): |
535 | + """Final page of the wizard""" |
536 | + |
537 | + def __init__(self, parent=None): |
538 | + QtGui.QWizardPage.__init__(self, parent) |
539 | + self.ui = congratulations_ui.Ui_Form() |
540 | + self.ui.setupUi(self) |
541 | + |
542 | + # Invalid names of Qt-inherited methods |
543 | + # pylint: disable=C0103 |
544 | + |
545 | + def initializePage(self): |
546 | + """Setup UI details""" |
547 | + |
548 | + # We need custom buttons |
549 | + self.wizard().setButtonText(QtGui.QWizard.FinishButton, |
550 | + _("Go to my Ubuntu One dashboard")) |
551 | + self.wizard().setOption(QtGui.QWizard.HaveCustomButton1, False) |
552 | + self.wizard().setOption(QtGui.QWizard.NoCancelButton, True) |
553 | + |
554 | |
555 | class MainWindow(QtGui.QWizard): |
556 | """The Main Window of the Installer wizard.""" |
557 | |
558 | + # Invalid constant names and Qt-inherited methods |
559 | + # pylint: disable=C0103 |
560 | + |
561 | + LICENSE_PAGE = 0 |
562 | + CONGRATULATIONS_PAGE = 1 |
563 | + |
564 | def __init__(self, close_callback=None): |
565 | """Initialize this instance with the UI layout.""" |
566 | + |
567 | QtGui.QWizard.__init__(self) |
568 | self.close_callback = close_callback |
569 | |
570 | self.setOption(self.NoBackButtonOnStartPage, True) |
571 | - |
572 | + self.setOption(self.DisabledBackButtonOnLastPage, True) |
573 | # PyQt doesn't support the (int, page) version of addPage |
574 | # Add the pages in the right order |
575 | - |
576 | + |
577 | # pylint: disable=C0103 |
578 | self.LICENSE_PAGE = self.addPage(LicensePage()) |
579 | - # Dummy page to have a "Next" |
580 | - self.addPage(QtGui.QWizardPage()) |
581 | + self.CONGRATULATIONS_PAGE = self.addPage(CongratulationsPage()) |
582 | |
583 | # Invalid name "closeEvent" |
584 | # pylint: disable=C0103 |
585 | |
586 | def done(self, result): |
587 | """The main window is being closed, call any custom callback.""" |
588 | + if result == 1: # Finished, not cancelled |
589 | + subprocess.Popen(["ubuntuone-control-panel-qt", ]) |
590 | if self.close_callback is not None: |
591 | self.close_callback() |
592 | QtGui.QWizard.done(self, result) |
593 | |
594 | === added directory 'ubuntuone_installer/gui/qt/tests' |
595 | === added file 'ubuntuone_installer/gui/qt/tests/__init__.py' |
596 | --- ubuntuone_installer/gui/qt/tests/__init__.py 1970-01-01 00:00:00 +0000 |
597 | +++ ubuntuone_installer/gui/qt/tests/__init__.py 2011-06-22 14:18:49 +0000 |
598 | @@ -0,0 +1,68 @@ |
599 | +# -*- coding: utf-8 -*- |
600 | + |
601 | +# Authors: Alejandro J. Cura <alecu@canonical.com> |
602 | +# |
603 | +# Copyright 2011 Canonical Ltd. |
604 | +# |
605 | +# This program is free software: you can redistribute it and/or modify it |
606 | +# under the terms of the GNU General Public License version 3, as published |
607 | +# by the Free Software Foundation. |
608 | +# |
609 | +# This program is distributed in the hope that it will be useful, but |
610 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
611 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
612 | +# PURPOSE. See the GNU General Public License for more details. |
613 | +# |
614 | +# You should have received a copy of the GNU General Public License along |
615 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
616 | + |
617 | +"""The test suite for the Qt UI of the Ubuntu One Installer.""" |
618 | + |
619 | +from ubuntuone_installer.tests import TestCase |
620 | +from ubuntuone_installer.gui.tests import FakedObject |
621 | + |
622 | +# Attribute 'yyy' defined outside __init__, access to a protected member |
623 | +# pylint: disable=W0201, W0212 |
624 | + |
625 | + |
626 | +NO_OP = lambda *args: None |
627 | + |
628 | + |
629 | +def skip_if_abstract_class(test): |
630 | + """Decorator to skip a test if is an abstract class.""" |
631 | + |
632 | + def inner(instance): |
633 | + """Skip a test if is an abstract class.""" |
634 | + abstract = instance.class_ui is None |
635 | + result = None |
636 | + if not abstract: |
637 | + result = test(instance) |
638 | + |
639 | + return result |
640 | + |
641 | + return inner |
642 | + |
643 | + |
644 | +class FakeUi(FakedObject): |
645 | + """A fake Ui object.""" |
646 | + |
647 | + exposed_methods = ['setupUi'] |
648 | + |
649 | + |
650 | +class BaseTestCase(TestCase): |
651 | + """Base Test Case.""" |
652 | + |
653 | + class_ui = None |
654 | + kwargs = {} |
655 | + |
656 | + @skip_if_abstract_class |
657 | + def setUp(self): |
658 | + super(BaseTestCase, self).setUp() |
659 | + # self.class_ui is not callable |
660 | + # pylint: disable=E1102 |
661 | + # pylint: disable=C0103 |
662 | + self.ui = self.class_ui(**self.kwargs) |
663 | + |
664 | + if hasattr(self.ui, 'backend'): |
665 | + # clean backend calls |
666 | + self.ui.backend._called.clear() |
667 | |
668 | === added file 'ubuntuone_installer/gui/qt/tests/test_gui.py' |
669 | --- ubuntuone_installer/gui/qt/tests/test_gui.py 1970-01-01 00:00:00 +0000 |
670 | +++ ubuntuone_installer/gui/qt/tests/test_gui.py 2011-06-22 14:18:49 +0000 |
671 | @@ -0,0 +1,61 @@ |
672 | +# -*- coding: utf-8 -*- |
673 | + |
674 | +# Authors: Alejandro J. Cura <alecu@canonical.com> |
675 | +# Roberto Alsina <roberto.alsina@canonical.com> |
676 | +# |
677 | +# Copyright 2011 Canonical Ltd. |
678 | +# |
679 | +# This program is free software: you can redistribute it and/or modify it |
680 | +# under the terms of the GNU General Public License version 3, as published |
681 | +# by the Free Software Foundation. |
682 | +# |
683 | +# This program is distributed in the hope that it will be useful, but |
684 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
685 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
686 | +# PURPOSE. See the GNU General Public License for more details. |
687 | +# |
688 | +# You should have received a copy of the GNU General Public License along |
689 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
690 | + |
691 | +"""Tests for the Qt UI.""" |
692 | + |
693 | +from ubuntuone_installer.gui.qt import gui |
694 | +from ubuntuone_installer.gui.qt.tests import BaseTestCase |
695 | + |
696 | + |
697 | +class MainWindowTestCase(BaseTestCase): |
698 | + """Test the qt main window.""" |
699 | + |
700 | + class_ui = gui.MainWindow |
701 | + |
702 | + def setUp(self): |
703 | + """Initialize this test instance.""" |
704 | + super(MainWindowTestCase, self).setUp() |
705 | + |
706 | + def test_done_calls_custom_close_callback(self): |
707 | + """When closing the window, close_callback is called.""" |
708 | + self.ui.close_callback = self._set_called |
709 | + self.ui.done(result=0) |
710 | + self.assertEqual(self._called, |
711 | + ((), {}), 'close_callback called.') |
712 | + |
713 | + def test_close_callback_can_be_none(self): |
714 | + """The close_callback can be None.""" |
715 | + self.ui.close_callback = None |
716 | + self.ui.done(result=0) |
717 | + # world did not explode |
718 | + |
719 | + def test_start_control_panel_on_finishing(self): |
720 | + """If done is called with result=1, the control panel |
721 | + should be called""" |
722 | + self.patch(gui.subprocess, "Popen", self._set_called) |
723 | + self.ui.done(result=1) |
724 | + self.assertEqual(self._called, |
725 | + ((['ubuntuone-control-panel-qt'],), {})) |
726 | + |
727 | + def test_not_start_control_panel_on_cancel(self): |
728 | + """If done is called with result=0, the control panel |
729 | + should NOT be called""" |
730 | + self.patch(gui.subprocess, "Popen", self._set_called) |
731 | + self.ui.done(result=0) |
732 | + self.assertEqual(self._called, False) |
733 | |
734 | === added directory 'ubuntuone_installer/gui/tests' |
735 | === added file 'ubuntuone_installer/gui/tests/__init__.py' |
736 | --- ubuntuone_installer/gui/tests/__init__.py 1970-01-01 00:00:00 +0000 |
737 | +++ ubuntuone_installer/gui/tests/__init__.py 2011-06-22 14:18:49 +0000 |
738 | @@ -0,0 +1,45 @@ |
739 | +# -*- coding: utf-8 -*- |
740 | + |
741 | +# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
742 | +# Roberto Alsina <roberto.alsina@canonical.com> |
743 | +# |
744 | +# Copyright 2011 Canonical Ltd. |
745 | +# |
746 | +# This program is free software: you can redistribute it and/or modify it |
747 | +# under the terms of the GNU General Public License version 3, as published |
748 | +# by the Free Software Foundation. |
749 | +# |
750 | +# This program is distributed in the hope that it will be useful, but |
751 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
752 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
753 | +# PURPOSE. See the GNU General Public License for more details. |
754 | +# |
755 | +# You should have received a copy of the GNU General Public License along |
756 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
757 | + |
758 | +"""The test suite for the Ubuntu One Installer.""" |
759 | + |
760 | +# Attribute 'yyy' defined outside __init__, access to a protected member |
761 | +# pylint: disable=W0201, W0212 |
762 | + |
763 | + |
764 | +class FakedObject(object): |
765 | + """Fake an object, record every call.""" |
766 | + |
767 | + exposed_methods = [] |
768 | + |
769 | + def __init__(self, *args, **kwargs): |
770 | + self._args = args |
771 | + self._kwargs = kwargs |
772 | + self._called = {} |
773 | + for i in self.exposed_methods: |
774 | + setattr(self, i, self._record_call(i)) |
775 | + |
776 | + def _record_call(self, func_name): |
777 | + """Store values when calling 'func_name'.""" |
778 | + |
779 | + def inner(*args, **kwargs): |
780 | + """Fake 'func_name'.""" |
781 | + self._called[func_name] = (args, kwargs) |
782 | + |
783 | + return inner |
784 | |
785 | === added directory 'ubuntuone_installer/tests' |
786 | === added file 'ubuntuone_installer/tests/__init__.py' |
787 | --- ubuntuone_installer/tests/__init__.py 1970-01-01 00:00:00 +0000 |
788 | +++ ubuntuone_installer/tests/__init__.py 2011-06-22 14:18:49 +0000 |
789 | @@ -0,0 +1,38 @@ |
790 | +# -*- coding: utf-8 -*- |
791 | + |
792 | +# Authors: Natalia B Bidart <natalia.bidart@canonical.com> |
793 | +# Roberto Alsina <roberto.alsina@canonical.com> |
794 | +# |
795 | +# Copyright 2010-2011 Canonical Ltd. |
796 | +# |
797 | +# This program is free software: you can redistribute it and/or modify it |
798 | +# under the terms of the GNU General Public License version 3, as published |
799 | +# by the Free Software Foundation. |
800 | +# |
801 | +# This program is distributed in the hope that it will be useful, but |
802 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
803 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
804 | +# PURPOSE. See the GNU General Public License for more details. |
805 | +# |
806 | +# You should have received a copy of the GNU General Public License along |
807 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
808 | + |
809 | +"""The test suite for the Ubuntu One Installer""" |
810 | + |
811 | +from ubuntuone.devtools.testcase import TestCase as BaseTestCase |
812 | + |
813 | + |
814 | +class TestCase(BaseTestCase): |
815 | + """Basics for testing.""" |
816 | + |
817 | + assertIs = BaseTestCase.assertIdentical |
818 | + |
819 | + def setUp(self): |
820 | + self._called = False |
821 | + |
822 | + def tearDown(self): |
823 | + self._called = False |
824 | + |
825 | + def _set_called(self, *args, **kwargs): |
826 | + """Store 'args' and 'kwargs' for test assertions.""" |
827 | + self._called = (args, kwargs) |
+ subprocess. Popen([ "ubuntuone- control- panel-gtk" ,])
Should this not be ubuntuone- control- panel-qt, given that we're running it from a qt gui? Also, should we not rely on IPC activation to just start the correct one for the user's environment, instead of running it directly?