Web · Wiki · Activities · Blog · Lists · Chat · Meeting · Bugs · Git · Translate · Archive · People · Donate

Commit acce94e7301a0f1c18a698a097522370f9dc20b9

lots of cleanup
LetterMatch.py
(126 / 140)
  
1# Copyright (c) 2012 Walter Bender
1# Copyright (c) 2012, 2013 Walter Bender
22# Copyright (c) 2013 Aneesh Dogra <lionaneesh@gmail.com>
33
44# This program is free software; you can redistribute it and/or modify
1515import gtk
1616
1717from sugar.activity import activity
18try:
19 from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
20 _HAVE_TOOLBOX = True
21except ImportError:
22 _HAVE_TOOLBOX = False
23
24if _HAVE_TOOLBOX:
25 from sugar.activity.widgets import ActivityToolbarButton
26 from sugar.activity.widgets import StopButton
27
28
18from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
19from sugar.activity.widgets import ActivityToolbarButton
20from sugar.activity.widgets import StopButton
2921from sugar.graphics.toolbutton import ToolButton
3022from sugar.graphics.combobox import ComboBox
3123from sugar.graphics.toolcombobox import ToolComboBox
4040
4141_logger = logging.getLogger('lettermatch-activity')
4242
43
4344class LetterMatch(activity.Activity):
4445 ''' Learning the alphabet.
4546
46 Level1: The alphabet appears and the user has the option to click
47 on a letter to listen the name of it and the sound of it.
47 Level1: A letter card and six picture cards appear; the user
48 listens to the name of letter and then selects the matching picture.
4849
49 Level2: The letters appear randomly and the user must place them
50 in the correct order.
50 Level2: A picture card and six letter cards appear; the user
51 listens to the name of the picture and then selects the matching letter.
5152
52 Level3: The laptop says a letter and the user must click on the
53 correct one. '''
53 Customization toolbar allows loading of new images and sounds.
54 '''
5455
5556 def __init__(self, handle):
5657 ''' Initialize the toolbars and the reading board '''
6161
6262 self.image_id = None
6363 self.audio_id = None
64 self.is_customization_toolbar = False
65 self.is_customization_toolbar_button = False
6664
6765 if 'LANG' in os.environ:
6866 language = os.environ['LANG'][0:2]
8585 self._sounds_path = self._lessons_path.replace('lessons', 'sounds')
8686 self.data_from_journal = {}
8787 if 'data_from_journal' in self.metadata:
88 self.data_from_journal = json.loads(str(self.metadata['data_from_journal']))
88 self.data_from_journal = json.loads(
89 str(self.metadata['data_from_journal']))
8990 self._setup_toolbars()
9091
91 # Create a canvas
9292 self.canvas = gtk.DrawingArea()
93 width = gtk.gdk.screen_width()
94 height = int(gtk.gdk.screen_height())
95 self.canvas.set_size_request(width, height)
93 self.canvas.set_size_request(gtk.gdk.screen_width(),
94 gtk.gdk.screen_height())
9695 self.canvas.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000"))
9796 self.canvas.show()
9897 self.set_canvas(self.canvas)
103103 parent=self)
104104
105105 def _setup_toolbars(self):
106 ''' Setup the toolbars.. '''
106 ''' Just 0.86+ toolbars '''
107 self.max_participants = 1 # no sharing
107108
108 # no sharing
109 self.max_participants = 1
109 toolbox = ToolbarBox()
110110
111 if _HAVE_TOOLBOX:
112 toolbox = ToolbarBox()
111 activity_button = ActivityToolbarButton(self)
112 toolbox.toolbar.insert(activity_button, 0)
113 activity_button.show()
113114
114 # Activity toolbar
115 activity_button = ActivityToolbarButton(self)
115 self.set_toolbar_box(toolbox)
116 toolbox.show()
117 primary_toolbar = toolbox.toolbar
118 custom_toolbar = ToolbarBox()
116119
117 toolbox.toolbar.insert(activity_button, 0)
118 activity_button.show()
120 self.custom_toolbar_button = ToolbarButton(
121 icon_name='view-source', page=custom_toolbar)
122 self.custom_toolbar_button.connect(
123 'clicked', self._customization_toolbar_cb)
124 toolbox.toolbar.insert(self.custom_toolbar_button, -1)
119125
120 self.set_toolbar_box(toolbox)
121 toolbox.show()
122 primary_toolbar = toolbox.toolbar
123 else:
124 # Use pre-0.86 toolbar design
125 primary_toolbar = gtk.Toolbar()
126 toolbox = activity.ActivityToolbox(self)
127 self.set_toolbox(toolbox)
128 toolbox.add_toolbar(_('Page'), primary_toolbar)
129 toolbox.show()
130 toolbox.set_current_toolbar(1)
131
132 # no sharing
133 if hasattr(toolbox, 'share'):
134 toolbox.share.hide()
135 elif hasattr(toolbox, 'props'):
136 toolbox.props.visible = False
137
138126 button = radio_factory('letter', primary_toolbar, self._letter_cb,
139127 tooltip=_('listen to the letter names'))
140128 radio_factory('picture', primary_toolbar, self._picture_cb,
133133
134134 self.letter_entry = None
135135
136 if _HAVE_TOOLBOX:
137 separator_factory(primary_toolbar, False, True)
136 self.image_button = button_factory('load_image_from_journal',
137 custom_toolbar.toolbar,
138 self._choose_image_from_journal_cb,
139 tooltip=_("Import Image"))
138140
139 journal_toolbar = ToolbarBox()
141 self.sound_button = button_factory('load_audio_from_journal',
142 custom_toolbar.toolbar,
143 self._choose_audio_from_journal_cb,
144 tooltip=_("Import Audio"))
140145
141 button_factory('load_image_from_journal', journal_toolbar.toolbar,
142 self._choose_image_from_journal_cb,
143 tooltip=_("Import Image"))
146 container = gtk.ToolItem()
147 self.letter_entry = gtk.Entry()
148 self.letter_entry.set_max_length(1)
149 self.letter_entry.set_width_chars(3) # because 1 char looks funny
150 self.letter_entry.connect('changed', self._set_letter)
151 self.letter_entry.set_sensitive(False)
152 self.letter_entry.show()
153 container.add(self.letter_entry)
154 container.show_all()
155 custom_toolbar.toolbar.insert(container, -1)
144156
145 button_factory('load_audio_from_journal', journal_toolbar.toolbar,
146 self._choose_audio_from_journal_cb,
147 tooltip=_("Import Audio"))
157 self.add_button = button_factory('list-add', custom_toolbar.toolbar,
158 self._copy_to_journal,
159 tooltip=_("Add"))
160 self.add_button.set_sensitive(False)
148161
149 container = gtk.ToolItem()
150 self.letter_entry = gtk.Entry()
151 self.letter_entry.connect('changed', self._set_letter)
152 self.letter_entry.set_sensitive(False)
153 self.letter_entry.show()
154 container.add(self.letter_entry)
155 container.show_all()
156 journal_toolbar.toolbar.insert(container, -1)
162 separator_factory(primary_toolbar, True, False)
157163
158 self.add_button = button_factory('add', journal_toolbar.toolbar,
159 self._copy_to_journal,
160 tooltip=_("Add"))
161 self.add_button.set_sensitive(False)
164 stop_button = StopButton(self)
165 stop_button.props.accelerator = '<Ctrl>q'
166 toolbox.toolbar.insert(stop_button, -1)
167 stop_button.show()
162168
163 # Add journal toolbar
164 self.journal_toolbar_button = ToolbarButton(icon_name='view-source',
165 page=journal_toolbar)
166 self.journal_toolbar_button.connect('clicked',
167 self._customization_toolbar_cb)
168 toolbox.toolbar.insert(self.journal_toolbar_button, -1)
169
170 separator_factory(primary_toolbar, True, False)
171
172 stop_button = StopButton(self)
173 stop_button.props.accelerator = '<Ctrl>q'
174 toolbox.toolbar.insert(stop_button, -1)
175 stop_button.show()
176
177169 def _set_letter(self, event):
170 ''' Process letter in text entry '''
178171 text = self.letter_entry.get_text().strip()
179172 if text and len(text) > 0:
180173 if len(text) != 1:
187187 self.add_button.set_sensitive(False)
188188
189189 def _copy_to_journal(self, event):
190 ''' Callback from add button on customization toolbar '''
191 # Save data to journal and load it into the card database
190192 self.metadata['data_from_journal'] = json.dumps(self.data_from_journal)
191193 self._page.load_from_journal(self.data_from_journal)
194
195 # Reinit the preview, et al. after add
192196 self.preview_image.hide()
193197 self._init_preview()
194198 self.image_id = None
195199 self.object_id = None
196 self.add_button.set_sensitive(False)
197200 self.letter_entry.set_text('')
198201 self.letter_entry.set_sensitive(False)
202 self.add_button.set_sensitive(False)
199203
200204 def _init_preview(self):
201 x = self._page._grid_x_offset + self._page._card_width + 12
202 y = self._page._grid_y_offset + 40
203 w = self._page._card_width
204 h = self._page._card_height
205 ''' Set up customization toolbar, preview image '''
206 w = int(self._page._card_width)
207 h = int(self._page._card_height)
208 x = int(self._page._grid_x_offset + w + 12)
209 y = int(self._page._grid_y_offset + 40)
205210
206 pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( \
207 os.path.join(self._images_path,'../drawing.png'), int(w),
208 int(h))
209 self.status.set_text(_('Please chose an image and ' \
210 'an audio clip from the journal'))
211 self._page._hide_cards()
212
213 if not hasattr(self, 'preview_image'):
214 self.preview_image = Sprite(self._page._sprites, 0, 0, pixbuf)
215 else:
216 self.preview_image.set_image(pixbuf)
217 self.preview_image.move((x, y))
218 self.preview_image.set_layer(100)
219 self._page._canvas.disconnect(self._page.button_press_event_id)
220 self._page._canvas.disconnect(self._page.button_release_event_id)
221 self._page.button_press_event_id = \
222 self._page._canvas.connect('button-press-event',
223 self._keypress_preview)
224 self._page.button_release_event_id = \
225 self._page._canvas.connect('button-release-event', self._dummy)
226 self.is_customization_toolbar = True
211 pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
212 os.path.join(self._images_path,'../drawing.png'), w, h)
213 self.status.set_text(
214 _('Please chose image and audio objects from the Journal.'))
215 self._page._hide_cards()
227216
228 def _customization_toolbar_cb(self, event):
229 if not self.is_customization_toolbar_button:
230 self.is_customization_toolbar_button = True
217 if not hasattr(self, 'preview_image'):
218 self.preview_image = Sprite(self._page._sprites, 0, 0, pixbuf)
219 else:
220 self.preview_image.set_image(pixbuf)
221 self.preview_image.move((x, y))
222 self.preview_image.set_layer(100)
223 self._page._canvas.disconnect(self._page.button_press_event_id)
224 self._page._canvas.disconnect(self._page.button_release_event_id)
225 self._page.button_press_event_id = \
226 self._page._canvas.connect('button-press-event',
227 self._preview_press_cb)
228 self._page.button_release_event_id = \
229 self._page._canvas.connect('button-release-event',
230 self._dummy_cb)
231
232 def _customization_toolbar_cb(self, event):
233 ''' Override toolbar button behavior '''
234 if self.custom_toolbar_button.is_expanded():
231235 self._init_preview()
232236 else:
233 self.is_customization_toolbar_button = False
234 if hasattr(self, 'preview_image'):
235 self.preview_image.hide()
237 if self.mode == 'letter':
238 self._letter_cb()
239 else:
240 self._picture_cb()
236241
237 def _keypress_preview(self, win, event):
242 def _preview_press_cb(self, win, event):
243 ''' Preview image was clicked '''
238244 self._choose_image_from_journal_cb(None)
239245
240 def _dummy(self, win, event):
246 def _dummy_cb(self, win, event):
241247 '''Does nothing'''
242248 return True
243249
244250 def _choose_audio_from_journal_cb(self, event):
251 ''' Create a chooser for audio objects '''
245252 self.add_button.set_sensitive(False)
246253 self.letter_entry.set_sensitive(False)
254 self.image_button.set_sensitive(False)
255 self.sound_button.set_sensitive(False)
247256 self.audio_id = None
248257 chooser = ObjectChooser(what_filter=mime.GENERIC_TYPE_AUDIO)
249258 result = chooser.run()
250259 if result == gtk.RESPONSE_ACCEPT:
251260 jobject = chooser.get_selected_object()
252261 self.audio_id = str(jobject._object_id)
262 self.image_button.set_sensitive(True)
263 self.sound_button.set_sensitive(True)
253264 if self.image_id and self.audio_id:
254265 self.letter_entry.set_sensitive(True)
255266 self._page._canvas.disconnect(self._page.button_press_event_id)
269269 self._play_audio_cb)
270270
271271 def _play_audio_cb(self, win, event):
272 ''' Preview audio '''
272273 if self.audio_id:
273274 play_audio_from_file(datastore.get(self.audio_id).get_file_path())
274275
275276 def _choose_image_from_journal_cb(self, event):
277 ''' Create a chooser for image objects '''
276278 self.add_button.set_sensitive(False)
277279 self.letter_entry.set_sensitive(False)
280 self.image_button.set_sensitive(False)
281 self.sound_button.set_sensitive(False)
278282 self.image_id = None
279283 chooser = ObjectChooser(what_filter=mime.GENERIC_TYPE_IMAGE)
280284 result = chooser.run()
291291 w = self._page._card_width
292292 h = self._page._card_height
293293
294 pb = gtk.gdk.pixbuf_new_from_file_at_size(jobject.get_file_path(),
295 w, h)
296 self.preview_image.hide()
297 self.preview_image.set_image(pb)
294 pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(
295 jobject.get_file_path(), w, h)
296 self.preview_image.set_image(pixbuf)
298297 self.preview_image.move((x, y))
299298 self.preview_image.set_layer(100)
299 self.image_button.set_sensitive(True)
300 self.sound_button.set_sensitive(True)
300301 if self.image_id and self.audio_id:
301302 self.letter_entry.set_sensitive(True)
302303 self._page._canvas.disconnect(self._page.button_press_event_id)
306306 self._play_audio_cb)
307307
308308 def _cleanup_preview(self):
309 self.preview_image.hide()
309 ''' No longer previewing, so hide image and clean up callbacks '''
310 if hasattr(self, 'preview_image'):
311 self.preview_image.hide()
310312 self._page._canvas.disconnect(self._page.button_press_event_id)
311313 self._page._canvas.disconnect(self._page.button_release_event_id)
312 self._page.button_release_event_id = \
313 self._canvas.connect("button-release-event",
314 self._page._button_release_cb)
315314 self._page.button_press_event_id = \
316315 self._canvas.connect("button-press-event",
317316 self._page._button_press_cb)
318 self._page.new_page()
319 self.is_customization_toolbar = False
317 self._page.button_release_event_id = \
318 self._canvas.connect("button-release-event",
319 self._page._button_release_cb)
320320
321321 def _letter_cb(self, event=None):
322 ''' click on card to hear the letter name '''
323 if self.is_customization_toolbar:
324 self._cleanup_preview()
325
322 ''' Click on card to hear the letter name '''
323 if self.custom_toolbar_button.is_expanded():
324 self.custom_toolbar_button.set_expanded(False)
325 self._cleanup_preview()
326326 self.mode = 'letter'
327327 self.status.set_text(_('Click on the picture that matches the letter.'))
328328 if hasattr(self, '_page'):
330330 return
331331
332332 def _picture_cb(self, event=None):
333 ''' click on card to hear the letter name '''
334 if self.is_customization_toolbar:
335 self._cleanup_preview()
336 self.is_customization_toolbar = False
337
333 ''' Click on card to hear the letter name '''
334 if self.custom_toolbar_button.is_expanded():
335 self.custom_toolbar_button.set_expanded(False)
336 self._cleanup_preview()
338337 self.mode = 'picture'
339338 self.status.set_text(_('Click on the letter that matches the picture.'))
340339 if hasattr(self, '_page'):
  
1<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
2 <!ENTITY stroke_color "#010101">
3 <!ENTITY fill_color "#FFFFFF">
4]><svg enable-background="new 0 0 55.125 55" height="55px" version="1.1" viewBox="0 0 55.125 55" width="55.125px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="list-add">
5 <path d="M43.467,11.644c-8.789-8.79-23.035-8.786-31.818-0.002 c-8.791,8.791-8.792,23.033-0.002,31.823c8.79,8.789,23.031,8.788,31.822-0.003C52.252,34.678,52.257,20.433,43.467,11.644z M30.768,38.767c-0.002,1.774-1.438,3.216-3.214,3.214c-0.889,0.001-1.693-0.359-2.275-0.941c-0.582-0.581-0.94-1.385-0.94-2.27 l0-8.146h-8.146c-0.886-0.001-1.689-0.359-2.271-0.94c-0.582-0.583-0.942-1.388-0.942-2.276c0-1.773,1.439-3.213,3.217-3.211h8.143 v-8.143c-0.003-1.776,1.438-3.217,3.212-3.217c1.774,0,3.218,1.438,3.215,3.215l0.001,8.145l8.146,0.001 c1.775-0.005,3.212,1.438,3.213,3.213c0.002,1.775-1.441,3.214-3.215,3.215h-8.143V38.767z" display="inline" fill="&fill_color;"/>
6</g></svg>
page.py
(2 / 3)
  
7878 self._canvas.connect("key_press_event", self._keypress_cb)
7979 self._width = gtk.gdk.screen_width()
8080 self._height = gtk.gdk.screen_height()
81 self._card_width = int((self._width / XDIM)) - GUTTER * 2
8281 self._card_height = int((self._height - GRID_CELL_SIZE) / YDIM) \
8382 - GUTTER * 2
83 self._card_width = int(self._card_height * 4 / 3.)
8484 self._grid_x_offset = int(
8585 (self._width - XDIM * (self._card_width + GUTTER * 2)) / 2)
8686 self._grid_y_offset = 0
87 # self._scale = self._width / 240.
88 self._scale = self._card_width / 80
87 self._scale = self._card_width / 80.
8988 self._sprites = Sprites(self._canvas)
9089 self.current_card = 0
9190 self._cards = []