Merge lp:~nataliabidart/magicicada-gui/build-gui into lp:magicicada-gui
- build-gui
- Merge into trunk
Proposed by
Natalia Bidart
Status: | Merged | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Facundo Batista | ||||||||||||||||||||||||
Approved revision: | 13 | ||||||||||||||||||||||||
Merged at revision: | 15 | ||||||||||||||||||||||||
Proposed branch: | lp:~nataliabidart/magicicada-gui/build-gui | ||||||||||||||||||||||||
Merge into: | lp:magicicada-gui | ||||||||||||||||||||||||
Diff against target: |
1396 lines (+599/-638) 14 files modified
bin/magicicada (+3/-56) data/ui/AboutMagicicadaDialog.ui (+0/-40) data/ui/MagicicadaWindow.ui (+0/-232) data/ui/PreferencesMagicicadaDialog.ui (+0/-67) data/ui/about_magicicada_dialog.xml (+0/-9) data/ui/gui.glade (+219/-52) data/ui/magicicada_window.xml (+0/-8) data/ui/preferences_magicicada_dialog.xml (+0/-9) magicicada/AboutMagicicadaDialog.py (+0/-48) magicicada/PreferencesMagicicadaDialog.py (+0/-111) magicicada/__init__.py (+204/-0) magicicada/helpers.py (+15/-3) magicicada/syncdaemon.py (+8/-3) magicicada/tests/test_magicicada.py (+150/-0) |
||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~nataliabidart/magicicada-gui/build-gui | ||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Facundo Batista | Approve | ||
Review via email: mp+24962@code.launchpad.net |
Commit message
Description of the change
First schema of Magicicada GUI.
To post a comment you must log in.
- 12. By Natalia Bidart
-
Fising some tests.
Revision history for this message
Natalia Bidart (nataliabidart) wrote : | # |
All fixed now!
- 13. By Natalia Bidart
-
Removing no longer needed patch def.
Revision history for this message
Facundo Batista (facundo) wrote : | # |
Approving, but one comment.
Why the decorator that logs to stdout is called "dummy"? When you see a method decorated dummy you expect it to do nothing, but here it *is* executed.
review:
Approve
Revision history for this message
Natalia Bidart (nataliabidart) wrote : | # |
> Approving, but one comment.
>
> Why the decorator that logs to stdout is called "dummy"? When you see a method
> decorated dummy you expect it to do nothing, but here it *is* executed.
I renamed it to print_debug. Thanks for pointing this out!
- 14. By Natalia Bidart
-
Renaming dumy decorator to print_debug.
- 15. By Natalia Bidart
-
Merged trunk in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bin/magicicada' |
2 | --- bin/magicicada 2010-04-21 23:50:09 +0000 |
3 | +++ bin/magicicada 2010-05-15 15:48:32 +0000 |
4 | @@ -6,7 +6,6 @@ |
5 | |
6 | import sys |
7 | import os |
8 | -import gtk |
9 | |
10 | import gettext |
11 | from gettext import gettext as _ |
12 | @@ -29,59 +28,7 @@ |
13 | sys.path.insert(0, PROJECT_ROOT_DIRECTORY) |
14 | os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses |
15 | |
16 | -from magicicada import ( |
17 | - AboutMagicicadaDialog, PreferencesMagicicadaDialog) |
18 | -from magicicada.helpers import get_builder |
19 | - |
20 | - |
21 | -class MagicicadaUI(object): |
22 | - |
23 | - def __init__(self): |
24 | - """Init.""" |
25 | - self.builder = get_builder('gui.glade') |
26 | - self.builder.connect_signals(self) |
27 | - |
28 | - global launchpad_available |
29 | - if launchpad_available: |
30 | - # see https://wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding for more information |
31 | - # about LaunchpadIntegration |
32 | - helpmenu = self.builder.get_object('helpMenu') |
33 | - if helpmenu: |
34 | - LaunchpadIntegration.set_sourcepackagename('magicicada') |
35 | - LaunchpadIntegration.add_items(helpmenu, 0, False, True) |
36 | - else: |
37 | - launchpad_available = False |
38 | - |
39 | - # Uncomment the following code to read in preferences at start up. |
40 | - #dlg = PreferencesMagicicadaDialog.NewPreferencesMagicicadaDialog() |
41 | - #self.preferences = dlg.get_preferences() |
42 | - |
43 | - # Code for other initialization actions should be added here. |
44 | - self.builder.get_object('main_window').show_all() |
45 | - |
46 | - def about(self, widget, data=None): |
47 | - """Display the about box for magicicada.""" |
48 | - about = AboutMagicicadaDialog.AboutMagicicadaDialog() |
49 | - response = about.run() |
50 | - about.destroy() |
51 | - |
52 | - def preferences(self, widget, data=None): |
53 | - """Display the preferences window for magicicada.""" |
54 | - prefs = PreferencesMagicicadaDialog.PreferencesMagicicadaDialog() |
55 | - response = prefs.run() |
56 | - if response == gtk.RESPONSE_OK: |
57 | - # Make any updates based on changed preferences here. |
58 | - pass |
59 | - prefs.destroy() |
60 | - |
61 | - def quit(self, widget, data=None): |
62 | - """Signal handler for closing the MagicicadaWindow.""" |
63 | - self.destroy() |
64 | - |
65 | - def on_destroy(self, widget, data=None): |
66 | - """Called when the MagicicadaWindow is closed.""" |
67 | - # Clean up code for saving application state should be added here. |
68 | - gtk.main_quit() |
69 | +from magicicada import MagicicadaUI |
70 | |
71 | if __name__ == "__main__": |
72 | # Support for command line options. |
73 | @@ -99,5 +46,5 @@ |
74 | logging.debug('logging enabled') |
75 | |
76 | # Run the application. |
77 | - window = MagicicadaUI() |
78 | - gtk.main() |
79 | + window = MagicicadaUI(launchpad_available=launchpad_available) |
80 | + window.run() |
81 | |
82 | === added file 'data/media/loader-ball.gif' |
83 | Binary files data/media/loader-ball.gif 1970-01-01 00:00:00 +0000 and data/media/loader-ball.gif 2010-05-15 15:48:32 +0000 differ |
84 | === added file 'data/media/ubuntuone.png' |
85 | Binary files data/media/ubuntuone.png 1970-01-01 00:00:00 +0000 and data/media/ubuntuone.png 2010-05-15 15:48:32 +0000 differ |
86 | === removed file 'data/ui/AboutMagicicadaDialog.ui' |
87 | --- data/ui/AboutMagicicadaDialog.ui 2010-04-21 21:18:31 +0000 |
88 | +++ data/ui/AboutMagicicadaDialog.ui 1970-01-01 00:00:00 +0000 |
89 | @@ -1,40 +0,0 @@ |
90 | -<?xml version="1.0"?> |
91 | -<interface> |
92 | - <requires lib="gtk+" version="2.16"/> |
93 | - <!-- interface-requires about_magicicada_dialog 1.0 --> |
94 | - <!-- interface-naming-policy project-wide --> |
95 | - <object class="AboutMagicicadaDialog" id="about_magicicada_dialog"> |
96 | - <property name="border_width">5</property> |
97 | - <property name="icon">../media/icon.png</property> |
98 | - <property name="type_hint">normal</property> |
99 | - <property name="has_separator">False</property> |
100 | - <property name="program_name">Magicicada</property> |
101 | - <property name="version"></property> |
102 | - <property name="copyright"></property> |
103 | - <property name="website"></property> |
104 | - <property name="license"></property> |
105 | - <property name="authors"></property> |
106 | - <property name="logo">../media/logo.png</property> |
107 | - <child internal-child="vbox"> |
108 | - <object class="GtkVBox" id="dialog-vbox1"> |
109 | - <property name="visible">True</property> |
110 | - <property name="orientation">vertical</property> |
111 | - <property name="spacing">2</property> |
112 | - <child> |
113 | - <placeholder/> |
114 | - </child> |
115 | - <child internal-child="action_area"> |
116 | - <object class="GtkHButtonBox" id="dialog-action_area1"> |
117 | - <property name="visible">True</property> |
118 | - <property name="layout_style">end</property> |
119 | - </object> |
120 | - <packing> |
121 | - <property name="expand">False</property> |
122 | - <property name="pack_type">end</property> |
123 | - <property name="position">0</property> |
124 | - </packing> |
125 | - </child> |
126 | - </object> |
127 | - </child> |
128 | - </object> |
129 | -</interface> |
130 | |
131 | === removed file 'data/ui/MagicicadaWindow.ui' |
132 | --- data/ui/MagicicadaWindow.ui 2010-04-21 21:18:31 +0000 |
133 | +++ data/ui/MagicicadaWindow.ui 1970-01-01 00:00:00 +0000 |
134 | @@ -1,232 +0,0 @@ |
135 | -<?xml version="1.0"?> |
136 | -<interface> |
137 | - <requires lib="gtk+" version="2.16"/> |
138 | - <!-- interface-requires magicicada_window 1.0 --> |
139 | - <!-- interface-naming-policy project-wide --> |
140 | - <!-- interface-local-resource-path ../media --> |
141 | - <object class="MagicicadaWindow" id="magicicada_window"> |
142 | - <property name="title" translatable="yes">Magicicada</property> |
143 | - <property name="icon">../media/icon.png</property> |
144 | - <signal name="destroy" handler="on_destroy"/> |
145 | - <child> |
146 | - <object class="GtkVBox" id="vbox1"> |
147 | - <property name="visible">True</property> |
148 | - <property name="orientation">vertical</property> |
149 | - <property name="spacing">5</property> |
150 | - <child> |
151 | - <object class="GtkMenuBar" id="menubar1"> |
152 | - <property name="visible">True</property> |
153 | - <child> |
154 | - <object class="GtkMenuItem" id="menuitem1"> |
155 | - <property name="visible">True</property> |
156 | - <property name="label" translatable="yes">_File</property> |
157 | - <property name="use_underline">True</property> |
158 | - <child type="submenu"> |
159 | - <object class="GtkMenu" id="menu1"> |
160 | - <property name="visible">True</property> |
161 | - <child> |
162 | - <object class="GtkImageMenuItem" id="imagemenuitem1"> |
163 | - <property name="label">gtk-new</property> |
164 | - <property name="visible">True</property> |
165 | - <property name="use_action_appearance">True</property> |
166 | - <property name="use_underline">True</property> |
167 | - <property name="use_stock">True</property> |
168 | - <accelerator key="n" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
169 | - </object> |
170 | - </child> |
171 | - <child> |
172 | - <object class="GtkImageMenuItem" id="imagemenuitem2"> |
173 | - <property name="label">gtk-open</property> |
174 | - <property name="visible">True</property> |
175 | - <property name="use_underline">True</property> |
176 | - <property name="use_stock">True</property> |
177 | - <accelerator key="o" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
178 | - </object> |
179 | - </child> |
180 | - <child> |
181 | - <object class="GtkImageMenuItem" id="imagemenuitem3"> |
182 | - <property name="label">gtk-save</property> |
183 | - <property name="visible">True</property> |
184 | - <property name="use_underline">True</property> |
185 | - <property name="use_stock">True</property> |
186 | - <accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
187 | - </object> |
188 | - </child> |
189 | - <child> |
190 | - <object class="GtkImageMenuItem" id="imagemenuitem4"> |
191 | - <property name="label">gtk-save-as</property> |
192 | - <property name="visible">True</property> |
193 | - <property name="use_underline">True</property> |
194 | - <property name="use_stock">True</property> |
195 | - <accelerator key="s" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/> |
196 | - </object> |
197 | - </child> |
198 | - <child> |
199 | - <object class="GtkSeparatorMenuItem" id="separatormenuitem1"> |
200 | - <property name="visible">True</property> |
201 | - </object> |
202 | - </child> |
203 | - <child> |
204 | - <object class="GtkImageMenuItem" id="imagemenuitem5"> |
205 | - <property name="label">gtk-quit</property> |
206 | - <property name="visible">True</property> |
207 | - <property name="use_underline">True</property> |
208 | - <property name="use_stock">True</property> |
209 | - <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
210 | - <signal name="activate" handler="quit"/> |
211 | - </object> |
212 | - </child> |
213 | - </object> |
214 | - </child> |
215 | - </object> |
216 | - </child> |
217 | - <child> |
218 | - <object class="GtkMenuItem" id="menuitem2"> |
219 | - <property name="visible">True</property> |
220 | - <property name="label" translatable="yes">_Edit</property> |
221 | - <property name="use_underline">True</property> |
222 | - <child type="submenu"> |
223 | - <object class="GtkMenu" id="menu2"> |
224 | - <property name="visible">True</property> |
225 | - <child> |
226 | - <object class="GtkImageMenuItem" id="imagemenuitem6"> |
227 | - <property name="label">gtk-cut</property> |
228 | - <property name="visible">True</property> |
229 | - <property name="use_underline">True</property> |
230 | - <property name="use_stock">True</property> |
231 | - <accelerator key="x" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
232 | - </object> |
233 | - </child> |
234 | - <child> |
235 | - <object class="GtkImageMenuItem" id="imagemenuitem7"> |
236 | - <property name="label">gtk-copy</property> |
237 | - <property name="visible">True</property> |
238 | - <property name="use_underline">True</property> |
239 | - <property name="use_stock">True</property> |
240 | - <accelerator key="c" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
241 | - </object> |
242 | - </child> |
243 | - <child> |
244 | - <object class="GtkImageMenuItem" id="imagemenuitem8"> |
245 | - <property name="label">gtk-paste</property> |
246 | - <property name="visible">True</property> |
247 | - <property name="use_underline">True</property> |
248 | - <property name="use_stock">True</property> |
249 | - <accelerator key="v" signal="activate" modifiers="GDK_CONTROL_MASK"/> |
250 | - </object> |
251 | - </child> |
252 | - <child> |
253 | - <object class="GtkImageMenuItem" id="imagemenuitem9"> |
254 | - <property name="label">gtk-delete</property> |
255 | - <property name="visible">True</property> |
256 | - <property name="use_underline">True</property> |
257 | - <property name="use_stock">True</property> |
258 | - <accelerator key="Delete" signal="activate"/> |
259 | - </object> |
260 | - </child> |
261 | - <child> |
262 | - <object class="GtkSeparatorMenuItem" id="separatormenuitem2"> |
263 | - <property name="visible">True</property> |
264 | - </object> |
265 | - </child> |
266 | - <child> |
267 | - <object class="GtkImageMenuItem" id="imagemenuitem11"> |
268 | - <property name="label">gtk-preferences</property> |
269 | - <property name="visible">True</property> |
270 | - <property name="use_underline">True</property> |
271 | - <property name="use_stock">True</property> |
272 | - <signal name="activate" handler="preferences"/> |
273 | - </object> |
274 | - </child> |
275 | - </object> |
276 | - </child> |
277 | - </object> |
278 | - </child> |
279 | - <child> |
280 | - <object class="GtkMenuItem" id="menuitem3"> |
281 | - <property name="visible">True</property> |
282 | - <property name="label" translatable="yes">_View</property> |
283 | - <property name="use_underline">True</property> |
284 | - </object> |
285 | - </child> |
286 | - <child> |
287 | - <object class="GtkMenuItem" id="menuitem4"> |
288 | - <property name="visible">True</property> |
289 | - <property name="label" translatable="yes">_Help</property> |
290 | - <property name="use_underline">True</property> |
291 | - <child type="submenu"> |
292 | - <object class="GtkMenu" id="helpMenu"> |
293 | - <property name="visible">True</property> |
294 | - <child> |
295 | - <object class="GtkImageMenuItem" id="imagemenuitem10"> |
296 | - <property name="label">gtk-about</property> |
297 | - <property name="visible">True</property> |
298 | - <property name="use_underline">True</property> |
299 | - <property name="use_stock">True</property> |
300 | - <signal name="activate" handler="about"/> |
301 | - </object> |
302 | - </child> |
303 | - </object> |
304 | - </child> |
305 | - </object> |
306 | - </child> |
307 | - </object> |
308 | - <packing> |
309 | - <property name="expand">False</property> |
310 | - <property name="position">0</property> |
311 | - </packing> |
312 | - </child> |
313 | - <child> |
314 | - <object class="GtkLabel" id="label1"> |
315 | - <property name="visible">True</property> |
316 | - <property name="xpad">30</property> |
317 | - <property name="ypad">5</property> |
318 | - <property name="label" translatable="yes">Your application has been created! |
319 | - |
320 | -To start changing this user interface, run 'quickly glade', which will open Glade so you can edit the default windows and dialogs. |
321 | - |
322 | -To change the behavior and edit the python code, run 'quickly edit', which will bring up a text editor.</property> |
323 | - <property name="wrap">True</property> |
324 | - </object> |
325 | - <packing> |
326 | - <property name="position">1</property> |
327 | - </packing> |
328 | - </child> |
329 | - <child> |
330 | - <object class="GtkImage" id="image1"> |
331 | - <property name="visible">True</property> |
332 | - <property name="xpad">5</property> |
333 | - <property name="ypad">5</property> |
334 | - <property name="pixbuf">../media/background.png</property> |
335 | - </object> |
336 | - <packing> |
337 | - <property name="padding">15</property> |
338 | - <property name="position">2</property> |
339 | - </packing> |
340 | - </child> |
341 | - <child> |
342 | - <object class="GtkStatusbar" id="statusbar1"> |
343 | - <property name="visible">True</property> |
344 | - <property name="spacing">2</property> |
345 | - <child> |
346 | - <object class="GtkLabel" id="label2"> |
347 | - <property name="visible">True</property> |
348 | - <property name="xalign">0</property> |
349 | - <property name="xpad">5</property> |
350 | - <property name="ypad">5</property> |
351 | - <property name="label" translatable="yes">Status Area</property> |
352 | - </object> |
353 | - <packing> |
354 | - <property name="position">0</property> |
355 | - </packing> |
356 | - </child> |
357 | - </object> |
358 | - <packing> |
359 | - <property name="expand">False</property> |
360 | - <property name="position">3</property> |
361 | - </packing> |
362 | - </child> |
363 | - </object> |
364 | - </child> |
365 | - </object> |
366 | -</interface> |
367 | |
368 | === removed file 'data/ui/PreferencesMagicicadaDialog.ui' |
369 | --- data/ui/PreferencesMagicicadaDialog.ui 2010-04-21 21:18:31 +0000 |
370 | +++ data/ui/PreferencesMagicicadaDialog.ui 1970-01-01 00:00:00 +0000 |
371 | @@ -1,67 +0,0 @@ |
372 | -<?xml version="1.0"?> |
373 | -<interface> |
374 | - <requires lib="gtk+" version="2.16"/> |
375 | - <!-- interface-requires preferences_magicicada_dialog 1.0 --> |
376 | - <!-- interface-naming-policy project-wide --> |
377 | - <object class="PreferencesMagicicadaDialog" id="preferences_magicicada_dialog"> |
378 | - <property name="border_width">5</property> |
379 | - <property name="icon">../media/icon.png</property> |
380 | - <property name="type_hint">normal</property> |
381 | - <property name="has_separator">False</property> |
382 | - <child internal-child="vbox"> |
383 | - <object class="GtkVBox" id="dialog-vbox1"> |
384 | - <property name="visible">True</property> |
385 | - <property name="orientation">vertical</property> |
386 | - <property name="spacing">2</property> |
387 | - <child> |
388 | - <placeholder/> |
389 | - </child> |
390 | - <child internal-child="action_area"> |
391 | - <object class="GtkHButtonBox" id="dialog-action_area1"> |
392 | - <property name="visible">True</property> |
393 | - <property name="layout_style">end</property> |
394 | - <child> |
395 | - <object class="GtkButton" id="button2"> |
396 | - <property name="label">gtk-cancel</property> |
397 | - <property name="visible">True</property> |
398 | - <property name="can_focus">True</property> |
399 | - <property name="receives_default">True</property> |
400 | - <property name="use_stock">True</property> |
401 | - <signal name="clicked" handler="cancel"/> |
402 | - </object> |
403 | - <packing> |
404 | - <property name="expand">False</property> |
405 | - <property name="fill">False</property> |
406 | - <property name="position">0</property> |
407 | - </packing> |
408 | - </child> |
409 | - <child> |
410 | - <object class="GtkButton" id="button1"> |
411 | - <property name="label">gtk-ok</property> |
412 | - <property name="visible">True</property> |
413 | - <property name="can_focus">True</property> |
414 | - <property name="receives_default">True</property> |
415 | - <property name="use_stock">True</property> |
416 | - <signal name="clicked" handler="ok"/> |
417 | - </object> |
418 | - <packing> |
419 | - <property name="expand">False</property> |
420 | - <property name="fill">False</property> |
421 | - <property name="position">1</property> |
422 | - </packing> |
423 | - </child> |
424 | - </object> |
425 | - <packing> |
426 | - <property name="expand">False</property> |
427 | - <property name="pack_type">end</property> |
428 | - <property name="position">0</property> |
429 | - </packing> |
430 | - </child> |
431 | - </object> |
432 | - </child> |
433 | - <action-widgets> |
434 | - <action-widget response="-6">button2</action-widget> |
435 | - <action-widget response="-5">button1</action-widget> |
436 | - </action-widgets> |
437 | - </object> |
438 | -</interface> |
439 | |
440 | === removed file 'data/ui/about_magicicada_dialog.xml' |
441 | --- data/ui/about_magicicada_dialog.xml 2010-04-21 21:18:31 +0000 |
442 | +++ data/ui/about_magicicada_dialog.xml 1970-01-01 00:00:00 +0000 |
443 | @@ -1,9 +0,0 @@ |
444 | -<glade-catalog name="about_magicicada_dialog" domain="glade-3" |
445 | - depends="gtk+" version="1.0"> |
446 | - <glade-widget-classes> |
447 | - <glade-widget-class title="About Magicicada Dialog" name="AboutMagicicadaDialog" |
448 | - generic-name="AboutMagicicadaDialog" parent="GtkAboutDialog" |
449 | - icon-name="widget-gtk-about-dialog"/> |
450 | - </glade-widget-classes> |
451 | - |
452 | -</glade-catalog> |
453 | |
454 | === modified file 'data/ui/gui.glade' |
455 | --- data/ui/gui.glade 2010-04-21 23:50:09 +0000 |
456 | +++ data/ui/gui.glade 2010-05-15 15:48:32 +0000 |
457 | @@ -2,83 +2,196 @@ |
458 | <interface> |
459 | <requires lib="gtk+" version="2.16"/> |
460 | <!-- interface-naming-policy project-wide --> |
461 | + <object class="GtkListStore" id="liststore1"/> |
462 | + <object class="GtkListStore" id="liststore2"/> |
463 | <object class="GtkWindow" id="main_window"> |
464 | + <property name="width_request">800</property> |
465 | + <property name="height_request">600</property> |
466 | <property name="title" translatable="yes">Magicicada</property> |
467 | - <signal name="destroy_event" handler="on_destroy"/> |
468 | + <signal name="destroy" handler="on_main_window_destroy"/> |
469 | <child> |
470 | <object class="GtkVBox" id="vbox1"> |
471 | <property name="visible">True</property> |
472 | <child> |
473 | - <object class="GtkVBox" id="vbox2"> |
474 | - <property name="visible">True</property> |
475 | - <child> |
476 | - <object class="GtkToolbar" id="toolbar"> |
477 | - <property name="visible">True</property> |
478 | - <property name="icon_size_set">True</property> |
479 | - </object> |
480 | - <packing> |
481 | - <property name="expand">False</property> |
482 | - <property name="position">0</property> |
483 | - </packing> |
484 | - </child> |
485 | - <child> |
486 | - <object class="GtkHBox" id="hbox1"> |
487 | + <object class="GtkMenuBar" id="menubar"> |
488 | + <property name="visible">True</property> |
489 | + <child> |
490 | + <object class="GtkMenuItem" id="menuitem1"> |
491 | + <property name="visible">True</property> |
492 | + <property name="label" translatable="yes">_File</property> |
493 | + <property name="use_underline">True</property> |
494 | + <child type="submenu"> |
495 | + <object class="GtkMenu" id="menu1"> |
496 | + <property name="visible">True</property> |
497 | + <child> |
498 | + <object class="GtkImageMenuItem" id="quit"> |
499 | + <property name="label">gtk-quit</property> |
500 | + <property name="visible">True</property> |
501 | + <property name="use_underline">True</property> |
502 | + <property name="use_stock">True</property> |
503 | + <signal name="activate" handler="on_quit_activate"/> |
504 | + </object> |
505 | + </child> |
506 | + </object> |
507 | + </child> |
508 | + </object> |
509 | + </child> |
510 | + <child> |
511 | + <object class="GtkMenuItem" id="menuitem4"> |
512 | + <property name="visible">True</property> |
513 | + <property name="label" translatable="yes">_Help</property> |
514 | + <property name="use_underline">True</property> |
515 | + <child type="submenu"> |
516 | + <object class="GtkMenu" id="menu3"> |
517 | + <property name="visible">True</property> |
518 | + <child> |
519 | + <object class="GtkImageMenuItem" id="about"> |
520 | + <property name="label">gtk-about</property> |
521 | + <property name="visible">True</property> |
522 | + <property name="use_underline">True</property> |
523 | + <property name="use_stock">True</property> |
524 | + <signal name="activate" handler="on_about_activate"/> |
525 | + </object> |
526 | + </child> |
527 | + </object> |
528 | + </child> |
529 | + </object> |
530 | + </child> |
531 | + </object> |
532 | + <packing> |
533 | + <property name="expand">False</property> |
534 | + <property name="position">0</property> |
535 | + </packing> |
536 | + </child> |
537 | + <child> |
538 | + <object class="GtkToolbar" id="toolbar"> |
539 | + <property name="visible">True</property> |
540 | + <property name="toolbar_style">both</property> |
541 | + <child> |
542 | + <object class="GtkToolButton" id="start"> |
543 | + <property name="width_request">50</property> |
544 | + <property name="visible">True</property> |
545 | + <property name="label" translatable="yes">Start</property> |
546 | + <property name="use_underline">True</property> |
547 | + <property name="stock_id">gtk-apply</property> |
548 | + <signal name="clicked" handler="on_start_clicked"/> |
549 | + </object> |
550 | + <packing> |
551 | + <property name="expand">False</property> |
552 | + <property name="homogeneous">True</property> |
553 | + </packing> |
554 | + </child> |
555 | + <child> |
556 | + <object class="GtkToolButton" id="stop"> |
557 | + <property name="width_request">50</property> |
558 | + <property name="label" translatable="yes">Stop</property> |
559 | + <property name="use_underline">True</property> |
560 | + <property name="stock_id">gtk-stop</property> |
561 | + <signal name="clicked" handler="on_stop_clicked"/> |
562 | + </object> |
563 | + <packing> |
564 | + <property name="expand">False</property> |
565 | + <property name="homogeneous">True</property> |
566 | + </packing> |
567 | + </child> |
568 | + <child> |
569 | + <object class="GtkToolButton" id="connect"> |
570 | + <property name="width_request">80</property> |
571 | + <property name="visible">True</property> |
572 | + <property name="sensitive">False</property> |
573 | + <property name="label" translatable="yes">Connect</property> |
574 | + <property name="use_underline">True</property> |
575 | + <property name="stock_id">gtk-connect</property> |
576 | + <signal name="clicked" handler="on_connect_clicked"/> |
577 | + </object> |
578 | + <packing> |
579 | + <property name="expand">False</property> |
580 | + <property name="homogeneous">True</property> |
581 | + </packing> |
582 | + </child> |
583 | + <child> |
584 | + <object class="GtkToolButton" id="disconnect"> |
585 | + <property name="width_request">80</property> |
586 | + <property name="label" translatable="yes">Disconnect</property> |
587 | + <property name="use_underline">True</property> |
588 | + <property name="stock_id">gtk-disconnect</property> |
589 | + <signal name="clicked" handler="on_disconnect_clicked"/> |
590 | + </object> |
591 | + <packing> |
592 | + <property name="expand">False</property> |
593 | + <property name="homogeneous">True</property> |
594 | + </packing> |
595 | + </child> |
596 | + </object> |
597 | + <packing> |
598 | + <property name="expand">False</property> |
599 | + <property name="position">1</property> |
600 | + </packing> |
601 | + </child> |
602 | + <child> |
603 | + <object class="GtkHBox" id="hbox1"> |
604 | + <property name="visible">True</property> |
605 | + <child> |
606 | + <object class="GtkHBox" id="hbox2"> |
607 | <property name="visible">True</property> |
608 | <child> |
609 | - <object class="GtkHBox" id="hbox2"> |
610 | + <object class="GtkImage" id="is_started"> |
611 | + <property name="width_request">30</property> |
612 | <property name="visible">True</property> |
613 | - <child> |
614 | - <object class="GtkImage" id="image1"> |
615 | - <property name="visible">True</property> |
616 | - <property name="stock">gtk-yes</property> |
617 | - </object> |
618 | - <packing> |
619 | - <property name="position">0</property> |
620 | - </packing> |
621 | - </child> |
622 | - <child> |
623 | - <object class="GtkImage" id="image2"> |
624 | - <property name="visible">True</property> |
625 | - <property name="stock">gtk-yes</property> |
626 | - </object> |
627 | - <packing> |
628 | - <property name="position">1</property> |
629 | - </packing> |
630 | - </child> |
631 | - <child> |
632 | - <object class="GtkImage" id="image3"> |
633 | - <property name="visible">True</property> |
634 | - <property name="stock">gtk-no</property> |
635 | - </object> |
636 | - <packing> |
637 | - <property name="position">2</property> |
638 | - </packing> |
639 | - </child> |
640 | + <property name="sensitive">False</property> |
641 | + <property name="xpad">3</property> |
642 | + <property name="ypad">3</property> |
643 | + <property name="stock">gtk-yes</property> |
644 | </object> |
645 | <packing> |
646 | <property name="position">0</property> |
647 | </packing> |
648 | </child> |
649 | <child> |
650 | - <object class="GtkLabel" id="status"> |
651 | + <object class="GtkImage" id="is_connected"> |
652 | + <property name="width_request">30</property> |
653 | <property name="visible">True</property> |
654 | - <property name="label" translatable="yes">Status</property> |
655 | + <property name="sensitive">False</property> |
656 | + <property name="xpad">3</property> |
657 | + <property name="ypad">3</property> |
658 | + <property name="stock">gtk-yes</property> |
659 | </object> |
660 | <packing> |
661 | <property name="position">1</property> |
662 | </packing> |
663 | </child> |
664 | + <child> |
665 | + <object class="GtkImage" id="is_online"> |
666 | + <property name="width_request">30</property> |
667 | + <property name="visible">True</property> |
668 | + <property name="sensitive">False</property> |
669 | + <property name="xpad">3</property> |
670 | + <property name="ypad">3</property> |
671 | + <property name="stock">gtk-yes</property> |
672 | + </object> |
673 | + <packing> |
674 | + <property name="position">2</property> |
675 | + </packing> |
676 | + </child> |
677 | + </object> |
678 | + <packing> |
679 | + <property name="expand">False</property> |
680 | + <property name="position">0</property> |
681 | + </packing> |
682 | + </child> |
683 | + <child> |
684 | + <object class="GtkLabel" id="status_label"> |
685 | + <property name="visible">True</property> |
686 | + <property name="label" translatable="yes">Service not started, click Start to continue.</property> |
687 | </object> |
688 | <packing> |
689 | <property name="position">1</property> |
690 | </packing> |
691 | </child> |
692 | - <child> |
693 | - <placeholder/> |
694 | - </child> |
695 | </object> |
696 | <packing> |
697 | - <property name="position">0</property> |
698 | + <property name="expand">False</property> |
699 | + <property name="position">2</property> |
700 | </packing> |
701 | </child> |
702 | <child> |
703 | @@ -86,14 +199,68 @@ |
704 | <property name="visible">True</property> |
705 | <property name="can_focus">True</property> |
706 | <child> |
707 | - <placeholder/> |
708 | + <object class="GtkTreeView" id="metaq_view"> |
709 | + <property name="visible">True</property> |
710 | + <property name="can_focus">True</property> |
711 | + <property name="model">liststore1</property> |
712 | + </object> |
713 | + <packing> |
714 | + <property name="resize">True</property> |
715 | + <property name="shrink">True</property> |
716 | + </packing> |
717 | </child> |
718 | <child> |
719 | - <placeholder/> |
720 | + <object class="GtkTreeView" id="contentq_view"> |
721 | + <property name="visible">True</property> |
722 | + <property name="can_focus">True</property> |
723 | + <property name="model">liststore2</property> |
724 | + </object> |
725 | + <packing> |
726 | + <property name="resize">True</property> |
727 | + <property name="shrink">True</property> |
728 | + </packing> |
729 | </child> |
730 | </object> |
731 | <packing> |
732 | - <property name="position">1</property> |
733 | + <property name="position">3</property> |
734 | + </packing> |
735 | + </child> |
736 | + </object> |
737 | + </child> |
738 | + </object> |
739 | + <object class="GtkStatusIcon" id="status_icon"> |
740 | + <property name="has_tooltip">True</property> |
741 | + <property name="tooltip_text">Magicicada</property> |
742 | + <property name="title">Magicicada</property> |
743 | + </object> |
744 | + <object class="GtkAboutDialog" id="about_dialog"> |
745 | + <property name="border_width">5</property> |
746 | + <property name="type_hint">normal</property> |
747 | + <property name="has_separator">False</property> |
748 | + <property name="program_name">Magicicada</property> |
749 | + <property name="copyright" translatable="yes">Copyright 2010 Natalia Bidart <natalia.bidart@gmail.com> |
750 | +Copyright 2010 Facundo Batista <facundo.batista@gmail.com> |
751 | +</property> |
752 | + <property name="website">http://launchpad.net/magicicada</property> |
753 | + <property name="license" translatable="yes">GPL v3.0</property> |
754 | + <property name="authors">Natalia Bidart <natalia.bidart@gmail.com> |
755 | +Facundo Batista <facundo.batista@gmail.com></property> |
756 | + <child internal-child="vbox"> |
757 | + <object class="GtkVBox" id="dialog-vbox1"> |
758 | + <property name="visible">True</property> |
759 | + <property name="spacing">2</property> |
760 | + <child> |
761 | + <placeholder/> |
762 | + </child> |
763 | + <child internal-child="action_area"> |
764 | + <object class="GtkHButtonBox" id="dialog-action_area1"> |
765 | + <property name="visible">True</property> |
766 | + <property name="layout_style">end</property> |
767 | + </object> |
768 | + <packing> |
769 | + <property name="expand">False</property> |
770 | + <property name="pack_type">end</property> |
771 | + <property name="position">0</property> |
772 | </packing> |
773 | </child> |
774 | </object> |
775 | |
776 | === removed file 'data/ui/magicicada_window.xml' |
777 | --- data/ui/magicicada_window.xml 2010-04-21 21:18:31 +0000 |
778 | +++ data/ui/magicicada_window.xml 1970-01-01 00:00:00 +0000 |
779 | @@ -1,8 +0,0 @@ |
780 | -<glade-catalog name="magicicada_window" domain="glade-3" |
781 | - depends="gtk+" version="1.0"> |
782 | - <glade-widget-classes> |
783 | - <glade-widget-class title="Magicicada Window" name="MagicicadaWindow" |
784 | - generic-name="MagicicadaWindow" parent="GtkWindow" |
785 | - icon-name="widget-gtk-window"/> |
786 | - </glade-widget-classes> |
787 | -</glade-catalog> |
788 | |
789 | === removed file 'data/ui/preferences_magicicada_dialog.xml' |
790 | --- data/ui/preferences_magicicada_dialog.xml 2010-04-21 21:18:31 +0000 |
791 | +++ data/ui/preferences_magicicada_dialog.xml 1970-01-01 00:00:00 +0000 |
792 | @@ -1,9 +0,0 @@ |
793 | -<glade-catalog name="preferences_magicicada_dialog" domain="glade-3" |
794 | - depends="gtk+" version="1.0"> |
795 | - <glade-widget-classes> |
796 | - <glade-widget-class title="Magicicada Preferences Dialog" name="PreferencesMagicicadaDialog" |
797 | - generic-name="PreferenceMagicicadaDialog" parent="GtkDialog" |
798 | - icon-name="widget-gtk-dialog"/> |
799 | - </glade-widget-classes> |
800 | - |
801 | -</glade-catalog> |
802 | |
803 | === removed file 'magicicada/AboutMagicicadaDialog.py' |
804 | --- magicicada/AboutMagicicadaDialog.py 2010-04-21 21:18:31 +0000 |
805 | +++ magicicada/AboutMagicicadaDialog.py 1970-01-01 00:00:00 +0000 |
806 | @@ -1,48 +0,0 @@ |
807 | -# -*- coding: utf-8 -*- |
808 | -### BEGIN LICENSE |
809 | -# This file is in the public domain |
810 | -### END LICENSE |
811 | - |
812 | -import gtk |
813 | - |
814 | -from magicicada.helpers import get_builder |
815 | - |
816 | -import gettext |
817 | -from gettext import gettext as _ |
818 | -gettext.textdomain('magicicada') |
819 | - |
820 | -class AboutMagicicadaDialog(gtk.AboutDialog): |
821 | - __gtype_name__ = "AboutMagicicadaDialog" |
822 | - |
823 | - def __new__(cls): |
824 | - """Special static method that's automatically called by Python when |
825 | - constructing a new instance of this class. |
826 | - |
827 | - Returns a fully instantiated AboutMagicicadaDialog object. |
828 | - """ |
829 | - builder = get_builder('AboutMagicicadaDialog') |
830 | - new_object = builder.get_object("about_magicicada_dialog") |
831 | - new_object.finish_initializing(builder) |
832 | - return new_object |
833 | - |
834 | - def finish_initializing(self, builder): |
835 | - """Called while initializing this instance in __new__ |
836 | - |
837 | - finish_initalizing should be called after parsing the ui definition |
838 | - and creating a AboutMagicicadaDialog object with it in order to |
839 | - finish initializing the start of the new AboutMagicicadaDialog |
840 | - instance. |
841 | - |
842 | - Put your initialization code in here and leave __init__ undefined. |
843 | - """ |
844 | - # Get a reference to the builder and set up the signals. |
845 | - self.builder = builder |
846 | - self.builder.connect_signals(self) |
847 | - |
848 | - # Code for other initialization actions should be added here. |
849 | - |
850 | - |
851 | -if __name__ == "__main__": |
852 | - dialog = AboutMagicicadaDialog() |
853 | - dialog.show() |
854 | - gtk.main() |
855 | |
856 | === removed file 'magicicada/PreferencesMagicicadaDialog.py' |
857 | --- magicicada/PreferencesMagicicadaDialog.py 2010-04-21 21:18:31 +0000 |
858 | +++ magicicada/PreferencesMagicicadaDialog.py 1970-01-01 00:00:00 +0000 |
859 | @@ -1,111 +0,0 @@ |
860 | -# -*- coding: utf-8 -*- |
861 | -### BEGIN LICENSE |
862 | -# This file is in the public domain |
863 | -### END LICENSE |
864 | - |
865 | -from desktopcouch.records.server import CouchDatabase |
866 | -from desktopcouch.records.record import Record |
867 | -import gtk |
868 | - |
869 | -from magicicada.helpers import get_builder |
870 | - |
871 | -import gettext |
872 | -from gettext import gettext as _ |
873 | -gettext.textdomain('magicicada') |
874 | - |
875 | -class PreferencesMagicicadaDialog(gtk.Dialog): |
876 | - __gtype_name__ = "PreferencesMagicicadaDialog" |
877 | - preferences = {} |
878 | - |
879 | - def __new__(cls): |
880 | - """Special static method that's automatically called by Python when |
881 | - constructing a new instance of this class. |
882 | - |
883 | - Returns a fully instantiated PreferencesMagicicadaDialog object. |
884 | - """ |
885 | - builder = get_builder('PreferencesMagicicadaDialog') |
886 | - new_object = builder.get_object("preferences_magicicada_dialog") |
887 | - new_object.finish_initializing(builder) |
888 | - return new_object |
889 | - |
890 | - def finish_initializing(self, builder): |
891 | - """Called while initializing this instance in __new__ |
892 | - |
893 | - finish_initalizing should be called after parsing the ui definition |
894 | - and creating a PreferencesMagicicadaDialog object with it in order to |
895 | - finish initializing the start of the new PerferencesMagicicadaDialog |
896 | - instance. |
897 | - |
898 | - Put your initialization code in here and leave __init__ undefined. |
899 | - """ |
900 | - |
901 | - # Get a reference to the builder and set up the signals. |
902 | - self.builder = builder |
903 | - self.builder.connect_signals(self) |
904 | - |
905 | - # Set up couchdb and the preference info. |
906 | - self._db_name = "magicicada" |
907 | - self._database = CouchDatabase(self._db_name, create=True) |
908 | - self._preferences = None |
909 | - self._key = None |
910 | - |
911 | - # Set the record type and then initalize the preferences. |
912 | - self._record_type = ( |
913 | - "http://wiki.ubuntu.com/Quickly/RecordTypes/Magicicada/" |
914 | - "Preferences") |
915 | - self._preferences = self.get_preferences() |
916 | - # TODO: code for other initialization actions should be added here |
917 | - |
918 | - def get_preferences(self): |
919 | - """Return a dict of preferences for magicicada. |
920 | - |
921 | - Creates a couchdb record if necessary. |
922 | - """ |
923 | - if self._preferences == None: |
924 | - # The dialog is initializing. |
925 | - self._load_preferences() |
926 | - |
927 | - # If there were no saved preference, this. |
928 | - return self._preferences |
929 | - |
930 | - def _load_preferences(self): |
931 | - # TODO: add preferences to the self._preferences dict default |
932 | - # preferences that will be overwritten if some are saved |
933 | - self._preferences = {"record_type": self._record_type} |
934 | - |
935 | - results = self._database.get_records( |
936 | - record_type=self._record_type, create_view=True) |
937 | - |
938 | - if len(results.rows) == 0: |
939 | - # No preferences have ever been saved, save them before returning. |
940 | - self._key = self._database.put_record(Record(self._preferences)) |
941 | - else: |
942 | - self._preferences = results.rows[0].value |
943 | - del self._preferences['_rev'] |
944 | - self._key = results.rows[0].value["_id"] |
945 | - |
946 | - def _save_preferences(self): |
947 | - self._database.update_fields(self._key, self._preferences) |
948 | - |
949 | - def ok(self, widget, data=None): |
950 | - """The user has elected to save the changes. |
951 | - |
952 | - Called before the dialog returns gtk.RESONSE_OK from run(). |
953 | - """ |
954 | - |
955 | - # Make any updates to self._preferences here. e.g. |
956 | - #self._preferences["preference1"] = "value2" |
957 | - self._save_preferences() |
958 | - |
959 | - def cancel(self, widget, data=None): |
960 | - """The user has elected cancel changes. |
961 | - |
962 | - Called before the dialog returns gtk.RESPONSE_CANCEL for run() |
963 | - """ |
964 | - # Restore any changes to self._preferences here. |
965 | - pass |
966 | - |
967 | -if __name__ == "__main__": |
968 | - dialog = PreferencesMagicicadaDialog() |
969 | - dialog.show() |
970 | - gtk.main() |
971 | |
972 | === modified file 'magicicada/__init__.py' |
973 | --- magicicada/__init__.py 2010-04-21 21:18:31 +0000 |
974 | +++ magicicada/__init__.py 2010-05-15 15:48:32 +0000 |
975 | @@ -0,0 +1,204 @@ |
976 | +# __init__.py |
977 | +# |
978 | +# Author: Natalia Bidart <natalia.bidart@gmail.com> |
979 | +# |
980 | +# Copyright 2010 Chicharreros |
981 | +# |
982 | +# This program is free software: you can redistribute it and/or modify it |
983 | +# under the terms of the GNU General Public License version 3, as published |
984 | +# by the Free Software Foundation. |
985 | +# |
986 | +# This program is distributed in the hope that it will be useful, but |
987 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
988 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
989 | +# PURPOSE. See the GNU General Public License for more details. |
990 | +# |
991 | +# You should have received a copy of the GNU General Public License along |
992 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
993 | + |
994 | +"""Magicicada.""" |
995 | + |
996 | +import gtk |
997 | + |
998 | +import gettext |
999 | +from gettext import gettext as _ |
1000 | +gettext.textdomain('magicicada') |
1001 | + |
1002 | +from twisted.internet import gtk2reactor # for gtk-2.0 |
1003 | +gtk2reactor.install() |
1004 | + |
1005 | +from twisted.internet import reactor |
1006 | + |
1007 | +from magicicada.helpers import get_data_file, get_builder, print_debug |
1008 | +from magicicada.syncdaemon import SyncDaemon |
1009 | + |
1010 | + |
1011 | +class MagicicadaUI(object): |
1012 | + |
1013 | + STATUS = { |
1014 | + 'started': _('Service started, click Connect to continue.'), |
1015 | + 'connected': _('Service connected. Doing internal synchronization...'), |
1016 | + 'online': _('Service reached Nirvana.'), |
1017 | + } |
1018 | + |
1019 | + def __init__(self, launchpad_available=False): |
1020 | + """Init.""" |
1021 | + self.builder = get_builder('gui.glade') |
1022 | + self.builder.connect_signals(self) |
1023 | + |
1024 | + if launchpad_available: |
1025 | + # for more information about LaunchpadIntegration: |
1026 | + # wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding |
1027 | + helpmenu = self.builder.get_object('helpMenu') |
1028 | + if helpmenu: |
1029 | + LaunchpadIntegration.set_sourcepackagename('magicicada') |
1030 | + LaunchpadIntegration.add_items(helpmenu, 0, False, True) |
1031 | + |
1032 | + animation_filename = get_data_file('media', 'loader-ball.gif') |
1033 | + self.loading_animation = gtk.gdk.PixbufAnimation(animation_filename) |
1034 | + |
1035 | + self.started = self.connected = self.online = False |
1036 | + |
1037 | + widgets = ( |
1038 | + 'start', 'stop', 'connect', 'disconnect', # toolbar buttons |
1039 | + 'is_started', 'is_connected', 'is_online', # status bar images |
1040 | + 'status_label', 'status_icon', # status label and systray icon |
1041 | + 'main_window', 'about_dialog', |
1042 | + ) |
1043 | + for widget in widgets: |
1044 | + setattr(self, widget, self.builder.get_object(widget)) |
1045 | + |
1046 | + icon_filename = get_data_file('media', 'ubuntuone.png') |
1047 | + self.status_icon.set_from_file(icon_filename) |
1048 | + |
1049 | + self.main_window.set_icon_from_file(icon_filename) |
1050 | + self.main_window.show() |
1051 | + |
1052 | + self.syncdaemon = SyncDaemon() |
1053 | + |
1054 | + def run(self): |
1055 | + """Do the deed.""" |
1056 | + reactor.run() # instead of: gtk.main() |
1057 | + |
1058 | + def shutdown(self): |
1059 | + """Stop the deed.""" |
1060 | + reactor.stop() # instead of: gtk.main_quit() |
1061 | + |
1062 | + # GTK callbacks |
1063 | + |
1064 | + def on_main_window_destroy(self, widget, data=None): |
1065 | + """Called when the MagicicadaWindow is closed.""" |
1066 | + # Clean up code for saving application state should be added here. |
1067 | + if self.started: |
1068 | + self.on_stop_clicked(self.stop) |
1069 | + self.syncdaemon.shutdown() |
1070 | + |
1071 | + def on_quit_activate(self, widget, data=None): |
1072 | + """Signal handler for closing the program.""" |
1073 | + self.on_main_window_destroy(self.main_window) |
1074 | + |
1075 | + def on_about_activate(self, widget, data=None): |
1076 | + """Display the about box.""" |
1077 | + response = self.about_dialog.run() |
1078 | + self.about_dialog.hide() |
1079 | + |
1080 | + @print_debug |
1081 | + def on_start_clicked(self, widget, data=None): |
1082 | + """Start syncdaemon.""" |
1083 | + self.started = True |
1084 | + self.connect.set_sensitive(True) |
1085 | + self.start.hide() |
1086 | + self.stop.show() |
1087 | + |
1088 | + self.doing_something(self.is_started) |
1089 | + |
1090 | + @print_debug |
1091 | + def on_stop_clicked(self, widget, data=None): |
1092 | + """Stop syncdaemon.""" |
1093 | + assert self.started |
1094 | + |
1095 | + if self.connected: |
1096 | + self.on_disconnect_clicked(self.disconnect) |
1097 | + self.connect.set_sensitive(False) |
1098 | + |
1099 | + self.started = False |
1100 | + self.start.show() |
1101 | + self.stop.hide() |
1102 | + |
1103 | + self.on_stopped() |
1104 | + |
1105 | + @print_debug |
1106 | + def on_connect_clicked(self, widget, data=None): |
1107 | + """Connect syncdaemon.""" |
1108 | + assert self.started |
1109 | + self.connected = True |
1110 | + self.connect.hide() |
1111 | + self.disconnect.show() |
1112 | + |
1113 | + self.on_started() |
1114 | + self.doing_something(self.is_connected) |
1115 | + |
1116 | + @print_debug |
1117 | + def on_disconnect_clicked(self, widget, data=None): |
1118 | + """Disconnect syncdaemon.""" |
1119 | + assert self.started |
1120 | + assert self.connected |
1121 | + self.connected = False |
1122 | + self.connect.show() |
1123 | + self.disconnect.hide() |
1124 | + |
1125 | + self.on_disconnected() |
1126 | + |
1127 | + # DBus callbacks |
1128 | + |
1129 | + def on_started(self, *args, **kwargs): |
1130 | + """Callback'ed when syncadaemon is started.""" |
1131 | + self.stop_doing_something(self.is_started) |
1132 | + self.status_label.set_text(self.STATUS['started']) |
1133 | + |
1134 | + def on_stopped(self, *args, **kwargs): |
1135 | + """Callback'ed when syncadaemon is stopped.""" |
1136 | + |
1137 | + self.stop_doing_something(self.is_started, sensitive=False) |
1138 | + |
1139 | + self.is_started.set_sensitive(False) |
1140 | + self.is_connected.set_sensitive(False) |
1141 | + self.is_online.set_sensitive(False) |
1142 | + |
1143 | + def on_connected(self, *args, **kwargs): |
1144 | + """Callback'ed when syncadaemon is connected.""" |
1145 | + self.is_connected.set_sensitive(True) |
1146 | + self.doing_something(self.is_online) |
1147 | + self.status_label.set_text(self.STATUS['connected']) |
1148 | + |
1149 | + def on_disconnected(self, *args, **kwargs): |
1150 | + """Callback'ed when syncadaemon is disconnected.""" |
1151 | + |
1152 | + self.stop_doing_something(self.is_connected, sensitive=False) |
1153 | + |
1154 | + self.is_connected.set_sensitive(False) |
1155 | + self.is_online.set_sensitive(False) |
1156 | + |
1157 | + def on_online(self, *args, **kwargs): |
1158 | + """Callback'ed when syncadaemon is online.""" |
1159 | + self.is_onlined.set_sensitive(True) |
1160 | + self.status_label.set_text(self.STATUS['online']) |
1161 | + |
1162 | + def on_offline(self, *args, **kwargs): |
1163 | + """Callback'ed when syncadaemon is offline.""" |
1164 | + |
1165 | + self.stop_doing_something(self.is_online, sensitive=False) |
1166 | + |
1167 | + self.is_online.set_sensitive(False) |
1168 | + |
1169 | + # custom |
1170 | + |
1171 | + def doing_something(self, what): |
1172 | + """Set a loader animation on 'what'.""" |
1173 | + what.set_sensitive(True) |
1174 | + what.set_from_animation(self.loading_animation) |
1175 | + |
1176 | + def stop_doing_something(self, what, sensitive=True): |
1177 | + """Set a loader animation on 'what'.""" |
1178 | + what.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON) |
1179 | + what.set_sensitive(sensitive) |
1180 | |
1181 | === modified file 'magicicada/helpers.py' |
1182 | --- magicicada/helpers.py 2010-04-21 23:50:09 +0000 |
1183 | +++ magicicada/helpers.py 2010-05-15 15:48:32 +0000 |
1184 | @@ -12,6 +12,8 @@ |
1185 | import os |
1186 | import gtk |
1187 | |
1188 | +from functools import wraps |
1189 | + |
1190 | from magicicada.magicicadaconfig import get_data_file |
1191 | |
1192 | import gettext |
1193 | @@ -19,9 +21,8 @@ |
1194 | gettext.textdomain('magicicada') |
1195 | |
1196 | def get_builder(builder_file_name): |
1197 | - """Return a fully-instantiated gtk.Builder instance from specified ui |
1198 | - file |
1199 | - |
1200 | + """Return a fully-instantiated gtk.Builder instance from specified ui file. |
1201 | + |
1202 | :param builder_file_name: The name of the builder file, without extension. |
1203 | Assumed to be in the 'ui' directory under the data path. |
1204 | """ |
1205 | @@ -34,3 +35,14 @@ |
1206 | builder.set_translation_domain('magicicada') |
1207 | builder.add_from_file(ui_filename) |
1208 | return builder |
1209 | + |
1210 | +def print_debug(f): |
1211 | + """Print debug info for 'f'.""" |
1212 | + |
1213 | + @wraps(f) |
1214 | + def inner(*args, **kwargs): |
1215 | + """Wrap f.""" |
1216 | + print('Calling', f.__name__, args, kwargs) |
1217 | + f(*args, **kwargs) |
1218 | + |
1219 | + return inner |
1220 | |
1221 | === modified file 'magicicada/syncdaemon.py' |
1222 | --- magicicada/syncdaemon.py 2010-05-04 01:30:42 +0000 |
1223 | +++ magicicada/syncdaemon.py 2010-05-15 15:48:32 +0000 |
1224 | @@ -18,9 +18,14 @@ |
1225 | |
1226 | """The backend that communicates Magicicada with the SyncDaemon.""" |
1227 | |
1228 | -# this always first |
1229 | -from twisted.internet import glib2reactor |
1230 | -glib2reactor.install() |
1231 | +import sys |
1232 | + |
1233 | +try: |
1234 | + from twisted.internet import glib2reactor |
1235 | + glib2reactor.install() |
1236 | +except AssertionError, e: |
1237 | + msg = '\nsyncdaemon.py: Not installing glib2reactor because: %s.\n' |
1238 | + sys.stderr.write(msg % e) |
1239 | |
1240 | import collections |
1241 | import re |
1242 | |
1243 | === added file 'magicicada/tests/test_magicicada.py' |
1244 | --- magicicada/tests/test_magicicada.py 1970-01-01 00:00:00 +0000 |
1245 | +++ magicicada/tests/test_magicicada.py 2010-05-15 15:48:32 +0000 |
1246 | @@ -0,0 +1,150 @@ |
1247 | +# test_magicicada.py |
1248 | +# |
1249 | +# Author: Natalia Bidart <natalia.bidart@gmail.com> |
1250 | +# |
1251 | +# Copyright 2010 Chicharreros |
1252 | +# |
1253 | +# This program is free software: you can redistribute it and/or modify it |
1254 | +# under the terms of the GNU General Public License version 3, as published |
1255 | +# by the Free Software Foundation. |
1256 | +# |
1257 | +# This program is distributed in the hope that it will be useful, but |
1258 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
1259 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1260 | +# PURPOSE. See the GNU General Public License for more details. |
1261 | +# |
1262 | +# You should have received a copy of the GNU General Public License along |
1263 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
1264 | + |
1265 | +"""Tests for magicicada.""" |
1266 | + |
1267 | +import gobject |
1268 | +import gtk |
1269 | +import unittest |
1270 | + |
1271 | +from functools import wraps |
1272 | + |
1273 | +from twisted.internet import reactor |
1274 | +from twisted.trial.unittest import TestCase |
1275 | + |
1276 | +from magicicada import MagicicadaUI |
1277 | +from magicicada.helpers import get_builder |
1278 | +from magicicada.syncdaemon import SyncDaemon |
1279 | + |
1280 | +DEFAULT_TIMEOUT = 200 |
1281 | +NO_OP = lambda *a, **kw: None |
1282 | + |
1283 | +def close_window_after(a_test): |
1284 | + """Decorator to close the main window after executing f.""" |
1285 | + @wraps(a_test) |
1286 | + def inner(*args, **kwargs): |
1287 | + """Inner function.""" |
1288 | + #gobject.timeout_add(DEFAULT_TIMEOUT, a_test) |
1289 | + #self.ui.run() |
1290 | + |
1291 | + return inner |
1292 | + |
1293 | + |
1294 | +class MagicicadaUITestCase(TestCase): |
1295 | + """UI test cases for Magicicada UI.""" |
1296 | + |
1297 | + def setUp(self): |
1298 | + """Init.""" |
1299 | + self.builder = get_builder('gui.glade') |
1300 | + self.ui = MagicicadaUI() |
1301 | + self._patched = {} |
1302 | + self._called = False |
1303 | + |
1304 | + def tearDown(self): |
1305 | + """Clenaup.""" |
1306 | + self.ui.on_main_window_destroy(self.ui.main_window) |
1307 | + for (instance, attr), old_value in self._patched.iteritems(): |
1308 | + setattr(instance, attr, old_value) |
1309 | + self._called = False |
1310 | + self.builder = None |
1311 | + |
1312 | + def test_init_creates_sd_instance(self): |
1313 | + """SyncDaemon instance is created at creation time.""" |
1314 | + self.assertTrue(isinstance(self.ui.syncdaemon, SyncDaemon)) |
1315 | + |
1316 | + def test_destroy_shutdowns_sd_instance(self): |
1317 | + """SyncDaemon instance is shutdown at destroy time.""" |
1318 | + self.patch(self.ui.syncdaemon, 'shutdown', |
1319 | + lambda *_: setattr(self, '_called', True)) |
1320 | + self.ui.on_main_window_destroy(self.ui.main_window) |
1321 | + self.assertTrue(self._called, 'syncdaemon.shutdown must be called at destroy time.') |
1322 | + |
1323 | + def test_shutdown_stops_reactor(self): |
1324 | + """SyncDaemon instance is shutdown at destroy time.""" |
1325 | + self.patch(reactor, 'stop', |
1326 | + lambda *_: setattr(self, '_called', True)) |
1327 | + self.ui.shutdown() |
1328 | + self.assertTrue(self._called, 'reactor.stop must be called at destroy time.') |
1329 | + |
1330 | + |
1331 | +class MagicicadaUIStartupTestCase(MagicicadaUITestCase): |
1332 | + """UI test cases for startup state.""" |
1333 | + |
1334 | + def test_main_window_is_visible(self): |
1335 | + """UI can be created.""" |
1336 | + self.assertTrue(self.ui.main_window.get_property('visible')) |
1337 | + |
1338 | + def test_start_connect_are_visible(self): |
1339 | + """Start and Connect buttons are visible.""" |
1340 | + self.assertTrue(self.ui.start.get_property('visible')) |
1341 | + self.assertTrue(self.ui.start.is_sensitive()) |
1342 | + |
1343 | + self.assertTrue(self.ui.connect.get_property('visible')) |
1344 | + self.assertFalse(self.ui.connect.is_sensitive()) |
1345 | + |
1346 | + def test_stop_disconnect_are_not_visible(self): |
1347 | + """Start and Connect buttons are visible.""" |
1348 | + self.assertFalse(self.ui.stop.get_property('visible')) |
1349 | + self.assertFalse(self.ui.disconnect.get_property('visible')) |
1350 | + |
1351 | + def test_not_started_not_connected_not_online(self): |
1352 | + """Test default values for flags.""" |
1353 | + self.assertFalse(self.ui.started) |
1354 | + self.assertFalse(self.ui.connected) |
1355 | + self.assertFalse(self.ui.online) |
1356 | + |
1357 | + def test_indicators_are_non_sensitive(self): |
1358 | + """Test default sensitivity for indicators.""" |
1359 | + #import pdb; pdb.set_trace() |
1360 | + self.assertFalse(self.ui.is_started.is_sensitive()) |
1361 | + self.assertFalse(self.ui.is_connected.is_sensitive()) |
1362 | + self.assertFalse(self.ui.is_online.is_sensitive()) |
1363 | + |
1364 | +class MagicicadaUIClickedTestCase(MagicicadaUIStartupTestCase): |
1365 | + """UI test cases.""" |
1366 | + |
1367 | + def test_started_if_start_clicked(self): |
1368 | + """Test started if Start was clicked.""" |
1369 | + self.ui.on_start_clicked(self.ui.start) |
1370 | + self.assertTrue(self.ui.started) |
1371 | + self.assertFalse(self.ui.connected) |
1372 | + self.assertFalse(self.ui.online) |
1373 | + |
1374 | + def test_can_connect_can_stop_if_start_clicked(self): |
1375 | + """Test Connect and Stop are enabled if Start was clicked.""" |
1376 | + self.ui.on_start_clicked(self.ui.start) |
1377 | + self.assertFalse(self.ui.start.get_property('visible')) |
1378 | + self.assertTrue(self.ui.stop.get_property('visible')) |
1379 | + self.assertTrue(self.ui.connect.is_sensitive()) |
1380 | + |
1381 | + def test_connected_if_connect_clicked(self): |
1382 | + """Test connected if Connect was clicked.""" |
1383 | + self.ui.on_start_clicked(self.ui.start) # need to be started |
1384 | + self.ui.on_connect_clicked(self.ui.connect) |
1385 | + |
1386 | + self.assertTrue(self.ui.started) |
1387 | + self.assertTrue(self.ui.connected) |
1388 | + self.assertFalse(self.ui.online) |
1389 | + |
1390 | + def test_can_disconnect_if_connect_clicked(self): |
1391 | + """Test Disconnect is enabled if Connect was clicked.""" |
1392 | + self.ui.on_start_clicked(self.ui.start) # need to be started |
1393 | + self.ui.on_connect_clicked(self.ui.connect) |
1394 | + self.assertFalse(self.ui.connect.get_property('visible')) |
1395 | + self.assertTrue(self.ui.disconnect.get_property('visible')) |
1396 | + |
facundo@ exepus: ~/devel/ reps/magicicada /review_ build-gui$ nosetests
syncdaemon.py: Not installing glib2reactor because: reactor already installed. ....... ....... ....... ....... ....... EEE.... .. ======= ======= ======= ======= ======= ======= ======= ======= ======= ------- ------- ------- ------- ------- ------- ------- ------- ------- regateError: Reactor was unclean. internet. base.DelayedCal l.debug = True to debug) _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()>
.......
=======
ERROR: Check that it polls mq until no more is needed.
-------
DirtyReactorAgg
DelayedCalls: (set twisted.
<DelayedCall 0xac7ab6c [3.80157804489s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7a8ac [3.79958200455s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7a96c [3.80020308495s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7aa6c [3.80084300041s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7ae6c [3.80354785919s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7ac6c [3.80206394196s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7ad6c [3.80287098885s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7fb8c [3.81115484238s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7af6c [3.80402112007s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f08c [3.80454802513s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f18c [3.80509400368s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f28c [3.80576300621s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f38c [3.80635905266s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f48c [3.80693697929s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f58c [3.80750989914s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f68c [3.80805492401s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f78c [3.80859208107s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f88c [3.80918884277s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f98c [3.80973696709s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7fa8c [3.81028389931s] called=0 cancelled=0 SyncDaemon.
======= ======= ======= ======= ======= ======= ======= ======= ======= ======= ------- ------- ------- ------- ------- ------- ------- ------- ------- regateError: Reactor was unclean. internet. base.DelayedCal l.debug = True to debug) _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()> _check_ mq()>
ERROR: Check that it polls mq while working in both.
-------
DirtyReactorAgg
DelayedCalls: (set twisted.
<DelayedCall 0xac7a72c [4.99101114273s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f8ec [4.98898601532s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f24c [4.98936009407s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7a86c [4.98973798752s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7a7cc [4.99011516571s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7a7ec [4.99048709869s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7f4cc [4.99738693237s] called=0 cancelled=0 SyncDaemon.
<DelayedCall 0xac7ad0c [4.99150681496s] called=0 cancelled=0 Sy...