1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import os
24
25 import sys
26
27 import gobject
28 import gtk
29 import gtk.glade
30
31 from flumotion.configure import configure
32
33 from flumotion.common import pygobject, log
34 from flumotion.common.pygobject import gsignal
35 from flumotion.ui.glade import GladeWidget, GladeWindow
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
87
88
117
119 """
120 A generic wizard.
121
122 This wizard runs its own GObject main loop.
123 The wizard is run with the run() method.
124
125 Example::
126 w = Wizard('foo', 'first-step', FirstStep)
127 w.show()
128 w.run() => {'bank-account': 'foo'}
129 """
130
131 name = None
132 steps = None
133
134
135
136 glade_file = 'admin-wizard.glade'
137
138 gsignal('finished')
139
141 """
142 @type initial_page: str
143 @param initial_page: name of the WizardStep to start on
144 """
145 GladeWindow.__init__(self)
146
147 self.page = None
148 self.page_stack = []
149 self.pages = {}
150 self.state = {}
151
152
153 assert self.name
154 assert self.steps
155
156
157 for cls in self.steps:
158 page = cls(self, self.name + '-')
159 self.pages[cls.name] = page
160 page.show()
161
162 self._setup_ui()
163 self.set_page(initial_page)
164
166 w = self.widgets
167
168 iconfile = os.path.join(configure.imagedir, 'fluendo.png')
169 self.window.set_icon_from_file(iconfile)
170 w['image_icon'].set_from_file(iconfile)
171
172
173
174 w['label_title'].realize()
175 style = w['label_title'].get_style()
176
177 title_bg = style.bg[gtk.STATE_SELECTED]
178 title_fg = style.fg[gtk.STATE_SELECTED]
179 w['eventbox_top'].modify_bg(gtk.STATE_NORMAL, title_bg)
180 w['eventbox_top'].modify_bg(gtk.STATE_INSENSITIVE, title_bg)
181 w['label_title'].modify_fg(gtk.STATE_NORMAL, title_fg)
182 w['label_title'].modify_fg(gtk.STATE_INSENSITIVE, title_fg)
183 normal_bg = style.bg[gtk.STATE_NORMAL]
184 w['textview_text'].modify_base(gtk.STATE_INSENSITIVE, normal_bg)
185 w['textview_text'].modify_bg(gtk.STATE_INSENSITIVE, normal_bg)
186 w['eventbox_content'].modify_base(gtk.STATE_INSENSITIVE, normal_bg)
187 w['eventbox_content'].modify_bg(gtk.STATE_INSENSITIVE, normal_bg)
188
189 - def set_page(self, name):
190 try:
191 page = self.pages[name]
192 except KeyError:
193 raise AssertionError ('No page named %s in %r' % (name, self.pages))
194
195 w = self.widgets
196 page.button_next = w['button_next']
197
198 available_pages = [p for p in page.next_pages
199 if self.pages[p].is_available()]
200
201 w['button_prev'].set_sensitive(bool(self.page_stack))
202
203 self.page = page
204 for x in w['page_bin'].get_children():
205 w['page_bin'].remove(x)
206 w['page_bin'].add(page)
207 w['label_title'].set_markup('<big><b>%s</b></big>' % page.title)
208 w['textview_text'].get_buffer().set_text(page.text)
209 w['button_next'].set_sensitive(True)
210 page.setup(self.state, available_pages)
211
213 self.state = None
214 self.emit('finished')
215
217 button.set_sensitive(False)
218 next_page = self.page.on_next(self.state)
219
220 if not next_page:
221
222 pass
223 elif next_page == '*finished*':
224 button.set_sensitive(True)
225 self.emit('finished')
226 elif next_page == '*signaled*':
227
228 def on_finished(page, next_page):
229 button.set_sensitive(True)
230 self.page.disconnect(self._finished_id)
231 if next_page == '*finished*':
232 self.emit('finished')
233 else:
234 self.page_stack.append(self.page)
235 self.set_page(next_page)
236 self._finished_id = self.page.connect('finished', on_finished)
237 else:
238 button.set_sensitive(True)
239 self.page_stack.append(self.page)
240 self.set_page(next_page)
241
245
248
250 """
251 Run in a recursive main loop. Will block until the user finishes
252 or closes the wizard.
253 """
254 loop = gobject.MainLoop()
255 d = self.run_async()
256 def async_done(_):
257 loop.quit()
258 d.addCallbacks(async_done, async_done)
259 loop.run()
260 return self.state
261
263 self.window.destroy()
264
266 """
267 Show the wizard. Returns a deferred that fires when the user has
268 closed the wizard, either via completing the process or has
269 cancelled somehow.
270
271 @returns: a deferred that will fire the state dict accumulated
272 by the pages, or None on cancel
273 """
274 assert self.window
275 self.set_sensitive(True)
276 self.show()
277 from twisted.internet import defer
278 d = defer.Deferred()
279 def finished(x):
280 self.disconnect(i)
281 self.hide()
282 if self.state:
283 d.callback(self.state)
284 else:
285 d.errback(WizardCancelled())
286 i = self.connect('finished', finished)
287 return d
288
289 pygobject.type_register(Wizard)
290