From 5778152f01cf35e25f2f94619c1c9d8907503c46 Mon Sep 17 00:00:00 2001 From: Muriel de Souza Godoi Date: Mon, 29 Oct 2007 11:06:02 +0000 Subject: Send game files over tubes do the other players --- diff --git a/activity.py b/activity.py index 51b0af2..2d5be77 100755 --- a/activity.py +++ b/activity.py @@ -1,25 +1,25 @@ #! /usr/bin/env python # -# Copyright (C) 2006, 2007, One Laptop Per Child +# Copyright (C) 2006, 2007, 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 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. +# 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. +# 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 logging from gettext import gettext as _ -import os +from os.path import join, dirname import dbus import gtk @@ -45,9 +45,9 @@ import createcardpanel from sugar.presence.tubeconn import TubeConnection -SERVICE = "org.laptop.Memorize" +SERVICE = 'org.laptop.Memorize' IFACE = SERVICE -PATH = "/org/laptop/Memorize" +PATH = '/org/laptop/Memorize' _TOOLBAR_CREATE = 1 _TOOLBAR_PLAY = 2 @@ -55,347 +55,354 @@ _TOOLBAR_PLAY = 2 _logger = logging.getLogger('memorize-activity') class MemorizeActivity(Activity): - def __init__(self, handle): - Activity.__init__(self, handle) - - self.play_load = False - self.play_mode = False - - toolbox = ActivityToolbox(self) - toolbox.connect('current-toolbar-changed', self.change_mode) - activity_toolbar = toolbox.get_activity_toolbar() - - self._createToolbar = createtoolbar.CreateToolbar(self) - toolbox.add_toolbar('Create', self._createToolbar) - self._createToolbar.show() - - self._memorizeToolbar = memorizetoolbar.MemorizeToolbar(self) - toolbox.add_toolbar(_('Play'), self._memorizeToolbar) - self._memorizeToolbar.show() - - self.set_toolbox(toolbox) - toolbox.show() - - self.cardlist = cardlist.CardList() - self.createcardpanel = createcardpanel.CreateCardPanel() - self.createcardpanel.connect('add-pair', self.cardlist.add_pair) - self.createcardpanel.connect('update-pair', self.cardlist.update_selected) - self.cardlist.connect('pair-selected', self.createcardpanel.load_pair) - self.cardlist.connect('update-create-toolbar', self._createToolbar.update_create_toolbar) - self.cardlist.connect('update-create-buttons', self._createToolbar.update_buttons_status) - self._createToolbar.connect('create_new_game', self.cardlist.clean_list) - self._createToolbar.connect('create_new_game', self.createcardpanel.clean) - self._createToolbar.connect('create_load_game', self.cardlist.load_game) - self._createToolbar.connect('create_save_game', self.cardlist.save_game) - self._createToolbar.connect('create_equal_pairs', self.createcardpanel.change_equal_pairs) - - self.hbox = gtk.HBox(False) - self.hbox.pack_start(self.createcardpanel) - self.hbox.pack_start(self.cardlist, False, False) - self.set_canvas(self.hbox) - - # create csound instance to play sound files - self.sound = 0 - try: - import csnd - del csnd - self.sound = 1 - except: - self.sound = 0 - - if self.sound == 1: - from csound.csoundserver import CsoundServer - cs = CsoundServer() - if cs.start() != 0: - self.sound = 0 - else: - cs.quit() - - # connect to the in/out events of the memorize activity - self.connect('focus_in_event', self._focus_in) - self.connect('focus_out_event', self._focus_out) - self.connect('destroy', self._cleanup_cb) - - # start on the game toolbar, might change this to the create toolbar later - self.toolbox.set_current_toolbar(_TOOLBAR_CREATE) - - # Get the Presence Service - self.pservice = presenceservice.get_instance() - try: - name, path = self.pservice.get_preferred_connection() - self.tp_conn_name = name - self.tp_conn_path = path - self.conn = telepathy.client.Connection(name, path) - except TypeError: - _logger.debug('Offline') - self.initiating = None - - # Buddy object for you - owner = self.pservice.get_owner() - self.owner = owner - self.current = 0 - # Owner.props.key - if self._shared_activity: - # We are joining the activity - #_logger.debug("Joined activity, add myself to buddy list nick=%s" %self.owner.props.nick) - #self.game.add_buddy(self.owner) - self.toolbox.set_current_toolbar(_TOOLBAR_PLAY) - self.connect('joined', self._joined_cb) - if self.get_shared(): - # We've already joined - self._joined_cb() - else: - _logger.debug("buddy joined - __init__: %s", self.owner.props.nick) - #game_file = game_file = os.path.join(os.path.dirname(__file__),'demos','addition.zip') - #self.game.load_game(game_file, 4) - _logger.debug('loading conventional') - #self.game.add_buddy(self.owner) - self.show_all() - - def read_file(self, file_path): - if self.metadata['mime_type'] == 'plain/text': - f = open(file_path, 'r') - try: - data = pickle.load(f) - finally: - f.close() - - _logger.debug('reading from datastore') - - self.game.load_remote(data[0], data[1]) - self.game.set_wait_list(data[2]) - elif self.metadata['mime_type'] == 'application/memorizegame': - self.game.change_game(file_path, 4) - - def write_file(self, file_path): - if not self.metadata['mime_type']: - self.metadata['mime_type'] = 'plain/text' - - if self.metadata['mime_type'] == 'plain/text': - - - data=[self.game.get_grid(), self.game.get_data(), self.game.get_players_data()] - - _logger.debug('writing to datastore') - f = open(file_path, 'w') - try: - pickle.dump(data, f) - finally: - f.close() - - def change_mode(self, notebook, index): - if index != _TOOLBAR_CREATE: - if not self.play_load: - # Create play components - self.table = cardtable.CardTable() - self.scoreboard = scoreboard.Scoreboard() - self.game = game.MemorizeGame() - self.game.set_myself(self.owner) - self.hbox.remove(self.createcardpanel) - self.hbox.remove(self.cardlist) - self.hbox.pack_start(self.scoreboard, False, False) - self.hbox.pack_start(self.table) - - self.table.connect('key-press-event', self.table.key_press_event) - self.table.connect('card-flipped', self.game.card_flipped) - self.table.connect('card-highlighted', self.game.card_highlighted) - - self.game.connect('reset_scoreboard', self.scoreboard.reset) - self.game.connect('reset_table', self.table.reset) - self.game.connect('load_game', self.table.load_game) - self.game.connect('change_game', self.table.change_game) - self.game.connect('load_game', self._memorizeToolbar.update_toolbar) - self.game.connect('change_game', self._memorizeToolbar.update_toolbar) - self.game.connect('set-border', self.table.set_border) - self.game.connect('flop-card', self.table.flop_card) - self.game.connect('flip-card', self.table.flip_card) - self.game.connect('highlight-card', self.table.highlight_card) - self.game.connect('add_buddy', self.scoreboard.add_buddy) - self.game.connect('rem_buddy', self.scoreboard.rem_buddy) - self.game.connect('increase-score', self.scoreboard.increase_score) - self.game.connect('wait_mode_buddy', self.scoreboard.set_wait_mode) - self.game.connect('change-turn', self.scoreboard.set_selected) - self.connect('shared', self._shared_cb) - self.play_load = True - if not self._shared_activity: - self.game.add_buddy(self.owner) - #game_file = os.path.join(os.path.dirname(__file__), 'demos', 'addition.zip') - #self.game.load_game(game_file, 4) - else: - self.hbox.remove(self.createcardpanel) - self.hbox.remove(self.cardlist) - self.hbox.pack_start(self.scoreboard, False, False) - self.hbox.pack_start(self.table) - self.play_mode = True - else: - if self.play_mode: - self.hbox.remove(self.scoreboard) - self.hbox.remove(self.table) - self.hbox.pack_start(self.createcardpanel) - self.hbox.pack_start(self.cardlist, False, False) - self.play_mode = False - - def restart(self, widget): - self.game.reset() - - def change_game(self, game_name, size): - self.game.change_game(game_name, size) - - def _shared_cb(self, activity): - _logger.debug('My activity was shared') - self.initiating = True - self._setup() - - for buddy in self._shared_activity.get_joined_buddies(): - pass # Can do stuff with newly acquired buddies here - - self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) - self._shared_activity.connect('buddy-left', self._buddy_left_cb) - - _logger.debug('This is my activity: making a tube...') - id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( - SERVICE, {}) - - def _setup(self): - if self._shared_activity is None: - _logger.error('Failed to share or join activity') - return - - bus_name, conn_path, channel_paths =\ - self._shared_activity.get_channels() - - # Work out what our room is called and whether we have Tubes already - room = None - tubes_chan = None - text_chan = None - for channel_path in channel_paths: - channel = telepathy.client.Channel(bus_name, channel_path) - htype, handle = channel.GetHandle() - if htype == telepathy.HANDLE_TYPE_ROOM: - _logger.debug('Found our room: it has handle#%d "%s"', - handle, self.conn.InspectHandles(htype, [handle])[0]) - room = handle - ctype = channel.GetChannelType() - if ctype == telepathy.CHANNEL_TYPE_TUBES: - _logger.debug('Found our Tubes channel at %s', channel_path) - tubes_chan = channel - elif ctype == telepathy.CHANNEL_TYPE_TEXT: - _logger.debug('Found our Text channel at %s', channel_path) - text_chan = channel - - if room is None: - _logger.error("Presence service didn't create a room") - return - if text_chan is None: - _logger.error("Presence service didn't create a text channel") - return - - # Make sure we have a Tubes channel - PS doesn't yet provide one - if tubes_chan is None: - _logger.debug("Didn't find our Tubes channel, requesting one...") - tubes_chan = self.conn.request_channel(telepathy.CHANNEL_TYPE_TUBES, - telepathy.HANDLE_TYPE_ROOM, room, True) - - self.tubes_chan = tubes_chan - self.text_chan = text_chan - - tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal('NewTube', - self._new_tube_cb) - - def _list_tubes_reply_cb(self, tubes): - for tube_info in tubes: - self._new_tube_cb(*tube_info) - - def _list_tubes_error_cb(self, e): - _logger.error('ListTubes() failed: %s', e) - - def _joined_cb(self, activity): - if not self._shared_activity: - return - - _logger.debug('Joined an existing shared activity') - - self.found = 0 - for buddy in self._shared_activity.get_joined_buddies(): - _logger.debug("buddy joined - _joined_cb: %s (get buddies of activity and add them to my list)", buddy.props.nick) - self.game.add_buddy(buddy) - if buddy == self.owner: - self.found = 1 - - if self.found == 0: - _logger.debug("buddy joined - _joined_cb: Not foud myself in buddy list - will add myself at end of the list.") - self.game.add_buddy(self.owner) - - self.initiating = False - self._setup() - - self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) - self._shared_activity.connect('buddy-left', self._buddy_left_cb) - - _logger.debug('This is not my activity: waiting for a tube...') - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( - reply_handler=self._list_tubes_reply_cb, - error_handler=self._list_tubes_error_cb) - - def _new_tube_cb(self, id, initiator, type, service, params, state): - _logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' - 'params=%r state=%d', id, initiator, type, service, - params, state) - - if (type == telepathy.TUBE_TYPE_DBUS and - service == SERVICE): - if state == telepathy.TUBE_STATE_LOCAL_PENDING: - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) - - self.tube_conn = TubeConnection(self.conn, - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], - id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) - - self.messenger = messenger.Messenger(self.tube_conn, self.initiating, self._get_buddy, self.game) - self.game.connect('flip-card-signal', self.messenger.flip) - self.game.connect('change_game_signal', self.messenger.change_game) - - def _get_buddy(self, cs_handle): - """Get a Buddy from a channel specific handle.""" - group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] - my_csh = group.GetSelfHandle() - if my_csh == cs_handle: - handle = self.conn.GetSelfHandle() - else: - handle = group.GetHandleOwners([cs_handle])[0] - assert handle != 0 - return self.pservice.get_buddy_by_telepathy_handle(self.tp_conn_name, - self.tp_conn_path, handle) - - def _buddy_joined_cb (self, activity, buddy): - if buddy <> self.owner: - if buddy.props.nick == '': - _logger.debug("buddy joined - _buddy_joined_cb: buddy name empty nick=%s. Will not add." %(buddy.props.nick)) - else: - _logger.debug("buddy joined - _buddy_joined_cb: %s", buddy.props.nick) - self.game.add_buddy(buddy) - - def _buddy_left_cb (self, activity, buddy): - if buddy.props.nick == '': - _logger.debug("buddy joined - _buddy_left_cb: buddy name empty nick=%s. Will not remove" %(buddy.props.nick)) - else: - _logger.debug("buddy left - _buddy_left_cb: %s", buddy.props.nick) - self.game.rem_buddy(buddy) - - def _focus_in(self, event, data=None): - if self.sound == 1: - pass - #self.game.cs.start() - #_logger.debug(" Memorize is visible: start csound server. ") - - def _focus_out(self, event, data=None): - if self.sound == 1: - pass - #self.game.cs.pause() - #_logger.debug(" Memorize is invisible: pause csound server. ") - - def _cleanup_cb(self, data=None): - if self.sound == 1: - pass - #self.game.cs.quit() - #_logger.debug(" Memorize closes: close csound server. ") + + def __init__(self, handle): + Activity.__init__(self, handle) + + self.play_load = False + self.play_mode = False + + toolbox = ActivityToolbox(self) + toolbox.connect('current-toolbar-changed', self.change_mode) + activity_toolbar = toolbox.get_activity_toolbar() + + self._createToolbar = createtoolbar.CreateToolbar(self) + toolbox.add_toolbar('Create', self._createToolbar) + self._createToolbar.show() + + self._memorizeToolbar = memorizetoolbar.MemorizeToolbar(self) + toolbox.add_toolbar(_('Play'), self._memorizeToolbar) + self._memorizeToolbar.show() + + self.set_toolbox(toolbox) + toolbox.show() + + self.cardlist = cardlist.CardList() + self.createcardpanel = createcardpanel.CreateCardPanel() + self.createcardpanel.connect('add-pair', self.cardlist.add_pair) + self.createcardpanel.connect('update-pair', self.cardlist.update_selected) + self.cardlist.connect('pair-selected', self.createcardpanel.load_pair) + self.cardlist.connect('update-create-toolbar', self._createToolbar.update_create_toolbar) + self.cardlist.connect('update-create-buttons', self._createToolbar.update_buttons_status) + self._createToolbar.connect('create_new_game', self.cardlist.clean_list) + self._createToolbar.connect('create_new_game', self.createcardpanel.clean) + self._createToolbar.connect('create_load_game', self.cardlist.load_game) + self._createToolbar.connect('create_save_game', self.cardlist.save_game) + self._createToolbar.connect('create_equal_pairs', self.createcardpanel.change_equal_pairs) + + self.hbox = gtk.HBox(False) + self.hbox.pack_start(self.createcardpanel) + self.hbox.pack_start(self.cardlist, False, False) + self.set_canvas(self.hbox) + + # create csound instance to play sound files + self.sound = 0 + try: + import csnd + del csnd + self.sound = 1 + except: + self.sound = 0 + + if self.sound == 1: + from csound.csoundserver import CsoundServer + cs = CsoundServer() + if cs.start() != 0: + self.sound = 0 + else: + cs.quit() + + # connect to the in/out events of the memorize activity + self.connect('focus_in_event', self._focus_in) + self.connect('focus_out_event', self._focus_out) + self.connect('destroy', self._cleanup_cb) + + # start on the game toolbar, might change this to the create toolbar later + self.toolbox.set_current_toolbar(_TOOLBAR_CREATE) + + # Get the Presence Service + self.pservice = presenceservice.get_instance() + try: + name, path = self.pservice.get_preferred_connection() + self.tp_conn_name = name + self.tp_conn_path = path + self.conn = telepathy.client.Connection(name, path) + except TypeError: + _logger.debug('Offline') + self.initiating = None + + # Buddy object for you + owner = self.pservice.get_owner() + self.owner = owner + self.current = 0 + # Owner.props.key + if self._shared_activity: + # We are joining the activity + self.toolbox.set_current_toolbar(_TOOLBAR_PLAY) + self.connect('joined', self._joined_cb) + if self.get_shared(): + # We've already joined + self._joined_cb() + else: + _logger.debug('buddy joined - __init__: %s', self.owner.props.nick) + #game_file = join(dirname(__file__),'demos','addition.zip') + #self.game.load_game(game_file, 4) + _logger.debug('loading conventional') + #self.game.add_buddy(self.owner) + self.show_all() + + def read_file(self, file_path): + ''' + if self.metadata['mime_type'] == 'plain/text': + f = open(file_path, 'r') + try: + data = pickle.load(f) + finally: + f.close() + + _logger.debug('reading from datastore') + + self.game.load_remote(data[0], data[1]) + self.game.set_wait_list(data[2]) + ''' + if self.metadata['mime_type'] == 'application/memorizegame': + self.toolbox.set_current_toolbar(_TOOLBAR_PLAY) + self.game.change_game(None, file_path, 4, 'file', self.metadata['title'], self.metadata['icon-color']) + + ''' + def write_file(self, file_path): + if not self.metadata['mime_type']: + self.metadata['mime_type'] = 'plain/text' + + if self.metadata['mime_type'] == 'plain/text': + + + data=[self.game.get_grid(), self.game.get_data(), self.game.get_players_data()] + + _logger.debug('writing to datastore') + f = open(file_path, 'w') + try: + pickle.dump(data, f) + finally: + f.close() + ''' + def change_mode(self, notebook, index): + if index != _TOOLBAR_CREATE: + if not self.play_load: + # Create play components + self.table = cardtable.CardTable() + self.scoreboard = scoreboard.Scoreboard() + self.game = game.MemorizeGame() + self.game.set_myself(self.owner) + self.hbox.remove(self.createcardpanel) + self.hbox.remove(self.cardlist) + self.hbox.pack_start(self.scoreboard, False, False) + self.hbox.pack_start(self.table) + + self.table.connect('key-press-event', self.table.key_press_event) + self.table.connect('card-flipped', self.game.card_flipped) + self.table.connect('card-highlighted', self.game.card_highlighted) + + self.game.connect('msg_buddy', self.scoreboard.set_buddy_message) + self.game.connect('reset_scoreboard', self.scoreboard.reset) + self.game.connect('reset_table', self.table.reset) + self.game.connect('load_game', self.table.load_game) + self.game.connect('load_mode', self.table.load_msg) + self.game.connect('change_game', self.table.change_game) + #self.game.connect('load_game', self._memorizeToolbar.update_toolbar) + #self.game.connect('change_game', self._memorizeToolbar.update_toolbar) + self.game.connect('set-border', self.table.set_border) + self.game.connect('flop-card', self.table.flop_card) + self.game.connect('flip-card', self.table.flip_card) + self.game.connect('highlight-card', self.table.highlight_card) + self.game.connect('add_buddy', self.scoreboard.add_buddy) + self.game.connect('rem_buddy', self.scoreboard.rem_buddy) + self.game.connect('increase-score', self.scoreboard.increase_score) + self.game.connect('wait_mode_buddy', self.scoreboard.set_wait_mode) + self.game.connect('change-turn', self.scoreboard.set_selected) + + self._memorizeToolbar.connect('game_changed', self.game.change_game) + self.connect('shared', self._shared_cb) + self.play_load = True + if not self._shared_activity: + self.game.add_buddy(self.owner) + #game_file = join(dirname(__file__), 'demos', 'addition.zip') + #self.game.load_game(game_file, 4) + else: + self.hbox.remove(self.createcardpanel) + self.hbox.remove(self.cardlist) + self.hbox.pack_start(self.scoreboard, False, False) + self.hbox.pack_start(self.table) + self.play_mode = True + else: + if self.play_mode: + self.hbox.remove(self.scoreboard) + self.hbox.remove(self.table) + self.hbox.pack_start(self.createcardpanel) + self.hbox.pack_start(self.cardlist, False, False) + self.play_mode = False + + def restart(self, widget): + self.game.reset() + + def change_game(self, game_name, size, title=None, color=None): + self.game.change_game(game_name, size, title, color) + + def _shared_cb(self, activity): + _logger.debug('My activity was shared') + self.initiating = True + self._setup() + + for buddy in self._shared_activity.get_joined_buddies(): + pass # Can do stuff with newly acquired buddies here + + self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) + self._shared_activity.connect('buddy-left', self._buddy_left_cb) + + _logger.debug('This is my activity: making a tube...') + id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( + SERVICE, {}) + + def _setup(self): + if self._shared_activity is None: + _logger.error('Failed to share or join activity') + return + + bus_name, conn_path, channel_paths =\ + self._shared_activity.get_channels() + + # Work out what our room is called and whether we have Tubes already + room = None + tubes_chan = None + text_chan = None + for channel_path in channel_paths: + channel = telepathy.client.Channel(bus_name, channel_path) + htype, handle = channel.GetHandle() + if htype == telepathy.HANDLE_TYPE_ROOM: + _logger.debug('Found our room: it has handle#%d "%s"', + handle, self.conn.InspectHandles(htype, [handle])[0]) + room = handle + ctype = channel.GetChannelType() + if ctype == telepathy.CHANNEL_TYPE_TUBES: + _logger.debug('Found our Tubes channel at %s', channel_path) + tubes_chan = channel + elif ctype == telepathy.CHANNEL_TYPE_TEXT: + _logger.debug('Found our Text channel at %s', channel_path) + text_chan = channel + + if room is None: + _logger.error("Presence service didn't create a room") + return + if text_chan is None: + _logger.error("Presence service didn't create a text channel") + return + + # Make sure we have a Tubes channel - PS doesn't yet provide one + if tubes_chan is None: + _logger.debug("Didn't find our Tubes channel, requesting one...") + tubes_chan = self.conn.request_channel(telepathy.CHANNEL_TYPE_TUBES, + telepathy.HANDLE_TYPE_ROOM, room, True) + + self.tubes_chan = tubes_chan + self.text_chan = text_chan + + tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal('NewTube', + self._new_tube_cb) + + def _list_tubes_reply_cb(self, tubes): + for tube_info in tubes: + self._new_tube_cb(*tube_info) + + def _list_tubes_error_cb(self, e): + _logger.error('ListTubes() failed: %s', e) + + def _joined_cb(self, activity): + if not self._shared_activity: + return + + _logger.debug('Joined an existing shared activity') + + self.found = 0 + for buddy in self._shared_activity.get_joined_buddies(): + _logger.debug("buddy joined - _joined_cb: %s (get buddies of activity and add them to my list)", buddy.props.nick) + self.game.add_buddy(buddy) + if buddy == self.owner: + self.found = 1 + + if self.found == 0: + _logger.debug("buddy joined - _joined_cb: Not foud myself in buddy list - will add myself at end of the list.") + self.game.add_buddy(self.owner) + + self.initiating = False + self._setup() + + self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) + self._shared_activity.connect('buddy-left', self._buddy_left_cb) + + _logger.debug('This is not my activity: waiting for a tube...') + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( + reply_handler=self._list_tubes_reply_cb, + error_handler=self._list_tubes_error_cb) + + def _new_tube_cb(self, id, initiator, type, service, params, state): + _logger.debug('New tube: ID=%d initator=%d type=%d service=%s ' + 'params=%r state=%d', id, initiator, type, service, + params, state) + + if (type == telepathy.TUBE_TYPE_DBUS and + service == SERVICE): + if state == telepathy.TUBE_STATE_LOCAL_PENDING: + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) + + self.tube_conn = TubeConnection(self.conn, + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], + id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) + + self.messenger = messenger.Messenger(self.tube_conn, self.initiating, self._get_buddy, self.game) + self.game.connect('flip-card-signal', self.messenger.flip_sender) + self.game.connect('change_game_signal', self.messenger.change_game) + + def _get_buddy(self, cs_handle): + """Get a Buddy from a channel specific handle.""" + group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] + my_csh = group.GetSelfHandle() + if my_csh == cs_handle: + handle = self.conn.GetSelfHandle() + else: + handle = group.GetHandleOwners([cs_handle])[0] + assert handle != 0 + return self.pservice.get_buddy_by_telepathy_handle(self.tp_conn_name, + self.tp_conn_path, handle) + + def _buddy_joined_cb (self, activity, buddy): + if buddy <> self.owner: + if buddy.props.nick == '': + _logger.debug("buddy joined - _buddy_joined_cb: buddy name empty nick=%s. Will not add." %(buddy.props.nick)) + else: + _logger.debug("buddy joined - _buddy_joined_cb: %s", buddy.props.nick) + self.game.add_buddy(buddy) + + def _buddy_left_cb (self, activity, buddy): + if buddy.props.nick == '': + _logger.debug("buddy joined - _buddy_left_cb: buddy name empty nick=%s. Will not remove" %(buddy.props.nick)) + else: + _logger.debug("buddy left - _buddy_left_cb: %s", buddy.props.nick) + self.game.rem_buddy(buddy) + + def _focus_in(self, event, data=None): + if self.sound == 1: + pass + #self.game.cs.start() + #_logger.debug(" Memorize is visible: start csound server. ") + + def _focus_out(self, event, data=None): + if self.sound == 1: + pass + #self.game.cs.pause() + #_logger.debug(" Memorize is invisible: pause csound server. ") + + def _cleanup_cb(self, data=None): + if self.sound == 1: + pass + #self.game.cs.quit() + #_logger.debug(" Memorize closes: close csound server. ") diff --git a/cardlist.py b/cardlist.py index 237d05d..35df613 100644 --- a/cardlist.py +++ b/cardlist.py @@ -1,25 +1,24 @@ #! /usr/bin/env python # -# Copyright (C) 2006, 2007, One Laptop Per Child +# Copyright (C) 2006, 2007, 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 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. +# 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. +# 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 gobject import logging from os.path import join import os @@ -27,278 +26,287 @@ import model import zipfile import tempfile import random +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT + from sugar import profile from sugar.datastore import datastore _logger = logging.getLogger('memorize-activity') class CardList(gtk.EventBox): - - __gsignals__ = { - 'pair-selected': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'update-create-toolbar': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'update-create-buttons': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - } - - def __init__(self): - gtk.EventBox.__init__(self) - self.model = model.Model(os.path.dirname(__file__)) - self.pairs = [] - self.current_pair = None - - self.set_size_request(450, 150) - 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_ALWAYS) - 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(os.path.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(os.path.join(self.model.data['pathimg'], game_pairs[key].props.bimg)) - else: - bimg = None - - asnd = os.path.join(self.data['pathsnd'],game_pairs[key].props.asnd) - bsnd = os.path.join(self.data['pathsnd'],game_pairs[key].props.bsnd) - - self.add_pair(None, game_pairs[key].props.achar, game_pairs[key].props.bchar, aimg, bimg, asnd, bsnd, False) - - def save_game(self, widget, game_name, equal_pairs, grouped): - - temp_folder = tempfile.mkdtemp() - temp_img_folder = join(temp_folder, 'images') - temp_snd_folder = join(temp_folder, 'sounds') + + __gsignals__ = { + 'pair-selected': (SIGNAL_RUN_FIRST, None, 6 * [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(os.path.dirname(__file__)) + self.pairs = [] + self.current_pair = None + + self.set_size_request(450, 150) + 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_ALWAYS) + 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(os.path.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(os.path.join(self.model.data['pathimg'], game_pairs[key].props.bimg)) + else: + bimg = None + + if game_pairs[key].props.asnd != None: + asnd = os.path.join(self.model.data['pathsnd'], game_pairs[key].props.asnd) + else: + asnd = None + + if game_pairs[key].props.bsnd != None: + bsnd = os.path.join(self.model.data['pathsnd'], game_pairs[key].props.bsnd) + else: + bsnd = None + + self.add_pair(None, game_pairs[key].props.achar, game_pairs[key].props.bchar, aimg, bimg, asnd, bsnd, False) + + def save_game(self, widget, game_name, equal_pairs, grouped): + + temp_folder = tempfile.mkdtemp() + temp_img_folder = join(temp_folder, 'images') + temp_snd_folder = join(temp_folder, 'sounds') - os.makedirs(temp_img_folder) - os.makedirs(temp_snd_folder) - - 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) + os.makedirs(temp_img_folder) + os.makedirs(temp_snd_folder) + + 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) - # 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'}) - zip.write(join(temp_img_folder, aimgfile), join('images', aimgfile)) - pair_card.set_property('aimg', aimgfile) + # 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'}) + 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'}) - 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)+'.wav' - else: - asndfile = 'asnd'+str(pair)+'.wav' - _logger.error(asndfile+': '+ asnd) - zip.write(asnd, join('sounds', asndfile)) - pair_card.set_property('asnd', asndfile) + # 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'}) + 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)+'.wav' + else: + asndfile = 'asnd'+str(pair)+'.wav' + _logger.error(asndfile+': '+ asnd) + 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)+'.wav' - else: - bsndfile = 'bsnd'+str(pair)+'.wav' - 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) - zip.write(join(temp_folder, 'game.xml'), 'game.xml') - zip.close() - - # Saves the zip in datastore - gameObject = datastore.create() - gameObject.metadata['title'] = game_name - gameObject.metadata['mime_type'] = 'application/memorizegame' - gameObject.metadata['icon-color'] = profile.get_color().to_string() - gameObject.file_path = join(temp_folder, 'game.zip') - datastore.write(gameObject) - - 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 add_pair(self, widget, achar, bchar, aimg, bimg, asnd, bsnd, show = True): - pair = Pair(achar, bchar, aimg, bimg, asnd, bsnd) - 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) - - def set_selected(self, widget, event): - if self.current_pair <> None: - self.old = self.current_pair - self.old.set_selected(False) - self.current_pair = widget - widget.set_selected(True) - self.emit('pair-selected', 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)) - - def update_selected(self, widget, newtext1, newtext2, aimg, bimg, asnd, bsnd): - self.current_pair.change_text(newtext1, newtext2) - self.current_pair.change_pixbuf(aimg, bimg) - self.current_pair.change_sound(asnd,bsnd) - - self.emit('update-create-buttons', True, True) - + # bsnd + bsnd = self.pairs[pair].get_sound(2) + if bsnd != None: + if equal_pairs: + bsndfile = 'snd'+str(pair)+'.wav' + else: + bsndfile = 'bsnd'+str(pair)+'.wav' + 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) + zip.write(join(temp_folder, 'game.xml'), 'game.xml') + zip.close() + + # Saves the zip in datastore + gameObject = datastore.create() + gameObject.metadata['title'] = game_name + gameObject.metadata['mime_type'] = 'application/memorizegame' + gameObject.metadata['icon-color'] = profile.get_color().to_string() + gameObject.file_path = join(temp_folder, 'game.zip') + datastore.write(gameObject) + + 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 add_pair(self, widget, achar, bchar, aimg, bimg, asnd, bsnd, show = True): + pair = Pair(achar, bchar, aimg, bimg, asnd, bsnd) + 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) + + def set_selected(self, widget, event): + if self.current_pair <> None: + self.old = self.current_pair + self.old.set_selected(False) + self.current_pair = widget + widget.set_selected(True) + self.emit('pair-selected', 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)) + + def update_selected(self, widget, newtext1, newtext2, aimg, bimg, asnd, bsnd): + self.current_pair.change_text(newtext1, newtext2) + self.current_pair.change_pixbuf(aimg, bimg) + self.current_pair.change_sound(asnd, bsnd) + + self.emit('update-create-buttons', True, True) + class Pair(gtk.EventBox): - - __gsignals__ = { - 'pair-selected': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - 'pair-closed': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - } - - def __init__(self, text1, text2 = None, aimg = None, bimg = None, asnd = None, bsnd = None): - gtk.EventBox.__init__(self) - self.bg_color = '#000000' - if text2 == None: - self.text2 = text1 - else: - self.text2 = text2 - self.text1 = text1 - - self.asnd = asnd - self.bsnd = bsnd - - self.current_game_key = None - - close_button = gtk.Button('X') - close_button.connect('button-press-event', self.emit_close) - table = gtk.Table() - table.connect('button-press-event', self.emit_selected) - table.set_col_spacings(0) - table.set_border_width(10) - self.bcard1 = svgcard.SvgCard(-1, {'front_text':{'card_text':text1, 'text_color':'#ffffff'}, 'front':{'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'}}, None, 184, 1, self.bg_color) - self.bcard2 = svgcard.SvgCard(-1, {'front_text':{'card_text':text2, 'text_color':'#ffffff'}, 'front':{'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'}}, None, 184, 1, self.bg_color) + + __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): + gtk.EventBox.__init__(self) + self.bg_color = '#000000' + if text2 == None: + self.text2 = text1 + else: + self.text2 = text2 + self.text1 = text1 + + self.asnd = asnd + self.bsnd = bsnd + + self.current_game_key = None + + close_button = gtk.Button('X') + close_button.connect('button-press-event', self.emit_close) + table = gtk.Table() + table.connect('button-press-event', self.emit_selected) + table.set_col_spacings(0) + table.set_border_width(10) + self.bcard1 = svgcard.SvgCard(-1, {'front_text':{'card_text':text1, 'text_color':'#ffffff'}, 'front':{'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'}}, None, 184, 1, self.bg_color) + self.bcard2 = svgcard.SvgCard(-1, {'front_text':{'card_text':text2, 'text_color':'#ffffff'}, 'front':{'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'}}, None, 184, 1, self.bg_color) - self.bcard1.flip() - self.bcard2.flip() - self.bcard1.set_pixbuf(aimg) - self.bcard2.set_pixbuf(bimg) - - table.attach(self.bcard1, 0, 1, 0, 8) - table.attach(self.bcard2, 1, 2, 0, 8) - table.attach(close_button, 2, 3, 0, 1, gtk.FILL, gtk.FILL) - - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color)) - self.add(table) - self.show_all() + self.bcard1.flip() + self.bcard2.flip() + self.bcard1.set_pixbuf(aimg) + self.bcard2.set_pixbuf(bimg) + + table.attach(self.bcard1, 0, 1, 0, 8) + table.attach(self.bcard2, 1, 2, 0, 8) + table.attach(close_button, 2, 3, 0, 1, gtk.FILL, gtk.FILL) + + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color)) + self.add(table) + self.show_all() - def emit_selected(self, widget, event): - self.emit('pair-selected', self) + def emit_selected(self, widget, event): + self.emit('pair-selected', self) - def emit_close(self, widget, event): - self.emit('pair-closed', self) + def emit_close(self, widget, event): + 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 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 get_text(self, card): - if card == 1: - return self.bcard1.get_text() - else: - return self.bcard2.get_text() - - 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 \ No newline at end of file + def change_sound(self, asnd, bsnd): + self.asnd = asnd + self.bsnd = bsnd + + def get_text(self, card): + if card == 1: + return self.bcard1.get_text() + else: + return self.bcard2.get_text() + + 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 \ No newline at end of file diff --git a/cardtable.py b/cardtable.py index a612647..28a2a4d 100755 --- a/cardtable.py +++ b/cardtable.py @@ -17,19 +17,21 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -import gtk, pygtk +import gtk +import pygtk +import pango import svgcard import os import time -import gobject import math import gc +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT class CardTable(gtk.EventBox): __gsignals__ = { - 'card-flipped': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT]), - 'card-highlighted': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT]), + 'card-flipped': (SIGNAL_RUN_FIRST, None, [int, TYPE_PYOBJECT]), + 'card-highlighted': (SIGNAL_RUN_FIRST, None, [int, TYPE_PYOBJECT]), } def __init__(self): @@ -46,7 +48,13 @@ class CardTable(gtk.EventBox): self.table.set_border_width(11) self.table.set_resize_mode(gtk.RESIZE_IMMEDIATE) self.set_property('child', self.table) - self.fist_load = True + self.load_message = gtk.Label('Loading Game') + self.load_message.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff')) + self.load_message.modify_font(pango.FontDescription("10")) + self.load_message.show() + self.first_load = True + self.load_mode = False + self.dict = None self.show_all() def load_game(self, widget, data, grid): @@ -67,11 +75,11 @@ class CardTable(gtk.EventBox): # Build the table if data['divided']=='1': - text1 = str(self.data.get('face1','')) - text2 = str(self.data.get('face2','')) + text1 = str(self.data.get('face1', '')) + text2 = str(self.data.get('face2', '')) else: - text1 = str(self.data.get('face','')) - text2 = str(self.data.get('face','')) + text1 = str(self.data.get('face', '')) + text2 = str(self.data.get('face', '')) x = 0 y = 0 @@ -79,7 +87,7 @@ class CardTable(gtk.EventBox): for card in self.cards_data: if card.get('img', None): - jpg = os.path.join(os.path.dirname(__file__), card['img']) + jpg = os.path.join(self.data['pathimg'], card['img']) else: jpg = None props = {} @@ -90,7 +98,8 @@ class CardTable(gtk.EventBox): elif card['ab']== 'b': props['back_text']= {'card_text':text2} - card = svgcard.SvgCard(id, props, jpg, self.card_size,self.data.get('align','1')) + align = self.data.get('align', '1') + card = svgcard.SvgCard(id, props, jpg, self.card_size, align) card.connect('enter-notify-event', self.mouse_event, [x, y]) card.connect("button-press-event", self.flip_card_mouse, id) self.table_positions[(x, y)]=1 @@ -105,17 +114,19 @@ class CardTable(gtk.EventBox): x = 0 y +=1 id += 1 - self.fist_load = False + self.first_load = False + if self.load_mode: + self._set_load_mode(False) + self.show_all() gc.collect() def change_game(self, widget, data, grid): - if not self.fist_load: + if not self.first_load: for card in self.cards.values(): self.table.remove(card) del card gc.collect() self.load_game(None, data, grid) - def get_card_size(self, size_table): x = (780 - (11*size_table))/size_table @@ -133,31 +144,31 @@ class CardTable(gtk.EventBox): x= self.selected_card[0] y= self.selected_card[1] - if event.keyval in (gtk.keysyms.Left, gtk.keysyms.KP_Left,gtk.keysyms.a): + if event.keyval in (gtk.keysyms.Left, gtk.keysyms.KP_Left): if self.table_positions.has_key((x-1, y)): card = self.cards[x-1, y] id = self.cd2id.get(card) self.emit('card-highlighted', id, False) - elif event.keyval in (gtk.keysyms.Right, gtk.keysyms.KP_Right,gtk.keysyms.d): + elif event.keyval in (gtk.keysyms.Right, gtk.keysyms.KP_Right): if self.table_positions.has_key((x+1, y)): card = self.cards[x+1, y] id = self.cd2id.get(card) self.emit('card-highlighted', id, False) - elif event.keyval in (gtk.keysyms.Up, gtk.keysyms.KP_Up,gtk.keysyms.w): + elif event.keyval in (gtk.keysyms.Up, gtk.keysyms.KP_Up): if self.table_positions.has_key((x, y-1)): card = self.cards[x, y-1] id = self.cd2id.get(card) self.emit('card-highlighted', id, False) - elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.KP_Down,gtk.keysyms.s): + elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.KP_Down): if self.table_positions.has_key((x, y+1)): card = self.cards[x, y+1] id = self.cd2id.get(card) self.emit('card-highlighted', id, False) - elif event.keyval in (gtk.keysyms.space,gtk.keysyms.KP_Page_Down): + elif event.keyval in (gtk.keysyms.space, gtk.keysyms.KP_Page_Down): card = self.cards[x, y] self.card_flipped(card) @@ -181,9 +192,28 @@ class CardTable(gtk.EventBox): self.id2cd.get(id).flip() def highlight_card(self, widget, id, status): - self.selected_card = self.dict.get(id) - self.id2cd.get(id).set_highlight(status) + if self.dict != None: + self.selected_card = self.dict.get(id) + self.id2cd.get(id).set_highlight(status) def reset(self, widget): for id in self.id2cd.keys(): self.id2cd[id].reset() + + def _set_load_mode(self,mode): + if mode: + self.remove(self.table) + self.set_property('child', self.load_message) + else: + self.remove(self.load_message) + self.set_property('child', self.table) + self.load_mode = mode + self.queue_draw() + while gtk.events_pending(): + gtk.main_iteration() + + def load_msg(self, widget, msg): + if not self.load_mode: + self._set_load_mode(True) + self.load_message.set_text(msg) + self.queue_draw() \ No newline at end of file diff --git a/createcardpanel.py b/createcardpanel.py index 5812d99..5f869e6 100644 --- a/createcardpanel.py +++ b/createcardpanel.py @@ -1,20 +1,20 @@ #! /usr/bin/env python # -# Copyright (C) 2006, 2007, One Laptop Per Child +# Copyright (C) 2006, 2007, 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 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. +# 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. +# 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 @@ -24,286 +24,286 @@ import tempfile from gettext import gettext as _ import svgcard import logging -import gobject +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT from xml.dom.minidom import parse from sugar.graphics.objectchooser import ObjectChooser _logger = logging.getLogger('memorize-activity') class CreateCardPanel(gtk.EventBox): - - __gsignals__ = { - 'add-pair': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'update-pair': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - } - - def __init__(self): - gtk.EventBox.__init__(self) - self.set_size_request(650, 320) - - self.equal_pairs = False - - # Set the add new pair buttom - add_icon = os.path.join(os.path.dirname(__file__), "images/pair-add.svg") - add_image = gtk.Image() - add_image.set_from_file(add_icon) - self._addbutton = gtk.Button(' ' + _('Add as new pair')) - self._addbutton.set_image(add_image) - self._addbutton.connect('button-press-event', self.emit_add_pair) - - # Set update selected pair buttom - update_icon = os.path.join(os.path.dirname(__file__), "images/pair-update.svg") - update_image = gtk.Image() - update_image.set_from_file(update_icon) - self._updatebutton = gtk.Button(' ' + _('Update selected pair')) - self._updatebutton.set_image(update_image) - self._updatebutton.connect('button-press-event', self.emit_update_pair) - - # Set card editors - self.cardeditor1 = CardEditor() - self.cardeditor2 = CardEditor() - self.clean(None) - self.cardeditor1.connect('has-text', self.receive_text_signals) - self.cardeditor2.connect('has-text', self.receive_text_signals) - self.cardeditor1.connect('has-picture', self.receive_picture_signals) - self.cardeditor2.connect('has-picture', self.receive_picture_signals) - - # Create table and add components to the table - self.table = gtk.Table() - self.table.set_homogeneous(False) - self.table.set_col_spacings(10) - self.table.set_row_spacings(10) - self.table.set_border_width(10) - self.table.attach(self.cardeditor1, 0, 2, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) - self.table.attach(self.cardeditor2, 2, 4, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) - self.table.attach(self._addbutton, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL, gtk.SHRINK) - self.table.attach(self._updatebutton, 2, 3, 1, 2, gtk.SHRINK|gtk.FILL, gtk.SHRINK) - self.add(self.table) - self.show_all() - - def emit_add_pair(self, widget, event): - if self.equal_pairs: - self.emit('add-pair', self.cardeditor1.get_text(), self.cardeditor1.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor1.get_snd()) - else: - self.emit('add-pair', self.cardeditor1.get_text(), self.cardeditor2.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor2.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor2.get_snd()) - self.clean(None) - + + __gsignals__ = { + 'add-pair': (SIGNAL_RUN_FIRST, None, 6 * [TYPE_PYOBJECT]), + 'update-pair': (SIGNAL_RUN_FIRST, None, 6 * [TYPE_PYOBJECT]), + } + + def __init__(self): + gtk.EventBox.__init__(self) + self.set_size_request(650, 320) + + self.equal_pairs = False + + # Set the add new pair buttom + add_icon = os.path.join(os.path.dirname(__file__), "images/pair-add.svg") + add_image = gtk.Image() + add_image.set_from_file(add_icon) + self._addbutton = gtk.Button(' ' + _('Add as new pair')) + self._addbutton.set_image(add_image) + self._addbutton.connect('button-press-event', self.emit_add_pair) + + # Set update selected pair buttom + update_icon = os.path.join(os.path.dirname(__file__), "images/pair-update.svg") + update_image = gtk.Image() + update_image.set_from_file(update_icon) + self._updatebutton = gtk.Button(' ' + _('Update selected pair')) + self._updatebutton.set_image(update_image) + self._updatebutton.connect('button-press-event', self.emit_update_pair) + + # Set card editors + self.cardeditor1 = CardEditor() + self.cardeditor2 = CardEditor() + self.clean(None) + self.cardeditor1.connect('has-text', self.receive_text_signals) + self.cardeditor2.connect('has-text', self.receive_text_signals) + self.cardeditor1.connect('has-picture', self.receive_picture_signals) + self.cardeditor2.connect('has-picture', self.receive_picture_signals) + + # Create table and add components to the table + self.table = gtk.Table() + self.table.set_homogeneous(False) + self.table.set_col_spacings(10) + self.table.set_row_spacings(10) + self.table.set_border_width(10) + self.table.attach(self.cardeditor1, 0, 2, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) + self.table.attach(self.cardeditor2, 2, 4, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) + self.table.attach(self._addbutton, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL, gtk.SHRINK) + self.table.attach(self._updatebutton, 2, 3, 1, 2, gtk.SHRINK|gtk.FILL, gtk.SHRINK) + self.add(self.table) + self.show_all() + + def emit_add_pair(self, widget, event): + if self.equal_pairs: + self.emit('add-pair', self.cardeditor1.get_text(), self.cardeditor1.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor1.get_snd()) + else: + self.emit('add-pair', self.cardeditor1.get_text(), self.cardeditor2.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor2.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor2.get_snd()) + self.clean(None) + - def emit_update_pair(self, widget, event): - if self.equal_pairs: - self.emit('update-pair', self.cardeditor1.get_text(), self.cardeditor1.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor1.get_snd()) - else: - self.emit('update-pair', self.cardeditor1.get_text(), self.cardeditor2.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor2.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor2.get_snd()) - self.clean(None) - - def load_pair(self, widget, newtext1, newtext2, aimg, bimg, asnd, bsnd): - self.cardeditor1.set_text(newtext1) - self.cardeditor2.set_text(newtext2) - self.cardeditor1.set_pixbuf(aimg) - self.cardeditor2.set_pixbuf(bimg) - self.cardeditor1.set_snd(asnd) - self.cardeditor2.set_snd(bsnd) - self._addbutton.set_sensitive(True) - self._updatebutton.set_sensitive(True) + def emit_update_pair(self, widget, event): + if self.equal_pairs: + self.emit('update-pair', self.cardeditor1.get_text(), self.cardeditor1.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor1.get_snd()) + else: + self.emit('update-pair', self.cardeditor1.get_text(), self.cardeditor2.get_text(), self.cardeditor1.get_pixbuf(), self.cardeditor2.get_pixbuf(), self.cardeditor1.get_snd(), self.cardeditor2.get_snd()) + self.clean(None) + + def load_pair(self, widget, newtext1, newtext2, aimg, bimg, asnd, bsnd): + self.cardeditor1.set_text(newtext1) + self.cardeditor2.set_text(newtext2) + self.cardeditor1.set_pixbuf(aimg) + self.cardeditor2.set_pixbuf(bimg) + self.cardeditor1.set_snd(asnd) + self.cardeditor2.set_snd(bsnd) + self._addbutton.set_sensitive(True) + self._updatebutton.set_sensitive(True) - def change_equal_pairs(self, widget, state): - self.equal_pairs = state - self.clean(None) - if self.equal_pairs: - self.table.remove(self.cardeditor1) - self.table.remove(self.cardeditor2) - self.table.attach(self.cardeditor1, 0, 4, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 200, 30) - else: - self.table.remove(self.cardeditor1) - self.table.attach(self.cardeditor1, 0, 2, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) - self.table.attach(self.cardeditor2, 2, 4, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) - - def clean(self, widget): - self.cardeditor1.clean() - self.cardeditor2.clean() - self._addbutton.set_sensitive(False) - self._updatebutton.set_sensitive(False) - self._card1_has_text = False - self._card2_has_text = False - self._card1_has_picture = False - self._card2_has_picture = False - - def receive_text_signals(self, widget, has_text): - if widget == self.cardeditor1: - self._card1_has_text = has_text - if widget == self.cardeditor2: - self._card2_has_text = has_text - self._update_buttom_status() - - def receive_picture_signals(self, widget, has_picture): - if widget == self.cardeditor1: - self._card1_has_picture = has_picture - if widget == self.cardeditor2: - self._card2_has_picture = has_picture - self._update_buttom_status() - - def _update_buttom_status(self): - if not self.equal_pairs: - if (self._card1_has_text or self._card1_has_picture) and (self._card2_has_text or self._card2_has_picture): - self._addbutton.set_sensitive(True) - self._updatebutton.set_sensitive(True) - else: - self._addbutton.set_sensitive(False) - self._updatebutton.set_sensitive(False) - else: - if self._card1_has_text or self._card1_has_picture: - self._addbutton.set_sensitive(True) - self._updatebutton.set_sensitive(True) - else: - self._addbutton.set_sensitive(False) - self._updatebutton.set_sensitive(False) - + def change_equal_pairs(self, widget, state): + self.equal_pairs = state + self.clean(None) + if self.equal_pairs: + self.table.remove(self.cardeditor1) + self.table.remove(self.cardeditor2) + self.table.attach(self.cardeditor1, 0, 4, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 200, 30) + else: + self.table.remove(self.cardeditor1) + self.table.attach(self.cardeditor1, 0, 2, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) + self.table.attach(self.cardeditor2, 2, 4, 0, 1, gtk.SHRINK|gtk.FILL, gtk.SHRINK, 10, 30) + + def clean(self, widget): + self.cardeditor1.clean() + self.cardeditor2.clean() + self._addbutton.set_sensitive(False) + self._updatebutton.set_sensitive(False) + self._card1_has_text = False + self._card2_has_text = False + self._card1_has_picture = False + self._card2_has_picture = False + + def receive_text_signals(self, widget, has_text): + if widget == self.cardeditor1: + self._card1_has_text = has_text + if widget == self.cardeditor2: + self._card2_has_text = has_text + self._update_buttom_status() + + def receive_picture_signals(self, widget, has_picture): + if widget == self.cardeditor1: + self._card1_has_picture = has_picture + if widget == self.cardeditor2: + self._card2_has_picture = has_picture + self._update_buttom_status() + + def _update_buttom_status(self): + if not self.equal_pairs: + if (self._card1_has_text or self._card1_has_picture) and (self._card2_has_text or self._card2_has_picture): + self._addbutton.set_sensitive(True) + self._updatebutton.set_sensitive(True) + else: + self._addbutton.set_sensitive(False) + self._updatebutton.set_sensitive(False) + else: + if self._card1_has_text or self._card1_has_picture: + self._addbutton.set_sensitive(True) + self._updatebutton.set_sensitive(True) + else: + self._addbutton.set_sensitive(False) + self._updatebutton.set_sensitive(False) + class CardEditor(gtk.EventBox): - - __gsignals__ = { - 'has-text': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - 'has-picture': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - } - - def __init__(self): - gtk.EventBox.__init__(self) - self.set_size_request(310, 320) + + __gsignals__ = { + 'has-text': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + 'has-picture': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + } + + def __init__(self): + gtk.EventBox.__init__(self) + self.set_size_request(310, 320) - self.temp_folder = tempfile.mkdtemp() - - table = gtk.Table() - self.previewlabel = gtk.Label(_('Preview:')) - self.previewlabel.set_alignment(1, 0.5) - self.textlabel = gtk.Label(_('Text:')) - self.textlabel.set_alignment(1, 0.5) - - picture_icon = os.path.join(os.path.dirname(__file__), 'images/import_picture.svg') - picture_image = gtk.Image() - picture_image.set_from_file(picture_icon) - self.browsepicture = gtk.Button() - self.browsepicture.set_image(picture_image) - self.browsepicture.connect('button-press-event', self._import_image) - - sound_icon = os.path.join(os.path.dirname(__file__), 'images/import_sound.svg') - sound_image = gtk.Image() - sound_image.set_from_file(sound_icon) - self.browsesound = gtk.Button() - self.browsesound.set_image(sound_image) - self.browsesound.connect('button-press-event', self._import_audio) - self.snd = None - self.textentry = gtk.Entry() - self.textentry.connect('changed', self.update_text) - - table.set_homogeneous(False) - table.set_col_spacings(10) - table.set_row_spacings(10) - table.set_border_width(10) - self.card = svgcard.SvgCard(-1, {'front_text':{'card_text':'', 'text_color':'#ffffff'}, 'front_border':{'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'}}, None, 184, 1, '#c0c0c0') - self.card.flip() - - table.attach(self.previewlabel, 0, 1, 1, 2, gtk.EXPAND, gtk.EXPAND) - table.attach(self.card, 1, 3, 1, 2, gtk.EXPAND, gtk.EXPAND, 10) - #Text label and entry - table.attach(self.textlabel, 0, 1, 2, 3, gtk.EXPAND|gtk.FILL, gtk.EXPAND) - table.attach(self.textentry, 1, 3, 2, 3, gtk.EXPAND|gtk.FILL, gtk.EXPAND) - #Picture label and entry - table.attach(self.browsepicture, 1, 2, 3, 4, gtk.EXPAND|gtk.FILL, gtk.EXPAND) - #Sound label and entry - table.attach(self.browsesound, 2, 3, 3, 4, gtk.EXPAND|gtk.FILL, gtk.EXPAND) - - self.add(table) - - def update_text(self, entry): - self.card.change_text(entry.get_text()) - if len(entry.get_text()) == 0: - self.emit('has-text', False) - else: - self.emit('has-text', True) - - def get_text(self): - return self.textentry.get_text() + self.temp_folder = tempfile.mkdtemp() + + table = gtk.Table() + self.previewlabel = gtk.Label(_('Preview:')) + self.previewlabel.set_alignment(1, 0.5) + self.textlabel = gtk.Label(_('Text:')) + self.textlabel.set_alignment(1, 0.5) + + picture_icon = os.path.join(os.path.dirname(__file__), 'images/import_picture.svg') + picture_image = gtk.Image() + picture_image.set_from_file(picture_icon) + self.browsepicture = gtk.Button() + self.browsepicture.set_image(picture_image) + self.browsepicture.connect('button-press-event', self._import_image) + + sound_icon = os.path.join(os.path.dirname(__file__), 'images/import_sound.svg') + sound_image = gtk.Image() + sound_image.set_from_file(sound_icon) + self.browsesound = gtk.Button() + self.browsesound.set_image(sound_image) + self.browsesound.connect('button-press-event', self._import_audio) + self.snd = None + self.textentry = gtk.Entry() + self.textentry.connect('changed', self.update_text) + + table.set_homogeneous(False) + table.set_col_spacings(10) + table.set_row_spacings(10) + table.set_border_width(10) + self.card = svgcard.SvgCard(-1, {'front_text':{'card_text':'', 'text_color':'#ffffff'}, 'front_border':{'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'}}, None, 184, 1, '#c0c0c0') + self.card.flip() + + table.attach(self.previewlabel, 0, 1, 1, 2, gtk.EXPAND, gtk.EXPAND) + table.attach(self.card, 1, 3, 1, 2, gtk.EXPAND, gtk.EXPAND, 10) + #Text label and entry + table.attach(self.textlabel, 0, 1, 2, 3, gtk.EXPAND|gtk.FILL, gtk.EXPAND) + table.attach(self.textentry, 1, 3, 2, 3, gtk.EXPAND|gtk.FILL, gtk.EXPAND) + #Picture label and entry + table.attach(self.browsepicture, 1, 2, 3, 4, gtk.EXPAND|gtk.FILL, gtk.EXPAND) + #Sound label and entry + table.attach(self.browsesound, 2, 3, 3, 4, gtk.EXPAND|gtk.FILL, gtk.EXPAND) + + self.add(table) + + def update_text(self, entry): + self.card.change_text(entry.get_text()) + if len(entry.get_text()) == 0: + self.emit('has-text', False) + else: + self.emit('has-text', True) + + def get_text(self): + return self.textentry.get_text() - def set_text(self, newtext): - if newtext == None: - newtext = '' - self.textentry.set_text(newtext) - - def get_pixbuf(self): - return self.card.get_pixbuf() - - def set_pixbuf(self, pixbuf): - self.card.set_pixbuf(pixbuf) - - def _import_image(self, widget, event): - chooser = ObjectChooser(_('Choose image'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - try: - result = chooser.run() - if result == gtk.RESPONSE_ACCEPT: - _logger.debug('ObjectChooser: %r' % chooser.get_selected_object()) - jobject = chooser.get_selected_object() - if jobject and jobject.file_path: - self._load_image(jobject.file_path) - finally: - chooser.destroy() - del chooser - - def _load_image(self, index): - pixbuf_t = gtk.gdk.pixbuf_new_from_file(index) - self.card.set_pixbuf(self.to_card_pixbuf(pixbuf_t)) - _logger.error('Picture Loaded: '+index) - self.emit('has-picture', True) - del pixbuf_t - - def _import_audio(self, widget, event): - chooser = ObjectChooser(_('Choose audio'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - jobject = '' - try: - result = chooser.run() - if result == gtk.RESPONSE_ACCEPT: - _logger.debug('ObjectChooser: %r' % chooser.get_selected_object()) - jobject = chooser.get_selected_object() - if not jobject or not jobject.file_path: - return - finally: - chooser.destroy() - del chooser - - if jobject and jobject.file_path: - self._load_audio(jobject.file_path) - - def _load_audio(self, index): - dst = os.path.join(self.temp_folder, os.path.basename(index)) - shutil.copy(index, dst) - self.set_snd(dst) - _logger.error('Audio Loaded: '+dst) - - def set_snd(self, snd): - self.snd = snd - - def get_snd(self): - return self.snd + def set_text(self, newtext): + if newtext == None: + newtext = '' + self.textentry.set_text(newtext) + + def get_pixbuf(self): + return self.card.get_pixbuf() + + def set_pixbuf(self, pixbuf): + self.card.set_pixbuf(pixbuf) + + def _import_image(self, widget, event): + chooser = ObjectChooser(_('Choose image'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + _logger.debug('ObjectChooser: %r' % chooser.get_selected_object()) + jobject = chooser.get_selected_object() + if jobject and jobject.file_path: + self._load_image(jobject.file_path) + finally: + chooser.destroy() + del chooser + + def _load_image(self, index): + pixbuf_t = gtk.gdk.pixbuf_new_from_file(index) + self.card.set_pixbuf(self.to_card_pixbuf(pixbuf_t)) + _logger.error('Picture Loaded: '+index) + self.emit('has-picture', True) + del pixbuf_t + + def _import_audio(self, widget, event): + chooser = ObjectChooser(_('Choose audio'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + jobject = '' + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + _logger.debug('ObjectChooser: %r' % chooser.get_selected_object()) + jobject = chooser.get_selected_object() + if not jobject or not jobject.file_path: + return + finally: + chooser.destroy() + del chooser + + if jobject and jobject.file_path: + self._load_audio(jobject.file_path) + + def _load_audio(self, index): + dst = os.path.join(self.temp_folder, os.path.basename(index)) + shutil.copy(index, dst) + self.set_snd(dst) + _logger.error('Audio Loaded: '+dst) + + def set_snd(self, snd): + self.snd = snd + + def get_snd(self): + return self.snd - def clean(self): - self.textentry.set_text('') - self.card.set_pixbuf(None) - self.emit('has-text', False) - self.emit('has-picture', False) - - def to_card_pixbuf(self, pixbuf): - if pixbuf.get_width() == pixbuf.get_height(): - new = pixbuf_t.scale_simple(162, 162, gtk.gdk.INTERP_BILINEAR) - elif pixbuf.get_width() > pixbuf.get_height(): - new = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 162, 162) - aspect = float(pixbuf.get_width()) / float(pixbuf.get_height()) - pixbuf_t = pixbuf.scale_simple(int(float(162)*aspect) , 162, gtk.gdk.INTERP_BILINEAR) - diff = pixbuf_t.get_width() - pixbuf_t.get_height() - pixbuf_t.scale(new, 0, 0, 162, 162, -(diff/2), 0, 1, 1, gtk.gdk.INTERP_BILINEAR) - del pixbuf_t - elif pixbuf.get_width() < pixbuf.get_height(): - new = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 162, 162) - aspect = float(pixbuf.get_height()) / float(pixbuf.get_width()) - pixbuf_t = pixbuf.scale_simple(162 , int(float(162)*aspect), gtk.gdk.INTERP_BILINEAR) - diff = pixbuf_t.get_height() - pixbuf_t.get_width() - pixbuf_t.scale(new, 0, 0, 162, 162, 0, -(diff/2), 1, 1, gtk.gdk.INTERP_BILINEAR) - del pixbuf_t - return new \ No newline at end of file + def clean(self): + self.textentry.set_text('') + self.card.set_pixbuf(None) + self.emit('has-text', False) + self.emit('has-picture', False) + + def to_card_pixbuf(self, pixbuf): + if pixbuf.get_width() == pixbuf.get_height(): + new = pixbuf_t.scale_simple(162, 162, gtk.gdk.INTERP_BILINEAR) + elif pixbuf.get_width() > pixbuf.get_height(): + new = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 162, 162) + aspect = float(pixbuf.get_width()) / float(pixbuf.get_height()) + pixbuf_t = pixbuf.scale_simple(int(float(162)*aspect) , 162, gtk.gdk.INTERP_BILINEAR) + diff = pixbuf_t.get_width() - pixbuf_t.get_height() + pixbuf_t.scale(new, 0, 0, 162, 162, -(diff/2), 0, 1, 1, gtk.gdk.INTERP_BILINEAR) + del pixbuf_t + elif pixbuf.get_width() < pixbuf.get_height(): + new = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 162, 162) + aspect = float(pixbuf.get_height()) / float(pixbuf.get_width()) + pixbuf_t = pixbuf.scale_simple(162 , int(float(162)*aspect), gtk.gdk.INTERP_BILINEAR) + diff = pixbuf_t.get_height() - pixbuf_t.get_width() + pixbuf_t.scale(new, 0, 0, 162, 162, 0, -(diff/2), 1, 1, gtk.gdk.INTERP_BILINEAR) + del pixbuf_t + return new \ No newline at end of file diff --git a/createtoolbar.py b/createtoolbar.py index 385dc99..4d64989 100755 --- a/createtoolbar.py +++ b/createtoolbar.py @@ -22,7 +22,7 @@ from gettext import gettext as _ import gtk import os -import gobject +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT from sugar.graphics.toolbutton import ToolButton from sugar.graphics.toggletoolbutton import ToggleToolButton @@ -33,10 +33,10 @@ class CreateToolbar(gtk.Toolbar): __gtype_name__ = 'CreateToolbar' __gsignals__ = { - 'create_new_game': (gobject.SIGNAL_RUN_FIRST, None, []), - 'create_load_game': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - 'create_save_game': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'create_equal_pairs': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), + 'create_new_game': (SIGNAL_RUN_FIRST, None, []), + 'create_load_game': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + 'create_save_game': (SIGNAL_RUN_FIRST, None, 3 * [TYPE_PYOBJECT]), + 'create_equal_pairs': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), } def __init__(self, activity): @@ -110,7 +110,7 @@ class CreateToolbar(gtk.Toolbar): def _game_changed_cb(self, combobox, game_name): self.game_name_entry.set_text(game_name) - self.emit('create_load_game',game_name) + self.emit('create_load_game', game_name) def _load_game(self, button): chooser = ObjectChooser(_('Choose memorize game'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) @@ -127,7 +127,7 @@ class CreateToolbar(gtk.Toolbar): del chooser if jobject and jobject.file_path: - self.emit('create_load_game',jobject.file_path) + self.emit('create_load_game', jobject.file_path) self._save_button.set_sensitive(False) def _new_game_bt(self, button): @@ -139,14 +139,14 @@ class CreateToolbar(gtk.Toolbar): self._save_button.set_sensitive(False) def _save_game_bt(self, button): - self.emit('create_save_game',self.game_name_entry.get_text(), self._equal_pairs.get_active(), self._grouped.get_active()) + self.emit('create_save_game', self.game_name_entry.get_text(), self._equal_pairs.get_active(), self._grouped.get_active()) self._save_button.set_sensitive(False) - def _emit_equal_pairs(self,checkbutton): - self.emit('create_equal_pairs',checkbutton.get_active()) + def _emit_equal_pairs(self, checkbutton): + self.emit('create_equal_pairs', checkbutton.get_active()) self._save_button.set_sensitive(True) - def _grouped_cb(self,widget): + def _grouped_cb(self, widget): self._save_button.set_sensitive(True) if self._grouped.get_active(): self._grouped.set_icon_widget(self._grouped_image2) diff --git a/game.py b/game.py index 1f0357d..0a867fb 100755 --- a/game.py +++ b/game.py @@ -17,43 +17,44 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -import os import logging import gobject +from os.path import join, dirname from sugar import profile from dbus.service import method, signal from dbus.gobject_service import ExportedGObject - -import gobject +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT, GObject, timeout_add from model import Model _logger = logging.getLogger('memorize-activity') -SERVICE = "org.laptop.Memorize" +SERVICE = 'org.laptop.Memorize' IFACE = SERVICE -PATH = "/org/laptop/Memorize" +PATH = '/org/laptop/Memorize' -class MemorizeGame(gobject.GObject): +class MemorizeGame(GObject): __gsignals__ = { - 'reset_scoreboard': (gobject.SIGNAL_RUN_FIRST, None, []), - 'reset_table': (gobject.SIGNAL_RUN_FIRST, None, []), - 'load_game': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'change_game': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'change_game_signal': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'set-border': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'flip-card': (gobject.SIGNAL_RUN_FIRST, None, [int]), - 'flip-card-signal': (gobject.SIGNAL_RUN_FIRST, None, [int]), - 'flop-card': (gobject.SIGNAL_RUN_FIRST, None, [int]), - 'highlight-card': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT]), - 'add_buddy': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, int]), - 'rem_buddy': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - 'increase-score': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), - 'wait_mode_buddy': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]), - 'change-turn': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]), + 'reset_scoreboard': (SIGNAL_RUN_FIRST, None, []), + 'reset_table': (SIGNAL_RUN_FIRST, None, []), + 'load_mode': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + 'load_game': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]), + 'change_game': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]), + 'change_game_signal': (SIGNAL_RUN_FIRST, None, 5 * [TYPE_PYOBJECT]), + 'set-border': (SIGNAL_RUN_FIRST, None, 3 * [TYPE_PYOBJECT]), + 'flip-card': (SIGNAL_RUN_FIRST, None, [int]), + 'flip-card-signal': (SIGNAL_RUN_FIRST, None, [int]), + 'flop-card': (SIGNAL_RUN_FIRST, None, [int]), + 'highlight-card': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]), + 'add_buddy': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]), + 'rem_buddy': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + 'increase-score': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + 'wait_mode_buddy': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]), + 'msg_buddy': (SIGNAL_RUN_FIRST, None, 2 * [TYPE_PYOBJECT]), + 'change-turn': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), } def __init__(self): @@ -65,10 +66,10 @@ class MemorizeGame(gobject.GObject): self.current_player = None self.last_flipped = -1 self.last_highlight = 1 - self.game_dir = os.path.join(os.path.dirname(__file__), 'games') + self.game_dir = join(dirname(__file__), 'games') self.messenger = None self.sentitive = True - self.model = Model(os.path.dirname(__file__)) + self.model = Model(dirname(__file__)) self.flip_block = False # create csound instance to play sound files @@ -87,17 +88,40 @@ class MemorizeGame(gobject.GObject): if self.cs.start() != 0: _logger.error(' Error starting csound performance.') self.sound = 0 - - def load_game(self, game_name, size): - + def load_game(self, game_name, size): + self.set_load_mode('Loading game') if self.model.read(game_name) == 0: self.model.def_grid(size) self.model.data['running'] = 'False' - logging.debug(' Read setup file %s: %s '%(game_name, self.model.grid)) + logging.debug(' Read setup file %s: %s '%(game_name, self.model.grid)) self.emit('load_game', self.model.data, self.model.grid) else: logging.error(' Reading setup file %s'%game_name) + + def load_remote(self, grid, data, mode, signal = False): + self.set_load_mode('Loading game...') + self.model.grid = grid + self.model.data = data + self.emit('reset_scoreboard') + if not signal: + self.emit('change_game_signal', mode, self.get_grid(), self.get_data(), self.waiting_players, self.model.data['game_file']) + self.emit('change_game', self.get_data(), self.get_grid()) + for buddy in self.players: + self.players_score[buddy] = 0 + self.current_player = None + self.last_flipped = -1 + self.last_highlight = 1 + self.change_turn() + self.model.data['running'] = 'False' + for card in self.model.grid: + if card['state'] == '1': + self.emit('flip-card', self.model.grid.index(card)) + self.last_flipped = self.model.grid.index(card) + elif card['state'] != '0': + stroke_color, fill_color = card['state'].split(',') + self.emit('flip-card', self.model.grid.index(card)) + self.emit('set-border', self.model.grid.index(card), stroke_color, fill_color) def add_buddy(self, buddy, score = 0): _logger.debug('Buddy %r was added to game', buddy.props.nick) @@ -112,16 +136,19 @@ class MemorizeGame(gobject.GObject): def rem_buddy(self, buddy): _logger.debug('Buddy %r was removed from game', buddy.props.nick) - index = self.players.index(buddy) + if self.current_player == buddy and len(self.players) >= 2: + self.change_turn() + index = self.players.index(buddy) del self.players[index] del (self.players_score[buddy]) - if self.current_player == buddy and len(self.players) >= 2: ### fix from <> 0 - self.change_turn() self.emit('rem_buddy', buddy) + + def buddy_message(self, buddy, text): + self.emit('msg_buddy', buddy, text) def change_turn(self): - if len(self.players) == 0: - return + if len(self.players) <= 1: + self.current_player = self.players[0] if self.current_player == None: self.current_player = self.players[0] elif self.current_player == self.players[-1]: @@ -152,12 +179,13 @@ class MemorizeGame(gobject.GObject): if self.sound == 1: snd = self.model.grid[id].get('snd', None) if snd != None: + sound_file = join(self.model.data.get('pathsnd'),snd) if len(snd.split('.')) > 1: if snd.split('.')[1] in ['wav', 'aif', 'aiff']: - self.cs.perform('i 102 0.0 3.0 "%s" 1 0.9 0'%(os.path.join(os.path.dirname(__file__), snd))) - else: - self.cs.perform('i 100 0.0 3.0 "%s" 1 0.9 0'%(os.path.join(os.path.dirname(__file__), snd))) - _logger.debug('Audio: play sound=%s'%snd) + self.cs.perform('i 102 0.0 3.0 "%s" 1 0.9 0'%(sound_file)) + else: + self.cs.perform('i 100 0.0 3.0 "%s" 1 0.9 0'%(sound_file)) + _logger.debug('Audio: play sound=%s'%sound_file) # First card case if self.last_flipped == -1: @@ -190,7 +218,7 @@ class MemorizeGame(gobject.GObject): if not signal: self.emit('flip-card-signal', id) self.model.grid[id]['state'] = '1' - gobject.timeout_add(2000, self.flop_card, id, widget) + timeout_add(2000, self.flop_card, id, widget) def flop_card(self, id, widget): self.emit('flop-card', id) @@ -235,12 +263,21 @@ class MemorizeGame(gobject.GObject): def get_data(self): return self.model.data - def change_game(self, game_name, size): - if self.model.read(game_name) == 0: - self.model.def_grid(size) - self.load_remote(self.model.grid, self.model.data, False) - else: - logging.error(' Reading setup file %s'%game_name) + def change_game(self, widget, game_name, size, mode, title = None, color= None): + if mode in ['file','demo']: + if self.model.read(game_name) != 0: + logging.error(' Reading setup file %s'%game_name) + return + #elif mode in ['reset','size']: + if size == None: + size = int(self.model.data['size']) + self.model.def_grid(size) + + if title != None: + self.model.data['title'] = title + if color != None: + self.model.data['color'] = color + self.load_remote(self.model.grid, self.model.data, mode, False) def reset_game(self, size = None): if size == None: @@ -248,29 +285,9 @@ class MemorizeGame(gobject.GObject): self.model.def_grid(size) self.load_remote(self.model.grid, self.model.data, False) - def load_remote(self, grid, data, signal = False): - self.model.grid = grid - self.model.data = data - self.emit('reset_scoreboard') - self.emit('change_game', self.get_data(), self.get_grid()) - if not signal: - self.emit('change_game_signal', self.get_grid(), self.get_data(), self.waiting_players) - for buddy in self.players: - self.players_score[buddy] = 0 - self.current_player = None - self.last_flipped = -1 - self.last_highlight = 1 - self.change_turn() - self.model.data['running'] = 'False' - for card in self.model.grid: - if card['state'] == '1': - self.emit('flip-card', self.model.grid.index(card)) - self.last_flipped = self.model.grid.index(card) - elif card['state'] != '0': - stroke_color, fill_color = card['state'].split(',') - self.emit('flip-card', self.model.grid.index(card)) - self.emit('set-border',self.model.grid.index(card), stroke_color, fill_color) - + def set_load_mode(self, msg): + self.emit('load_mode', msg) + def set_messenger(self, messenger): self.messenger = messenger @@ -288,8 +305,8 @@ class MemorizeGame(gobject.GObject): def get_players_data(self): data = [] - for player,score in self.players_score.items(): - data.append([player.props.key,player.props.nick,player.props.color,score]) + for player, score in self.players_score.items(): + data.append([player.props.key, player.props.nick, player.props.color, score]) return data def set_wait_list(self, list): @@ -304,17 +321,17 @@ class MemorizeGame(gobject.GObject): def set_myself(self, buddy): self.myself = buddy - def add_to_waiting_list(self,buddy): + def add_to_waiting_list(self, buddy): self.players.remove(buddy) self.waiting_players.append(buddy) - self.emit('wait_mode_buddy',buddy,True) + self.emit('wait_mode_buddy', buddy, True) - def rem_to_waiting_list(self,buddy): + def rem_to_waiting_list(self, buddy): self.waiting_players.remove(buddy) self.players.append(buddy) - self.emit('wait_mode_buddy',buddy,False) + self.emit('wait_mode_buddy', buddy, False) - def load_waiting_list(self,list): + def load_waiting_list(self, list): for buddy in list: self.add_to_waiting_list(buddy) diff --git a/memorizetoolbar.py b/memorizetoolbar.py index 68b7d1c..015ac47 100755 --- a/memorizetoolbar.py +++ b/memorizetoolbar.py @@ -18,13 +18,14 @@ # import gtk -import os +from os.path import join, dirname from gettext import gettext as _ from sugar.graphics.toolbutton import ToolButton from sugar.graphics.toolcombobox import ToolComboBox from sugar.graphics.objectchooser import ObjectChooser import logging +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT _logger = logging.getLogger('memorize-activity') @@ -34,14 +35,18 @@ class MemorizeToolbar(gtk.Toolbar): standard_game_names = ['Load demo games', 'addition', 'capitals', 'drumgit', 'letters', 'numbers', 'phonemes'] translated_game_names = [_('Load demo games'), _('addition'), _('capitals'), _('drumgit'), _('letters'), _('numbers'), _('phonemes')] + __gsignals__ = { + 'game_changed': (SIGNAL_RUN_FIRST, None, 5 * [TYPE_PYOBJECT]) + } + def __init__(self, activity): gtk.Toolbar.__init__(self) self.activity = activity self._lock = True - + self.jobject = None # Reset Button - restart_icon = os.path.join(os.path.dirname(__file__), "images/game-restart.svg") + restart_icon = join(dirname(__file__), 'images', 'game-restart.svg') restart_image = gtk.Image() restart_image.set_from_file(restart_icon) self._restart_button = ToolButton() @@ -52,7 +57,7 @@ class MemorizeToolbar(gtk.Toolbar): self._restart_button.show() # Load Button - load_icon = os.path.join(os.path.dirname(__file__), "images/game-load.svg") + load_icon = join(dirname(__file__), 'images', 'game-load.svg') load_image = gtk.Image() load_image.set_from_file(load_icon) self._load_button = ToolButton() @@ -97,7 +102,7 @@ class MemorizeToolbar(gtk.Toolbar): tool_item.show() def _game_reset_cb(self, widget): - self.activity.game.reset_game() + self.emit('game_changed', None, None, 'reset', None, None) def _load_game(self, button): chooser = ObjectChooser(_('Choose memorize game'), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) @@ -113,23 +118,30 @@ class MemorizeToolbar(gtk.Toolbar): chooser.destroy() del chooser - if jobject and jobject.file_path: - self.activity.change_game(jobject.file_path, 4) + if jobject and jobject.file_path: + title = jobject.metadata['title'] + color = jobject.metadata['icon-color'] + self.emit('game_changed', jobject.file_path, 4, 'file', title, color) + + if self.jobject != None: + self.jobject.destroy() + self.jobject = jobject def _game_size_cb(self, widget): game_size = int(self._sizes[self._size_combo.combo.get_active()][0]) - self.activity.game.reset_game(game_size) + self.emit('game_changed', None, game_size, 'size', None, None) def _game_changed_cb(self, combobox): if combobox.get_active() == 0: return if not self._lock: game_name = self.standard_game_names[self._game_combo.combo.get_active()] - game_file = os.path.join(os.path.dirname(__file__),'demos',game_name+'.zip') + game_file = join(dirname(__file__), 'demos', game_name+'.zip') game_size = int(self._sizes[self._size_combo.combo.get_active()][0]) if game_name in self.translated_game_names: index = self.translated_game_names.index(game_name) game_name = self.standard_game_names[index] - self.activity.change_game(game_file, game_size) + self.emit('game_changed', game_file, game_size, 'demo', None, None) + #self.activity.change_game(game_file, game_size) self._game_combo.combo.set_active(0) def update_toolbar(self, widget, data, grid): diff --git a/messenger.py b/messenger.py index f23dcf9..e66e115 100644 --- a/messenger.py +++ b/messenger.py @@ -18,14 +18,17 @@ # import logging -import dbus +_logger = logging.getLogger('memorize-activity') + +import tempfile +from os.path import join, getsize, isfile, dirname, basename +from dbus.service import method, signal from dbus.gobject_service import ExportedGObject +from sugar.datastore import datastore -SERVICE = "org.laptop.Memorize" +SERVICE = 'org.laptop.Memorize' IFACE = SERVICE -PATH = "/org/laptop/Memorize" - -_logger = logging.getLogger('memorize-activity') +PATH = '/org/laptop/Memorize' class Messenger(ExportedGObject): @@ -38,81 +41,171 @@ class Messenger(ExportedGObject): self.ordered_bus_names = [] self.entered = False self._tube.watch_participants(self.participant_change_cb) + self.files = {} def participant_change_cb(self, added, removed): - _logger.debug('Participants change add=%s rem=%s' %(added, removed)) - if not self.entered: - self._tube.add_signal_receiver(self._flip_receiver, '_flip_signal', IFACE, path=PATH, sender_keyword='sender') - self._tube.add_signal_receiver(self._change_game_receiver, '_change_game_signal', IFACE, path=PATH, sender_keyword='sender') + self._flip_handler() + self._change_game_handler() + self._file_part_handler() if self.is_initiator: - _logger.debug('Initialising a new game, I am %s .', self._tube.get_unique_name()) self.player_id = self._tube.get_unique_name() self.ordered_bus_names = [self.player_id] - self._tube.add_signal_receiver(self._hello_receiver, '_hello_signal', IFACE, path=PATH, sender_keyword='sender') + self._hello_handler() else: self._hello_signal() self.entered = True - - @dbus.service.signal(IFACE, signature='') + + # hello methods + + @signal(IFACE, signature='') def _hello_signal(self): - ''' Notify current players that you joined ''' - _logger.debug('Sending hello to all') + pass + + def _hello_handler(self): + self._tube.add_signal_receiver(self._hello_receiver, + '_hello_signal', + IFACE, + path=PATH, + sender_keyword='sender') def _hello_receiver(self, sender=None): - ''' Someone joined the game, so sync the new player ''' - _logger.debug('The new player %s has joined', sender) self.ordered_bus_names.append(sender) - _logger.debug('The grid to send: %s', self.game.get_grid()) - _logger.debug('The data to send: %s', self.game.get_data()) - self._tube.get_object(sender, PATH).load_game(self.ordered_bus_names, self.game.get_grid(), self.game.get_data(), self.game.players.index(self.game.current_player), self.game.waiting_players, dbus_interface=IFACE) - _logger.debug('Sent the game state') + data = self.game.model.data + path = data['game_file'] + title = data.get('title', 'Received game') + color = data.get('color', '#ff00ff,#00ff00') + self.file_sender(path, title, color) + + remote_object = self._tube.get_object(sender, PATH) + remote_object.load_game(self.ordered_bus_names, + self.game.get_grid(), + self.game.get_data(), + self.game.players.index(self.game.current_player), + #self.game.waiting_players, + path) - @dbus.service.method(dbus_interface=IFACE, in_signature='asaa{ss}a{ss}nav', out_signature='') - def load_game(self, bus_names, grid, data, current_player, list): - ''' Sync the game with with players ''' - _logger.debug('Data received to sync game data') - _logger.debug('grid %s '%grid) + @method(dbus_interface=IFACE, in_signature='asaa{ss}a{ss}ns', out_signature='', byte_arrays=True) + def load_game(self, bus_names, grid, data, current_player, path): self.ordered_bus_names = bus_names self.player_id = bus_names.index(self._tube.get_unique_name()) - self.game.load_remote(grid, data, True) - self.game.load_waiting_list(list) - _logger.debug('Current player id=%d' %current_player) + #self.game.load_waiting_list(list) self.game.current_player = self.game.players[current_player] + self._change_game_receiver('file', grid, data, path) + + # Change game method + + def change_game(self, sender, mode, grid, data, waiting_list, zip): + path = self.game.model.data['game_file'] + title = data.get('title', 'Received game') + color = data.get('color', '') + if mode == 'file': + self.file_sender(path, title, color) + self._change_game_signal(mode, grid, data, path) + + def _change_game_handler(self): + self._tube.add_signal_receiver(self._change_game_receiver, + '_change_game_signal', + IFACE, path=PATH, + sender_keyword='sender', + byte_arrays=True) + + @signal(IFACE, signature='saa{ss}a{ss}s') + def _change_game_signal(self, mode, grid, data, path): + pass + + def _change_game_receiver(self, mode, grid, data, path, sender=None): + # ignore my own signal + if sender == self._tube.get_unique_name(): + return + if mode == 'demo': + game_name = self.game.model.data['key'] + game_file = join(dirname(__file__), 'demos', game_name+'.zip') + self.game.model.read(game_file) + if mode == 'file': + self.game.model.read(self.files[path]) + data['path'] = self.game.model.data['path'] + data['pathimg'] = self.game.model.data['pathimg'] + data['pathsnd'] = self.game.model.data['pathsnd'] + if mode == 'demo': + self.game.load_remote(grid, data, mode, True) + else: + self.game.load_remote(grid, data, mode, True) + + # File transfer methods + + def file_sender(self, filename, title, color): + size = getsize(filename) + f = open(filename, 'r+b') + part_size = 4096 + num_parts = (size / part_size) +1 + for part in range(num_parts): + bytes = f.read(part_size) + self._file_part_signal(filename, part+1, num_parts, bytes, title, color) + f.close() + + @signal(dbus_interface=IFACE, signature='suuayss') + def _file_part_signal(self, filename, part, numparts, bytes, title, color): + pass + + def _file_part_handler(self): + self._tube.add_signal_receiver(self._file_part_receiver, + '_file_part_signal', + IFACE, + path=PATH, + sender_keyword='sender', + byte_arrays=True) + + def _file_part_receiver(self, filename, part, numparts, bytes, title=None, color=None, sender=None): + # ignore my own signal + if sender == self._tube.get_unique_name(): + return - def flip(self, widget, id): - ''' Notify other players that you flipped a card ''' - _logger.debug('Sending flip message: '+str(id)) + # first chunk + if part == 1: + temp_dir = tempfile.mkdtemp() + self.temp_file = join(temp_dir, 'game.zip') + self.files[filename] = self.temp_file + self.f = open(self.temp_file, 'a+b') + + self.f.write(bytes) + + percentage = int(float(part) / float(numparts) * 100.0) + self.game.set_load_mode('Receiving game: '+str(percentage)+'% done.') + + # last chunk + if part == numparts: + self.f.close() + #file = self.files[filename] + # Saves the zip in datastore + gameObject = datastore.create() + gameObject.metadata['title'] = title + gameObject.metadata['mime_type'] = 'application/memorizegame' + gameObject.metadata['icon-color'] = color + gameObject.file_path = self.temp_file + datastore.write(gameObject) + #gameObject.destroy() + + + # flip card methods + + def flip_sender(self, widget, id): self._flip_signal(id) - @dbus.service.signal(IFACE, signature='n') + def _flip_handler(self): + self._tube.add_signal_receiver(self._flip_receiver, + '_flip_signal', + IFACE, + path=PATH, + sender_keyword='sender') + + @signal(IFACE, signature='n') def _flip_signal(self, card_number): - _logger.debug('Notifing other players that you flipped: %s', str(card_number)) - ''' Notify current players that you flipped a card ''' + pass def _flip_receiver(self, card_number, sender=None): - ''' Someone flipped a card ''' - handle = self._tube.bus_name_to_handle[sender] - - if self._tube.self_handle <> handle: - _logger.debug('Other player flipped: %s ', str(card_number)) - self.game.card_flipped(None, card_number, True) - - def change_game(self, sender, grid, data, waiting_list): - ''' Notify other players that you changed the game ''' - _logger.debug('Sending changed game message') - self._change_game_signal(grid, data) - - @dbus.service.signal(IFACE, signature='aa{ss}a{ss}') - def _change_game_signal(self, grid, data): - _logger.debug('Notifing other players that you changed the game') - ''' Notify current players that you changed the game ''' - - def _change_game_receiver(self, grid, data, sender=None): - ''' Game changed by other player ''' - handle = self._tube.bus_name_to_handle[sender] - - if self._tube.self_handle <> handle: - _logger.debug('Game changed by other player') - self.game.load_remote(grid, data, True) + # ignore my own signal + if sender == self._tube.get_unique_name(): + return + self.game.card_flipped(None, card_number, True) \ No newline at end of file diff --git a/model.py b/model.py index 857d7ee..0751d57 100644 --- a/model.py +++ b/model.py @@ -1,417 +1,340 @@ #! /usr/bin/env python # -# Copyright (C) 2006, 2007, One Laptop Per Child +# Copyright (C) 2006, 2007, 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 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. +# 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. +# 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 libxml2 import os +from os.path import join, basename import logging import random import gobject import zipfile import tempfile +from sugar import profile +from sugar.datastore import datastore _logger = logging.getLogger('model') -class Pair(gobject.GObject): - __gproperties__ = { - 'aimg' : (str, None, None, None, gobject.PARAM_READWRITE), - 'asnd' : (str, None, None, None, gobject.PARAM_READWRITE), - 'achar' : (str, None, None, None, gobject.PARAM_READWRITE), - 'bimg' : (str, None, None, None, gobject.PARAM_READWRITE), - 'bsnd' : (str, None, None, None, gobject.PARAM_READWRITE), - 'bchar' : (str, None, None, None, gobject.PARAM_READWRITE), - 'color': (gobject.TYPE_INT, 'Base', 'Base', 0, 10, 0, gobject.PARAM_READWRITE) - } - - def __init__(self): - gobject.GObject.__init__(self) - self._properties = {'aimg':None, 'asnd':None, 'achar':None, 'bimg':None, - 'bsnd':None, 'bchar':None, 'color':100} - - def do_get_property(self, pspec): - """Retrieve a particular property from our property dictionary - """ - if pspec.name == "aimg": - return self._properties["aimg"] - elif pspec.name == "asnd": - return self._properties["asnd"] - elif pspec.name == "achar": - return self._properties["achar"] - elif pspec.name == "bimg": - return self._properties["bimg"] - elif pspec.name == "bsnd": - return self._properties["bsnd"] - elif pspec.name == "bchar": - return self._properties["bchar"] - elif pspec.name == "color": - return self._properties["color"] +class Pair(gobject.GObject): + __gproperties__ = { + 'aimg' : (str, None, None, None, gobject.PARAM_READWRITE), + 'asnd' : (str, None, None, None, gobject.PARAM_READWRITE), + 'achar' : (str, None, None, None, gobject.PARAM_READWRITE), + 'bimg' : (str, None, None, None, gobject.PARAM_READWRITE), + 'bsnd' : (str, None, None, None, gobject.PARAM_READWRITE), + 'bchar' : (str, None, None, None, gobject.PARAM_READWRITE), + 'color': (gobject.TYPE_INT, 'Base', 'Base', 0, 10, 0, gobject.PARAM_READWRITE) + } + + def __init__(self): + gobject.GObject.__init__(self) + self._properties = {'aimg':None, 'asnd':None, 'achar':None, 'bimg':None, + 'bsnd':None, 'bchar':None, 'color':100} + + def do_get_property(self, pspec): + """Retrieve a particular property from our property dictionary + """ + if pspec.name == "aimg": + return self._properties["aimg"] + elif pspec.name == "asnd": + return self._properties["asnd"] + elif pspec.name == "achar": + return self._properties["achar"] + elif pspec.name == "bimg": + return self._properties["bimg"] + elif pspec.name == "bsnd": + return self._properties["bsnd"] + elif pspec.name == "bchar": + return self._properties["bchar"] + elif pspec.name == "color": + return self._properties["color"] - def set_property(self, name, value): - if name == 'aimg': - self._properties['aimg'] = value - elif name == "asnd": - self._properties["asnd"] = value - elif name == "achar": - self._properties["achar"] = value - elif name == "bimg": - self._properties["bimg"] = value - elif name == "bsnd": - self._properties["bsnd"] = value - elif name == "bchar": - self._properties["bchar"] = value - elif name == "color": - self._properties["color"] = value + def set_property(self, name, value): + if name == 'aimg': + self._properties['aimg'] = value + elif name == "asnd": + self._properties["asnd"] = value + elif name == "achar": + self._properties["achar"] = value + elif name == "bimg": + self._properties["bimg"] = value + elif name == "bsnd": + self._properties["bsnd"] = value + elif name == "bchar": + self._properties["bchar"] = value + elif name == "color": + self._properties["color"] = value class Model(object): - ''' The model of the activity. Contains methods to read and write - the configuration for a game from xml. Stores the pairs and grid - information. - ''' - - def __init__(self, game_path, dtd_path = None): - self.data = {} - if dtd_path == None: - self.dtd_path = os.path.dirname(__file__) - else: - self.dtd_path = dtd_path - - if os.path.isdir(game_path): - self.game_path = game_path - else: - _logger.error('Game_path not found ' +str(e)) - return - - self.data['face'] = '' - self.data['align'] = '1' - - try: - self.dtd = libxml2.parseDTD(None, os.path.join(self.dtd_path, 'memorize.dtd')) - except libxml2.parserError, e: - _logger.error('Init: no memorize.dtd found ' +str(e)) - self.dtd = None - self.ctxt = libxml2.newValidCtxt() + ''' The model of the activity. Contains methods to read and write + the configuration for a game from xml. Stores the pairs and grid + information. + ''' + + def __init__(self, game_path, dtd_path = None): + self.data = {} + if dtd_path == None: + self.dtd_path = os.path.dirname(__file__) + else: + self.dtd_path = dtd_path + + if os.path.isdir(game_path): + self.game_path = game_path + else: + _logger.error('Game_path not found ' +str(e)) + return + + self.data['face'] = '' + self.data['align'] = '1' + + try: + self.dtd = libxml2.parseDTD(None, os.path.join(self.dtd_path, 'memorize.dtd')) + except libxml2.parserError, e: + _logger.error('Init: no memorize.dtd found ' +str(e)) + self.dtd = None + self.ctxt = libxml2.newValidCtxt() - self.pairs = {} - self.grid = [] + self.pairs = {} + self.grid = [] - # used by the leader of the game to keep track of the game state - self.players = {} - self.player_active = 0 - self.selected = 0 - self.turn = 0 - self.started = 0 - self.count = 0 + # used by the leader of the game to keep track of the game state + self.players = {} + self.player_active = 0 + self.selected = 0 + self.turn = 0 + self.started = 0 + self.count = 0 - def read(self, game_file): - if game_file in ["addition", "capitals", "drumgit", "letters", "numbers", "phonemes"]: - game_file = os.path.join(os.path.dirname(__file__), 'games', game_file+'.zip') - game_name = os.path.basename(game_file)[:-4] - - temp_folder = tempfile.mkdtemp() - self.data['key'] = os.path.basename(game_file) - self.data['game_file'] = game_file - self.data['path'] = temp_folder - self.data['pathimg'] = os.path.join(self.data['path'], 'images') - self.data['pathsnd'] = os.path.join(self.data['path'], 'sounds') - - ''' extracts files in the zip file ''' - game_name = os.path.basename(game_file)[:-4] - zipFile = zipfile.ZipFile(game_file, "r") - for each in zipFile.namelist(): - if not each.endswith('/'): - root, name = os.path.split(each) - directory = os.path.normpath(os.path.join(self.data['path'], root)) - if not os.path.isdir(directory): - os.makedirs(directory) - file(os.path.join(directory, name), 'wb').write(zipFile.read(each)) + def read(self, game_file): + if game_file in ["addition", "capitals", "drumgit", "letters", "numbers", "phonemes"]: + game_file = os.path.join(os.path.dirname(__file__), 'games', game_file+'.zip') + game_name = os.path.basename(game_file)[:-4] + + temp_folder = tempfile.mkdtemp() + self.data['key'] = os.path.basename(game_file) + self.data['game_file'] = game_file + self.data['path'] = temp_folder + self.data['pathimg'] = os.path.join(self.data['path'], 'images') + self.data['pathsnd'] = os.path.join(self.data['path'], 'sounds') + + ''' extracts files in the zip file ''' + game_name = os.path.basename(game_file)[:-4] + zipFile = zipfile.ZipFile(game_file, "r") + for each in zipFile.namelist(): + if not each.endswith('/'): + root, name = os.path.split(each) + directory = os.path.normpath(os.path.join(self.data['path'], root)) + if not os.path.isdir(directory): + os.makedirs(directory) + file(os.path.join(directory, name), 'wb').write(zipFile.read(each)) - self.pairs = {} - - ''' reads the configuration from an xml file ''' - try: - doc = libxml2.parseFile(os.path.join(os.path.dirname(__file__), os.path.join(self.data['path'], 'game.xml'))) - if doc.validateDtd(self.ctxt, self.dtd): - - # get the requested nodes - xpa = doc.xpathNewContext() - res = xpa.xpathEval("//*") + self.pairs = {} + + ''' reads the configuration from an xml file ''' + try: + doc = libxml2.parseFile(os.path.join(os.path.dirname(__file__), os.path.join(self.data['path'], 'game.xml'))) + if doc.validateDtd(self.ctxt, self.dtd): + + # get the requested nodes + xpa = doc.xpathNewContext() + res = xpa.xpathEval("//*") - # write their content to the data structure - self.idpair = 0 - for elem in res: - attributes = elem.get_properties() - pair = Pair() - if(elem.name == 'pair'): - for attribute in attributes: - if(attribute.name == 'text'): - pass - else: - pair.set_property(attribute.name, attribute.content) - self.pairs[str(self.idpair)] = pair - self.idpair+=1 - elif(elem.name == 'memorize'): - for attribute in attributes: - if(attribute.name == 'text'): - pass - elif(attribute.name == 'name'): - self.data['name'] = attribute.content - elif(attribute.name == 'scoresnd'): - self.data['scoresnd'] = attribute.content - elif(attribute.name == 'winsnd'): - self.data['winsnd'] = attribute.content - elif(attribute.name == 'divided'): - self.data['divided'] = attribute.content - elif(attribute.name == 'face'): - self.data['face'] = attribute.content - elif(attribute.name == 'face1'): - self.data['face1'] = attribute.content - elif(attribute.name == 'face2'): - self.data['face2'] = attribute.content - elif(attribute.name == 'align'): - self.data['align'] = attribute.content - elif(attribute.name == 'equal_pairs'): - self.data['equal_pairs'] = attribute.content - xpa.xpathFreeContext() - else: - _logger.error('Read: Error in validation of the file') - doc.freeDoc() - return 1 - doc.freeDoc() - return 0 - except libxml2.parserError, e: - _logger.error('Read: Error parsing file ' +str(e)) - return 2 - - def write(self, equal_pairs, divided): - ''' writes the configuration to an xml file ''' - doc = libxml2.newDoc("1.0") - root = doc.newChild(None, "memorize", None) - - if(self.data.get('name', None) != None): - root.setProp("name", self.data['name']) - - if divided: - root.setProp('divided', '1') - root.setProp('face1', '1') - root.setProp('face2', '2') - else: - root.setProp('divided', '0') - - if equal_pairs: - root.setProp('equal_pairs', str(equal_pairs)) - - if(self.data.get('scoresnd', None) != None): - root.setProp("scoresnd", self.data['scoresnd']) - if(self.data.get('winsnd', None) != None): - root.setProp("winsnd", self.data['winsnd']) - if(self.data.get('divided', None) != None): - root.setProp("divided", self.data['divided']) - if(self.data.get('face', None) != None): - root.setProp("face", self.data['face']) - if(self.data.get('face1', None) != None): - root.setProp("face1", self.data['face1']) - if(self.data.get('face2', None) != None): - root.setProp("face2", self.data['face2']) - if(self.data.get('align', None) != None): - root.setProp("align", self.data['align']) + # write their content to the data structure + self.idpair = 0 + for elem in res: + attributes = elem.get_properties() + pair = Pair() + if(elem.name == 'pair'): + for attribute in attributes: + if(attribute.name == 'text'): + pass + else: + pair.set_property(attribute.name, attribute.content) + self.pairs[str(self.idpair)] = pair + self.idpair+=1 + elif(elem.name == 'memorize'): + for attribute in attributes: + if(attribute.name == 'text'): + pass + elif(attribute.name == 'name'): + self.data['name'] = attribute.content + elif(attribute.name == 'scoresnd'): + self.data['scoresnd'] = attribute.content + elif(attribute.name == 'winsnd'): + self.data['winsnd'] = attribute.content + elif(attribute.name == 'divided'): + self.data['divided'] = attribute.content + elif(attribute.name == 'face'): + self.data['face'] = attribute.content + elif(attribute.name == 'face1'): + self.data['face1'] = attribute.content + elif(attribute.name == 'face2'): + self.data['face2'] = attribute.content + elif(attribute.name == 'align'): + self.data['align'] = attribute.content + elif(attribute.name == 'equal_pairs'): + self.data['equal_pairs'] = attribute.content + xpa.xpathFreeContext() + else: + _logger.error('Read: Error in validation of the file') + doc.freeDoc() + return 1 + doc.freeDoc() + return 0 + except libxml2.parserError, e: + _logger.error('Read: Error parsing file ' +str(e)) + return 2 + + def write(self, equal_pairs, divided): + ''' writes the configuration to an xml file ''' + doc = libxml2.newDoc("1.0") + root = doc.newChild(None, "memorize", None) + + if(self.data.get('name', None) != None): + root.setProp("name", self.data['name']) + + if divided: + root.setProp('divided', '1') + root.setProp('face1', '1') + root.setProp('face2', '2') + else: + root.setProp('divided', '0') + + if equal_pairs: + root.setProp('equal_pairs', str(equal_pairs)) + + if(self.data.get('scoresnd', None) != None): + root.setProp("scoresnd", self.data['scoresnd']) + if(self.data.get('winsnd', None) != None): + root.setProp("winsnd", self.data['winsnd']) + if(self.data.get('divided', None) != None): + root.setProp("divided", self.data['divided']) + if(self.data.get('face', None) != None): + root.setProp("face", self.data['face']) + if(self.data.get('face1', None) != None): + root.setProp("face1", self.data['face1']) + if(self.data.get('face2', None) != None): + root.setProp("face2", self.data['face2']) + if(self.data.get('align', None) != None): + root.setProp("align", self.data['align']) - for key in self.pairs: - elem = root.newChild(None, "pair", None) - if self.pairs[key].props.aimg != None: - elem.setProp("aimg", self.pairs[key].props.aimg) - if self.pairs[key].props.asnd != None: - elem.setProp("asnd", self.pairs[key].props.asnd) - if self.pairs[key].props.achar != None: - elem.setProp("achar", self.pairs[key].props.achar) - if self.pairs[key].props.bimg != None: - elem.setProp("bimg", self.pairs[key].props.bimg) - if self.pairs[key].props.bsnd != None: - elem.setProp("bsnd", self.pairs[key].props.bsnd) - if self.pairs[key].props.bchar != None: - elem.setProp("bchar", self.pairs[key].props.bchar) - # elem.setProp("color", str(self.pairs[key].props.color)) - - if doc.validateDtd(self.ctxt, self.dtd): - doc.saveFormatFile(os.path.join(self.game_path, 'game.xml'), 1) - else: - _logger.error('Write: Error in validation of the file') - doc.freeDoc() - return 2 - doc.freeDoc() - return 0 - + for key in self.pairs: + elem = root.newChild(None, "pair", None) + if self.pairs[key].props.aimg != None: + elem.setProp("aimg", self.pairs[key].props.aimg) + if self.pairs[key].props.asnd != None: + elem.setProp("asnd", self.pairs[key].props.asnd) + if self.pairs[key].props.achar != None: + elem.setProp("achar", self.pairs[key].props.achar) + if self.pairs[key].props.bimg != None: + elem.setProp("bimg", self.pairs[key].props.bimg) + if self.pairs[key].props.bsnd != None: + elem.setProp("bsnd", self.pairs[key].props.bsnd) + if self.pairs[key].props.bchar != None: + elem.setProp("bchar", self.pairs[key].props.bchar) + # elem.setProp("color", str(self.pairs[key].props.color)) + + if doc.validateDtd(self.ctxt, self.dtd): + doc.saveFormatFile(os.path.join(self.game_path, 'game.xml'), 1) + else: + _logger.error('Write: Error in validation of the file') + doc.freeDoc() + return 2 + doc.freeDoc() + return 0 + - def def_grid(self, size): - ''' create the grid for the play from the pairs information - and shuffles the grid so they always appear in a different - place - ''' - psize=(size*size/2) - _logger.debug('Size requested: %d' %psize) - self.grid = [] - temp1 = [] - temp2 = [] - i=0 + def def_grid(self, size): + ''' create the grid for the play from the pairs information + and shuffles the grid so they always appear in a different + place + ''' + psize=(size*size/2) + _logger.debug('Size requested: %d' %psize) + self.grid = [] + temp1 = [] + temp2 = [] + i=0 - # shuffle the pairs first to avoid only taking the first ones when there are more - # pairs in the config file then the grid is using - keys = self.pairs.keys() - random.shuffle(keys) + # shuffle the pairs first to avoid only taking the first ones when there are more + # pairs in the config file then the grid is using + keys = self.pairs.keys() + random.shuffle(keys) - for key in keys: - if i < psize: - elem = {} - elem['pairkey'] = key - elem['state'] = '0' - elem['ab'] = 'a' - if self.pairs[key].props.aimg != None: - elem['img'] = os.path.join(self.data['pathimg'], self.pairs[key].props.aimg) - if self.pairs[key].props.asnd != None: - elem['snd'] = os.path.join(self.data['pathsnd'], self.pairs[key].props.asnd) - if self.pairs[key].props.achar != None: - elem['char'] = self.pairs[key].props.achar - temp1.append(elem) - - elem = {} - elem['pairkey'] = key - elem['state'] = '0' - elem['ab'] = 'b' - if self.pairs[key].props.bimg != None: - elem['img'] = os.path.join(self.data['pathimg'], self.pairs[key].props.bimg) - if self.pairs[key].props.bsnd != None: - elem['snd'] = os.path.join(self.data['pathsnd'], self.pairs[key].props.bsnd) - if self.pairs[key].props.bchar != None: - elem['char'] = self.pairs[key].props.bchar - temp2.append(elem) - i+=1 - else: - break - - numpairs = len(self.pairs) - if numpairs < psize: - _logger.debug('Defgrid: We did not have enough pairs. requested=%s had=%s' %(psize, numpairs)) - self.data['size'] = str(size) + for key in keys: + if i < psize: + elem = {} + elem['pairkey'] = key + elem['state'] = '0' + elem['ab'] = 'a' + if self.pairs[key].props.aimg != None: + elem['img'] = self.pairs[key].props.aimg + if self.pairs[key].props.asnd != None: + elem['snd'] = self.pairs[key].props.asnd + if self.pairs[key].props.achar != None: + elem['char'] = self.pairs[key].props.achar + temp1.append(elem) + + elem = {} + elem['pairkey'] = key + elem['state'] = '0' + elem['ab'] = 'b' + if self.pairs[key].props.bimg != None: + elem['img'] = self.pairs[key].props.bimg + if self.pairs[key].props.bsnd != None: + elem['snd'] = self.pairs[key].props.bsnd + if self.pairs[key].props.bchar != None: + elem['char'] = self.pairs[key].props.bchar + temp2.append(elem) + i+=1 + else: + break + + numpairs = len(self.pairs) + if numpairs < psize: + _logger.debug('Defgrid: We did not have enough pairs. requested=%s had=%s' %(psize, numpairs)) + self.data['size'] = str(size) - if self.data['divided'] == '1': - random.shuffle(temp1) - random.shuffle(temp2) - temp1.extend(temp2) - else: - temp1.extend(temp2) - random.shuffle(temp1) - self.grid = temp1 - _logger.debug('Defgrid: grid( size=%s ): %s' %(self.data['size'], self.grid)) + if self.data['divided'] == '1': + random.shuffle(temp1) + random.shuffle(temp2) + temp1.extend(temp2) + else: + temp1.extend(temp2) + random.shuffle(temp1) + self.grid = temp1 + _logger.debug('Defgrid: grid( size=%s ): %s' %(self.data['size'], self.grid)) - def set_data_grid(self, data, grid): - self.data = data - self.grid = grid - -if __name__ == '__main__': - model = Model(os.path.dirname(__file__)) - model.data['name'] = 'hilde' - pair = Pair() - id = '0' - model.pairs[id] = pair - - model.pairs[id].set_property('aimg', 'eva.png') - - print [model.pairs[key].props.aimg for key in model.pairs] - if model.write('/tmp/save.mem') != 0: - print 'error' - - ''' - print 'name=%s scoresnd=%s winsnd=%s div=%s' %(model.data['name'], model.data['scoresnd'], - model.data['winsnd'], model.data['divided']) - - model.def_grid(4) - print 'grid %s'%model.grid #['size'] - - print 'Test set state of tile 7:' - tilenum = 7 - model.grid[tilenum]['state'] = '1' - print ' %s' %model.grid[tilenum] - - print 'Test sound:' - snd = model.grid[tilenum].get('snd', None) - if snd == None: - print ' no sound' - else: - print ' play sound=%s'%snd - - print 'Test the same function: 0 1' - if model.grid[0]['pairkey'] == model.grid[1]['pairkey']: - print ' they are the same' - else: - print ' they are NOT the same' - - for tile in model.grid: - id = model.grid.index(tile) - if tile.get('img', None): - print 'we got an image=%s '%tile['img'] - elif tile.get('char', None): - print 'we got an char=%s'%tile.get('char') - else: - print 'we got no pic so prepare for sound game' - - print '\n_______________________________\n' - - if model.read('addition') == 0: - print '%s' %model.pairs[0]._properties - print 'name=%s' %model.data['name'] - print 'scoresnd=%s' %model.data['scoresnd'] - print 'winsnd=%s' %model.data['winsnd'] - print 'div=%d' %model.data['divided'] - - model.def_grid(12) - for tile in model.grid: - id = model.grid.index(tile) - if tile.get('img', None): - print 'we got an image=%s '%tile.get('img') - elif tile.get('char', None): - print 'we got an char=%s'%tile.get('char') - else: - print 'we got no img so prepare for sound game' - - else: - print 'error during reading of the game' - - - print '\n_______________________________\n' - if model.read('numbers') == 0: - print '%s' %model.pairs[0]._properties - print 'name=%s' %model.data['name'] - print 'scoresnd=%s' %model.data['scoresnd'] - print 'winsnd=%s' %model.data['winsnd'] - print 'div=%d' %model.data['divided'] - print 'face1=%s' %model.data['face1'] - print 'face2=%s' %model.data['face2'] - - model.def_grid(12) - for tile in model.grid: - id = model.grid.index(tile) - if tile.get('img', None): - print 'we got an image=%s '%tile.get('img') - elif tile.get('char', None): - print 'we got an char=%s'%tile.get('char') - else: - print 'we got no img so prepare for sound game' - - else: - print 'error during reading of the game' - ''' + def set_data_grid(self, data, grid): + self.data = data + self.grid = grid + + def save_byte_array(self, path, title= None, color= None): + if color == None: + color = profile.get_color().to_string() + _logger.debug('Save new game in datastore') + + # Saves the zip in datastore + gameObject = datastore.create() + gameObject.metadata['title'] = title + gameObject.metadata['mime_type'] = 'application/memorizegame' + gameObject.metadata['icon-color'] = color + gameObject.file_path = path + datastore.write(gameObject) + \ No newline at end of file diff --git a/playerscoreboard.py b/playerscoreboard.py index e7f2835..b0c0a88 100755 --- a/playerscoreboard.py +++ b/playerscoreboard.py @@ -22,14 +22,14 @@ import gtk, pygtk import pango import svglabel import logging -import os +from os.path import join, dirname from score import Score _logger = logging.getLogger('memorize-activity') class PlayerScoreboard(gtk.EventBox): - def __init__(self, nick, fill_color, stroke_color,score = 0): + def __init__(self, nick, fill_color, stroke_color, score = 0): gtk.EventBox.__init__(self) self.default_color = '#4c4d4f' @@ -53,7 +53,7 @@ class PlayerScoreboard(gtk.EventBox): status = False # Set buddy icon - self.xo_buddy = os.path.join(os.path.dirname(__file__), "images/stock-buddy.svg") + self.xo_buddy = join(dirname(__file__), 'images', 'stock-buddy.svg') self.icon = svglabel.SvgLabel(self.xo_buddy, fill_color, stroke_color, False, self.current_color, 45, 55) # Set waiting buddy icon @@ -61,15 +61,15 @@ class PlayerScoreboard(gtk.EventBox): # Set nick label self.nick = gtk.Label(nick) - self.nick.modify_font(pango.FontDescription("12")) + self.nick.modify_font(pango.FontDescription('12')) self.nick.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff')) self.nick.set_alignment(0, 0.5) # Set message label - #self.msg = gtk.Label('Waiting for next game...') - #self.msg.modify_font(pango.FontDescription("12")) - #self.msg.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff')) - #self.msg.set_alignment(0, 0.5) + self.msg = gtk.Label('Waiting for next game...') + self.msg.modify_font(pango.FontDescription('12')) + self.msg.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff')) + self.msg.set_alignment(0, 0.5) self.add(self.table) self.table.attach(self.icon, 0, 1, 0, 1) @@ -78,16 +78,15 @@ class PlayerScoreboard(gtk.EventBox): if score <> 0: for i in range(score): self.increase_score() - + def increase_score(self): - _logger.debug('Increase to: '+self.nick.get_text()) if len(self.scores) == 0: # Cache the score icon score_label = Score(self.fill_color, self.stroke_color) self.score_pixbuf_unsel = score_label.get_pixbuf() self.score_pixbuf_sel = score_label.get_pixbuf_sel() - new_score = Score(self.fill_color, self.stroke_color, self.score_pixbuf_sel, self.score_pixbuf_unsel,self.status) + new_score = Score(self.fill_color, self.stroke_color, self.score_pixbuf_sel, self.score_pixbuf_unsel, self.status) self.scores.append(new_score) new_score.show() self.table.attach(new_score, self.current_x , self.current_x+1, self.current_y, self.current_y+1) @@ -118,7 +117,7 @@ class PlayerScoreboard(gtk.EventBox): self.scores = [] self.queue_draw() - def set_wait_mode(self,status): + def set_wait_mode(self, status): if status: self.table.remove(self.icon) self.table.attach(self.waiting_icon, 0, 1, 0, 1) @@ -132,3 +131,6 @@ class PlayerScoreboard(gtk.EventBox): self.table.remove(self.msg) self.queue_draw() + def set_message(self, msg): + self.msg.set_text(msg) + diff --git a/score.py b/score.py index 1ee1028..74e68b6 100755 --- a/score.py +++ b/score.py @@ -30,7 +30,7 @@ class Score(svglabel.SvgLabel): default_color = "#4c4d4f" status = False - def __init__(self, fill_color, stroke_color, pixbuf= None, pixbuf_sel = None,status= False): + def __init__(self, fill_color, stroke_color, pixbuf= None, pixbuf_sel = None, status= False): filename = os.path.join(os.path.dirname(__file__), "images/score.svg") self.pixbuf_un = pixbuf self.pixbuf_sel = pixbuf_sel @@ -51,10 +51,10 @@ class Score(svglabel.SvgLabel): self.status = status if status: self.pixbuf = self.pixbuf_sel - self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(self.selected_color)) + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.selected_color)) else: self.pixbuf = self.pixbuf_un - self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(self.default_color)) + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.default_color)) self.queue_draw() def get_pixbuf_un(self): diff --git a/scoreboard.py b/scoreboard.py index 847c38d..f370f75 100755 --- a/scoreboard.py +++ b/scoreboard.py @@ -70,9 +70,11 @@ class Scoreboard(gtk.EventBox): self.current_buddy = buddy player = self.players[buddy] player.set_selected(True) + + def set_buddy_message(self, widget, buddy, msg): + self.players[buddy].set_message(msg) def increase_score(self, widget, buddy): - _logger.debug('Increase to: '+buddy.props.nick) self.players[buddy].increase_score() def reset(self, widget): diff --git a/svgcard.py b/svgcard.py index 7423b38..dec2d46 100755 --- a/svgcard.py +++ b/svgcard.py @@ -1,25 +1,25 @@ #! /usr/bin/env python # -# Copyright (C) 2007, One Laptop Per Child +# Copyright (C) 2007, One Laptop Per Child # -# Muriel de Souza Godoi - muriel@laptop.org +# Muriel de Souza Godoi - muriel@laptop.org # -# 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 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. +# 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. +# 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 os +from os.path import join, dirname import gc import rsvg import re @@ -30,238 +30,238 @@ import logging _logger = logging.getLogger('memorize-activity') class SvgCard(gtk.DrawingArea): - - border_svg = os.path.join(os.path.dirname(__file__), "images/card.svg") + + border_svg = join(dirname(__file__), 'images', 'card.svg') - # Default properties - default_props = {} - default_props['back'] = {'fill_color':'#b2b3b7', 'stroke_color':'#b2b3b7', 'opacity':'1'} - default_props['back_h'] = {'fill_color':'#b2b3b7', 'stroke_color':'#ffffff', 'opacity':'1'} - default_props['back_text'] = {'text_color':'#c7c8cc'} - default_props['front'] = {'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'} - default_props['front_h'] = {'fill_color':'#555555', 'stroke_color':'#888888', 'opacity':'1'} - default_props['front_text'] = {'text_color':'#ffffff'} - - cache = {} - - def __init__(self, id, pprops, jpeg, size, align, bg_color='#000000'): - gtk.DrawingArea.__init__(self) - self.set_size_request(size, size) - self.bg_color = bg_color - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color)) - self.flipped = False - self.flipped_once = False - self.id = id - self.jpeg = jpeg - self.show_jpeg = False - self.show_text = False - self.size = size - self.align = align - - # Views properties - views = ['back', 'back_h', 'back_text', 'front', 'front_h', 'front_text'] - self.pprops = pprops - self.props = {} - for view in views: - self.props[view] = {} - self.props[view].update(self.default_props[view]) - self.props[view].update(pprops.get(view, {})) - - if len(self.props['back_text'].get('card_text', '')) > 0: - self.back_layout = self.get_text_layout(self.props['back_text']['card_text'], self.size-12) - self.back_layout_position = (self.size -(self.back_layout.get_size()[1]/1000))/2 - self.current_layout = self.back_layout - self.current_layout_position = self.back_layout_position - self.current_text_color = self.props['back_text']['text_color'] - self.show_text = True - self.current_face = 'back' - - # Set events and listeners - self.connect('expose-event', self._expose_cb) - self.set_events(gtk.gdk.ALL_EVENTS_MASK) - gc.collect() - self.show() + # Default properties + default_props = {} + default_props['back'] = {'fill_color':'#b2b3b7', 'stroke_color':'#b2b3b7', 'opacity':'1'} + default_props['back_h'] = {'fill_color':'#b2b3b7', 'stroke_color':'#ffffff', 'opacity':'1'} + default_props['back_text'] = {'text_color':'#c7c8cc'} + default_props['front'] = {'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'1'} + default_props['front_h'] = {'fill_color':'#555555', 'stroke_color':'#888888', 'opacity':'1'} + default_props['front_text'] = {'text_color':'#ffffff'} + + cache = {} + + def __init__(self, id, pprops, jpeg, size, align, bg_color='#000000'): + gtk.DrawingArea.__init__(self) + self.set_size_request(size, size) + self.bg_color = bg_color + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color)) + self.flipped = False + self.flipped_once = False + self.id = id + self.jpeg = jpeg + self.show_jpeg = False + self.show_text = False + self.size = size + self.align = align + + # Views properties + views = ['back', 'back_h', 'back_text', 'front', 'front_h', 'front_text'] + self.pprops = pprops + self.props = {} + for view in views: + self.props[view] = {} + self.props[view].update(self.default_props[view]) + self.props[view].update(pprops.get(view, {})) + + if len(self.props['back_text'].get('card_text', '')) > 0: + self.back_layout = self.get_text_layout(self.props['back_text']['card_text'], self.size-12) + self.back_layout_position = (self.size -(self.back_layout.get_size()[1]/1000))/2 + self.current_layout = self.back_layout + self.current_layout_position = self.back_layout_position + self.current_text_color = self.props['back_text']['text_color'] + self.show_text = True + self.current_face = 'back' + + # Set events and listeners + self.connect('expose-event', self._expose_cb) + self.set_events(gtk.gdk.ALL_EVENTS_MASK) + gc.collect() + self.show() - def _expose_cb(self, widget, event): - gc = self.window.new_gc() - pixbuf = self._read_icon_data(self.current_face) - self.window.draw_pixbuf(None, pixbuf, 0, 0, 0, 0) - if self.show_jpeg: - self.window.draw_pixbuf(None, self.jpeg, 0, 0, 11, 11) - if self.show_text: - widget.window.draw_layout(gc, x=6, y=self.current_layout_position, layout=self.current_layout, foreground=gtk.gdk.color_parse(self.current_text_color)) - return False + def _expose_cb(self, widget, event): + gc = self.window.new_gc() + pixbuf = self._read_icon_data(self.current_face) + self.window.draw_pixbuf(None, pixbuf, 0, 0, 0, 0) + if self.show_jpeg: + self.window.draw_pixbuf(None, self.jpeg, 0, 0, 11, 11) + if self.show_text: + widget.window.draw_layout(gc, x=6, y=self.current_layout_position, layout=self.current_layout, foreground=gtk.gdk.color_parse(self.current_text_color)) + return False - def _read_icon_data(self, view): - dict = self.props[view] - set = str(self.size)+dict.get('fill_color')+dict.get('stroke_color') - if self.cache.has_key(set): - return self.cache[set] - - icon_file = open(self.border_svg, 'r') - data = icon_file.read() - icon_file.close() + def _read_icon_data(self, view): + dict = self.props[view] + set = str(self.size)+dict.get('fill_color')+dict.get('stroke_color') + if self.cache.has_key(set): + return self.cache[set] + + icon_file = open(self.border_svg, 'r') + data = icon_file.read() + icon_file.close() - # Replace borders parameters - entity = '' % dict.get('fill_color', '') - data = re.sub('', entity, data) + # Replace borders parameters + entity = '' % dict.get('fill_color', '') + data = re.sub('', entity, data) - entity = '' % dict.get('stroke_color', '') - data = re.sub('', entity, data) - - entity = '' % dict.get('opacity', '') - data = re.sub('', entity, data) - - data = re.sub('size_card1', str(self.size), data) - data = re.sub('size_card2', str(self.size-6), data) - data = re.sub('size_card3', str(self.size-17), data) - pixbuf = rsvg.Handle(data=data).get_pixbuf() - self.cache[set] = pixbuf - return pixbuf - - def set_border(self, stroke_color, fill_color): - self.props['front'].update({'fill_color':fill_color, 'stroke_color':stroke_color}) - self.queue_draw() - while gtk.events_pending(): - gtk.main_iteration() - - def set_pixbuf(self, pixbuf): - if pixbuf == None: - self.jpeg = None - self.show_jpeg = False - else: - if self.jpeg != None: - del self.jpeg - - self.jpeg = pixbuf - del pixbuf - self.show_jpeg = True - - self.queue_draw() - while gtk.events_pending(): - gtk.main_iteration() - - def get_pixbuf(self): - return self.jpeg - - def set_highlight(self, status, mouse = False): - if self.flipped: - if mouse: - return - if status: - self.current_face = 'front_h' - else: - self.current_face = 'front' - else: - if status: - self.current_face = 'back_h' - else: - self.current_face = 'back' - self.queue_draw() - - def flip(self): - if not self.flipped: - if not self.flipped_once: - if self.jpeg <> None: - pixbuf_t = gtk.gdk.pixbuf_new_from_file(self.jpeg) - if pixbuf_t.get_width() != self.size-22 or pixbuf_t.get_height() != self.size-22: - self.jpeg = pixbuf_t.scale_simple(self.size-22, self.size-22, gtk.gdk.INTERP_BILINEAR) - del pixbuf_t - else: - self.jpeg = pixbuf_t - text = self.props.get('front_text', {}).get('card_text', '') - if text != None and len(text) > 0: - self.front_layout = self.get_text_layout(self.props['front_text']['card_text'], self.size-12) - self.front_layout_position = (self.size -(self.front_layout.get_size()[1]/1000))/2 - self.flipped_once = True - - if self.jpeg <> None: - self.show_jpeg = True - text = self.props.get('front_text', {}).get('card_text', '') - if text != None and len(text) > 0: - self.current_layout = self.front_layout - self.current_layout_position = self.front_layout_position - self.current_text_color = self.props['front_text']['text_color'] - self.show_text = True - else: - self.show_text = False + entity = '' % dict.get('stroke_color', '') + data = re.sub('', entity, data) + + entity = '' % dict.get('opacity', '') + data = re.sub('', entity, data) + + data = re.sub('size_card1', str(self.size), data) + data = re.sub('size_card2', str(self.size-6), data) + data = re.sub('size_card3', str(self.size-17), data) + pixbuf = rsvg.Handle(data=data).get_pixbuf() + self.cache[set] = pixbuf + return pixbuf + + def set_border(self, stroke_color, fill_color): + self.props['front'].update({'fill_color':fill_color, 'stroke_color':stroke_color}) + self.queue_draw() + while gtk.events_pending(): + gtk.main_iteration() + + def set_pixbuf(self, pixbuf): + if pixbuf == None: + self.jpeg = None + self.show_jpeg = False + else: + if self.jpeg != None: + del self.jpeg + + self.jpeg = pixbuf + del pixbuf + self.show_jpeg = True + + self.queue_draw() + while gtk.events_pending(): + gtk.main_iteration() + + def get_pixbuf(self): + return self.jpeg + + def set_highlight(self, status, mouse = False): + if self.flipped: + if mouse: + return + if status: + self.current_face = 'front_h' + else: + self.current_face = 'front' + else: + if status: + self.current_face = 'back_h' + else: + self.current_face = 'back' + self.queue_draw() + + def flip(self): + if not self.flipped: + if not self.flipped_once: + if self.jpeg <> None: + pixbuf_t = gtk.gdk.pixbuf_new_from_file(self.jpeg) + if pixbuf_t.get_width() != self.size-22 or pixbuf_t.get_height() != self.size-22: + self.jpeg = pixbuf_t.scale_simple(self.size-22, self.size-22, gtk.gdk.INTERP_BILINEAR) + del pixbuf_t + else: + self.jpeg = pixbuf_t + text = self.props.get('front_text', {}).get('card_text', '') + if text != None and len(text) > 0: + self.front_layout = self.get_text_layout(self.props['front_text']['card_text'], self.size-12) + self.front_layout_position = (self.size -(self.front_layout.get_size()[1]/1000))/2 + self.flipped_once = True + + if self.jpeg <> None: + self.show_jpeg = True + text = self.props.get('front_text', {}).get('card_text', '') + if text != None and len(text) > 0: + self.current_layout = self.front_layout + self.current_layout_position = self.front_layout_position + self.current_text_color = self.props['front_text']['text_color'] + self.show_text = True + else: + self.show_text = False - self.current_face = 'front' + self.current_face = 'front' - self.flipped = True - self.queue_draw() - - while gtk.events_pending(): - gtk.main_iteration() - gc.collect() - - def flop(self): - self.current_face = 'back' - if len(self.props['back_text'].get('card_text', '')) > 0: - self.current_layout = self.back_layout - self.current_layout_position = self.back_layout_position - self.current_text_color = self.props['back_text']['text_color'] - self.show_text = True - else: - self.show_text = False - self.flipped = False - self.show_jpeg = False - self.queue_draw() - - def is_flipped(self): - return self.flipped - - def get_id(self): - return self.id - - def reset(self): - if self.flipped: - fill_color = self.default_props.get('front_border').get('fill_color') - stroke_color = self.default_propsfront_text.get('front_border').get('stroke_color') - self.set_border(fill_color, stroke_color) - self.flop() - - def get_text_layout(self, text, size): - if self.size == 119: - font_sizes = [30, 24, 16, 13, 10, 8, 8, 8] - elif self.size == 145: - font_sizes = [45, 28, 20, 16, 13, 11, 9, 8] - else: - font_sizes = [50, 40, 26, 20, 17, 13, 11, 8] - # Set font size considering string length - if len(text) <= 8: - font_size = font_sizes[len(text)-1] - else: - font_size = 8 + self.flipped = True + self.queue_draw() + + while gtk.events_pending(): + gtk.main_iteration() + gc.collect() + + def flop(self): + self.current_face = 'back' + if len(self.props['back_text'].get('card_text', '')) > 0: + self.current_layout = self.back_layout + self.current_layout_position = self.back_layout_position + self.current_text_color = self.props['back_text']['text_color'] + self.show_text = True + else: + self.show_text = False + self.flipped = False + self.show_jpeg = False + self.queue_draw() + + def is_flipped(self): + return self.flipped + + def get_id(self): + return self.id + + def reset(self): + if self.flipped: + fill_color = self.default_props.get('front_border').get('fill_color') + stroke_color = self.default_propsfront_text.get('front_border').get('stroke_color') + self.set_border(fill_color, stroke_color) + self.flop() + + def get_text_layout(self, text, size): + if self.size == 119: + font_sizes = [30, 24, 16, 13, 10, 8, 8, 8] + elif self.size == 145: + font_sizes = [45, 28, 20, 16, 13, 11, 9, 8] + else: + font_sizes = [50, 40, 26, 20, 17, 13, 11, 8] + # Set font size considering string length + if len(text) <= 8: + font_size = font_sizes[len(text)-1] + else: + font_size = 8 - # Set Pango context and Pango layout - context = self.create_pango_context() - layout = self.create_pango_layout(text) - desc = pango.FontDescription('Deja Vu Sans bold '+str(font_size)) - layout.set_font_description(desc) - layout.set_alignment(pango.ALIGN_CENTER) - layout.set_width(size*1000) - return layout + # Set Pango context and Pango layout + context = self.create_pango_context() + layout = self.create_pango_layout(text) + desc = pango.FontDescription('Deja Vu Sans bold '+str(font_size)) + layout.set_font_description(desc) + layout.set_alignment(pango.ALIGN_CENTER) + layout.set_width(size*1000) + return layout - def set_background(self, color): - self.bg_color = color - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color)) - - def change_text(self, newtext): - self.props['front_text']['card_text'] = newtext - self.front_layout = self.get_text_layout(self.props['front_text'].get('card_text', ''), self.size-11) - if self.align == '2': # top - self.front_layout_position = 6 - elif self.align == '3': # bottom - self.front_layout_position = self.size -(self.front_layout.get_size()[1]/1000) - else: # center and none - self.front_layout_position = (self.size -(self.front_layout.get_size()[1]/1000))/2 - - self.current_layout = self.front_layout - self.current_layout_position = self.front_layout_position - self.current_text_color = self.props['front_text']['text_color'] - if len(newtext) > 0: - self.show_text = True - self.queue_draw() - def get_text(self): - return self.props['front_text'].get('card_text', '') + def set_background(self, color): + self.bg_color = color + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color)) + + def change_text(self, newtext): + self.props['front_text']['card_text'] = newtext + self.front_layout = self.get_text_layout(self.props['front_text'].get('card_text', ''), self.size-11) + if self.align == '2': # top + self.front_layout_position = 6 + elif self.align == '3': # bottom + self.front_layout_position = self.size -(self.front_layout.get_size()[1]/1000) + else: # center and none + self.front_layout_position = (self.size -(self.front_layout.get_size()[1]/1000))/2 + + self.current_layout = self.front_layout + self.current_layout_position = self.front_layout_position + self.current_text_color = self.props['front_text']['text_color'] + if len(newtext) > 0: + self.show_text = True + self.queue_draw() + def get_text(self): + return self.props['front_text'].get('card_text', '') diff --git a/svglabel.py b/svglabel.py index d30883e..9f98640 100755 --- a/svglabel.py +++ b/svglabel.py @@ -37,7 +37,7 @@ class SvgLabel(gtk.DrawingArea): self.background_color = background_color self.fill_color = fill_color self.stroke_color = stroke_color - self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(background_color)) + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(background_color)) if pixbuf: self.pixbuf = pixbuf else: @@ -46,7 +46,7 @@ class SvgLabel(gtk.DrawingArea): self.connect('expose-event', self._expose_cb) def _expose_cb(self, widget, event): - widget.window.draw_pixbuf(None,self.pixbuf, 0, 0, 0, 0) + widget.window.draw_pixbuf(None, self.pixbuf, 0, 0, 0, 0) return False def _read_icon_data(self, filename, fill_color, stroke_color): @@ -96,6 +96,6 @@ class SvgLabel(gtk.DrawingArea): def set_background(self, background_color): self.background_color = background_color - self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(self.background_color)) + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.background_color)) self.queue_draw() -- cgit v0.9.1