class CollabEdit(Gtk.VBox): __gsignals__ = { "insert-char": (GObject.SIGNAL_RUN_FIRST, None, [int, int]), "cursor-position-changed": (GObject.SIGNAL_RUN_FIRST, None, [int]) } def __init__(self, activity): Gtk.VBox.__init__(self) self.collab = CollabWrapper(activity) self.collab.connect('message', self.__message_cb) self.collab.connect('joined', self.__joined_cb) self.view = View() self.view.connect("insert-char", self.__insert_char_cb) self.view.connect("cursor-position-changed", self.__cursor_position_changed_cb) self.view.connect("tag-applied", self.__tag_applied_cb) self.view.connect("tag-removed", self.__tag_removed_cb) self.pack_start(self.view, True, True, 0) def __message_cb(self, collab, buddy, msg): action = msg.get("action") if action is None: return elif action == "insert": self.view.insert_at_position(msg.get("key"), msg.get("position")) elif action == "curosr_moved": self.view.draw_other_cursor(msg.get("id"), msg.get("position")) elif action == "insert_tag": self.view.insert_tag(msg.get("tag"), msg.get("start"), msg.get("end")) elif action == "remove_tag": self.view.remove_tag(msg.get("tag"), msg.get("start"), msg.get("end")) def __joined_cb(self, sender): if self.collab._leader: return self.collab.post(dict(action='init_request', res_id=10)) # How get an unique id? def __insert_char_cb(self, view, key, position): self.collab.post(dict(action="insert", key=Gdk.keyval_name(key), position=position)) def __cursor_position_changed_cb(self, view, position): self.collab.post(dict(action="cursor_moved", id=10, # How get an unique id? position=position)) self.emit("cursor-position-changed", position) def __tag_applied_cb(self, buffer, tag, start, end): self.collab.post(dict(action="insert_tag", tag=tag, start=start, end=end)) def __tag_removed_cb(self, buffer, tag, start, end): self.collab.post(dict(action="remove_tag", tag=tag, start=start, end=end)) def toggle_bold(self): self.view.toggle_bold() def toggle_italic(self): self.view.toggle_italic() def toggle_underline(self): self.view.toggle_underline() def check_tag_at_offset(self, tag, position): return self.view.check_tag_at_offset(tag, position)
class ReflectionActivity(activity.Activity): ''' Reflection puzzle game ''' def __init__(self, handle): ''' Initialize the toolbars and the game board ''' try: super(ReflectionActivity, self).__init__(handle) except dbus.exceptions.DBusException as e: _logger.error(str(e)) self.nick = profile.get_nick_name() if profile.get_color() is not None: self.colors = profile.get_color().to_string().split(',') else: self.colors = ['#A0FFA0', '#FF8080'] self._setup_toolbars() # Create a canvas canvas = Gtk.DrawingArea() canvas.set_size_request(Gdk.Screen.width(), \ Gdk.Screen.height()) self.set_canvas(canvas) canvas.show() self.show_all() self._game = Game(canvas, parent=self, colors=self.colors) self._setup_collab() if 'dotlist' in self.metadata: self._restore() else: self._game.new_game('horizontal') def _setup_toolbars(self): ''' Setup the toolbars. ''' self.max_participants = 4 toolbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.toolbar = toolbox.toolbar my_colors = radio_factory('my-colors', self.toolbar, self._my_colors_cb, group=None) radio_factory('toolbar-colors', self.toolbar, self._roygbiv_colors_cb, group=my_colors) self._new_game_button_h = button_factory( 'new-game-horizontal', self.toolbar, self._new_game_cb, cb_arg='horizontal', tooltip=_('Start a new horizontal-reflection game.')) self._new_game_button_v = button_factory( 'new-game-vertical', self.toolbar, self._new_game_cb, cb_arg='vertical', tooltip=_('Start a new vertical-reflection game.')) self._new_game_button_b = button_factory( 'new-game-bilateral', self.toolbar, self._new_game_cb, cb_arg='bilateral', tooltip=_('Start a new bilateral-reflection game.')) self.status = label_factory(self.toolbar, '') separator_factory(toolbox.toolbar, False, True) self.robot_button = button_factory('robot-off', self.toolbar, self._robot_cb, tooltip=_('Play with the robot.')) separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() def _my_colors_cb(self, button=None): if hasattr(self, '_game'): self._game.roygbiv = False self._game.new_game() def _roygbiv_colors_cb(self, button=None): if hasattr(self, '_game'): self._game.roygbiv = True self._game.new_game() def _new_game_cb(self, button=None, orientation='horizontal'): ''' Start a new game. ''' self._game.new_game(orientation) def _robot_cb(self, button=None): ''' Play with the computer (or not). ''' if not self._game.playing_with_robot: self.set_robot_status(True, 'robot-on') else: self.set_robot_status(False, 'robot-off') def set_robot_status(self, status, icon): ''' Reset robot icon and status ''' self._game.playing_with_robot = status self.robot_button.set_icon_name(icon) def write_file(self, file_path): ''' Write the grid status to the Journal ''' [dot_list, orientation] = self._game.save_game() self.metadata['orientation'] = orientation self.metadata['dotlist'] = '' for dot in dot_list: self.metadata['dotlist'] += str(dot) if dot_list.index(dot) < len(dot_list) - 1: self.metadata['dotlist'] += ' ' def _restore(self): ''' Restore the game state from metadata ''' if 'orientation' in self.metadata: orientation = self.metadata['orientation'] else: orientation = 'horizontal' dot_list = [] dots = self.metadata['dotlist'].split() for dot in dots: dot_list.append(int(dot)) self._game.restore_game(dot_list, orientation) # Collaboration-related methods def _setup_collab(self): ''' Setup the Collab Wrapper. ''' self.initiating = None # sharing (True) or joining (False) self._collab = CollabWrapper(self) self._collab.connect('message', self.__message_cb) owner = self._collab._leader self.owner = owner self._game.set_sharing(True) self._collab.setup() def __message_cb(self, collab, buddy, message): action = message.get('action') payload = message.get('payload') if action == 'n': '''Get a new game grid''' self._receive_new_game(payload) elif action == 'p': '''Get a dot click''' self._receive_dot_click(payload) def send_new_game(self): ''' Send a new orientation, grid to all players ''' self._collab.post( dict(action='n', payload=json_dump(self._game.save_game()))) def _receive_new_game(self, payload): ''' Sharer can start a new game. ''' [dot_list, orientation] = json_load(payload) self._game.restore_game(dot_list, orientation) def send_dot_click(self, dot, color): ''' Send a dot click to all the players ''' self._collab.post(dict(action='p', payload=json_dump([dot, color]))) def _receive_dot_click(self, payload): ''' When a dot is clicked, everyone should change its color. ''' (dot, color) = json_load(payload) self._game.remote_button_press(dot, color)
class RecallActivity(activity.Activity): """ A memory game """ def __init__(self, handle): """ Initialize the toolbars and the game board """ super(RecallActivity, self).__init__(handle) self.path = activity.get_bundle_path() self.nick = profile.get_nick_name() if profile.get_color() is not None: self.colors = profile.get_color().to_string().split(',') else: self.colors = ['#A0FFA0', '#FF8080'] self._restoring = False self._setup_toolbars(True) # Create a canvas canvas = Gtk.DrawingArea() canvas.set_size_request(Gdk.Screen.width(), \ Gdk.Screen.height()) self.set_canvas(canvas) canvas.show() self.show_all() self._game = Game(canvas, parent=self, path=self.path, colors=self.colors) self._setup_collab() if 'dotlist' in self.metadata: self._restore() else: self._game.new_game() def _setup_toolbars(self, have_toolbox): """ Setup the toolbars. """ self.max_participants = 4 toolbox = ToolbarBox() # Activity toolbar activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.toolbar = toolbox.toolbar self.radio = [] self.radio.append( radio_factory('game-1', self.toolbar, self._new_game_cb, cb_arg=0, tooltip=_('Play attention game (repeated symbol).'), group=None)) self.radio.append( radio_factory('game-2', self.toolbar, self._new_game_cb, cb_arg=1, tooltip=_('Play attention game (missing symbol).'), group=self.radio[0])) self.radio.append( radio_factory('game-4', self.toolbar, self._new_game_cb, cb_arg=2, tooltip=_('Play n-back game.'), group=self.radio[0])) """ # Game mode disabled self.radio.append(radio_factory( 'game-3', self.toolbar, self._new_game_cb, cb_arg=3, tooltip=_('Play attention game (color symbols).'), group=self.radio[0])) """ self.status = label_factory(self.toolbar, '') separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() def _new_game_cb(self, button=None, game=0): ''' Reload a new level. ''' self._game.new_game(game=game, restart=(not self._restoring)) def write_file(self, file_path): """ Write the grid status to the Journal """ dot_list, correct, level, game = self._game.save_game() self.metadata['dotlist'] = '' for dot in dot_list: self.metadata['dotlist'] += str(dot) if dot_list.index(dot) < len(dot_list) - 1: self.metadata['dotlist'] += ' ' self.metadata['correct'] = str(correct) self.metadata['level'] = str(level) self.metadata['game'] = str(game) def _restore(self): """ Restore the game state from metadata """ self._restoring = True dot_list = [] dots = self.metadata['dotlist'].split() for dot in dots: dot_list.append(int(dot)) if 'correct' in self.metadata: correct = int(self.metadata['correct']) else: correct = 0 if 'level' in self.metadata: level = int(self.metadata['level']) else: level = 0 if 'game' in self.metadata: game = int(self.metadata['game']) self.radio[game].set_active(True) else: game = 0 self._game.restore_game(dot_list, correct, level, game) self._restoring = False # Collaboration-related methods def _setup_collab(self): """ Setup the Collab Wrapper. """ self.initiating = None # sharing (True) or joining (False) self._collab = CollabWrapper(self) self._collab.connect('message', self.__message_cb) owner = self._collab._leader self.owner = owner self._game.set_sharing(True) def __message_cb(self, collab, buddy, message): action = message.get('action') payload = message.get('payload') if action == 'n': '''Get a new game grid''' self._receive_new_game(payload) elif action == 'p': '''Get a dot click''' self._receive_dot_click(payload) def send_new_game(self): ''' Send a new grid to all players ''' self._collab.post( dict(action='n', payload=json_dump(self._game.save_game()))) def _receive_new_game(self, payload): ''' Sharer can start a new game. ''' dot_list, correct, level, game = json_load(payload) self._game.restore_game(dot_list, correct, level, game) def send_dot_click(self, dot, color): ''' Send a dot click to all the players ''' self._collab.post(dict(action='p', payload=json_dump([dot, color]))) def _receive_dot_click(self, payload): ''' When a dot is clicked, everyone should change its color. ''' (dot, color) = json_load(payload) self._game.remote_button_press(dot, color)
class CollabEdit(Gtk.VBox): __gsignals__ = { "insert-char": (GObject.SIGNAL_RUN_FIRST, None, [int, int]), "cursor-position-changed": (GObject.SIGNAL_RUN_FIRST, None, [int]) } def __init__(self, activity): Gtk.VBox.__init__(self) self.collab = CollabWrapper(activity) self.collab.connect('message', self.__message_cb) self.collab.connect('joined', self.__joined_cb) self.view = View() self.view.connect("insert-char", self.__insert_char_cb) self.view.connect("cursor-position-changed", self.__cursor_position_changed_cb) self.view.connect("tag-applied", self.__tag_applied_cb) self.view.connect("tag-removed", self.__tag_removed_cb) self.pack_start(self.view, True, True, 0) def __message_cb(self, collab, buddy, msg): action = msg.get("action") if action is None: return elif action == "insert": self.view.insert_at_position(msg.get("key"), msg.get("position")) elif action == "curosr_moved": self.view.draw_other_cursor(msg.get("id"), msg.get("position")) elif action == "insert_tag": self.view.insert_tag(msg.get("tag"), msg.get("start"), msg.get("end")) elif action == "remove_tag": self.view.remove_tag(msg.get("tag"), msg.get("start"), msg.get("end")) def __joined_cb(self, sender): if self.collab._leader: return self.collab.post(dict(action='init_request', res_id=10)) # How get an unique id? def __insert_char_cb(self, view, key, position): if key in utils.LETTERS_KEYS: self.collab.post(dict(action="insert", key=Gdk.keyval_name(key), position=position)) def __cursor_position_changed_cb(self, view, position): self.collab.post(dict(action="cursor_moved", id=10, # How get an unique id? position=position)) self.emit("cursor-position-changed", position) def __tag_applied_cb(self, buffer, tag, start, end): self.collab.post(dict(action="insert_tag", tag=tag, start=start, end=end)) def __tag_removed_cb(self, buffer, tag, start, end): self.collab.post(dict(action="remove_tag", tag=tag, start=start, end=end)) def toggle_bold(self): self.view.toggle_bold() def toggle_italic(self): self.view.toggle_italic() def toggle_underline(self): self.view.toggle_underline() def check_tag_at_offset(self, tag, position): return self.view.check_tag_at_offset(tag, position)
class GNUChessActivity(activity.Activity): ''' Gnuchess interface from Sugar ''' def __init__(self, handle): ''' Initialize the toolbars and the gnuchess ''' try: super(GNUChessActivity, self).__init__(handle) except dbus.exceptions.DBusException as e: _logger.error(str(e)) self.game_data = None self.playing_white = True self.playing_mode = 'easy' self.playing_robot = True self.showing_game_history = False self._restoring = True self.stopwatch_running = False self.time_interval = None self.timer_panel_visible = False self.nick = profile.get_nick_name() if profile.get_color() is not None: self.colors = profile.get_color().to_string().split(',') else: self.colors = ['#A0FFA0', '#FF8080'] self.buddy = None self.opponent_colors = None self.hardware = get_hardware() self._setup_toolbars() self._setup_dispatch_table() # Create a canvas canvas = Gtk.DrawingArea() canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self.set_canvas(canvas) canvas.show() self.show_all() self.old_cursor = self.get_window().get_cursor() self._gnuchess = Gnuchess(canvas, parent=self, path=activity.get_bundle_path(), colors=self.colors) self.connect('shared', self._shared_cb) self.connect('joined', self._joined_cb) self._restoring = False self.collab = CollabWrapper(self) self.collab.connect('message', self._message_cb) self.collab.connect('joined', self._joined_cb) self.collab.setup() # Send the nick to our opponent if not self.collab.props.leader: self.send_nick() # And let the sharer know we've joined self.send_join() if self.game_data is not None: # 'saved_game' in self.metadata: self._restore() else: self._gnuchess.new_game() def set_data(self, data): pass def get_data(self): return None def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) def restore_cursor(self): ''' No longer thinking, so restore standard cursor. ''' self.get_window().set_cursor(self.old_cursor) def set_thinking_cursor(self): ''' Thinking, so set watch cursor. ''' self.old_cursor = self.get_window().get_cursor() Watch = Gdk.Cursor(Gdk.CursorType.WATCH) self.get_window().set_cursor(Watch) def _setup_toolbars(self): ''' Setup the toolbars. ''' self.max_participants = 2 self.edit_toolbar = Gtk.Toolbar() self.view_toolbar = Gtk.Toolbar() self.adjust_toolbar = Gtk.Toolbar() self.custom_toolbar = Gtk.Toolbar() toolbox = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbox.toolbar.insert(activity_button, 0) activity_button.show() edit_toolbar_button = ToolbarButton(label=_("Edit"), page=self.edit_toolbar, icon_name='toolbar-edit') self.edit_toolbar.show() toolbox.toolbar.insert(edit_toolbar_button, -1) edit_toolbar_button.show() view_toolbar_button = ToolbarButton(label=_("View"), page=self.view_toolbar, icon_name='toolbar-view') self.view_toolbar.show() toolbox.toolbar.insert(view_toolbar_button, -1) view_toolbar_button.show() adjust_toolbar_button = ToolbarButton(label=_('Adjust'), page=self.adjust_toolbar, icon_name='preferences-system') self.adjust_toolbar.show() toolbox.toolbar.insert(adjust_toolbar_button, -1) adjust_toolbar_button.show() custom_toolbar_button = ToolbarButton(label=_("Custom"), page=self.custom_toolbar, icon_name='view-source') self.custom_toolbar.show() toolbox.toolbar.insert(custom_toolbar_button, -1) custom_toolbar_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.toolbar = toolbox.toolbar adjust_toolbar_button.set_expanded(True) button_factory('edit-copy', self.edit_toolbar, self._copy_cb, tooltip=_('Copy'), accelerator='<Ctrl>c') button_factory('edit-paste', self.edit_toolbar, self._paste_cb, tooltip=_('Paste'), accelerator='<Ctrl>v') button_factory('view-fullscreen', self.view_toolbar, self.do_fullscreen_cb, tooltip=_('Fullscreen'), accelerator='<Alt>Return') button_factory('media-playback-start', self.view_toolbar, self._play_history_cb, tooltip=_('Play game history')) self.history_button = button_factory('list-numbered', self.view_toolbar, self._show_history_cb, tooltip=_('Show game history')) separator_factory(self.view_toolbar, False, True) label_factory(self.view_toolbar, _('White: ')) self.white_entry = entry_factory('', self.view_toolbar, tooltip=_("White's move")) separator_factory(self.view_toolbar, False, False) label_factory(self.view_toolbar, _('Black: ')) self.black_entry = entry_factory('', self.view_toolbar, tooltip=_("Black's move")) separator_factory(self.view_toolbar, False, True) skin_button1 = radio_factory('white-knight', self.view_toolbar, self.do_default_skin_cb, tooltip=_('Default pieces'), group=None) skin_button2 = radio_factory('white-knight-sugar', self.view_toolbar, self.do_sugar_skin_cb, tooltip=_('Sugar-style pieces'), group=skin_button1) xocolors = XoColor(','.join(self.colors)) icon = Icon(icon_name='white-knight-sugar', xo_color=xocolors) icon.show() skin_button2.set_icon_widget(icon) self.skin_button3 = radio_factory('white-knight-custom', self.view_toolbar, self.do_custom_skin_cb, tooltip=_('Custom pieces'), group=skin_button1) skin_button1.set_active(True) self.play_white_button = radio_factory('white-rook', self.adjust_toolbar, self._play_white_cb, group=None, tooltip=_('Play White')) self.play_black_button = radio_factory('black-rook', self.adjust_toolbar, self._play_black_cb, group=self.play_white_button, tooltip=_('Play Black')) self.play_white_button.set_active(True) separator_factory(self.adjust_toolbar, False, True) self.easy_button = radio_factory('beginner', self.adjust_toolbar, self._easy_cb, group=None, tooltip=_('Beginner')) self.hard_button = radio_factory('expert', self.adjust_toolbar, self._hard_cb, group=self.easy_button, tooltip=_('Expert')) self.easy_button.set_active(True) separator_factory(self.adjust_toolbar, False, True) self.robot_button = radio_factory( 'robot', self.adjust_toolbar, self._robot_cb, group=None, tooltip=_('Play against the computer')) self.human_button = radio_factory('human', self.adjust_toolbar, self._human_cb, group=self.robot_button, tooltip=_('Play against a person')) separator_factory(self.adjust_toolbar, False, False) self.opponent = label_factory(self.adjust_toolbar, '') separator_factory(self.adjust_toolbar, False, True) self.timer_button = ToolButton('timer-0') self.timer_button.set_tooltip(_('Timer')) self.timer_button.connect('clicked', self._timer_button_cb) self.toolbar.insert(self.timer_button, -1) self._setup_timer_palette() self.timer_button.show() self.timer_button.set_sensitive(True) self.robot_button.set_active(True) button_factory('new-game', self.toolbar, self._new_gnuchess_cb, tooltip=_('New game')) button_factory('edit-undo', self.toolbar, self._undo_cb, tooltip=_('Undo')) button_factory('hint', self.toolbar, self._hint_cb, tooltip=_('Hint')) separator_factory(self.toolbar, False, False) self.status = label_factory(self.toolbar, '', width=150) self.status.set_label(_("It is White's move.")) separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = '<Ctrl>q' toolbox.toolbar.insert(stop_button, -1) stop_button.show() for piece in list(PIECES.keys()): for color in ['white', 'black']: button_factory('%s-%s' % (color, piece), self.custom_toolbar, self._reskin_cb, cb_arg='%s_%s' % (color, piece), tooltip=PIECES[piece][color]) def do_default_skin_cb(self, button=None): for piece in list(PIECES.keys()): for color in ['white', 'black']: self._gnuchess.reskin_from_file( '%s_%s' % (color, piece), '%s/icons/%s-%s.svg' % (activity.get_bundle_path(), color, piece)) def _black_pieces(self, colors): for piece in list(PIECES.keys()): self._gnuchess.reskin_from_svg('black_%s' % piece, colors, bw='#000000') def _white_pieces(self, colors): for piece in list(PIECES.keys()): self._gnuchess.reskin_from_svg('white_%s' % piece, colors, bw='#ffffff') def do_sugar_skin_cb(self, button=None): colors = self.colors if not self._gnuchess.we_are_sharing: self._black_pieces(colors) self._white_pieces(colors) else: if self.playing_white: self._white_pieces(colors) if self.opponent_colors is not None: colors = self.opponent_colors self._black_pieces(colors) else: self._black_pieces(colors) if self.opponent_colors is not None: colors = self.opponent_colors self._white_pieces(colors) def do_custom_skin_cb(self, button=None): for piece in list(PIECES.keys()): for color in ['white', 'black']: name = '%s_%s' % (color, piece) if name in self.metadata: id = self.metadata[name] jobject = datastore.get(id) if jobject is not None and jobject.file_path is not None: self._do_reskin(name, jobject.file_path) def _do_reskin(self, name, file_path): ''' If we are sharing, only reskin pieces of your color ''' if self._gnuchess.we_are_sharing and self.buddy is not None: if 'white' in name and self.playing_white: pixbuf = self._gnuchess.reskin_from_file(name, file_path, return_pixbuf=True) self.send_piece(name, pixbuf) elif 'black' in name and not self.playing_white: pixbuf = self._gnuchess.reskin_from_file(name, file_path, return_pixbuf=True) self.send_piece(name, pixbuf) else: self._gnuchess.reskin_from_file(name, file_path) return def _timer_button_cb(self, button): if not self.timer_palette.is_up() and not self.timer_panel_visible: self.timer_palette.popup(immediate=True) self.timer_panel_visible = True else: self.timer_palette.popdown(immediate=True) self.timer_panel_visible = False def _setup_timer_palette(self): self.timer_values = [None, 30, 180, 600] self.timer_tooltips = [ '', _('30 seconds'), _('3 minutes'), _('10 minutes') ] self.timer_labels = [ _('Disabled'), # TRANS: Lightning chess 30 seconds between moves _('Lightning: %d seconds') % (30), # TRANS: Blitz chess 3 minutes between moves _('Blitz: %d minutes') % (3), # TRANS: Tournament chess 10 minutes between moves _('Tournament: %d minutes') % (10) ] self.timer_palette = self.timer_button.get_palette() for i, label in enumerate(self.timer_labels): menu_item = MenuItem(icon_name='timer-%d' % (i), text_label=label) menu_item.connect('activate', self._timer_selected_cb, i) self.timer_palette.menu.append(menu_item) menu_item.show() def _timer_selected_cb(self, button, index): game_already_started = 0 if self.time_interval is not None: game_already_started = 1 self.time_interval = self.timer_values[index] if self.time_interval is None: self.timer_button.set_tooltip(_('Timer off')) else: self.timer_button.set_tooltip( _('Timer') + ' (' + self.timer_tooltips[index] + ')') if game_already_started: self.alert_reset(self.timer_labels[index]) if self.time_interval and self.time_interval is not None: self.stopwatch(self.time_interval, self.alert_time) else: GLib.source_remove(self.stopwatch_timer) else: self._gnuchess.new_game() def _reskin_cb(self, button, piece): object_id, file_path = self._choose_skin() if file_path is not None: self._do_reskin(piece, file_path) self.metadata[piece] = str(object_id) def do_fullscreen_cb(self, button): ''' Hide the Sugar toolbars. ''' self.fullscreen() def _play_history_cb(self, button): self._gnuchess.play_game_history() return def _show_history_cb(self, button): self._gnuchess.show_game_history(self.tag_pairs()) if self.showing_game_history: self.history_button.set_icon_name('checkerboard') self.history_button.set_tooltip(_('Show game board')) else: self.history_button.set_icon_name('list-numbered') self.history_button.set_tooltip(_('Show game history')) return def _copy_cb(self, *args): clipboard = Gtk.Clipboard() clipboard.set_text(self.tag_pairs() + self._gnuchess.copy_game()) def _paste_cb(self, *args): ''' Pasting ''' clipboard = Gtk.Clipboard() move_list = self._parse_move_list(clipboard.wait_for_text()) if move_list is not None: self._gnuchess.restore_game(move_list) def _parse_move_list(self, text): ''' Take a standard game description and return a move list ''' # Assuming of form ... 1. e4 e6 2. ... move_list = [] found_one = False comment = False for move in text.split(): if move[0] == '{': comment = True elif move[-1] == '}': comment = False if not comment: if move == '1.': found_one = True number = True white = False elif found_one: if not number: number = True elif not white: move_list.append(move) white = True else: move_list.append(move) number = False white = False return move_list def _undo_cb(self, *args): # No undo while sharing if self.collab.props.leader is None: self._gnuchess.undo() def _hint_cb(self, *args): self._gnuchess.hint() def _play_white_cb(self, *args): if not self.play_white_button.get_active(): return if not self._restoring: self._new_game_alert('white') return True def _play_black_cb(self, *args): if not self.play_black_button.get_active(): return if not self._restoring: self._new_game_alert('black') return True def _easy_cb(self, *args): if not self.easy_button.get_active(): return if not self._restoring: self._new_game_alert('easy') return True def _hard_cb(self, *args): if not self.hard_button.get_active(): return if not self._restoring: self._new_game_alert('hard') return True def _robot_cb(self, *args): if not self.robot_button.get_active(): return if not self._restoring: self._new_game_alert('robot') return True def _human_cb(self, *args): if not self.human_button.get_active(): return if not self._restoring: self._new_game_alert('human') return True def _new_gnuchess_cb(self, button=None): ''' Start a new gnuchess. ''' self._new_game_alert('new') def tag_pairs(self): ''' Tag paris must be ascii ''' if type(self.nick) is str: nick = self.nick.encode('ascii', 'replace') else: nick = self.nick if self.buddy is not None and type(self.buddy) is str: buddy = self.buddy.encode('ascii', 'replace') else: buddy = self.buddy if self.playing_white: white = nick if self.playing_robot: black = 'gnuchess (%s)' % (self.playing_mode) elif self._gnuchess.we_are_sharing and buddy is not None: black = buddy else: black = '?' else: black = nick if self.playing_robot: white = 'gnuchess (%s)' % (self.playing_mode) elif self._gnuchess.we_are_sharing and buddy is not None: white = buddy else: white = '?' return '[White "%s"]\n[Black "%s"]\n\n' % (white, black) def write_file(self, file_path): ''' Write the grid status to the Journal ''' fd = open(file_path, 'w') fd.write(self.tag_pairs()) fd.write(self._gnuchess.copy_game()) fd.close() # self.metadata['saved_game'] = json_dump(self._gnuchess.save_game()) if self.playing_white: self.metadata['playing_white'] = 'True' else: self.metadata['playing_white'] = 'False' self.metadata['playing_mode'] = self.playing_mode if self.playing_robot: self.metadata['playing_robot'] = 'True' else: self.metadata['playing_robot'] = 'False' ''' self.metadata['timer_mode'] = self.timer.get_active_text() ''' def read_file(self, file_path): ''' Read project file on relaunch ''' fd = open(file_path, 'r') self.game_data = fd.read() fd.close() _logger.debug(self.game_data) def _restore(self): ''' Restore the gnuchess state from metadata ''' if 'playing_white' in self.metadata: if self.metadata['playing_white'] == 'False': self.playing_white = False self.play_black_button.set_active(True) if 'playing_mode' in self.metadata: self.playing_mode = self.metadata['playing_mode'] if self.playing_mode == 'hard': self.hard_button.set_active(True) if 'playing_robot' in self.metadata: if self.metadata['playing_robot'] == 'False': self.playing_robot = False self.human_button.set_active(True) ''' if 'timer_mode' in self.metadata: self.timer_intervale.set_active(self.timer_list.index( self.metadata['timer_mode'])) ''' self._gnuchess.restore_game(self._parse_move_list(self.game_data)) self.do_custom_skin_cb() def _choose_skin(self): ''' Select a skin from the Journal ''' chooser = None name = None if hasattr(mime, 'GENERIC_TYPE_IMAGE'): if 'image/svg+xml' not in \ mime.get_generic_type(mime.GENERIC_TYPE_IMAGE).mime_types: mime.get_generic_type( mime.GENERIC_TYPE_IMAGE).mime_types.append('image/svg+xml') chooser = ObjectChooser(parent=self, what_filter=mime.GENERIC_TYPE_IMAGE) else: try: chooser = ObjectChooser(parent=self, what_filter=None) except TypeError: chooser = ObjectChooser( None, activity, Gtk.DialogType.MODAL | Gtk.DialogType.DESTROY_WITH_PARENT) if chooser is not None: try: result = chooser.run() if result == Gtk.ResponseType.ACCEPT: jobject = chooser.get_selected_object() if jobject and jobject.file_path: name = jobject.metadata['title'] finally: jobject.destroy() chooser.destroy() del chooser if name is not None: return jobject.object_id, jobject.file_path else: return None, None def _take_button_action(self, button): if button == 'black': self.playing_white = False elif button == 'white': self.playing_white = True elif button == 'easy': self.playing_mode = 'easy' elif button == 'hard': self.playing_mode = 'hard' elif button == 'robot': self.playing_robot = True elif button == 'human': self.playing_robot = False self._gnuchess.new_game() def _no_action(self, button): if button == 'black': self.play_white_button.set_active(True) self.playing_white = True elif button == 'white': self.play_black_button.set_active(True) self.playing_white = False elif button == 'easy': self.hard_button.set_active(True) self.playing_mode = 'hard' elif button == 'hard': self.easy_button.set_active(True) self.playing_mode = 'easy' elif button == 'robot': self.human_button.set_active(True) self.playing_robot = False elif button == 'human': self.robot_button.set_active(True) self.playing_robot = True def _new_game_alert(self, button): ''' We warn the user if the game is in progress before loading a new game. ''' if self.collab.props.leader is not None and not self.collab.props.leader: # joiner cannot push buttons self._restoring = True self._no_action(button) self._restoring = False return if len(self._gnuchess.move_list) == 0: self._take_button_action(button) return self._restoring = True alert = ConfirmationAlert() alert.props.title = _('Game in progress.') alert.props.msg = _('Do you want to start a new game?') def _new_game_alert_response_cb(alert, response_id, self, button): if response_id is Gtk.ResponseType.OK: self._take_button_action(button) elif response_id is Gtk.ResponseType.CANCEL: self._no_action(button) self._restoring = False self.remove_alert(alert) alert.connect('response', _new_game_alert_response_cb, self, button) self.add_alert(alert) alert.show() # Collaboration-related methods def _shared_cb(self, activity): ''' Either set up initial share...''' _logger.debug('shared') self.after_share_join(True) def _joined_cb(self, activity): ''' ...or join an exisiting share. ''' _logger.debug('joined') self.after_share_join(False) self.send_nick() # And let the sharer know we've joined self.send_join() def after_share_join(self, sharer): self._gnuchess.set_sharing(True) self.restoring = True self.playing_robot = False self.human_button.set_active(True) self.robot_button.set_active(False) self.restoring = False self.easy_button.set_sensitive(False) self.hard_button.set_sensitive(False) self.robot_button.set_sensitive(False) def _setup_dispatch_table(self): ''' Associate tokens with commands. ''' self._processing_methods = { 'n': [self._receive_new_game, 'start a new game'], 'm': [self._receive_move, 'make a move'], 'r': [self._receive_restore, 'restore game state'], 'N': [self._receive_nick, 'receive nick from opponent'], 'C': [self._receive_colors, 'receive colors from opponent'], 'j': [self._receive_join, 'receive new joiner'], 'p': [self._receive_piece, 'receive new piece'], } def _message_cb(self, collab, buddy, msg): ''' Data from a tube has arrived. ''' command = msg.get("command") payload = msg.get("payload") self._processing_methods[command][0](payload) def send_new_game(self): ''' Send a new game to joiner. ''' if not self.collab.props.leader: return self.send_nick() if self.playing_white: _logger.debug('send_new_game: B') self.send_event("n", "B") else: _logger.debug('send_new_game: W') self.send_event("n", "W") def send_restore(self): ''' Send a new game to joiner. ''' if not self.collab.props.leader: return _logger.debug('send_restore') self.send_event("r", self._gnuchess.copy_game()) def send_join(self): _logger.debug('send_join') self.send_event("j", self.nick) def send_nick(self): _logger.debug('send_nick') self.send_event("N", self.nick) self.send_event("C", "%s,%s" % (self.colors[0], self.colors[1])) def alert_time(self): def _alert_response_cb(alert, response_id): self.remove_alert(alert) alert = NotifyAlert() alert.props.title = _('Time Up!') alert.props.msg = _('Your time is up.') alert.connect('response', _alert_response_cb) alert.show() self.add_alert(alert) def alert_reset(self, mode): def _alert_response_cb(alert, response_id): self.remove_alert(alert) alert = NotifyAlert() alert.props.title = _('Time Reset') alert.props.msg = _('The timer mode was reset to %s' % mode) alert.connect('response', _alert_response_cb) alert.show() self.add_alert(alert) def stopwatch(self, time, alert_callback): if self.stopwatch_running: GLib.source_remove(self.stopwatch_timer) time = self.time_interval self.stopwatch_timer = GLib.timeout_add(time * 1000, alert_callback) self.stopwatch_running = True def _receive_join(self, payload): _logger.debug('received_join %s' % (payload)) if self.collab.props.leader: self.send_new_game() _logger.debug(self.game_data) if self.game_data is not None: self.send_restore() def _receive_nick(self, payload): _logger.debug('received_nick %s' % (payload)) self.buddy = payload self.opponent.set_label(self.buddy) if self.collab.props.leader: self.send_nick() def _receive_colors(self, payload): _logger.debug('received_colors %s' % (payload)) self.opponent_colors = payload.split(',') xocolors = XoColor(payload) icon = Icon(icon_name='human', xo_color=xocolors) icon.show() self.human_button.set_icon_widget(icon) self.human_button.show() def _receive_restore(self, payload): ''' Get game state from sharer. ''' if self.collab.props.leader: return _logger.debug('received_restore %s' % (payload)) self._gnuchess.restore_game(self._parse_move_list(payload)) def _receive_move(self, payload): ''' Get a move from opponent. ''' _logger.debug('received_move %s' % (payload)) self._gnuchess.remote_move(payload) def _receive_new_game(self, payload): ''' Sharer can start a new gnuchess. ''' _logger.debug('receive_new_game %s' % (payload)) # The leader cannot receive new game if self.collab.props.leader: return self.send_nick() if payload == 'W': if not self.playing_white: self.restoring = True self.play_black_button.set_active(False) self.play_white_button.set_active(True) self.playing_white = True else: if self.playing_white: self.restoring = True self.play_white_button.set_active(False) self.play_black_button.set_active(True) self.playing_white = False self.robot_button.set_active(False) self.human_button.set_active(True) self.playing_robot = False self.restoring = False self._gnuchess.set_sharing(True) self._gnuchess.new_game() def send_event(self, command, payload): ''' Send event through the tube. ''' if hasattr(self, 'collab') and self.collab is not None: self.collab.post(dict(command=command, payload=payload)) # sharing pieces def send_piece(self, piece, pixbuf): _logger.debug('send_piece %s' % (piece)) GLib.idle_add(self.send_event, ("p", self._dump(piece, pixbuf))) def _receive_piece(self, payload): piece, pixbuf = self._load(payload) _logger.debug('received_piece %s' % (piece)) self._gnuchess.reskin(piece, pixbuf) def _dump(self, piece, pixbuf): ''' Dump data for sharing.''' _logger.debug('dumping %s' % (piece)) data = [piece, pixbuf_to_base64(activity, pixbuf)] return json_dump(data) def _load(self, data): ''' Load game data from the journal. ''' piece, pixbuf_data = json_load(data) pixbuf = base64_to_pixbuf(activity, pixbuf_data, width=self._gnuchess.scale, height=self._gnuchess.scale) return piece, pixbuf