Merge lp:~nataliabidart/magicicada-gui/build-gui into lp:magicicada-gui

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
Reviewer Review Type Date Requested Status
Facundo Batista Approve
Review via email: mp+24962@code.launchpad.net

Description of the change

First schema of Magicicada GUI.

To post a comment you must log in.
Revision history for this message
Facundo Batista (facundo) wrote :
Download full text (7.6 KiB)

facundo@exepus:~/devel/reps/magicicada/review_build-gui$ nosetests

syncdaemon.py: Not installing glib2reactor because: reactor already installed.
..........................................EEE......
======================================================================
ERROR: Check that it polls mq until no more is needed.
----------------------------------------------------------------------
DirtyReactorAggregateError: Reactor was unclean.
DelayedCalls: (set twisted.internet.base.DelayedCall.debug = True to debug)
<DelayedCall 0xac7ab6c [3.80157804489s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7a8ac [3.79958200455s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7a96c [3.80020308495s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7aa6c [3.80084300041s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7ae6c [3.80354785919s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7ac6c [3.80206394196s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7ad6c [3.80287098885s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7fb8c [3.81115484238s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7af6c [3.80402112007s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f08c [3.80454802513s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f18c [3.80509400368s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f28c [3.80576300621s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f38c [3.80635905266s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f48c [3.80693697929s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f58c [3.80750989914s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f68c [3.80805492401s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f78c [3.80859208107s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f88c [3.80918884277s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f98c [3.80973696709s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7fa8c [3.81028389931s] called=0 cancelled=0 SyncDaemon._check_mq()>

======================================================================
ERROR: Check that it polls mq while working in both.
----------------------------------------------------------------------
DirtyReactorAggregateError: Reactor was unclean.
DelayedCalls: (set twisted.internet.base.DelayedCall.debug = True to debug)
<DelayedCall 0xac7a72c [4.99101114273s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f8ec [4.98898601532s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f24c [4.98936009407s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7a86c [4.98973798752s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7a7cc [4.99011516571s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7a7ec [4.99048709869s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7f4cc [4.99738693237s] called=0 cancelled=0 SyncDaemon._check_mq()>
<DelayedCall 0xac7ad0c [4.99150681496s] called=0 cancelled=0 Sy...

Read more...

review: Needs Fixing
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
=== modified file 'bin/magicicada'
--- bin/magicicada 2010-04-21 23:50:09 +0000
+++ bin/magicicada 2010-05-15 15:48:32 +0000
@@ -6,7 +6,6 @@
66
7import sys7import sys
8import os8import os
9import gtk
109
11import gettext10import gettext
12from gettext import gettext as _11from gettext import gettext as _
@@ -29,59 +28,7 @@
29 sys.path.insert(0, PROJECT_ROOT_DIRECTORY)28 sys.path.insert(0, PROJECT_ROOT_DIRECTORY)
30 os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses29 os.putenv('PYTHONPATH', PROJECT_ROOT_DIRECTORY) # for subprocesses
3130
32from magicicada import (31from magicicada import MagicicadaUI
33 AboutMagicicadaDialog, PreferencesMagicicadaDialog)
34from magicicada.helpers import get_builder
35
36
37class MagicicadaUI(object):
38
39 def __init__(self):
40 """Init."""
41 self.builder = get_builder('gui.glade')
42 self.builder.connect_signals(self)
43
44 global launchpad_available
45 if launchpad_available:
46 # see https://wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding for more information
47 # about LaunchpadIntegration
48 helpmenu = self.builder.get_object('helpMenu')
49 if helpmenu:
50 LaunchpadIntegration.set_sourcepackagename('magicicada')
51 LaunchpadIntegration.add_items(helpmenu, 0, False, True)
52 else:
53 launchpad_available = False
54
55 # Uncomment the following code to read in preferences at start up.
56 #dlg = PreferencesMagicicadaDialog.NewPreferencesMagicicadaDialog()
57 #self.preferences = dlg.get_preferences()
58
59 # Code for other initialization actions should be added here.
60 self.builder.get_object('main_window').show_all()
61
62 def about(self, widget, data=None):
63 """Display the about box for magicicada."""
64 about = AboutMagicicadaDialog.AboutMagicicadaDialog()
65 response = about.run()
66 about.destroy()
67
68 def preferences(self, widget, data=None):
69 """Display the preferences window for magicicada."""
70 prefs = PreferencesMagicicadaDialog.PreferencesMagicicadaDialog()
71 response = prefs.run()
72 if response == gtk.RESPONSE_OK:
73 # Make any updates based on changed preferences here.
74 pass
75 prefs.destroy()
76
77 def quit(self, widget, data=None):
78 """Signal handler for closing the MagicicadaWindow."""
79 self.destroy()
80
81 def on_destroy(self, widget, data=None):
82 """Called when the MagicicadaWindow is closed."""
83 # Clean up code for saving application state should be added here.
84 gtk.main_quit()
8532
86if __name__ == "__main__":33if __name__ == "__main__":
87 # Support for command line options.34 # Support for command line options.
@@ -99,5 +46,5 @@
99 logging.debug('logging enabled')46 logging.debug('logging enabled')
10047
101 # Run the application.48 # Run the application.
102 window = MagicicadaUI()49 window = MagicicadaUI(launchpad_available=launchpad_available)
103 gtk.main()50 window.run()
10451
=== added file 'data/media/loader-ball.gif'
105Binary 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 differ52Binary 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
=== added file 'data/media/ubuntuone.png'
106Binary files data/media/ubuntuone.png 1970-01-01 00:00:00 +0000 and data/media/ubuntuone.png 2010-05-15 15:48:32 +0000 differ53Binary 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
=== removed file 'data/ui/AboutMagicicadaDialog.ui'
--- data/ui/AboutMagicicadaDialog.ui 2010-04-21 21:18:31 +0000
+++ data/ui/AboutMagicicadaDialog.ui 1970-01-01 00:00:00 +0000
@@ -1,40 +0,0 @@
1<?xml version="1.0"?>
2<interface>
3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-requires about_magicicada_dialog 1.0 -->
5 <!-- interface-naming-policy project-wide -->
6 <object class="AboutMagicicadaDialog" id="about_magicicada_dialog">
7 <property name="border_width">5</property>
8 <property name="icon">../media/icon.png</property>
9 <property name="type_hint">normal</property>
10 <property name="has_separator">False</property>
11 <property name="program_name">Magicicada</property>
12 <property name="version"></property>
13 <property name="copyright"></property>
14 <property name="website"></property>
15 <property name="license"></property>
16 <property name="authors"></property>
17 <property name="logo">../media/logo.png</property>
18 <child internal-child="vbox">
19 <object class="GtkVBox" id="dialog-vbox1">
20 <property name="visible">True</property>
21 <property name="orientation">vertical</property>
22 <property name="spacing">2</property>
23 <child>
24 <placeholder/>
25 </child>
26 <child internal-child="action_area">
27 <object class="GtkHButtonBox" id="dialog-action_area1">
28 <property name="visible">True</property>
29 <property name="layout_style">end</property>
30 </object>
31 <packing>
32 <property name="expand">False</property>
33 <property name="pack_type">end</property>
34 <property name="position">0</property>
35 </packing>
36 </child>
37 </object>
38 </child>
39 </object>
40</interface>
410
=== removed file 'data/ui/MagicicadaWindow.ui'
--- data/ui/MagicicadaWindow.ui 2010-04-21 21:18:31 +0000
+++ data/ui/MagicicadaWindow.ui 1970-01-01 00:00:00 +0000
@@ -1,232 +0,0 @@
1<?xml version="1.0"?>
2<interface>
3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-requires magicicada_window 1.0 -->
5 <!-- interface-naming-policy project-wide -->
6 <!-- interface-local-resource-path ../media -->
7 <object class="MagicicadaWindow" id="magicicada_window">
8 <property name="title" translatable="yes">Magicicada</property>
9 <property name="icon">../media/icon.png</property>
10 <signal name="destroy" handler="on_destroy"/>
11 <child>
12 <object class="GtkVBox" id="vbox1">
13 <property name="visible">True</property>
14 <property name="orientation">vertical</property>
15 <property name="spacing">5</property>
16 <child>
17 <object class="GtkMenuBar" id="menubar1">
18 <property name="visible">True</property>
19 <child>
20 <object class="GtkMenuItem" id="menuitem1">
21 <property name="visible">True</property>
22 <property name="label" translatable="yes">_File</property>
23 <property name="use_underline">True</property>
24 <child type="submenu">
25 <object class="GtkMenu" id="menu1">
26 <property name="visible">True</property>
27 <child>
28 <object class="GtkImageMenuItem" id="imagemenuitem1">
29 <property name="label">gtk-new</property>
30 <property name="visible">True</property>
31 <property name="use_action_appearance">True</property>
32 <property name="use_underline">True</property>
33 <property name="use_stock">True</property>
34 <accelerator key="n" signal="activate" modifiers="GDK_CONTROL_MASK"/>
35 </object>
36 </child>
37 <child>
38 <object class="GtkImageMenuItem" id="imagemenuitem2">
39 <property name="label">gtk-open</property>
40 <property name="visible">True</property>
41 <property name="use_underline">True</property>
42 <property name="use_stock">True</property>
43 <accelerator key="o" signal="activate" modifiers="GDK_CONTROL_MASK"/>
44 </object>
45 </child>
46 <child>
47 <object class="GtkImageMenuItem" id="imagemenuitem3">
48 <property name="label">gtk-save</property>
49 <property name="visible">True</property>
50 <property name="use_underline">True</property>
51 <property name="use_stock">True</property>
52 <accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
53 </object>
54 </child>
55 <child>
56 <object class="GtkImageMenuItem" id="imagemenuitem4">
57 <property name="label">gtk-save-as</property>
58 <property name="visible">True</property>
59 <property name="use_underline">True</property>
60 <property name="use_stock">True</property>
61 <accelerator key="s" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
62 </object>
63 </child>
64 <child>
65 <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
66 <property name="visible">True</property>
67 </object>
68 </child>
69 <child>
70 <object class="GtkImageMenuItem" id="imagemenuitem5">
71 <property name="label">gtk-quit</property>
72 <property name="visible">True</property>
73 <property name="use_underline">True</property>
74 <property name="use_stock">True</property>
75 <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
76 <signal name="activate" handler="quit"/>
77 </object>
78 </child>
79 </object>
80 </child>
81 </object>
82 </child>
83 <child>
84 <object class="GtkMenuItem" id="menuitem2">
85 <property name="visible">True</property>
86 <property name="label" translatable="yes">_Edit</property>
87 <property name="use_underline">True</property>
88 <child type="submenu">
89 <object class="GtkMenu" id="menu2">
90 <property name="visible">True</property>
91 <child>
92 <object class="GtkImageMenuItem" id="imagemenuitem6">
93 <property name="label">gtk-cut</property>
94 <property name="visible">True</property>
95 <property name="use_underline">True</property>
96 <property name="use_stock">True</property>
97 <accelerator key="x" signal="activate" modifiers="GDK_CONTROL_MASK"/>
98 </object>
99 </child>
100 <child>
101 <object class="GtkImageMenuItem" id="imagemenuitem7">
102 <property name="label">gtk-copy</property>
103 <property name="visible">True</property>
104 <property name="use_underline">True</property>
105 <property name="use_stock">True</property>
106 <accelerator key="c" signal="activate" modifiers="GDK_CONTROL_MASK"/>
107 </object>
108 </child>
109 <child>
110 <object class="GtkImageMenuItem" id="imagemenuitem8">
111 <property name="label">gtk-paste</property>
112 <property name="visible">True</property>
113 <property name="use_underline">True</property>
114 <property name="use_stock">True</property>
115 <accelerator key="v" signal="activate" modifiers="GDK_CONTROL_MASK"/>
116 </object>
117 </child>
118 <child>
119 <object class="GtkImageMenuItem" id="imagemenuitem9">
120 <property name="label">gtk-delete</property>
121 <property name="visible">True</property>
122 <property name="use_underline">True</property>
123 <property name="use_stock">True</property>
124 <accelerator key="Delete" signal="activate"/>
125 </object>
126 </child>
127 <child>
128 <object class="GtkSeparatorMenuItem" id="separatormenuitem2">
129 <property name="visible">True</property>
130 </object>
131 </child>
132 <child>
133 <object class="GtkImageMenuItem" id="imagemenuitem11">
134 <property name="label">gtk-preferences</property>
135 <property name="visible">True</property>
136 <property name="use_underline">True</property>
137 <property name="use_stock">True</property>
138 <signal name="activate" handler="preferences"/>
139 </object>
140 </child>
141 </object>
142 </child>
143 </object>
144 </child>
145 <child>
146 <object class="GtkMenuItem" id="menuitem3">
147 <property name="visible">True</property>
148 <property name="label" translatable="yes">_View</property>
149 <property name="use_underline">True</property>
150 </object>
151 </child>
152 <child>
153 <object class="GtkMenuItem" id="menuitem4">
154 <property name="visible">True</property>
155 <property name="label" translatable="yes">_Help</property>
156 <property name="use_underline">True</property>
157 <child type="submenu">
158 <object class="GtkMenu" id="helpMenu">
159 <property name="visible">True</property>
160 <child>
161 <object class="GtkImageMenuItem" id="imagemenuitem10">
162 <property name="label">gtk-about</property>
163 <property name="visible">True</property>
164 <property name="use_underline">True</property>
165 <property name="use_stock">True</property>
166 <signal name="activate" handler="about"/>
167 </object>
168 </child>
169 </object>
170 </child>
171 </object>
172 </child>
173 </object>
174 <packing>
175 <property name="expand">False</property>
176 <property name="position">0</property>
177 </packing>
178 </child>
179 <child>
180 <object class="GtkLabel" id="label1">
181 <property name="visible">True</property>
182 <property name="xpad">30</property>
183 <property name="ypad">5</property>
184 <property name="label" translatable="yes">Your application has been created!
185
186To start changing this user interface, run 'quickly glade', which will open Glade so you can edit the default windows and dialogs.
187
188To change the behavior and edit the python code, run 'quickly edit', which will bring up a text editor.</property>
189 <property name="wrap">True</property>
190 </object>
191 <packing>
192 <property name="position">1</property>
193 </packing>
194 </child>
195 <child>
196 <object class="GtkImage" id="image1">
197 <property name="visible">True</property>
198 <property name="xpad">5</property>
199 <property name="ypad">5</property>
200 <property name="pixbuf">../media/background.png</property>
201 </object>
202 <packing>
203 <property name="padding">15</property>
204 <property name="position">2</property>
205 </packing>
206 </child>
207 <child>
208 <object class="GtkStatusbar" id="statusbar1">
209 <property name="visible">True</property>
210 <property name="spacing">2</property>
211 <child>
212 <object class="GtkLabel" id="label2">
213 <property name="visible">True</property>
214 <property name="xalign">0</property>
215 <property name="xpad">5</property>
216 <property name="ypad">5</property>
217 <property name="label" translatable="yes">Status Area</property>
218 </object>
219 <packing>
220 <property name="position">0</property>
221 </packing>
222 </child>
223 </object>
224 <packing>
225 <property name="expand">False</property>
226 <property name="position">3</property>
227 </packing>
228 </child>
229 </object>
230 </child>
231 </object>
232</interface>
2330
=== removed file 'data/ui/PreferencesMagicicadaDialog.ui'
--- data/ui/PreferencesMagicicadaDialog.ui 2010-04-21 21:18:31 +0000
+++ data/ui/PreferencesMagicicadaDialog.ui 1970-01-01 00:00:00 +0000
@@ -1,67 +0,0 @@
1<?xml version="1.0"?>
2<interface>
3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-requires preferences_magicicada_dialog 1.0 -->
5 <!-- interface-naming-policy project-wide -->
6 <object class="PreferencesMagicicadaDialog" id="preferences_magicicada_dialog">
7 <property name="border_width">5</property>
8 <property name="icon">../media/icon.png</property>
9 <property name="type_hint">normal</property>
10 <property name="has_separator">False</property>
11 <child internal-child="vbox">
12 <object class="GtkVBox" id="dialog-vbox1">
13 <property name="visible">True</property>
14 <property name="orientation">vertical</property>
15 <property name="spacing">2</property>
16 <child>
17 <placeholder/>
18 </child>
19 <child internal-child="action_area">
20 <object class="GtkHButtonBox" id="dialog-action_area1">
21 <property name="visible">True</property>
22 <property name="layout_style">end</property>
23 <child>
24 <object class="GtkButton" id="button2">
25 <property name="label">gtk-cancel</property>
26 <property name="visible">True</property>
27 <property name="can_focus">True</property>
28 <property name="receives_default">True</property>
29 <property name="use_stock">True</property>
30 <signal name="clicked" handler="cancel"/>
31 </object>
32 <packing>
33 <property name="expand">False</property>
34 <property name="fill">False</property>
35 <property name="position">0</property>
36 </packing>
37 </child>
38 <child>
39 <object class="GtkButton" id="button1">
40 <property name="label">gtk-ok</property>
41 <property name="visible">True</property>
42 <property name="can_focus">True</property>
43 <property name="receives_default">True</property>
44 <property name="use_stock">True</property>
45 <signal name="clicked" handler="ok"/>
46 </object>
47 <packing>
48 <property name="expand">False</property>
49 <property name="fill">False</property>
50 <property name="position">1</property>
51 </packing>
52 </child>
53 </object>
54 <packing>
55 <property name="expand">False</property>
56 <property name="pack_type">end</property>
57 <property name="position">0</property>
58 </packing>
59 </child>
60 </object>
61 </child>
62 <action-widgets>
63 <action-widget response="-6">button2</action-widget>
64 <action-widget response="-5">button1</action-widget>
65 </action-widgets>
66 </object>
67</interface>
680
=== removed file 'data/ui/about_magicicada_dialog.xml'
--- data/ui/about_magicicada_dialog.xml 2010-04-21 21:18:31 +0000
+++ data/ui/about_magicicada_dialog.xml 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
1<glade-catalog name="about_magicicada_dialog" domain="glade-3"
2 depends="gtk+" version="1.0">
3 <glade-widget-classes>
4 <glade-widget-class title="About Magicicada Dialog" name="AboutMagicicadaDialog"
5 generic-name="AboutMagicicadaDialog" parent="GtkAboutDialog"
6 icon-name="widget-gtk-about-dialog"/>
7 </glade-widget-classes>
8
9</glade-catalog>
100
=== modified file 'data/ui/gui.glade'
--- data/ui/gui.glade 2010-04-21 23:50:09 +0000
+++ data/ui/gui.glade 2010-05-15 15:48:32 +0000
@@ -2,83 +2,196 @@
2<interface>2<interface>
3 <requires lib="gtk+" version="2.16"/>3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-naming-policy project-wide -->4 <!-- interface-naming-policy project-wide -->
5 <object class="GtkListStore" id="liststore1"/>
6 <object class="GtkListStore" id="liststore2"/>
5 <object class="GtkWindow" id="main_window">7 <object class="GtkWindow" id="main_window">
8 <property name="width_request">800</property>
9 <property name="height_request">600</property>
6 <property name="title" translatable="yes">Magicicada</property>10 <property name="title" translatable="yes">Magicicada</property>
7 <signal name="destroy_event" handler="on_destroy"/>11 <signal name="destroy" handler="on_main_window_destroy"/>
8 <child>12 <child>
9 <object class="GtkVBox" id="vbox1">13 <object class="GtkVBox" id="vbox1">
10 <property name="visible">True</property>14 <property name="visible">True</property>
11 <child>15 <child>
12 <object class="GtkVBox" id="vbox2">16 <object class="GtkMenuBar" id="menubar">
13 <property name="visible">True</property>17 <property name="visible">True</property>
14 <child>18 <child>
15 <object class="GtkToolbar" id="toolbar">19 <object class="GtkMenuItem" id="menuitem1">
16 <property name="visible">True</property>20 <property name="visible">True</property>
17 <property name="icon_size_set">True</property>21 <property name="label" translatable="yes">_File</property>
18 </object>22 <property name="use_underline">True</property>
19 <packing>23 <child type="submenu">
20 <property name="expand">False</property>24 <object class="GtkMenu" id="menu1">
21 <property name="position">0</property>25 <property name="visible">True</property>
22 </packing>26 <child>
23 </child>27 <object class="GtkImageMenuItem" id="quit">
24 <child>28 <property name="label">gtk-quit</property>
25 <object class="GtkHBox" id="hbox1">29 <property name="visible">True</property>
30 <property name="use_underline">True</property>
31 <property name="use_stock">True</property>
32 <signal name="activate" handler="on_quit_activate"/>
33 </object>
34 </child>
35 </object>
36 </child>
37 </object>
38 </child>
39 <child>
40 <object class="GtkMenuItem" id="menuitem4">
41 <property name="visible">True</property>
42 <property name="label" translatable="yes">_Help</property>
43 <property name="use_underline">True</property>
44 <child type="submenu">
45 <object class="GtkMenu" id="menu3">
46 <property name="visible">True</property>
47 <child>
48 <object class="GtkImageMenuItem" id="about">
49 <property name="label">gtk-about</property>
50 <property name="visible">True</property>
51 <property name="use_underline">True</property>
52 <property name="use_stock">True</property>
53 <signal name="activate" handler="on_about_activate"/>
54 </object>
55 </child>
56 </object>
57 </child>
58 </object>
59 </child>
60 </object>
61 <packing>
62 <property name="expand">False</property>
63 <property name="position">0</property>
64 </packing>
65 </child>
66 <child>
67 <object class="GtkToolbar" id="toolbar">
68 <property name="visible">True</property>
69 <property name="toolbar_style">both</property>
70 <child>
71 <object class="GtkToolButton" id="start">
72 <property name="width_request">50</property>
73 <property name="visible">True</property>
74 <property name="label" translatable="yes">Start</property>
75 <property name="use_underline">True</property>
76 <property name="stock_id">gtk-apply</property>
77 <signal name="clicked" handler="on_start_clicked"/>
78 </object>
79 <packing>
80 <property name="expand">False</property>
81 <property name="homogeneous">True</property>
82 </packing>
83 </child>
84 <child>
85 <object class="GtkToolButton" id="stop">
86 <property name="width_request">50</property>
87 <property name="label" translatable="yes">Stop</property>
88 <property name="use_underline">True</property>
89 <property name="stock_id">gtk-stop</property>
90 <signal name="clicked" handler="on_stop_clicked"/>
91 </object>
92 <packing>
93 <property name="expand">False</property>
94 <property name="homogeneous">True</property>
95 </packing>
96 </child>
97 <child>
98 <object class="GtkToolButton" id="connect">
99 <property name="width_request">80</property>
100 <property name="visible">True</property>
101 <property name="sensitive">False</property>
102 <property name="label" translatable="yes">Connect</property>
103 <property name="use_underline">True</property>
104 <property name="stock_id">gtk-connect</property>
105 <signal name="clicked" handler="on_connect_clicked"/>
106 </object>
107 <packing>
108 <property name="expand">False</property>
109 <property name="homogeneous">True</property>
110 </packing>
111 </child>
112 <child>
113 <object class="GtkToolButton" id="disconnect">
114 <property name="width_request">80</property>
115 <property name="label" translatable="yes">Disconnect</property>
116 <property name="use_underline">True</property>
117 <property name="stock_id">gtk-disconnect</property>
118 <signal name="clicked" handler="on_disconnect_clicked"/>
119 </object>
120 <packing>
121 <property name="expand">False</property>
122 <property name="homogeneous">True</property>
123 </packing>
124 </child>
125 </object>
126 <packing>
127 <property name="expand">False</property>
128 <property name="position">1</property>
129 </packing>
130 </child>
131 <child>
132 <object class="GtkHBox" id="hbox1">
133 <property name="visible">True</property>
134 <child>
135 <object class="GtkHBox" id="hbox2">
26 <property name="visible">True</property>136 <property name="visible">True</property>
27 <child>137 <child>
28 <object class="GtkHBox" id="hbox2">138 <object class="GtkImage" id="is_started">
139 <property name="width_request">30</property>
29 <property name="visible">True</property>140 <property name="visible">True</property>
30 <child>141 <property name="sensitive">False</property>
31 <object class="GtkImage" id="image1">142 <property name="xpad">3</property>
32 <property name="visible">True</property>143 <property name="ypad">3</property>
33 <property name="stock">gtk-yes</property>144 <property name="stock">gtk-yes</property>
34 </object>
35 <packing>
36 <property name="position">0</property>
37 </packing>
38 </child>
39 <child>
40 <object class="GtkImage" id="image2">
41 <property name="visible">True</property>
42 <property name="stock">gtk-yes</property>
43 </object>
44 <packing>
45 <property name="position">1</property>
46 </packing>
47 </child>
48 <child>
49 <object class="GtkImage" id="image3">
50 <property name="visible">True</property>
51 <property name="stock">gtk-no</property>
52 </object>
53 <packing>
54 <property name="position">2</property>
55 </packing>
56 </child>
57 </object>145 </object>
58 <packing>146 <packing>
59 <property name="position">0</property>147 <property name="position">0</property>
60 </packing>148 </packing>
61 </child>149 </child>
62 <child>150 <child>
63 <object class="GtkLabel" id="status">151 <object class="GtkImage" id="is_connected">
152 <property name="width_request">30</property>
64 <property name="visible">True</property>153 <property name="visible">True</property>
65 <property name="label" translatable="yes">Status</property>154 <property name="sensitive">False</property>
155 <property name="xpad">3</property>
156 <property name="ypad">3</property>
157 <property name="stock">gtk-yes</property>
66 </object>158 </object>
67 <packing>159 <packing>
68 <property name="position">1</property>160 <property name="position">1</property>
69 </packing>161 </packing>
70 </child>162 </child>
163 <child>
164 <object class="GtkImage" id="is_online">
165 <property name="width_request">30</property>
166 <property name="visible">True</property>
167 <property name="sensitive">False</property>
168 <property name="xpad">3</property>
169 <property name="ypad">3</property>
170 <property name="stock">gtk-yes</property>
171 </object>
172 <packing>
173 <property name="position">2</property>
174 </packing>
175 </child>
176 </object>
177 <packing>
178 <property name="expand">False</property>
179 <property name="position">0</property>
180 </packing>
181 </child>
182 <child>
183 <object class="GtkLabel" id="status_label">
184 <property name="visible">True</property>
185 <property name="label" translatable="yes">Service not started, click Start to continue.</property>
71 </object>186 </object>
72 <packing>187 <packing>
73 <property name="position">1</property>188 <property name="position">1</property>
74 </packing>189 </packing>
75 </child>190 </child>
76 <child>
77 <placeholder/>
78 </child>
79 </object>191 </object>
80 <packing>192 <packing>
81 <property name="position">0</property>193 <property name="expand">False</property>
194 <property name="position">2</property>
82 </packing>195 </packing>
83 </child>196 </child>
84 <child>197 <child>
@@ -86,14 +199,68 @@
86 <property name="visible">True</property>199 <property name="visible">True</property>
87 <property name="can_focus">True</property>200 <property name="can_focus">True</property>
88 <child>201 <child>
89 <placeholder/>202 <object class="GtkTreeView" id="metaq_view">
203 <property name="visible">True</property>
204 <property name="can_focus">True</property>
205 <property name="model">liststore1</property>
206 </object>
207 <packing>
208 <property name="resize">True</property>
209 <property name="shrink">True</property>
210 </packing>
90 </child>211 </child>
91 <child>212 <child>
92 <placeholder/>213 <object class="GtkTreeView" id="contentq_view">
214 <property name="visible">True</property>
215 <property name="can_focus">True</property>
216 <property name="model">liststore2</property>
217 </object>
218 <packing>
219 <property name="resize">True</property>
220 <property name="shrink">True</property>
221 </packing>
93 </child>222 </child>
94 </object>223 </object>
95 <packing>224 <packing>
96 <property name="position">1</property>225 <property name="position">3</property>
226 </packing>
227 </child>
228 </object>
229 </child>
230 </object>
231 <object class="GtkStatusIcon" id="status_icon">
232 <property name="has_tooltip">True</property>
233 <property name="tooltip_text">Magicicada</property>
234 <property name="title">Magicicada</property>
235 </object>
236 <object class="GtkAboutDialog" id="about_dialog">
237 <property name="border_width">5</property>
238 <property name="type_hint">normal</property>
239 <property name="has_separator">False</property>
240 <property name="program_name">Magicicada</property>
241 <property name="copyright" translatable="yes">Copyright 2010 Natalia Bidart &lt;natalia.bidart@gmail.com&gt;
242Copyright 2010 Facundo Batista &lt;facundo.batista@gmail.com&gt;
243</property>
244 <property name="website">http://launchpad.net/magicicada</property>
245 <property name="license" translatable="yes">GPL v3.0</property>
246 <property name="authors">Natalia Bidart &lt;natalia.bidart@gmail.com&gt;
247Facundo Batista &lt;facundo.batista@gmail.com&gt;</property>
248 <child internal-child="vbox">
249 <object class="GtkVBox" id="dialog-vbox1">
250 <property name="visible">True</property>
251 <property name="spacing">2</property>
252 <child>
253 <placeholder/>
254 </child>
255 <child internal-child="action_area">
256 <object class="GtkHButtonBox" id="dialog-action_area1">
257 <property name="visible">True</property>
258 <property name="layout_style">end</property>
259 </object>
260 <packing>
261 <property name="expand">False</property>
262 <property name="pack_type">end</property>
263 <property name="position">0</property>
97 </packing>264 </packing>
98 </child>265 </child>
99 </object>266 </object>
100267
=== removed file 'data/ui/magicicada_window.xml'
--- data/ui/magicicada_window.xml 2010-04-21 21:18:31 +0000
+++ data/ui/magicicada_window.xml 1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
1<glade-catalog name="magicicada_window" domain="glade-3"
2 depends="gtk+" version="1.0">
3 <glade-widget-classes>
4 <glade-widget-class title="Magicicada Window" name="MagicicadaWindow"
5 generic-name="MagicicadaWindow" parent="GtkWindow"
6 icon-name="widget-gtk-window"/>
7 </glade-widget-classes>
8</glade-catalog>
90
=== removed file 'data/ui/preferences_magicicada_dialog.xml'
--- data/ui/preferences_magicicada_dialog.xml 2010-04-21 21:18:31 +0000
+++ data/ui/preferences_magicicada_dialog.xml 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
1<glade-catalog name="preferences_magicicada_dialog" domain="glade-3"
2 depends="gtk+" version="1.0">
3 <glade-widget-classes>
4 <glade-widget-class title="Magicicada Preferences Dialog" name="PreferencesMagicicadaDialog"
5 generic-name="PreferenceMagicicadaDialog" parent="GtkDialog"
6 icon-name="widget-gtk-dialog"/>
7 </glade-widget-classes>
8
9</glade-catalog>
100
=== removed file 'magicicada/AboutMagicicadaDialog.py'
--- magicicada/AboutMagicicadaDialog.py 2010-04-21 21:18:31 +0000
+++ magicicada/AboutMagicicadaDialog.py 1970-01-01 00:00:00 +0000
@@ -1,48 +0,0 @@
1# -*- coding: utf-8 -*-
2### BEGIN LICENSE
3# This file is in the public domain
4### END LICENSE
5
6import gtk
7
8from magicicada.helpers import get_builder
9
10import gettext
11from gettext import gettext as _
12gettext.textdomain('magicicada')
13
14class AboutMagicicadaDialog(gtk.AboutDialog):
15 __gtype_name__ = "AboutMagicicadaDialog"
16
17 def __new__(cls):
18 """Special static method that's automatically called by Python when
19 constructing a new instance of this class.
20
21 Returns a fully instantiated AboutMagicicadaDialog object.
22 """
23 builder = get_builder('AboutMagicicadaDialog')
24 new_object = builder.get_object("about_magicicada_dialog")
25 new_object.finish_initializing(builder)
26 return new_object
27
28 def finish_initializing(self, builder):
29 """Called while initializing this instance in __new__
30
31 finish_initalizing should be called after parsing the ui definition
32 and creating a AboutMagicicadaDialog object with it in order to
33 finish initializing the start of the new AboutMagicicadaDialog
34 instance.
35
36 Put your initialization code in here and leave __init__ undefined.
37 """
38 # Get a reference to the builder and set up the signals.
39 self.builder = builder
40 self.builder.connect_signals(self)
41
42 # Code for other initialization actions should be added here.
43
44
45if __name__ == "__main__":
46 dialog = AboutMagicicadaDialog()
47 dialog.show()
48 gtk.main()
490
=== removed file 'magicicada/PreferencesMagicicadaDialog.py'
--- magicicada/PreferencesMagicicadaDialog.py 2010-04-21 21:18:31 +0000
+++ magicicada/PreferencesMagicicadaDialog.py 1970-01-01 00:00:00 +0000
@@ -1,111 +0,0 @@
1# -*- coding: utf-8 -*-
2### BEGIN LICENSE
3# This file is in the public domain
4### END LICENSE
5
6from desktopcouch.records.server import CouchDatabase
7from desktopcouch.records.record import Record
8import gtk
9
10from magicicada.helpers import get_builder
11
12import gettext
13from gettext import gettext as _
14gettext.textdomain('magicicada')
15
16class PreferencesMagicicadaDialog(gtk.Dialog):
17 __gtype_name__ = "PreferencesMagicicadaDialog"
18 preferences = {}
19
20 def __new__(cls):
21 """Special static method that's automatically called by Python when
22 constructing a new instance of this class.
23
24 Returns a fully instantiated PreferencesMagicicadaDialog object.
25 """
26 builder = get_builder('PreferencesMagicicadaDialog')
27 new_object = builder.get_object("preferences_magicicada_dialog")
28 new_object.finish_initializing(builder)
29 return new_object
30
31 def finish_initializing(self, builder):
32 """Called while initializing this instance in __new__
33
34 finish_initalizing should be called after parsing the ui definition
35 and creating a PreferencesMagicicadaDialog object with it in order to
36 finish initializing the start of the new PerferencesMagicicadaDialog
37 instance.
38
39 Put your initialization code in here and leave __init__ undefined.
40 """
41
42 # Get a reference to the builder and set up the signals.
43 self.builder = builder
44 self.builder.connect_signals(self)
45
46 # Set up couchdb and the preference info.
47 self._db_name = "magicicada"
48 self._database = CouchDatabase(self._db_name, create=True)
49 self._preferences = None
50 self._key = None
51
52 # Set the record type and then initalize the preferences.
53 self._record_type = (
54 "http://wiki.ubuntu.com/Quickly/RecordTypes/Magicicada/"
55 "Preferences")
56 self._preferences = self.get_preferences()
57 # TODO: code for other initialization actions should be added here
58
59 def get_preferences(self):
60 """Return a dict of preferences for magicicada.
61
62 Creates a couchdb record if necessary.
63 """
64 if self._preferences == None:
65 # The dialog is initializing.
66 self._load_preferences()
67
68 # If there were no saved preference, this.
69 return self._preferences
70
71 def _load_preferences(self):
72 # TODO: add preferences to the self._preferences dict default
73 # preferences that will be overwritten if some are saved
74 self._preferences = {"record_type": self._record_type}
75
76 results = self._database.get_records(
77 record_type=self._record_type, create_view=True)
78
79 if len(results.rows) == 0:
80 # No preferences have ever been saved, save them before returning.
81 self._key = self._database.put_record(Record(self._preferences))
82 else:
83 self._preferences = results.rows[0].value
84 del self._preferences['_rev']
85 self._key = results.rows[0].value["_id"]
86
87 def _save_preferences(self):
88 self._database.update_fields(self._key, self._preferences)
89
90 def ok(self, widget, data=None):
91 """The user has elected to save the changes.
92
93 Called before the dialog returns gtk.RESONSE_OK from run().
94 """
95
96 # Make any updates to self._preferences here. e.g.
97 #self._preferences["preference1"] = "value2"
98 self._save_preferences()
99
100 def cancel(self, widget, data=None):
101 """The user has elected cancel changes.
102
103 Called before the dialog returns gtk.RESPONSE_CANCEL for run()
104 """
105 # Restore any changes to self._preferences here.
106 pass
107
108if __name__ == "__main__":
109 dialog = PreferencesMagicicadaDialog()
110 dialog.show()
111 gtk.main()
1120
=== modified file 'magicicada/__init__.py'
--- magicicada/__init__.py 2010-04-21 21:18:31 +0000
+++ magicicada/__init__.py 2010-05-15 15:48:32 +0000
@@ -0,0 +1,204 @@
1# __init__.py
2#
3# Author: Natalia Bidart <natalia.bidart@gmail.com>
4#
5# Copyright 2010 Chicharreros
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""Magicicada."""
20
21import gtk
22
23import gettext
24from gettext import gettext as _
25gettext.textdomain('magicicada')
26
27from twisted.internet import gtk2reactor # for gtk-2.0
28gtk2reactor.install()
29
30from twisted.internet import reactor
31
32from magicicada.helpers import get_data_file, get_builder, print_debug
33from magicicada.syncdaemon import SyncDaemon
34
35
36class MagicicadaUI(object):
37
38 STATUS = {
39 'started': _('Service started, click Connect to continue.'),
40 'connected': _('Service connected. Doing internal synchronization...'),
41 'online': _('Service reached Nirvana.'),
42 }
43
44 def __init__(self, launchpad_available=False):
45 """Init."""
46 self.builder = get_builder('gui.glade')
47 self.builder.connect_signals(self)
48
49 if launchpad_available:
50 # for more information about LaunchpadIntegration:
51 # wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding
52 helpmenu = self.builder.get_object('helpMenu')
53 if helpmenu:
54 LaunchpadIntegration.set_sourcepackagename('magicicada')
55 LaunchpadIntegration.add_items(helpmenu, 0, False, True)
56
57 animation_filename = get_data_file('media', 'loader-ball.gif')
58 self.loading_animation = gtk.gdk.PixbufAnimation(animation_filename)
59
60 self.started = self.connected = self.online = False
61
62 widgets = (
63 'start', 'stop', 'connect', 'disconnect', # toolbar buttons
64 'is_started', 'is_connected', 'is_online', # status bar images
65 'status_label', 'status_icon', # status label and systray icon
66 'main_window', 'about_dialog',
67 )
68 for widget in widgets:
69 setattr(self, widget, self.builder.get_object(widget))
70
71 icon_filename = get_data_file('media', 'ubuntuone.png')
72 self.status_icon.set_from_file(icon_filename)
73
74 self.main_window.set_icon_from_file(icon_filename)
75 self.main_window.show()
76
77 self.syncdaemon = SyncDaemon()
78
79 def run(self):
80 """Do the deed."""
81 reactor.run() # instead of: gtk.main()
82
83 def shutdown(self):
84 """Stop the deed."""
85 reactor.stop() # instead of: gtk.main_quit()
86
87 # GTK callbacks
88
89 def on_main_window_destroy(self, widget, data=None):
90 """Called when the MagicicadaWindow is closed."""
91 # Clean up code for saving application state should be added here.
92 if self.started:
93 self.on_stop_clicked(self.stop)
94 self.syncdaemon.shutdown()
95
96 def on_quit_activate(self, widget, data=None):
97 """Signal handler for closing the program."""
98 self.on_main_window_destroy(self.main_window)
99
100 def on_about_activate(self, widget, data=None):
101 """Display the about box."""
102 response = self.about_dialog.run()
103 self.about_dialog.hide()
104
105 @print_debug
106 def on_start_clicked(self, widget, data=None):
107 """Start syncdaemon."""
108 self.started = True
109 self.connect.set_sensitive(True)
110 self.start.hide()
111 self.stop.show()
112
113 self.doing_something(self.is_started)
114
115 @print_debug
116 def on_stop_clicked(self, widget, data=None):
117 """Stop syncdaemon."""
118 assert self.started
119
120 if self.connected:
121 self.on_disconnect_clicked(self.disconnect)
122 self.connect.set_sensitive(False)
123
124 self.started = False
125 self.start.show()
126 self.stop.hide()
127
128 self.on_stopped()
129
130 @print_debug
131 def on_connect_clicked(self, widget, data=None):
132 """Connect syncdaemon."""
133 assert self.started
134 self.connected = True
135 self.connect.hide()
136 self.disconnect.show()
137
138 self.on_started()
139 self.doing_something(self.is_connected)
140
141 @print_debug
142 def on_disconnect_clicked(self, widget, data=None):
143 """Disconnect syncdaemon."""
144 assert self.started
145 assert self.connected
146 self.connected = False
147 self.connect.show()
148 self.disconnect.hide()
149
150 self.on_disconnected()
151
152 # DBus callbacks
153
154 def on_started(self, *args, **kwargs):
155 """Callback'ed when syncadaemon is started."""
156 self.stop_doing_something(self.is_started)
157 self.status_label.set_text(self.STATUS['started'])
158
159 def on_stopped(self, *args, **kwargs):
160 """Callback'ed when syncadaemon is stopped."""
161
162 self.stop_doing_something(self.is_started, sensitive=False)
163
164 self.is_started.set_sensitive(False)
165 self.is_connected.set_sensitive(False)
166 self.is_online.set_sensitive(False)
167
168 def on_connected(self, *args, **kwargs):
169 """Callback'ed when syncadaemon is connected."""
170 self.is_connected.set_sensitive(True)
171 self.doing_something(self.is_online)
172 self.status_label.set_text(self.STATUS['connected'])
173
174 def on_disconnected(self, *args, **kwargs):
175 """Callback'ed when syncadaemon is disconnected."""
176
177 self.stop_doing_something(self.is_connected, sensitive=False)
178
179 self.is_connected.set_sensitive(False)
180 self.is_online.set_sensitive(False)
181
182 def on_online(self, *args, **kwargs):
183 """Callback'ed when syncadaemon is online."""
184 self.is_onlined.set_sensitive(True)
185 self.status_label.set_text(self.STATUS['online'])
186
187 def on_offline(self, *args, **kwargs):
188 """Callback'ed when syncadaemon is offline."""
189
190 self.stop_doing_something(self.is_online, sensitive=False)
191
192 self.is_online.set_sensitive(False)
193
194 # custom
195
196 def doing_something(self, what):
197 """Set a loader animation on 'what'."""
198 what.set_sensitive(True)
199 what.set_from_animation(self.loading_animation)
200
201 def stop_doing_something(self, what, sensitive=True):
202 """Set a loader animation on 'what'."""
203 what.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON)
204 what.set_sensitive(sensitive)
0205
=== modified file 'magicicada/helpers.py'
--- magicicada/helpers.py 2010-04-21 23:50:09 +0000
+++ magicicada/helpers.py 2010-05-15 15:48:32 +0000
@@ -12,6 +12,8 @@
12import os12import os
13import gtk13import gtk
1414
15from functools import wraps
16
15from magicicada.magicicadaconfig import get_data_file17from magicicada.magicicadaconfig import get_data_file
1618
17import gettext19import gettext
@@ -19,9 +21,8 @@
19gettext.textdomain('magicicada')21gettext.textdomain('magicicada')
2022
21def get_builder(builder_file_name):23def get_builder(builder_file_name):
22 """Return a fully-instantiated gtk.Builder instance from specified ui 24 """Return a fully-instantiated gtk.Builder instance from specified ui file.
23 file25
24
25 :param builder_file_name: The name of the builder file, without extension.26 :param builder_file_name: The name of the builder file, without extension.
26 Assumed to be in the 'ui' directory under the data path.27 Assumed to be in the 'ui' directory under the data path.
27 """28 """
@@ -34,3 +35,14 @@
34 builder.set_translation_domain('magicicada')35 builder.set_translation_domain('magicicada')
35 builder.add_from_file(ui_filename)36 builder.add_from_file(ui_filename)
36 return builder37 return builder
38
39def print_debug(f):
40 """Print debug info for 'f'."""
41
42 @wraps(f)
43 def inner(*args, **kwargs):
44 """Wrap f."""
45 print('Calling', f.__name__, args, kwargs)
46 f(*args, **kwargs)
47
48 return inner
3749
=== modified file 'magicicada/syncdaemon.py'
--- magicicada/syncdaemon.py 2010-05-04 01:30:42 +0000
+++ magicicada/syncdaemon.py 2010-05-15 15:48:32 +0000
@@ -18,9 +18,14 @@
1818
19"""The backend that communicates Magicicada with the SyncDaemon."""19"""The backend that communicates Magicicada with the SyncDaemon."""
2020
21# this always first21import sys
22from twisted.internet import glib2reactor22
23glib2reactor.install()23try:
24 from twisted.internet import glib2reactor
25 glib2reactor.install()
26except AssertionError, e:
27 msg = '\nsyncdaemon.py: Not installing glib2reactor because: %s.\n'
28 sys.stderr.write(msg % e)
2429
25import collections30import collections
26import re31import re
2732
=== added file 'magicicada/tests/test_magicicada.py'
--- magicicada/tests/test_magicicada.py 1970-01-01 00:00:00 +0000
+++ magicicada/tests/test_magicicada.py 2010-05-15 15:48:32 +0000
@@ -0,0 +1,150 @@
1# test_magicicada.py
2#
3# Author: Natalia Bidart <natalia.bidart@gmail.com>
4#
5# Copyright 2010 Chicharreros
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""Tests for magicicada."""
20
21import gobject
22import gtk
23import unittest
24
25from functools import wraps
26
27from twisted.internet import reactor
28from twisted.trial.unittest import TestCase
29
30from magicicada import MagicicadaUI
31from magicicada.helpers import get_builder
32from magicicada.syncdaemon import SyncDaemon
33
34DEFAULT_TIMEOUT = 200
35NO_OP = lambda *a, **kw: None
36
37def close_window_after(a_test):
38 """Decorator to close the main window after executing f."""
39 @wraps(a_test)
40 def inner(*args, **kwargs):
41 """Inner function."""
42 #gobject.timeout_add(DEFAULT_TIMEOUT, a_test)
43 #self.ui.run()
44
45 return inner
46
47
48class MagicicadaUITestCase(TestCase):
49 """UI test cases for Magicicada UI."""
50
51 def setUp(self):
52 """Init."""
53 self.builder = get_builder('gui.glade')
54 self.ui = MagicicadaUI()
55 self._patched = {}
56 self._called = False
57
58 def tearDown(self):
59 """Clenaup."""
60 self.ui.on_main_window_destroy(self.ui.main_window)
61 for (instance, attr), old_value in self._patched.iteritems():
62 setattr(instance, attr, old_value)
63 self._called = False
64 self.builder = None
65
66 def test_init_creates_sd_instance(self):
67 """SyncDaemon instance is created at creation time."""
68 self.assertTrue(isinstance(self.ui.syncdaemon, SyncDaemon))
69
70 def test_destroy_shutdowns_sd_instance(self):
71 """SyncDaemon instance is shutdown at destroy time."""
72 self.patch(self.ui.syncdaemon, 'shutdown',
73 lambda *_: setattr(self, '_called', True))
74 self.ui.on_main_window_destroy(self.ui.main_window)
75 self.assertTrue(self._called, 'syncdaemon.shutdown must be called at destroy time.')
76
77 def test_shutdown_stops_reactor(self):
78 """SyncDaemon instance is shutdown at destroy time."""
79 self.patch(reactor, 'stop',
80 lambda *_: setattr(self, '_called', True))
81 self.ui.shutdown()
82 self.assertTrue(self._called, 'reactor.stop must be called at destroy time.')
83
84
85class MagicicadaUIStartupTestCase(MagicicadaUITestCase):
86 """UI test cases for startup state."""
87
88 def test_main_window_is_visible(self):
89 """UI can be created."""
90 self.assertTrue(self.ui.main_window.get_property('visible'))
91
92 def test_start_connect_are_visible(self):
93 """Start and Connect buttons are visible."""
94 self.assertTrue(self.ui.start.get_property('visible'))
95 self.assertTrue(self.ui.start.is_sensitive())
96
97 self.assertTrue(self.ui.connect.get_property('visible'))
98 self.assertFalse(self.ui.connect.is_sensitive())
99
100 def test_stop_disconnect_are_not_visible(self):
101 """Start and Connect buttons are visible."""
102 self.assertFalse(self.ui.stop.get_property('visible'))
103 self.assertFalse(self.ui.disconnect.get_property('visible'))
104
105 def test_not_started_not_connected_not_online(self):
106 """Test default values for flags."""
107 self.assertFalse(self.ui.started)
108 self.assertFalse(self.ui.connected)
109 self.assertFalse(self.ui.online)
110
111 def test_indicators_are_non_sensitive(self):
112 """Test default sensitivity for indicators."""
113 #import pdb; pdb.set_trace()
114 self.assertFalse(self.ui.is_started.is_sensitive())
115 self.assertFalse(self.ui.is_connected.is_sensitive())
116 self.assertFalse(self.ui.is_online.is_sensitive())
117
118class MagicicadaUIClickedTestCase(MagicicadaUIStartupTestCase):
119 """UI test cases."""
120
121 def test_started_if_start_clicked(self):
122 """Test started if Start was clicked."""
123 self.ui.on_start_clicked(self.ui.start)
124 self.assertTrue(self.ui.started)
125 self.assertFalse(self.ui.connected)
126 self.assertFalse(self.ui.online)
127
128 def test_can_connect_can_stop_if_start_clicked(self):
129 """Test Connect and Stop are enabled if Start was clicked."""
130 self.ui.on_start_clicked(self.ui.start)
131 self.assertFalse(self.ui.start.get_property('visible'))
132 self.assertTrue(self.ui.stop.get_property('visible'))
133 self.assertTrue(self.ui.connect.is_sensitive())
134
135 def test_connected_if_connect_clicked(self):
136 """Test connected if Connect was clicked."""
137 self.ui.on_start_clicked(self.ui.start) # need to be started
138 self.ui.on_connect_clicked(self.ui.connect)
139
140 self.assertTrue(self.ui.started)
141 self.assertTrue(self.ui.connected)
142 self.assertFalse(self.ui.online)
143
144 def test_can_disconnect_if_connect_clicked(self):
145 """Test Disconnect is enabled if Connect was clicked."""
146 self.ui.on_start_clicked(self.ui.start) # need to be started
147 self.ui.on_connect_clicked(self.ui.connect)
148 self.assertFalse(self.ui.connect.get_property('visible'))
149 self.assertTrue(self.ui.disconnect.get_property('visible'))
150

Subscribers

People subscribed via source and target branches

to all changes: