Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/cardlist.py
diff options
context:
space:
mode:
Diffstat (limited to 'cardlist.py')
-rw-r--r--cardlist.py408
1 files changed, 408 insertions, 0 deletions
diff --git a/cardlist.py b/cardlist.py
new file mode 100644
index 0000000..5b5793e
--- /dev/null
+++ b/cardlist.py
@@ -0,0 +1,408 @@
+# Copyright (C) 2006, 2007, 2008 One Laptop Per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import gtk
+import svgcard
+import logging
+
+import os
+from os import environ
+from os.path import join
+
+import model
+import zipfile
+import tempfile
+from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT
+
+from sugar.graphics import style
+from sugar.graphics.icon import Icon
+
+import theme
+
+_logger = logging.getLogger('memorize-activity')
+
+class CardList(gtk.EventBox):
+
+ __gsignals__ = {
+ 'pair-selected': (SIGNAL_RUN_FIRST, None, 11 * [TYPE_PYOBJECT]),
+ 'update-create-toolbar': (SIGNAL_RUN_FIRST, None, 3 * [TYPE_PYOBJECT]),
+ 'update-create-buttons': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]),
+ }
+
+ def __init__(self):
+ gtk.EventBox.__init__(self)
+ self.model = model.Model()
+ self.pairs = []
+ self.current_pair = None
+ self.current_game_key = None
+
+ self.vbox = gtk.VBox(False)
+
+ fill_box = gtk.Label()
+ fill_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#000000'))
+ fill_box.show()
+ self.vbox.pack_end(fill_box, True, True)
+
+ scroll = gtk.ScrolledWindow()
+ scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scroll.add_with_viewport(self.vbox)
+ scroll.set_border_width(0)
+ scroll.get_child().modify_bg(gtk.STATE_NORMAL,
+ gtk.gdk.color_parse('#000000'))
+ self.add(scroll)
+ self.show_all()
+
+ def load_game(self, widget, game_name):
+ self.model.read(game_name)
+ self.current_game_key = self.model.data['game_file']
+ self.emit('update-create-toolbar', self.model.data['name'],
+ self.model.data.get('equal_pairs', 'False'),
+ self.model.data.get('divided', '0'))
+ game_pairs = self.model.pairs
+ game_data = self.model.data
+ self.clean_list()
+ for key in game_pairs:
+ if game_pairs[key].props.aimg != None:
+ aimg = gtk.gdk.pixbuf_new_from_file( \
+ join(self.model.data['pathimg'],
+ game_pairs[key].props.aimg))
+ else:
+ aimg = None
+
+ if game_pairs[key].props.bimg != None:
+ bimg = gtk.gdk.pixbuf_new_from_file( \
+ join(self.model.data['pathimg'],
+ game_pairs[key].props.bimg))
+ else:
+ bimg = None
+
+ if game_pairs[key].props.asnd != None:
+ asnd = join(self.model.data['pathsnd'],
+ game_pairs[key].props.asnd)
+ else:
+ asnd = None
+
+ if game_pairs[key].props.bsnd != None:
+ bsnd = join(self.model.data['pathsnd'],
+ game_pairs[key].props.bsnd)
+ else:
+ bsnd = None
+
+ if game_pairs[key].props.asensor != None:
+ asensor = game_pairs[key].props.asensor
+ if game_pairs[key].props.bsensor != None:
+ bsensor = game_pairs[key].props.bsensor
+
+ self.add_pair(None, game_pairs[key].props.achar,
+ game_pairs[key].props.bchar, aimg, bimg, asnd, bsnd,
+ game_pairs[key].props.aspeak, game_pairs[key].props.bspeak,
+ game_pairs[key].props.asensor, game_pairs[key].props.bsensor,
+ False)
+
+ def save_game(self, widget, game_name, equal_pairs, grouped):
+
+ tmp_root = join(environ['SUGAR_ACTIVITY_ROOT'], 'instance')
+ temp_folder = tempfile.mkdtemp(dir=tmp_root)
+ os.chmod(temp_folder, 0777)
+ temp_img_folder = join(temp_folder, 'images')
+ temp_snd_folder = join(temp_folder, 'sounds')
+
+ os.makedirs(temp_img_folder)
+ os.makedirs(temp_snd_folder)
+
+ game_zip = zipfile.ZipFile(join(temp_folder, 'game.zip'), 'w')
+
+ game_model = model.Model(temp_folder)
+ game_model.data['name'] = game_name
+ for pair in range(len(self.pairs)):
+ pair_card = model.Pair()
+
+ # achar
+ achar = self.pairs[pair].get_text(1)
+ if achar != '':
+ pair_card.set_property('achar', achar)
+
+ # bchar
+ bchar = self.pairs[pair].get_text(2)
+ if bchar != '':
+ pair_card.set_property('bchar', bchar)
+
+ # aspeak
+ aspeak = self.pairs[pair].get_speak(1)
+ pair_card.set_property('aspeak', aspeak)
+
+ # bspeak
+ bspeak = self.pairs[pair].get_speak(2)
+ pair_card.set_property('bspeak', bspeak)
+
+ # aimg
+ aimg = self.pairs[pair].get_pixbuf(1)
+ if aimg != None:
+
+ if equal_pairs:
+ aimgfile = 'img' + str(pair) + '.jpg'
+ else:
+ aimgfile = 'aimg' + str(pair) + '.jpg'
+ aimg.save(join(temp_img_folder, aimgfile), 'jpeg',
+ {'quality':'85'})
+ game_zip.write(join(temp_img_folder, aimgfile),
+ join('images', aimgfile))
+ pair_card.set_property('aimg', aimgfile)
+
+ # bimg
+ bimg = self.pairs[pair].get_pixbuf(2)
+ if bimg != None:
+ if equal_pairs:
+ bimgfile = 'img' + str(pair) + '.jpg'
+ else:
+ bimgfile = 'bimg' + str(pair) + '.jpg'
+ bimg.save(join(temp_img_folder, bimgfile), 'jpeg',
+ {'quality':'85'})
+ game_zip.write(join(temp_img_folder, bimgfile),
+ join('images', bimgfile))
+ pair_card.set_property('bimg', bimgfile)
+ # asnd
+ asnd = self.pairs[pair].get_sound(1)
+ if asnd != None:
+ if equal_pairs:
+ asndfile = 'snd' + str(pair) + '.ogg'
+ else:
+ asndfile = 'asnd' + str(pair) + '.ogg'
+ _logger.error(asndfile + ': ' + asnd)
+ game_zip.write(asnd, join('sounds', asndfile))
+ pair_card.set_property('asnd', asndfile)
+
+ # bsnd
+ bsnd = self.pairs[pair].get_sound(2)
+ if bsnd != None:
+ if equal_pairs:
+ bsndfile = 'snd'+str(pair)+'.ogg'
+ else:
+ bsndfile = 'bsnd' + str(pair) + '.ogg'
+ game_zip.write(bsnd, join('sounds', bsndfile))
+ _logger.error(bsndfile + ': ' + bsnd)
+ pair_card.set_property('bsnd', bsndfile)
+
+ game_model.pairs[pair] = pair_card
+ game_model.write(equal_pairs, grouped)
+ game_zip.write(join(temp_folder, 'game.xml'), 'game.xml')
+ game_zip.close()
+ game_model.save_byte_array(join(temp_folder, 'game.zip'), game_name)
+
+ def clean_list(self, button = None):
+ if button != None:
+ self.current_game_key = None
+ map(lambda x: self.vbox.remove(x), self.pairs)
+ del self.pairs
+ self.pairs = []
+
+ def clean_tmp_folder(self, path):
+ for root, dirs, files in os.walk(path, topdown=False):
+ for name in files:
+ os.remove(join(root, name))
+ for name in dirs:
+ os.rmdir(join(root, name))
+ os.rmdir(path)
+
+ def trysensor(self, avg):
+ for pair in self.pairs:
+ if(abs(avg-int(pair.asensor)) < 100):
+ self.bcard1.set_sensor(pair.asensor)
+ elif(abs(avg-int(pair.bsensor)) < 100):
+ self.bcard2.set_sensor(pair.bsensor)
+
+ def add_pair(self, widget, achar, bchar, aimg, bimg, asnd, bsnd,
+ aspeak, bspeak, asensor, bsensor, show = True):
+ pair = Pair(achar, bchar, aimg, bimg, asnd, bsnd, aspeak, bspeak, asensor, bsensor)
+ self.vbox.pack_end(pair, False, True)
+ self.pairs.append(pair)
+ pair.connect('pair-selected', self.set_selected)
+ pair.connect('pair-closed', self.rem_pair)
+ self.emit('update-create-buttons', True, True)
+ if show:
+ self.show_all()
+
+ def rem_pair(self, widget, event):
+ self.vbox.remove(widget)
+ self.pairs.remove(widget)
+ del widget
+ self.emit('update-create-buttons', True, True)
+ self.emit('pair-selected', False, None, None, None, None, None, None,
+ False, False, False, False)
+
+ def set_selected(self, widget, event):
+ if self.current_pair is not None:
+ current_pair = self.current_pair
+ current_pair.set_selected(False)
+ self.current_pair = widget
+ widget.set_selected(True)
+ self.emit('pair-selected', True,
+ self.current_pair.get_text(1), self.current_pair.get_text(2),
+ self.current_pair.get_pixbuf(1), self.current_pair.get_pixbuf(2),
+ self.current_pair.get_sound(1), self.current_pair.get_sound(2),
+ self.current_pair.get_speak(1), self.current_pair.get_speak(2),
+ self.current_pair.get_sensor(1), self.current_pair.get_sensor(2))
+
+ def update_selected(self, widget, newtext1, newtext2, aimg, bimg,
+ asnd, bsnd, aspeak, bspeak, asensor, bsensor):
+ self.current_pair.change_text(newtext1, newtext2)
+ self.current_pair.change_pixbuf(aimg, bimg)
+ self.current_pair.change_sound(asnd, bsnd)
+ self.current_pair.change_speak(aspeak, bspeak)
+ self.current_pair.change_sensor(asensor, bsensor)
+
+ self.emit('update-create-buttons', True, True)
+
+class Pair(gtk.EventBox):
+
+ __gsignals__ = {
+ 'pair-selected': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ 'pair-closed': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
+ }
+
+ def __init__(self, text1, text2 = None, aimg = None, bimg = None,
+ asnd = None, bsnd = None, aspeak=None, bspeak=None, asensor=None, bsensor=None):
+ gtk.EventBox.__init__(self)
+ self.bg_color = '#000000'
+
+ self.asnd = asnd
+ self.bsnd = bsnd
+ self.asensor = asensor
+ self.bsensor = bsensor
+
+ self.current_game_key = None
+
+ row = gtk.HBox()
+ row.props.border_width = 10
+ row.props.spacing = 10
+
+ self.bcard1 = svgcard.SvgCard(-1,
+ { 'front_text' : { 'card_text' : text1,
+ 'speak' : aspeak,
+ 'text_color' : '#ffffff' },
+ 'front' : { 'fill_color' : '#4c4d4f',
+ 'stroke_color' : '#ffffff',
+ 'opacity' : '1' } },
+ None, theme.PAIR_SIZE, 1, self.bg_color)
+ self.bcard1.flip()
+ self.bcard1.set_pixbuf(aimg)
+ self.bcard1.set_sensor(asensor)
+ align = gtk.Alignment(.5, .5, 0, 0)
+ align.add(self.bcard1)
+ row.pack_start(align)
+
+ self.bcard2 = svgcard.SvgCard(-1,
+ { 'front_text' : { 'card_text' : text2,
+ 'speak' : bspeak,
+ 'text_color' : '#ffffff' },
+ 'front' : { 'fill_color' : '#4c4d4f',
+ 'stroke_color' : '#ffffff',
+ 'opacity' : '1' } },
+ None, theme.PAIR_SIZE, 1, self.bg_color)
+ self.bcard2.flip()
+ self.bcard2.set_pixbuf(bimg)
+ self.bcard2.set_sensor(bsensor)
+ align = gtk.Alignment(.5, .5, 0, 0)
+ align.add(self.bcard2)
+ row.pack_start(align)
+
+ close_image = Icon(
+ icon_name='remove',
+ icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR)
+ align = gtk.Alignment(.5, .5)
+ align.add(close_image)
+ close_button = gtk.ToolButton()
+ close_button.set_icon_widget(align)
+ close_button.connect('clicked', self.emit_close)
+ close_button.set_size_request(style.STANDARD_ICON_SIZE,
+ style.STANDARD_ICON_SIZE)
+ align = gtk.Alignment(.5, 0, 0, 0)
+ align.add(close_button)
+ row.pack_start(align, False)
+
+ self.connect('button-press-event', self.emit_selected)
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color))
+ self.add(row)
+ self.show_all()
+
+ def emit_selected(self, widget, event):
+ self.emit('pair-selected', self)
+
+ def emit_close(self, widget):
+ self.emit('pair-closed', self)
+
+ def set_selected(self, status):
+ if not status:
+ self.bg_color = '#000000'
+ else:
+ self.bg_color = '#b2b3b7'
+
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color))
+ self.bcard1.set_background(self.bg_color)
+ self.bcard2.set_background(self.bg_color)
+
+ def change_pixbuf(self, aimg, bimg):
+ self.bcard1.set_pixbuf(aimg)
+ self.bcard2.set_pixbuf(bimg)
+
+ def change_text(self, text1, text2):
+ self.bcard1.change_text(text1)
+ self.bcard2.change_text(text2)
+
+ def change_sound(self, asnd, bsnd):
+ self.asnd = asnd
+ self.bsnd = bsnd
+
+ def change_sensor(self, asensor, bsensor):
+ self.asensor = asensor
+ self.bcard1.set_sensor(asensor)
+ self.bsensor = bsensor
+ self.bcard2.set_sensor(bsensor)
+
+ def get_text(self, card):
+ if card == 1:
+ return self.bcard1.get_text()
+ else:
+ return self.bcard2.get_text()
+
+ def change_speak(self, aspeak, bspeak):
+ self.bcard1.change_speak(aspeak)
+ self.bcard2.change_speak(bspeak)
+
+ def get_speak(self, card):
+ if card == 1:
+ return self.bcard1.get_speak()
+ else:
+ return self.bcard2.get_speak()
+
+ def get_pixbuf(self, card):
+ if card == 1:
+ return self.bcard1.get_pixbuf()
+ else:
+ return self.bcard2.get_pixbuf()
+
+ def get_sound(self, card):
+ if card == 1:
+ return self.asnd
+ else:
+ return self.bsnd
+
+ def get_sensor(self, card):
+ if card == 1:
+ return self.asensor
+ else:
+ return self.bsensor