You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(8) |
Sep
(3) |
Oct
(5) |
Nov
|
Dec
(1) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
(7) |
Mar
(17) |
Apr
(37) |
May
|
Jun
(46) |
Jul
(40) |
Aug
(2) |
Sep
(4) |
Oct
(2) |
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <umg...@us...> - 2007-06-20 15:14:27
|
Revision: 432 http://svn.sourceforge.net/pybridge/?rev=432&view=rev Author: umgangee Date: 2007-06-20 08:14:28 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Add simple vulnerability rotation. TODO: consider vulnerability rules for duplicate, rubber bridge. Modified Paths: -------------- trunk/pybridge/pybridge/bridge/board.py trunk/pybridge/pybridge/bridge/game.py Modified: trunk/pybridge/pybridge/bridge/board.py =================================================================== --- trunk/pybridge/pybridge/bridge/board.py 2007-06-20 15:13:03 UTC (rev 431) +++ trunk/pybridge/pybridge/bridge/board.py 2007-06-20 15:14:28 UTC (rev 432) @@ -65,6 +65,11 @@ self['dealer'] = random.choice(Direction) if result: - self['vuln'] = Vulnerable.All # TODO + # TODO: proper GameResult object. + # TODO: consider vulnerability rules for duplicate, rubber bridge. + #if result.bidding.isPassedOut(): + # self['vuln'] = result.board['vuln'] + #elif result.getScore() >= 0 + self['vuln'] = Vulnerable[(result.board['vuln'].index + 1) % 4] else: self['vuln'] = Vulnerable.None # The default value. Modified: trunk/pybridge/pybridge/bridge/game.py =================================================================== --- trunk/pybridge/pybridge/bridge/game.py 2007-06-20 15:13:03 UTC (rev 431) +++ trunk/pybridge/pybridge/bridge/game.py 2007-06-20 15:14:28 UTC (rev 432) @@ -79,7 +79,7 @@ if board: # Use specified board. self.board = board elif self.board: # Advance to next deal. - self.board.nextDeal(result=999) + self.board.nextDeal(result=self) # TODO: proper GameResult object. else: # Create a board. self.board = Board() self.board.nextDeal() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-20 15:13:24
|
Revision: 431 http://svn.sourceforge.net/pybridge/?rev=431&view=rev Author: umgangee Date: 2007-06-20 08:13:03 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Add "click to start next game" message to game result dialog, fix "show no buttons when bidding passed out" bug. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-20 15:10:30 UTC (rev 430) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-20 15:13:03 UTC (rev 431) @@ -267,8 +267,7 @@ self.setTurnIndicator() - dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, - type=gtk.MESSAGE_INFO) + dialog = gtk.MessageDialog(parent=self.window, type=gtk.MESSAGE_INFO) dialog.set_title(_('Game result')) # Determine and display score in dialog box. @@ -281,26 +280,24 @@ contractText = self.formatContract(self.table.game.contract) if offset > 0: - dialog.set_markup(_('Contract %s made by %s tricks.') \ - % (contractText, offset)) + resultText = _('Contract %s made by %s tricks.') % (contractText, offset) elif offset < 0: - dialog.set_markup(_('Contract %s failed by %s tricks.') \ - % (contractText, abs(offset))) + resultText = _('Contract %s failed by %s tricks.') % (contractText, abs(offset)) else: - dialog.set_markup(_('Contract %s made exactly.') % contractText) - + resultText = _('Contract %s made exactly.') % contractText scorer = (score >= 0 and _('declarer')) or _('defence') - dialog.format_secondary_text(_('Score %s points for %s.' % (abs(score), scorer))) + scoreText = _('Score %s points for %s.' % (abs(score), scorer)) + dialog.set_markup(resultText + '\n' + scoreText) - if self.player: - dialog.add_button(_('Leave Seat'), gtk.RESPONSE_CANCEL) - dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) - - else: dialog.set_markup(_('Bidding passed out.')) dialog.format_secondary_text(_('No score.')) + if self.player: + dialog.add_button(_('Leave Seat'), gtk.RESPONSE_CANCEL) + dialog.format_secondary_text(_('Click OK to start next game.')) + dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + def dialog_response_cb(dialog, response_id): dialog.destroy() if self.player: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-20 15:10:34
|
Revision: 430 http://svn.sourceforge.net/pybridge/?rev=430&view=rev Author: umgangee Date: 2007-06-20 08:10:30 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Display notification dialog when connection is lost unexpectedly. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_main.py Modified: trunk/pybridge/pybridge/ui/window_main.py =================================================================== --- trunk/pybridge/pybridge/ui/window_main.py 2007-06-20 15:09:13 UTC (rev 429) +++ trunk/pybridge/pybridge/ui/window_main.py 2007-06-20 15:10:30 UTC (rev 430) @@ -96,7 +96,7 @@ # Event handlers. - def event_connectedAsUser(self, username): + def event_loggedIn(self, username): self.notebook.set_property('sensitive', True) self.menu_connect.set_property('visible', False) self.menu_disconnect.set_property('visible', True) @@ -104,7 +104,7 @@ self.newtable.set_property('sensitive', True) - def event_connectionLost(self, reason): + def event_loggedOut(self): for table in self.tables.values(): self.tables.close(table) @@ -118,6 +118,23 @@ self.peopleview_model.clear() + def event_connectionLost(self, host, port): + dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, + type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK) + dialog.set_title(_('Connection to server lost')) + dialog.set_markup(_('The connection to %s was lost unexpectedly.' % host)) + dialog.format_secondary_text(_('Please check your computer\'s network connection status. If you cannot reconnect, the server may be offline.')) + # If this problem persists... + + #dialog.add_button() + + def dialog_response_cb(dialog, response_id): + dialog.destroy() + + dialog.connect('response', dialog_response_cb) + dialog.show() + + def event_gotRoster(self, name, roster): lookup = {'tables' : (self.tableview_model, self.tableview_icon), 'users' : (self.peopleview_model, self.peopleview_icon)} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-20 15:09:28
|
Revision: 429 http://svn.sourceforge.net/pybridge/?rev=429&view=rev Author: umgangee Date: 2007-06-20 08:09:13 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Force disconnect from server when connect/login fails, so multiple connections are avoided. Modified Paths: -------------- trunk/pybridge/pybridge/ui/dialog_connection.py Modified: trunk/pybridge/pybridge/ui/dialog_connection.py =================================================================== --- trunk/pybridge/pybridge/ui/dialog_connection.py 2007-06-20 15:07:38 UTC (rev 428) +++ trunk/pybridge/pybridge/ui/dialog_connection.py 2007-06-20 15:09:13 UTC (rev 429) @@ -67,15 +67,22 @@ def connectFailure(self, failure): """Actions to perform when connecting fails.""" - error = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, - type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK) - error.set_markup(_('Could not connect to server.')) - error.format_secondary_text(_('Reason: %s') % failure.getErrorMessage()) - error.run() - error.destroy() - self.button_connect.set_property('sensitive', True) + client.disconnect() + dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, + type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK) + dialog.set_title(_('Connection failed')) + dialog.set_markup(_('Could not connect to server.')) + dialog.format_secondary_text(_('Reason: %s') % failure.getErrorMessage()) + def dialog_response_cb(dialog, response_id): + dialog.destroy() + self.button_connect.set_property('sensitive', True) + + dialog.connect('response', dialog_response_cb) + dialog.show() + + # Signal handlers. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-20 15:07:37
|
Revision: 428 http://svn.sourceforge.net/pybridge/?rev=428&view=rev Author: umgangee Date: 2007-06-20 08:07:38 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Add code to determine when loss of connection is expected (disconnection) and when the connection is severed unexpectedly (network failure). Modified Paths: -------------- trunk/pybridge/pybridge/network/client.py Modified: trunk/pybridge/pybridge/network/client.py =================================================================== --- trunk/pybridge/pybridge/network/client.py 2007-06-20 15:04:58 UTC (rev 427) +++ trunk/pybridge/pybridge/network/client.py 2007-06-20 15:07:38 UTC (rev 428) @@ -48,6 +48,8 @@ self.factory = pb.PBClientFactory() self.factory.clientConnectionLost = self.connectionLost + self.expectLoseConnection = False # Indicates when disconnecting. + self.username = None self.tables = {} # Tables observed. self.tableRoster = None @@ -61,11 +63,17 @@ self.tables.clear() self.tableRoster.clear() self.userRoster.clear() + self.username = None - print "Lost connection: %s" % reason.getErrorMessage() - self.notify('connectionLost', reason=reason.getErrorMessage()) + self.notify('loggedOut') + if not self.expectLoseConnection: + # Connection lost unexpectedly, so notify user. + print "Lost connection: %s" % reason.getErrorMessage() + self.notify('connectionLost', host=connector.host, + port=connector.port) + def errback(self, failure): print "Error: %s" % failure.getErrorMessage() @@ -89,17 +97,21 @@ # Methods - def connect(self, hostname, port): + def connect(self, host, port): """Connect to server. - @param hostname: - @param port: + @param host: the host name or IP address of the server. + @type host: string + @param port: the port number on which the server is listening. + @type port: int """ - connector = reactor.connectTCP(hostname, port, self.factory) + connector = reactor.connectTCP(host, port, self.factory) + self.expectLoseConnection = False def disconnect(self): """Drops connection to server.""" + self.expectLoseConnection = True self.factory.disconnect() @@ -124,7 +136,7 @@ """Actions to perform when connection succeeds.""" self.avatar = avatar self.username = username - self.notify('connectedAsUser', username=username) + self.notify('loggedIn', username=username) # Request services from server. for rostername in ['tables', 'users']: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-20 15:05:01
|
Revision: 427 http://svn.sourceforge.net/pybridge/?rev=427&view=rev Author: umgangee Date: 2007-06-20 08:04:58 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Add call to startNextGame when bot becomes a player at game, don't name arguments to client.connect(). Modified Paths: -------------- trunk/pybridge/tests/monkey.py Modified: trunk/pybridge/tests/monkey.py =================================================================== --- trunk/pybridge/tests/monkey.py 2007-06-18 11:56:47 UTC (rev 426) +++ trunk/pybridge/tests/monkey.py 2007-06-20 15:04:58 UTC (rev 427) @@ -140,7 +140,10 @@ self.player = player self.position = position + d = self.player.callRemote('startNextGame') + d.addErrback(self.errback) + # Selection of calls and cards. @@ -263,7 +266,7 @@ client.factory.clientConnectionLost = lostConnection client.eventHandler = Monkey(client) - client.connect(hostname="localhost", port=5040) + client.connect("localhost", 5040) d = client.login(username, password) d.addCallbacks(client.eventHandler.connected, loginFailed) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-18 11:56:50
|
Revision: 426 http://svn.sourceforge.net/pybridge/?rev=426&view=rev Author: umgangee Date: 2007-06-18 04:56:47 -0700 (Mon, 18 Jun 2007) Log Message: ----------- Switch to ConfigObj configuration management. Modified Paths: -------------- trunk/pybridge/pybridge/ui/__init__.py trunk/pybridge/pybridge/ui/dialog_connection.py Modified: trunk/pybridge/pybridge/ui/__init__.py =================================================================== --- trunk/pybridge/pybridge/ui/__init__.py 2007-06-18 11:56:20 UTC (rev 425) +++ trunk/pybridge/pybridge/ui/__init__.py 2007-06-18 11:56:47 UTC (rev 426) @@ -32,8 +32,8 @@ gettext.textdomain('pybridge') gettext.install('pybridge') -filename = env.find_config_client('client.cfg') -settings = Settings(filename, ['Connection', 'General']) +import config +config.load() def run(): @@ -47,3 +47,5 @@ reactor.run() gtk.main() + config.save() # Save config at exit. + Modified: trunk/pybridge/pybridge/ui/dialog_connection.py =================================================================== --- trunk/pybridge/pybridge/ui/dialog_connection.py 2007-06-18 11:56:20 UTC (rev 425) +++ trunk/pybridge/pybridge/ui/dialog_connection.py 2007-06-18 11:56:47 UTC (rev 426) @@ -20,8 +20,8 @@ from wrapper import GladeWrapper from pybridge.network.client import client +from config import config from manager import wm -from pybridge.ui import settings TCP_PORT = 5040 @@ -34,13 +34,14 @@ def setUp(self): # Read connection parameters from client settings. - connection = settings.connection + connection = config['Connection'] if connection: - self.entry_hostname.set_text(connection['hostname']) - self.entry_portnum.set_text(connection['portnum']) - self.entry_username.set_text(connection['username']) - self.entry_password.set_text(connection['password']) - self.check_savepassword.set_active(connection['password'] != '') + self.entry_hostname.set_text(connection.get('HostAddress', 'localhost')) + self.entry_portnum.set_text(str(connection.get('Port', TCP_PORT))) + self.entry_username.set_text(connection.get('Username', '')) + password = connection.get('Password', '').decode('rot13') + self.entry_password.set_text(password) + self.check_savepassword.set_active(password != '') else: self.entry_portnum.set_text(str(TCP_PORT)) @@ -49,14 +50,17 @@ """Actions to perform when connecting succeeds.""" # Save connection information. - settings.connection = {} - settings.connection['hostname'] = self.entry_hostname.get_text() - settings.connection['portnum'] = self.entry_portnum.get_text() - settings.connection['username'] = self.entry_username.get_text() + connection = config['Connection'] + connection['HostAddress'] = self.entry_hostname.get_text() + connection['PortNumber'] = int(self.entry_portnum.get_text()) + connection['Username'] = self.entry_username.get_text() if self.check_savepassword.get_active(): - settings.connection['password'] = self.entry_password.get_text() - else: # Flush password. - settings.connection['password'] = '' + # Encode password, to confuse password sniffer software. + # ROT13 encoding does *not* provide security! + password = self.entry_password.get_text().encode('rot13') + else: + password = '' # Flush password. + connection['Password'] = password wm.close(self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-18 11:56:26
|
Revision: 425 http://svn.sourceforge.net/pybridge/?rev=425&view=rev Author: umgangee Date: 2007-06-18 04:56:20 -0700 (Mon, 18 Jun 2007) Log Message: ----------- Enhance game result dialog with "Leave Seat" option if playing, switch to ConfigObj configuration management. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-18 11:55:03 UTC (rev 424) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-18 11:56:20 UTC (rev 425) @@ -21,6 +21,7 @@ from cardarea import CardArea from pybridge.network.client import client +from config import config from eventhandler import SimpleEventHandler from manager import WindowManager @@ -220,7 +221,7 @@ iter = self.call_store.get_iter_first() while self.call_store.iter_next(iter) != None: iter = self.call_store.iter_next(iter) - + if isinstance(call, Bid): format = '%s%s' % (LEVEL_SYMBOLS[call.level], STRAIN_SYMBOLS[call.strain]) @@ -234,7 +235,7 @@ position = self.table.game.play.whoPlayed(card) column = position.index row = self.table.game.play.played[position].index(card) - + if self.trick_store.get_iter_first() == None: self.trick_store.append() iter = self.trick_store.get_iter_first() @@ -242,10 +243,9 @@ iter = self.trick_store.iter_next(iter) if iter is None: iter = self.trick_store.append() - + strain_equivalent = getattr(Strain, card.suit.key) # TODO: clean up. - format = '%s%s' % (STRAIN_SYMBOLS[strain_equivalent], - RANK_SYMBOLS[card.rank]) + format = '%s%s' % (RANK_SYMBOLS[card.rank], STRAIN_SYMBOLS[strain_equivalent]) self.trick_store.set(iter, column, format) @@ -268,7 +268,7 @@ self.setTurnIndicator() dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, - type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_OK) + type=gtk.MESSAGE_INFO) dialog.set_title(_('Game result')) # Determine and display score in dialog box. @@ -292,15 +292,23 @@ scorer = (score >= 0 and _('declarer')) or _('defence') dialog.format_secondary_text(_('Score %s points for %s.' % (abs(score), scorer))) + if self.player: + dialog.add_button(_('Leave Seat'), gtk.RESPONSE_CANCEL) + dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) + + else: dialog.set_markup(_('Bidding passed out.')) dialog.format_secondary_text(_('No score.')) def dialog_response_cb(dialog, response_id): dialog.destroy() - if self.player and self.table.game.isNextGameReady(): - d = self.player.callRemote('startNextGame') - d.addErrback(self.errback) + if self.player: + if response_id == gtk.RESPONSE_OK and self.table.game.isNextGameReady(): + d = self.player.callRemote('startNextGame') + d.addErrback(self.errback) + elif response_id == gtk.RESPONSE_CANCEL: + self.on_leaveseat_clicked(dialog) dialog.connect('response', dialog_response_cb) dialog.show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-18 11:55:02
|
Revision: 424 http://svn.sourceforge.net/pybridge/?rev=424&view=rev Author: umgangee Date: 2007-06-18 04:55:03 -0700 (Mon, 18 Jun 2007) Log Message: ----------- Display disconnect confirm dialog only when user is playing at a table, switch to ConfigObj configuration management. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_main.py Modified: trunk/pybridge/pybridge/ui/window_main.py =================================================================== --- trunk/pybridge/pybridge/ui/window_main.py 2007-06-18 11:53:43 UTC (rev 423) +++ trunk/pybridge/pybridge/ui/window_main.py 2007-06-18 11:55:03 UTC (rev 424) @@ -28,7 +28,6 @@ from eventhandler import SimpleEventHandler from manager import WindowManager, wm -from pybridge.ui import settings from dialog_connection import DialogConnection from dialog_newtable import DialogNewtable @@ -82,9 +81,7 @@ wm.close(window) client.disconnect() - settings.save() # Save configuration. - def quit(self): """Shut down gracefully.""" wm.close(self) @@ -244,16 +241,15 @@ def on_disconnect_activate(self, widget, *args): do_disconnect = True - #if len([True for table in self.tables if table.player]) > 0: - if self.tables: + if len([True for table in self.tables.values() if table.player]) > 0: dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, type=gtk.MESSAGE_QUESTION) - dialog.set_title(_('Disconnect from Server')) + dialog.set_title(_('Disconnect from server')) dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) dialog.add_button(gtk.STOCK_DISCONNECT, gtk.RESPONSE_OK) dialog.set_markup(_('Are you sure you wish to disconnect?')) - dialog.format_secondary_text(_('You are playing a game. Disconnecting may forfeit the game, or incur penalties.')) + dialog.format_secondary_text(_('You are playing at a table. Disconnecting may forfeit the game, or incur penalties.')) do_disconnect = (dialog.run() == gtk.RESPONSE_OK) dialog.destroy() @@ -292,7 +288,10 @@ logo_path = env.find_pixmap('pybridge.png') logo = gtk.gdk.pixbuf_new_from_file(logo_path) about.set_logo(logo) - - about.run() - about.destroy() + def dialog_response_cb(dialog, response_id): + dialog.destroy() + + about.connect('response', dialog_response_cb) + about.show() + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-18 11:53:45
|
Revision: 423 http://svn.sourceforge.net/pybridge/?rev=423&view=rev Author: umgangee Date: 2007-06-18 04:53:43 -0700 (Mon, 18 Jun 2007) Log Message: ----------- Add support for user-specifiable suit colours, switch to ConfigObj configuration management. Modified Paths: -------------- trunk/pybridge/pybridge/ui/dialog_preferences.py Modified: trunk/pybridge/pybridge/ui/dialog_preferences.py =================================================================== --- trunk/pybridge/pybridge/ui/dialog_preferences.py 2007-06-18 11:51:35 UTC (rev 422) +++ trunk/pybridge/pybridge/ui/dialog_preferences.py 2007-06-18 11:53:43 UTC (rev 423) @@ -21,8 +21,8 @@ from wrapper import GladeWrapper import pybridge.environment as env +from config import config from manager import wm -from pybridge.ui import settings from pybridge.bridge.symbols import Suit @@ -57,7 +57,7 @@ self.cardstyle.pack_start(cell, True) self.cardstyle.add_attribute(cell, 'text', 0) - activedeck = settings.appearance.get('deck', 'bonded.png') + activedeck = config['Appearance'].get('CardStyle', 'bonded.png') # Populate list of card decks. path = env.find_pixmap('') for filename in os.listdir(path): @@ -66,7 +66,17 @@ if filename == activedeck: self.cardstyle.set_active_iter(iter) + self.suit_colours = {} + for suit in Suit: + rgb = config['Appearance']['Colours'].get(suit.key, (0, 0, 0)) + colour = gtk.gdk.Color(*rgb) + self.suit_colours[suit] = colour + # Set button label colour from self.suit_colours. + hexrep = gtk.color_selection_palette_to_string([colour]) + label = getattr(self, 'label_%scolour' % suit.key.lower()) + label.set_markup(SUIT_LABEL_TEMPLATE % (hexrep, SUIT_SYMBOLS[suit])) + # Signal handlers. @@ -80,30 +90,25 @@ def on_suitcolour_clicked(self, widget, *args): # Get symbol in Suit corresponding to button clicked. - suit_buttons = {self.button_clubcolour: Suit.Club, - self.button_diamondcolour: Suit.Diamond, - self.button_heartcolour: Suit.Heart, - self.button_spadecolour: Suit.Spade } - suit = suit_buttons[widget] + suit = [s for s in Suit if s.key.lower() in widget.get_name()][0] title = _("Select colour for %s symbol" % SUIT_NAMES[suit]) dialog = gtk.ColorSelectionDialog(title) - dialog.colorsel.set_current_color(gtk.gdk.color_parse('#888888')) + dialog.colorsel.set_current_color(self.suit_colours[suit]) def dialog_response_cb(dialog, response_id): if response_id == gtk.RESPONSE_OK: colour = dialog.colorsel.get_current_color() - + self.suit_colours[suit] = colour # Set button label to colour selected by user. - label = widget.get_children()[0] hexrep = gtk.color_selection_palette_to_string([colour]) + label = getattr(self, 'label_%scolour' % suit.key.lower()) label.set_markup(SUIT_LABEL_TEMPLATE % (hexrep, SUIT_SYMBOLS[suit])) dialog.destroy() dialog.connect('response', dialog_response_cb) - #dialog.show() - dialog.run() + dialog.run() # show() def on_cancelbutton_clicked(self, widget, *args): @@ -111,6 +116,10 @@ def on_okbutton_clicked(self, widget, *args): - print "SAVE SETTINGS" + # Save preferences to config file. + for suit, colour in self.suit_colours.items(): + rgb = (colour.red, colour.green, colour.blue) + config['Appearance']['Colours'][suit.key] = rgb + print "TODO: background and card style" wm.close(self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-18 11:51:39
|
Revision: 422 http://svn.sourceforge.net/pybridge/?rev=422&view=rev Author: umgangee Date: 2007-06-18 04:51:35 -0700 (Mon, 18 Jun 2007) Log Message: ----------- Add wrapper for ConfigObj configuration management. ConfigObj has some nice features which are not in ConfigParser. Added Paths: ----------- trunk/pybridge/pybridge/ui/config.py Added: trunk/pybridge/pybridge/ui/config.py =================================================================== --- trunk/pybridge/pybridge/ui/config.py (rev 0) +++ trunk/pybridge/pybridge/ui/config.py 2007-06-18 11:51:35 UTC (rev 422) @@ -0,0 +1,64 @@ +# PyBridge -- online contract bridge made easy. +# Copyright (C) 2004-2007 PyBridge Project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +""" +Manages PyBridge client configuration file. +""" + +from StringIO import StringIO +from configobj import ConfigObj +from validate import Validator + +import pybridge.environment as env + +# Config spec +spec = StringIO("""# PyBridge configuration file + +[Connection] + HostAddress = string + PortNumber = integer(0, 65535) + Username = string + Password = string + +[Appearance] + CardStyle = string + BackgroundImage = string + + [[Colours]] + Club = int_list(3, 3) + Diamond = int_list(3, 3) + Heart = int_list(3, 3) + Spade = int_list(3, 3) + +""") + + +config = None +val = Validator() + +def load(): + global config + filename = env.find_config_client('config') + config = ConfigObj(filename, create_empty=True, configspec=spec) + config.validate(val, copy=True) + +def save(): + global config + config.validate(val, copy=True) + config.write() + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-16 13:21:42
|
Revision: 421 http://svn.sourceforge.net/pybridge/?rev=421&view=rev Author: umgangee Date: 2007-06-16 06:21:39 -0700 (Sat, 16 Jun 2007) Log Message: ----------- Preliminary work on the Preferences dialog. Modified Paths: -------------- trunk/pybridge/glade/pybridge.glade trunk/pybridge/pybridge/ui/dialog_preferences.py Modified: trunk/pybridge/glade/pybridge.glade =================================================================== --- trunk/pybridge/glade/pybridge.glade 2007-06-14 16:22:05 UTC (rev 420) +++ trunk/pybridge/glade/pybridge.glade 2007-06-16 13:21:39 UTC (rev 421) @@ -1411,7 +1411,7 @@ </widget> </child> <child> - <widget class="GtkLabel" id="label62"> + <widget class="GtkLabel" id="label_useraccount"> <property name="visible">True</property> <property name="label" translatable="yes"><b>User Account</b></property> <property name="use_markup">True</property> @@ -1948,200 +1948,6 @@ </packing> </child> <child> - <widget class="GtkExpander" id="expander_players"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <child> - <widget class="GtkTable" id="table5"> - <property name="visible">True</property> - <property name="n_rows">4</property> - <property name="n_columns">3</property> - <property name="column_spacing">4</property> - <property name="row_spacing">2</property> - <child> - <widget class="GtkLabel" id="label_west"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="xpad">4</property> - <property name="label" translatable="yes"><i>Vacant</i></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label_south"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="xpad">4</property> - <property name="label" translatable="yes"><i>Vacant</i></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label_north"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="xpad">4</property> - <property name="label" translatable="yes"><i>Vacant</i></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label_east"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="xpad">4</property> - <property name="label" translatable="yes"><i>Vacant</i></property> - <property name="use_markup">True</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkImage" id="image321"> - <property name="visible">True</property> - <property name="stock">gtk-go-back</property> - </widget> - <packing> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <widget class="GtkImage" id="image320"> - <property name="visible">True</property> - <property name="stock">gtk-go-down</property> - </widget> - <packing> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <widget class="GtkImage" id="image319"> - <property name="visible">True</property> - <property name="stock">gtk-go-forward</property> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <widget class="GtkImage" id="image318"> - <property name="visible">True</property> - <property name="stock">gtk-go-up</property> - </widget> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label49"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">West:</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label48"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">South:</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label47"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">East:</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - <child> - <widget class="GtkLabel" id="label46"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">North:</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - </child> - <child> - <widget class="GtkLabel" id="label45"> - <property name="visible">True</property> - <property name="label" translatable="yes">Players</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="position">4</property> - </packing> - </child> - <child> <widget class="GtkExpander" id="expander_observers"> <property name="visible">True</property> <property name="can_focus">True</property> @@ -2174,7 +1980,7 @@ </widget> <packing> <property name="expand">False</property> - <property name="position">5</property> + <property name="position">4</property> </packing> </child> </widget> @@ -2278,7 +2084,7 @@ <widget class="GtkDialog" id="dialog_preferences"> <property name="visible">True</property> <property name="border_width">5</property> - <property name="title" translatable="yes">Preferences</property> + <property name="title" translatable="yes">PyBridge Preferences</property> <property name="resizable">False</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="has_separator">False</property> @@ -2296,92 +2102,166 @@ <property name="border_width">4</property> <property name="spacing">8</property> <child> - <widget class="GtkFrame" id="frame3"> + <widget class="GtkTable" id="table3"> <property name="visible">True</property> - <property name="label_xalign">0</property> - <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="column_spacing">8</property> + <property name="row_spacing">4</property> <child> - <widget class="GtkAlignment" id="alignment1"> + <widget class="GtkLabel" id="label_cardstyle"> <property name="visible">True</property> - <property name="left_padding">12</property> - <child> - <widget class="GtkComboBox" id="carddeck"> - <property name="visible">True</property> - <signal name="changed" handler="on_carddeck_changed"/> - </widget> - </child> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Card Style:</property> </widget> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> </child> <child> - <widget class="GtkLabel" id="label1"> + <widget class="GtkLabel" id="label_background"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Card Deck</b></property> - <property name="use_markup">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Background:</property> </widget> <packing> - <property name="type">label_item</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> </packing> </child> + <child> + <widget class="GtkComboBox" id="cardstyle"> + <property name="width_request">160</property> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="changed" handler="on_cardstyle_changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkFileChooserButton" id="background"> + <property name="width_request">160</property> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="selection_changed" handler="on_background_changed"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> </widget> + <packing> + <property name="expand">False</property> + </packing> </child> <child> - <widget class="GtkFrame" id="frame4"> + <widget class="GtkFrame" id="frame5"> <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="label_xalign">0</property> <property name="shadow_type">GTK_SHADOW_NONE</property> <child> - <widget class="GtkAlignment" id="alignment2"> + <widget class="GtkAlignment" id="alignment3"> <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="left_padding">12</property> <child> - <widget class="GtkTable" id="table3"> + <widget class="GtkHBox" id="hbox1"> <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="column_spacing">9</property> - <property name="row_spacing">4</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">4</property> + <property name="homogeneous">True</property> <child> - <widget class="GtkFileChooserButton" id="filechooserbutton1"> + <widget class="GtkButton" id="button_clubcolour"> <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="clicked" handler="on_suitcolour_clicked"/> + <child> + <widget class="GtkLabel" id="label_clubcolour"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes"><span color='#000000' size='xx-large'>♣</span></property> + <property name="use_markup">True</property> + </widget> + </child> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <property name="expand">False</property> </packing> </child> <child> - <widget class="GtkColorButton" id="colorbutton1"> + <widget class="GtkButton" id="button_diamondcolour"> <property name="visible">True</property> - <property name="color">#000000000000</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="clicked" handler="on_suitcolour_clicked"/> + <child> + <widget class="GtkLabel" id="label_diamondcolour"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes"><span color='#ff0000' size='xx-large'>♦</span></property> + <property name="use_markup">True</property> + </widget> + </child> </widget> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> + <property name="expand">False</property> + <property name="position">1</property> </packing> </child> <child> - <widget class="GtkRadioButton" id="radio_image"> + <widget class="GtkButton" id="button_heartcolour"> <property name="visible">True</property> - <property name="label" translatable="yes">Image</property> - <property name="draw_indicator">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="clicked" handler="on_suitcolour_clicked"/> + <child> + <widget class="GtkLabel" id="label_heartcolour"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes"><span color='#ff0000' size='xx-large'>♥</span></property> + <property name="use_markup">True</property> + </widget> + </child> </widget> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">GTK_FILL</property> + <property name="expand">False</property> + <property name="position">2</property> </packing> </child> <child> - <widget class="GtkRadioButton" id="radio_colour"> + <widget class="GtkButton" id="button_spadecolour"> <property name="visible">True</property> - <property name="label" translatable="yes">Colour</property> - <property name="draw_indicator">True</property> - <property name="group">radio_image</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="clicked" handler="on_suitcolour_clicked"/> + <child> + <widget class="GtkLabel" id="label_spadecolour"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes"><span color='#000000' size='xx-large'>♠</span></property> + <property name="use_markup">True</property> + </widget> + </child> </widget> <packing> - <property name="x_options">GTK_FILL</property> + <property name="expand">False</property> + <property name="position">3</property> </packing> </child> </widget> @@ -2389,9 +2269,10 @@ </widget> </child> <child> - <widget class="GtkLabel" id="label2"> + <widget class="GtkLabel" id="label_suitcolours"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Background</b></property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Colours for Suits</property> <property name="use_markup">True</property> </widget> <packing> @@ -2400,6 +2281,7 @@ </child> </widget> <packing> + <property name="expand">False</property> <property name="position">1</property> </packing> </child> @@ -2409,9 +2291,9 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label_style"> + <widget class="GtkLabel" id="label_gamedisplay"> <property name="visible">True</property> - <property name="label" translatable="yes">Style</property> + <property name="label" translatable="yes">Game Display</property> </widget> <packing> <property name="type">tab</property> Modified: trunk/pybridge/pybridge/ui/dialog_preferences.py =================================================================== --- trunk/pybridge/pybridge/ui/dialog_preferences.py 2007-06-14 16:22:05 UTC (rev 420) +++ trunk/pybridge/pybridge/ui/dialog_preferences.py 2007-06-16 13:21:39 UTC (rev 421) @@ -22,41 +22,95 @@ import pybridge.environment as env from manager import wm +from pybridge.ui import settings +from pybridge.bridge.symbols import Suit +SUIT_NAMES = {Suit.Club: _("Club"), Suit.Diamond: _("Diamond"), + Suit.Heart: _("Heart"), Suit.Spade: _("Spade") } + +SUIT_SYMBOLS = {Suit.Club: u'\N{BLACK CLUB SUIT}', + Suit.Diamond: u'\N{BLACK DIAMOND SUIT}', + Suit.Heart: u'\N{BLACK HEART SUIT}', + Suit.Spade: u'\N{BLACK SPADE SUIT}' } + +SUIT_LABEL_TEMPLATE = "<span color=\'%s\' size=\'xx-large\'>%s</span>" + + class DialogPreferences(GladeWrapper): glade_name = 'dialog_preferences' - def new(self): + def setUp(self): + # Allow user to select only image files for background. + filter_pixbufs = gtk.FileFilter() + filter_pixbufs.add_pixbuf_formats() + filter_pixbufs.set_name(_("Image files")) + self.background.add_filter(filter_pixbufs) + + # Build a list of card decks from which the user may choose. + # (The user is prevented from selecting an arbitary image.) model = gtk.ListStore(str) - self.carddeck.set_model(model) + self.cardstyle.set_model(model) cell = gtk.CellRendererText() - self.carddeck.pack_start(cell, True) - self.carddeck.add_attribute(cell, 'text', 0) + self.cardstyle.pack_start(cell, True) + self.cardstyle.add_attribute(cell, 'text', 0) + + activedeck = settings.appearance.get('deck', 'bonded.png') # Populate list of card decks. path = env.find_pixmap('') for filename in os.listdir(path): if filename.endswith('.png'): iter = model.append((filename,)) - if filename == 'bonded.png': - self.carddeck.set_active_iter(iter) + if filename == activedeck: + self.cardstyle.set_active_iter(iter) # Signal handlers. - def on_carddeck_changed(self, widget, *args): - print "changed" + def on_cardstyle_changed(self, widget, *args): + print "cardstyle changed" + def on_background_changed(self, widget, *args): + print "background changed" + + + def on_suitcolour_clicked(self, widget, *args): + # Get symbol in Suit corresponding to button clicked. + suit_buttons = {self.button_clubcolour: Suit.Club, + self.button_diamondcolour: Suit.Diamond, + self.button_heartcolour: Suit.Heart, + self.button_spadecolour: Suit.Spade } + suit = suit_buttons[widget] + + title = _("Select colour for %s symbol" % SUIT_NAMES[suit]) + dialog = gtk.ColorSelectionDialog(title) + dialog.colorsel.set_current_color(gtk.gdk.color_parse('#888888')) + + def dialog_response_cb(dialog, response_id): + if response_id == gtk.RESPONSE_OK: + colour = dialog.colorsel.get_current_color() + + # Set button label to colour selected by user. + label = widget.get_children()[0] + hexrep = gtk.color_selection_palette_to_string([colour]) + label.set_markup(SUIT_LABEL_TEMPLATE % (hexrep, SUIT_SYMBOLS[suit])) + + dialog.destroy() + + dialog.connect('response', dialog_response_cb) + #dialog.show() + dialog.run() + + def on_cancelbutton_clicked(self, widget, *args): - print "cancel" wm.close(self) def on_okbutton_clicked(self, widget, *args): - print "ok" + print "SAVE SETTINGS" wm.close(self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-14 16:22:07
|
Revision: 420 http://svn.sourceforge.net/pybridge/?rev=420&view=rev Author: umgangee Date: 2007-06-14 09:22:05 -0700 (Thu, 14 Jun 2007) Log Message: ----------- Add display of all hands when game complete. Make results dialog non-blocking, to allow UI events in the background. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-14 16:19:10 UTC (rev 419) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-14 16:22:05 UTC (rev 420) @@ -261,8 +261,10 @@ def gameComplete(self): - for position in Direction: + # Display all previously revealed hands - the server will reveal the others. + for position in self.table.game.visibleHands: self.redrawHand(position, all=True) + self.setTurnIndicator() dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, @@ -294,12 +296,14 @@ dialog.set_markup(_('Bidding passed out.')) dialog.format_secondary_text(_('No score.')) - dialog.run() - dialog.destroy() + def dialog_response_cb(dialog, response_id): + dialog.destroy() + if self.player and self.table.game.isNextGameReady(): + d = self.player.callRemote('startNextGame') + d.addErrback(self.errback) - if self.player and self.table.game.isNextGameReady(): - d = self.player.callRemote('startNextGame') - d.addErrback(self.errback) + dialog.connect('response', dialog_response_cb) + dialog.show() def redrawHand(self, position, all=False): @@ -486,6 +490,8 @@ if self.player: d = self.player.callRemote('getHand') + # When player's hand is returned by server, reveal it to client-side Game. + # TODO: is there a better way of synchronising hands? d.addCallbacks(self.table.game.revealHand, self.errback, callbackKeywords={'position' : self.position}) bidbox = self.children.open(WindowBidbox, parent=self) @@ -519,7 +525,8 @@ def event_revealHand(self, hand, position): - self.redrawHand(position) + all = not self.table.game.inProgress() # Show all cards if game has finished. + self.redrawHand(position, all) def event_sendMessage(self, message, sender, recipients): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-14 16:19:13
|
Revision: 419 http://svn.sourceforge.net/pybridge/?rev=419&view=rev Author: umgangee Date: 2007-06-14 09:19:10 -0700 (Thu, 14 Jun 2007) Log Message: ----------- Necessary to weaken start-game check, since client-side Game objects will not have a full set of players. Add "reveal all hands" at end of game. Modified Paths: -------------- trunk/pybridge/pybridge/bridge/game.py Modified: trunk/pybridge/pybridge/bridge/game.py =================================================================== --- trunk/pybridge/pybridge/bridge/game.py 2007-06-14 13:15:37 UTC (rev 418) +++ trunk/pybridge/pybridge/bridge/game.py 2007-06-14 16:19:10 UTC (rev 419) @@ -73,8 +73,8 @@ def start(self, board=None): - if not self.isNextGameReady(): - raise GameError, "Not ready to start game" + if self.inProgress(): + raise GameError, "Game in progress" if board: # Use specified board. self.board = board @@ -242,8 +242,12 @@ self.notify('makeCall', call=call, position=position) - if self.bidding.isPassedOut(): - self.notify('gameOver') # TODO: reveal all hands + # If bidding is passed out, reveal all hands. + if not self.inProgress() and self.board['deal']: + for position in Direction: + hand = self.board['deal'].get(position) + if hand and position not in self.visibleHands: + self.revealHand(hand, position) def signalAlert(self, alert, position): @@ -302,7 +306,13 @@ dummyhand = self.board['deal'].get(self.play.dummy) if dummyhand: # Reveal hand only if known. self.revealHand(dummyhand, self.play.dummy) - # TODO: if game over, reveal all hands + + # If play is complete, reveal all hands. + if not self.inProgress() and self.board['deal']: + for position in Direction: + hand = self.board['deal'].get(position) + if hand and position not in self.visibleHands: + self.revealHand(hand, position) def revealHand(self, hand, position): @@ -412,7 +422,9 @@ def startNextGame(self): - self.__game.start() # Raises GameError if not ready to start next game. + if not self.__game.isNextGameReady(): + raise GameError, "Not ready to start game" + self.__game.start() # Raises GameError if game in progress. # Aliases for remote-callable methods. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-14 13:15:38
|
Revision: 418 http://svn.sourceforge.net/pybridge/?rev=418&view=rev Author: umgangee Date: 2007-06-14 06:15:37 -0700 (Thu, 14 Jun 2007) Log Message: ----------- Add more informative messages to the status bar of WindowBridgetable, when playing a game. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-13 15:18:35 UTC (rev 417) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-14 13:15:37 UTC (rev 418) @@ -394,14 +394,30 @@ """Sets the statusbar text to indicate which player is on turn.""" context = self.statusbar.get_context_id('turn') self.statusbar.pop(context) + try: turn = self.table.game.getTurn() - text = _("It is %s's turn") % str(turn) - self.statusbar.push(context, text) - except GameError: # Game not in progress - pass + if self.table.game.play: + declarer, dummy = self.table.game.play.declarer, self.table.game.play.dummy + if self.position and self.position == turn != dummy: + text = _("Play a card from your hand.") + elif self.position and self.position == declarer and turn == dummy: + text = _("Play a card from dummy's hand.") + else: + text = _("It is %s's turn to play a card.") % DIRECTION_SYMBOLS[turn] + else: # Bidding. + if self.position and self.position == turn: + text = _("Make a call from the bidding box.") + else: + text = _("It is %s's turn to make a call.") % DIRECTION_SYMBOLS[turn] + + except GameError: # Game not in progress. + text = _("Waiting for next game to start.") + + self.statusbar.push(context, text) + def setVulnerability(self): """Sets the vulnerability indicators.""" format = "<b>%s</b>" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-13 15:18:36
|
Revision: 417 http://svn.sourceforge.net/pybridge/?rev=417&view=rev Author: umgangee Date: 2007-06-13 08:18:35 -0700 (Wed, 13 Jun 2007) Log Message: ----------- Fix a bug in connectionLost(), which would call .clear() on rosters even if they were NoneType objects. Modified Paths: -------------- trunk/pybridge/pybridge/network/client.py Modified: trunk/pybridge/pybridge/network/client.py =================================================================== --- trunk/pybridge/pybridge/network/client.py 2007-06-13 15:14:20 UTC (rev 416) +++ trunk/pybridge/pybridge/network/client.py 2007-06-13 15:18:35 UTC (rev 417) @@ -1,5 +1,5 @@ # PyBridge -- online contract bridge made easy. -# Copyright (C) 2004-2006 PyBridge Project. +# Copyright (C) 2004-2007 PyBridge Project. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -10,7 +10,7 @@ # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -55,11 +55,12 @@ def connectionLost(self, connector, reason): - # Reset invalidated remote references. - self.avatar = None - self.tables.clear() - self.tableRoster.clear() - self.userRoster.clear() + if self.avatar: + # Reset invalidated remote references. + self.avatar = None + self.tables.clear() + self.tableRoster.clear() + self.userRoster.clear() print "Lost connection: %s" % reason.getErrorMessage() self.notify('connectionLost', reason=reason.getErrorMessage()) @@ -133,8 +134,7 @@ hash = sha.new(password).hexdigest() creds = credentials.UsernamePassword(username, hash) d = self.factory.login(creds, client=self) - d.addCallbacks(connectedAsUser, self.errback) - # for rostername... + d.addCallback(connectedAsUser) return d This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-13 15:14:21
|
Revision: 416 http://svn.sourceforge.net/pybridge/?rev=416&view=rev Author: umgangee Date: 2007-06-13 08:14:20 -0700 (Wed, 13 Jun 2007) Log Message: ----------- Move responsibility for starting games from LocalTable to BridgeGame, add appropriate functionality to WindowBridgetable. Modified Paths: -------------- trunk/pybridge/pybridge/network/localtable.py trunk/pybridge/pybridge/network/remotetable.py trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/network/localtable.py =================================================================== --- trunk/pybridge/pybridge/network/localtable.py 2007-06-13 15:11:39 UTC (rev 415) +++ trunk/pybridge/pybridge/network/localtable.py 2007-06-13 15:14:20 UTC (rev 416) @@ -145,11 +145,6 @@ self.players[position] = user self.notify('joinGame', player=user.name, position=position) - # If no game is active and all players are ready, start game. - if not self.game.inProgress(): - if len(self.players) == len(self.game.positions): - self.game.start() - return player Modified: trunk/pybridge/pybridge/network/remotetable.py =================================================================== --- trunk/pybridge/pybridge/network/remotetable.py 2007-06-13 15:11:39 UTC (rev 415) +++ trunk/pybridge/pybridge/network/remotetable.py 2007-06-13 15:14:20 UTC (rev 416) @@ -65,6 +65,8 @@ self.observers = state['observers'] self.players = state['players'] + for position in self.players: + self.game.addPlayer(position) # Implementation of ITable. @@ -115,11 +117,13 @@ def observe_joinGame(self, player, position): + self.game.addPlayer(position) self.players[position] = player self.notify('joinGame', player, position) def observe_leaveGame(self, player, position): + self.game.removePlayer(position) del self.players[position] self.notify('leaveGame', player, position) Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-13 15:11:39 UTC (rev 415) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-06-13 15:14:20 UTC (rev 416) @@ -297,7 +297,11 @@ dialog.run() dialog.destroy() + if self.player and self.table.game.isNextGameReady(): + d = self.player.callRemote('startNextGame') + d.addErrback(self.errback) + def redrawHand(self, position, all=False): """Redraws cards making up the hand at position. @@ -431,23 +435,21 @@ # Disable menu item corresponding to position. widget = self.takeseat_items[position] widget.set_property('sensitive', False) - # Set player label. - label = getattr(self, 'label_%s' % position.key.lower()) - label.set_markup('<b>%s</b>' % player) # If all positions occupied, disable Take Seat. if len(self.table.players.values()) == len(Direction): self.takeseat.set_property('sensitive', False) + if self.player and self.table.game.isNextGameReady(): + d = self.player.callRemote('startNextGame') + d.addErrback(self.errback) + def event_leaveGame(self, player, position): self.cardarea.set_player_name(position, None) # Enable menu item corresponding to position. widget = self.takeseat_items[position] widget.set_property('sensitive', True) - # Reset player label. - label = getattr(self, 'label_%s' % position.key.lower()) - label.set_markup('<i>%s</i>' % _('Position vacant')) # If we are not seated, ensure Take Seat is enabled. if self.position is None: @@ -504,7 +506,7 @@ self.redrawHand(position) - def event_messageReceived(self, message, sender, recipients): + def event_sendMessage(self, message, sender, recipients): buffer = self.chat_messagehistory.get_buffer() iter = buffer.get_end_iter() buffer.insert(iter, '%s: %s\n' % (sender, message)) @@ -562,8 +564,8 @@ self.player = player # RemoteReference to BridgePlayer object. self.position = position - self.takeseat.set_property('visible', False) - self.leaveseat.set_property('visible', True) + self.takeseat.set_property('sensitive', False) + self.leaveseat.set_property('sensitive', True) self.cardarea.set_player_mapping(self.position) @@ -576,7 +578,7 @@ if not self.table.game.bidding.isComplete(): bidbox = self.children.open(WindowBidbox, parent=self) bidbox.monitor(self.table.game, self.position, self.on_call_selected) - + d = self.table.joinGame(position) d.addCallbacks(success, self.errback) @@ -594,8 +596,8 @@ def success(r): self.player = None self.position = None - self.takeseat.set_property('visible', True) - self.leaveseat.set_property('visible', False) + self.takeseat.set_property('sensitive', True) + self.leaveseat.set_property('sensitive', False) if self.children.get(WindowBidbox): self.children.close(self.children[WindowBidbox]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-13 15:11:44
|
Revision: 415 http://svn.sourceforge.net/pybridge/?rev=415&view=rev Author: umgangee Date: 2007-06-13 08:11:39 -0700 (Wed, 13 Jun 2007) Log Message: ----------- Add a isNextGameReady() method to BridgeGame, add startNextGame() to BridgePlayer. Modified Paths: -------------- trunk/pybridge/pybridge/bridge/game.py trunk/pybridge/pybridge/interfaces/game.py Modified: trunk/pybridge/pybridge/bridge/game.py =================================================================== --- trunk/pybridge/pybridge/bridge/game.py 2007-06-11 13:10:16 UTC (rev 414) +++ trunk/pybridge/pybridge/bridge/game.py 2007-06-13 15:11:39 UTC (rev 415) @@ -26,6 +26,7 @@ from bidding import Bidding from board import Board from playing import Playing +from scoring import scoreDuplicate from call import Bid, Pass, Double, Redouble from card import Card @@ -72,8 +73,8 @@ def start(self, board=None): - if self.inProgress(): - raise GameError, "Game in progress" + if not self.isNextGameReady(): + raise GameError, "Not ready to start game" if board: # Use specified board. self.board = board @@ -103,6 +104,10 @@ return False + def isNextGameReady(self): + return (not self.inProgress()) and len(self.players) == 4 + + def getState(self): state = {} @@ -374,7 +379,7 @@ result = {'contract' : contract, 'tricksMade' : tricksMade, 'vulnerable' : vulnerable, } - return self.scoring(result) + return scoreDuplicate(result) @@ -384,7 +389,7 @@ def __init__(self, game): - self.__game = game # Provide access to game only through this object. + self.__game = game # Access to game is private to this object. def getHand(self): @@ -393,16 +398,21 @@ def makeCall(self, call): - return self.__game.makeCall(call, player=self) + try: + return self.__game.makeCall(call, player=self) + except TypeError, e: + raise GameError, e def playCard(self, card): - # TODO: need try/except block on each. - return self.__game.playCard(card, player=self) + try: + return self.__game.playCard(card, player=self) + except TypeError, e: + raise GameError, e - def nextGame(self): - pass + def startNextGame(self): + self.__game.start() # Raises GameError if not ready to start next game. # Aliases for remote-callable methods. @@ -410,4 +420,5 @@ remote_getHand = getHand remote_makeCall = makeCall remote_playCard = playCard + remote_startNextGame = startNextGame Modified: trunk/pybridge/pybridge/interfaces/game.py =================================================================== --- trunk/pybridge/pybridge/interfaces/game.py 2007-06-11 13:10:16 UTC (rev 414) +++ trunk/pybridge/pybridge/interfaces/game.py 2007-06-13 15:11:39 UTC (rev 415) @@ -84,6 +84,13 @@ """ + def isNextGameReady(self): + """Indicates whether the next game is ready to start. + + @return: True if next game is ready to start, False otherwise. + """ + + class ICardGame(IGame): """ICardGame defines methods specific to card games. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-11 13:10:14
|
Revision: 414 http://svn.sourceforge.net/pybridge/?rev=414&view=rev Author: umgangee Date: 2007-06-11 06:10:16 -0700 (Mon, 11 Jun 2007) Log Message: ----------- Add support for other database backends, to be specified in server config file. Requires testing with MySQL, PostgreSQL etc. Modified Paths: -------------- trunk/pybridge/pybridge/server/database.py Modified: trunk/pybridge/pybridge/server/database.py =================================================================== --- trunk/pybridge/pybridge/server/database.py 2007-06-11 13:07:15 UTC (rev 413) +++ trunk/pybridge/pybridge/server/database.py 2007-06-11 13:10:16 UTC (rev 414) @@ -20,21 +20,55 @@ from datetime import datetime from sqlobject import * from sqlobject.inheritance import InheritableSQLObject +from twisted.python import log import pybridge.environment as env +from pybridge.settings import Settings -backend = "sqlite" +# TODO: when fields are not empty, avoid writing default values to fields. +configfile = env.find_config_server('server.cfg') +settings = Settings(configfile, ['database']) + + # Initiate connection to the appropriate database backend. -if backend == "sqlite": - db_filename = env.find_config_server("pybridge-server.db") - connection_string = "sqlite://" + db_filename # TODO: fix for Win32. +# See http://sqlobject.org/SQLObject.html#declaring-the-class -connection = connectionForURI(connection_string) -sqlhub.processConnection = connection # Set all classes to use connection. +# This code has been tested with the SQLite database backend. If you experience +# problems with databases supported by SQLObject, please file a bug report. +backend = settings.database.get('backend', 'sqlite') # Default to SQLite. +settings.database['backend'] = backend +if backend == 'sqlite': + dbfile = settings.database.get('dbfile') + if dbfile is None: + dbfile = env.find_config_server('pybridge-server.db') + settings.database['dbfile'] = dbfile + connection_string = "sqlite://" + dbfile +else: + username = settings.database.get('username', '') + password = settings.database.get('password', '') + hostname = settings.database.get('hostname', 'localhost') + dbname = settings.database.get('dbname', 'pybridge') + connection_string = "%s://%s:%s/%s" % (username, password, hostname, dbname) + +settings.save() + +try: + connection = connectionForURI(connection_string) # TODO: fix for Win32. + log.msg("Connection to %s database succeeded" % backend) +except Exception, e: + log.err(e) + log.msg("Could not connect to %s database with URI: %s" + % (backend, connection_string)) + log.msg("Please check configuration file %s" % configfile) + raise SystemExit # Database connection is required for server operation. + +sqlhub.processConnection = connection # Set all SQLObjects to use connection. + + class UserAccount(SQLObject): """A store of user information. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-06-11 13:07:16
|
Revision: 413 http://svn.sourceforge.net/pybridge/?rev=413&view=rev Author: umgangee Date: 2007-06-11 06:07:15 -0700 (Mon, 11 Jun 2007) Log Message: ----------- Start logging service before importing pybridge.server.factory, so log messages from the initialisation of pybridge are caught and displayed. Modified Paths: -------------- trunk/pybridge/bin/pybridge-server Modified: trunk/pybridge/bin/pybridge-server =================================================================== --- trunk/pybridge/bin/pybridge-server 2007-04-18 15:04:50 UTC (rev 412) +++ trunk/pybridge/bin/pybridge-server 2007-06-11 13:07:15 UTC (rev 413) @@ -1,7 +1,7 @@ #!/usr/bin/env python # PyBridge -- online contract bridge made easy. -# Copyright (C) 2004-2006 PyBridge Project. +# Copyright (C) 2004-2007 PyBridge Project. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -12,7 +12,7 @@ # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -71,10 +71,10 @@ from twisted.internet import reactor from twisted.python import log - from pybridge.server import factory + log.startLogging(sys.stdout) # Log to stdout. # TODO: replace with a service. - log.startLogging(sys.stdout) # Log to stdout. + from pybridge.server import factory reactor.listenTCP(PORT, factory) reactor.run() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-04-18 15:04:58
|
Revision: 412 http://svn.sourceforge.net/pybridge/?rev=412&view=rev Author: umgangee Date: 2007-04-18 08:04:50 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Implement table rotation to CardArea, so user's hand is displayed at the bottom to give a "bird's eye view" of the table. In CardArea, store list of visible cards instead of list of cards to omit. Modified Paths: -------------- trunk/pybridge/pybridge/ui/cardarea.py trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2007-04-09 15:33:32 UTC (rev 411) +++ trunk/pybridge/pybridge/ui/cardarea.py 2007-04-18 15:04:50 UTC (rev 412) @@ -41,7 +41,7 @@ class CardArea(CairoCanvas): - """This widget displays a graphical view of card hands and tricks. + """This widget is a graphical display of tricks and hands of cards. Requirements: Cairo (>=1.0), PyGTK (>= 2.8). """ @@ -66,10 +66,11 @@ self.on_card_clicked = lambda card, position: True self.on_hand_clicked = lambda position: True + self.focus = Direction.South self.hands = {} self.trick = None self.players = {} - self.set_player_mapping(Direction.South) + self.set_player_mapping(Direction.South, redraw=False) self.connect('button_press_event', self.button_press) self.add_events(gtk.gdk.BUTTON_PRESS_MASK) @@ -96,21 +97,21 @@ context.reset_clip() - def set_hand(self, hand, player, facedown=False, omit=[]): - """Sets the hand of player. Draws cards in hand to context. + def set_hand(self, hand, position, facedown=False, visible=[]): + """Sets the hand of player at position. Draws cards in hand to context. The hand is buffered into an ImageSurface, since hands change infrequently and multiple calls to draw_card() are expensive. @param hand: a list of Card objects. - @param player: a member of Direction. + @param position: a member of Direction. @param facedown: if True, cards are drawn face-down. - @param omit: a list of elements of hand not to draw. + @param visible: a list of elements of hand to draw. """ def get_coords_for_hand(): coords = {} - if player in (self.TOP, self.BOTTOM): + if position in (self.TOP, self.BOTTOM): pos_y = 0 if facedown is True: # Draw cards in one continuous row. for index, card in enumerate(hand): @@ -127,14 +128,14 @@ else: # LEFT or RIGHT. if facedown is True: # Wrap cards to a 4x4 grid. for index, card in enumerate(hand): - adjust = player == self.RIGHT and index == 12 and 3 + adjust = position == self.RIGHT and index == 12 and 3 pos_x = ((index % 4) + adjust) * self.spacing_x pos_y = (index / 4) * self.spacing_y coords[card] = (pos_x, pos_y) else: longest = max([len(cards) for cards in suits.values()]) for index, card in enumerate(hand): - adjust = player == self.RIGHT and longest - len(suits[card.suit]) + adjust = position == self.RIGHT and longest - len(suits[card.suit]) pos_x = (suits[card.suit].index(card) + adjust) * self.spacing_x pos_y = RED_BLACK.index(card.suit) * self.spacing_y coords[card] = (pos_x, pos_y) @@ -153,7 +154,7 @@ for suit in RED_BLACK: hand.extend(suits[suit]) - saved = self.hands.get(player) + saved = self.hands.get(position) if saved and saved['hand'] == hand: # If hand has been set previously, do not recalculate coords. coords = saved['coords'] @@ -166,22 +167,24 @@ surface, context = self.new_surface(width, height) # Draw cards to surface. - visible = [(i, card) for i, card in enumerate(hand) if card not in omit] - for i, card in visible: - pos_x, pos_y = coords[card] - self.draw_card(context, pos_x, pos_y, card) + for i, card in enumerate(hand): + if card in visible: + pos_x, pos_y = coords[card] + self.draw_card(context, pos_x, pos_y, card) - # Save - self.hands[player] = {'hand' : hand, 'visible' : visible, - 'surface' : surface, 'coords' : coords, } + # Save. + self.hands[position] = {'hand' : hand, 'visible' : visible, + 'surface' : surface, 'coords' : coords, + 'facedown' : facedown} - id = 'hand-%s' % player # Identifier for this item. + id = 'hand-%s' % position # Identifier for this item. if id in self.items: self.update_item(id, source=surface) else: xy = {self.TOP : (0.5, 0.15), self.BOTTOM : (0.5, 0.85), self.LEFT : (0.15, 0.5), self.RIGHT : (0.85, 0.5), } - self.add_item(id, surface, xy[player], 0) + opacity = (self.players.get(position) is None) and 0.5 or 1 + self.add_item(id, surface, xy[position], 0, opacity=opacity) def set_player_name(self, position, name=None): @@ -190,11 +193,12 @@ @param position: the position of the player. @param name: the name of the player, or None. """ - self.players[position] = None + self.players[position] = name # If no name specified, show hand at position as translucent. - opacity = (name is None) and 0.5 or 1 - self.update_item('hand-%s' % position, opacity=opacity) + if ('hand-%s' % position) in self.items: + opacity = (name is None) and 0.5 or 1 + self.update_item('hand-%s' % position, opacity=opacity) id = 'player-%s' % position @@ -230,18 +234,37 @@ self.add_item(id, surface, xy[position], 2) - def set_player_mapping(self, focus=Direction.South): + def set_player_mapping(self, focus=Direction.South, redraw=True): """Sets the mapping between players at table and positions of hands. @param focus: the position to be drawn "closest" to the observer. + @param redraw: if True, redraw the card area display immediately. """ # Assumes Direction elements are ordered clockwise from North. order = Direction[focus.index:] + Direction[:focus.index] for player, attr in zip(order, ('BOTTOM', 'LEFT', 'TOP', 'RIGHT')): setattr(self, attr, player) - # TODO: set player labels. + # Only redraw if focus has changed. + if redraw and focus != self.focus: + self.focus = focus + self.clear() # Wipe all saved ImageSurface objects - not subtle! + # Use a copy of self.hands, since it will be changed by set_hand(). + hands = self.hands.copy() + self.hands.clear() + for position in Direction: + self.set_player_name(position, self.players.get(position)) + self.set_hand(hands[position]['hand'], position, + facedown=hands[position]['facedown'], + visible=hands[position]['visible']) + + trick = self.trick + self.trick = None + self.set_trick(trick) + + + def set_trick(self, trick): """Sets the current trick. Draws representation of current trick to context. @@ -252,18 +275,19 @@ self.LEFT : (0.425, 0.5), self.RIGHT : (0.575, 0.5), } if trick: + leader, cards = trick # The order of play is the leader, then clockwise around Direction. - leader = trick[0] order = Direction[leader.index:] + Direction[:leader.index] - for i, player in enumerate(order): - id = 'trick-%s' % player - old_card = self.trick and self.trick[1].get(player) or None - new_card = trick[1].get(player) + for i, position in enumerate(order): + id = 'trick-%s' % position + old_card = self.trick and self.trick[1].get(position) or None + new_card = cards.get(position) or None + # If old card matches new card, take no action. if old_card is None and new_card is not None: surface, context = self.new_surface(self.card_width, self.card_height) self.draw_card(context, 0, 0, new_card) - self.add_item(id, surface, xy[player], z_index=i+1) + self.add_item(id, surface, xy[position], z_index=i+1) elif new_card is None and old_card is not None: self.remove_item(id) elif old_card != new_card: @@ -275,7 +299,7 @@ for player in self.trick[1]: self.remove_item('trick-%s' % player) - self.trick = trick # Save trick and return. + self.trick = trick # Save trick. def button_press(self, widget, event): @@ -299,12 +323,13 @@ # Determine the card in hand which was clicked. pos_x, pos_y = event.x - hand_x, event.y - hand_y # Iterate through visible cards backwards. - for i, card in self.hands[position]['visible'][::-1]: - x, y = card_coords[card] - if (x <= pos_x <= x + self.card_width) and \ - (y <= pos_y <= y + self.card_height): - self.on_card_clicked(card, position) - break + for card in reversed(self.hands[position]['hand']): + if card in self.hands[position]['visible']: + x, y = card_coords[card] + if (x <= pos_x <= x + self.card_width) and \ + (y <= pos_y <= y + self.card_height): + self.on_card_clicked(card, position) + break return True # Expected to return True. Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-04-09 15:33:32 UTC (rev 411) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-04-18 15:04:50 UTC (rev 412) @@ -136,6 +136,7 @@ def errback(self, failure): print "Error: %s" % failure.getErrorMessage() + #print failure.getBriefTraceback() def setTable(self, table): @@ -306,17 +307,23 @@ @param position: @param all: If True, do not filter out cards played. """ + try: + hand = self.table.game.getHand(position) + facedown = False + except GameError: # Unknown hand. + hand = range(13) + facedown = True + if all is True or self.table.game.play is None: - played = [] + available = hand else: played = self.table.game.play.played[position] + if facedown: # Draw cards face down for unknown hand. + available = range(13 - len(played)) + else: + available = [card for card in hand if card not in played] - try: - hand = self.table.game.getHand(position) - self.cardarea.set_hand(hand, position, omit=played) - except GameError: # Unknown hand: draw cards face down. - cards, played = range(13), range(len(played)) - self.cardarea.set_hand(cards, position, facedown=True, omit=played) + self.cardarea.set_hand(hand, position, facedown, visible=available) def redrawTrick(self): @@ -557,11 +564,15 @@ self.takeseat.set_property('visible', False) self.leaveseat.set_property('visible', True) - # If game is running and bidding is active, open bidding box. + + self.cardarea.set_player_mapping(self.position) + if self.table.game.inProgress(): d = self.player.callRemote('getHand') d.addCallbacks(self.table.game.revealHand, self.errback, callbackKeywords={'position' : self.position}) + + # If game is running and bidding is active, open bidding box. if not self.table.game.bidding.isComplete(): bidbox = self.children.open(WindowBidbox, parent=self) bidbox.monitor(self.table.game, self.position, self.on_call_selected) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-04-09 15:33:31
|
Revision: 411 http://svn.sourceforge.net/pybridge/?rev=411&view=rev Author: umgangee Date: 2007-04-09 08:33:32 -0700 (Mon, 09 Apr 2007) Log Message: ----------- Use a dict to store card coords. Add hand-click event. Disable turn notifier for now. Modified Paths: -------------- trunk/pybridge/pybridge/ui/cardarea.py Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2007-04-09 15:31:52 UTC (rev 410) +++ trunk/pybridge/pybridge/ui/cardarea.py 2007-04-09 15:33:32 UTC (rev 411) @@ -62,11 +62,13 @@ def __init__(self): super(CardArea, self).__init__() # Initialise parent. - # To receive card clicked events, override this with external method. - self.on_card_clicked = lambda card, player: True + # To receive these events, override with external method. + self.on_card_clicked = lambda card, position: True + self.on_hand_clicked = lambda position: True self.hands = {} self.trick = None + self.players = {} self.set_player_mapping(Direction.South) self.connect('button_press_event', self.button_press) @@ -106,15 +108,14 @@ @param omit: a list of elements of hand not to draw. """ - # TODO: coords should be dict (card : (pos_x, pos_y)), but this breaks when hashing. def get_coords_for_hand(): - coords = [] + coords = {} if player in (self.TOP, self.BOTTOM): pos_y = 0 if facedown is True: # Draw cards in one continuous row. for index, card in enumerate(hand): pos_x = index * self.spacing_x - coords.append((card, pos_x, pos_y)) + coords[card] = (pos_x, pos_y) else: # Insert a space between each suit. spaces = len([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 for index, card in enumerate(hand): @@ -122,21 +123,21 @@ insert = len([1 for suit, suitcards in suits.items() if len(suitcards) > 0 and RED_BLACK.index(card.suit) > RED_BLACK.index(suit)]) pos_x = (index + insert) * self.spacing_x - coords.append((card, pos_x, pos_y)) + coords[card] = (pos_x, pos_y) else: # LEFT or RIGHT. if facedown is True: # Wrap cards to a 4x4 grid. for index, card in enumerate(hand): adjust = player == self.RIGHT and index == 12 and 3 pos_x = ((index % 4) + adjust) * self.spacing_x pos_y = (index / 4) * self.spacing_y - coords.append((card, pos_x, pos_y)) + coords[card] = (pos_x, pos_y) else: longest = max([len(cards) for cards in suits.values()]) for index, card in enumerate(hand): adjust = player == self.RIGHT and longest - len(suits[card.suit]) pos_x = (suits[card.suit].index(card) + adjust) * self.spacing_x pos_y = RED_BLACK.index(card.suit) * self.spacing_y - coords.append((card, pos_x, pos_y)) + coords[card] = (pos_x, pos_y) return coords if facedown is False: @@ -160,14 +161,14 @@ coords = get_coords_for_hand() # Determine dimensions of hand. - width = max([x for card, x, y in coords]) + self.card_width - height = max([y for card, x, y in coords]) + self.card_height + width = max([x for x, y in coords.values()]) + self.card_width + height = max([y for x, y in coords.values()]) + self.card_height surface, context = self.new_surface(width, height) # Draw cards to surface. visible = [(i, card) for i, card in enumerate(hand) if card not in omit] for i, card in visible: - pos_x, pos_y = coords[i][1:] + pos_x, pos_y = coords[card] self.draw_card(context, pos_x, pos_y, card) # Save @@ -189,14 +190,21 @@ @param position: the position of the player. @param name: the name of the player, or None. """ + self.players[position] = None + + # If no name specified, show hand at position as translucent. + opacity = (name is None) and 0.5 or 1 + self.update_item('hand-%s' % position, opacity=opacity) + id = 'player-%s' % position - if name is None or id in self.items: - self.remove_item(id) - return layout = pango.Layout(self.create_pango_context()) layout.set_font_description(self.font_description) - layout.set_text('%s: %s' % (DIRECTION_SYMBOLS[position], name)) + if name is None: + layout.set_text('%s' % DIRECTION_SYMBOLS[position]) + else: + layout.set_text('%s: %s' % (DIRECTION_SYMBOLS[position], name)) + # Create an ImageSurface respective to dimensions of text. width, height = layout.get_pixel_size() width += 8; height += 4 @@ -270,47 +278,32 @@ self.trick = trick # Save trick and return. - def set_turn(self, turn): - """Sets the turn indicator. - - The hand of the player on turn is drawn opaque; - the other hands are drawn translucent. - - @param turn: the position of the turn indicator. - @type turn: Direction or None - """ - if turn is None: - return - - for position in Direction: - opacity = (position is turn) and 1 or 0.5 - self.update_item('hand-%s' % position, opacity=opacity) - - def button_press(self, widget, event): - """Determines if a card was clicked: if so, calls card_selected.""" + """Determines if a card was clicked: if so, calls on_card_selected.""" if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: found_hand = False # Determine the hand which was clicked. - for player in self.hands: - card_coords = self.hands[player]['coords'] - surface = self.hands[player]['surface'] - hand_x, hand_y = self.items['hand-%s' % player]['area'][0:2] + for position in self.hands: + card_coords = self.hands[position]['coords'] + surface = self.hands[position]['surface'] + hand_x, hand_y = self.items['hand-%s' % position]['area'][0:2] if (hand_x <= event.x <= hand_x + surface.get_width()) and \ (hand_y <= event.y <= hand_y + surface.get_height()): found_hand = True break if found_hand: + self.on_hand_clicked(position) + # Determine the card in hand which was clicked. pos_x, pos_y = event.x - hand_x, event.y - hand_y # Iterate through visible cards backwards. - for i, card in self.hands[player]['visible'][::-1]: - x, y = card_coords[i][1:] + for i, card in self.hands[position]['visible'][::-1]: + x, y = card_coords[card] if (x <= pos_x <= x + self.card_width) and \ (y <= pos_y <= y + self.card_height): - self.on_card_clicked(card, player) + self.on_card_clicked(card, position) break return True # Expected to return True. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-04-09 15:31:55
|
Revision: 410 http://svn.sourceforge.net/pybridge/?rev=410&view=rev Author: umgangee Date: 2007-04-09 08:31:52 -0700 (Mon, 09 Apr 2007) Log Message: ----------- Move game result message box into gameComplete(). Support hand-click to join game. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-04-09 11:56:19 UTC (rev 409) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2007-04-09 15:31:52 UTC (rev 410) @@ -84,6 +84,7 @@ # Set up CardArea widget. self.cardarea = CardArea() self.cardarea.on_card_clicked = self.on_card_clicked + self.cardarea.on_hand_clicked = self.on_hand_clicked self.cardarea.set_size_request(640, 480) self.scrolled_cardarea.add_with_viewport(self.cardarea) self.cardarea.show() @@ -258,6 +259,44 @@ self.score_store.prepend([textContract, textMade, textNS, textEW]) + def gameComplete(self): + for position in Direction: + self.redrawHand(position, all=True) + self.setTurnIndicator() + + dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL, + type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_OK) + dialog.set_title(_('Game result')) + + # Determine and display score in dialog box. + if self.table.game.contract: + declarerWon, defenceWon = self.table.game.play.getTrickCount() + required = self.table.game.contract['bid'].level.index + 7 + offset = declarerWon - required + score = self.table.game.getScore() + self.addScore(self.table.game.contract, declarerWon, score) + + contractText = self.formatContract(self.table.game.contract) + if offset > 0: + dialog.set_markup(_('Contract %s made by %s tricks.') \ + % (contractText, offset)) + elif offset < 0: + dialog.set_markup(_('Contract %s failed by %s tricks.') \ + % (contractText, abs(offset))) + else: + dialog.set_markup(_('Contract %s made exactly.') % contractText) + + scorer = (score >= 0 and _('declarer')) or _('defence') + dialog.format_secondary_text(_('Score %s points for %s.' % (abs(score), scorer))) + + else: + dialog.set_markup(_('Bidding passed out.')) + dialog.format_secondary_text(_('No score.')) + + dialog.run() + dialog.destroy() + + def redrawHand(self, position, all=False): """Redraws cards making up the hand at position. @@ -349,8 +388,7 @@ text = _("It is %s's turn") % str(turn) self.statusbar.push(context, text) except GameError: # Game not in progress - turn = None - self.cardarea.set_turn(turn) + pass def setVulnerability(self): @@ -413,7 +451,7 @@ #self.children.close('dialog_gameresult') self.resetGame() - #self.redrawTrick() # Clear trick. + self.redrawTrick() # Clear trick. for position in Direction: self.redrawHand(position) @@ -432,12 +470,16 @@ def event_makeCall(self, call, position): self.addCall(call, position) self.setTurnIndicator() + if self.table.game.bidding.isComplete(): self.setContract() if self.children.get(WindowBidbox): # If a player. self.children.close(self.children[WindowBidbox]) + if not self.table.game.inProgress(): + self.gameComplete() + def event_playCard(self, card, position): # Determine the position of the hand from which card was played. playfrom = self.table.game.play.whoPlayed(card) @@ -446,36 +488,11 @@ self.setTrickCount() self.redrawTrick() self.redrawHand(playfrom) + + if not self.table.game.inProgress(): + self.gameComplete() - def event_gameFinished(self): - for position in self.table.game.deal: - self.redrawHand(position, all=True) - self.setTurnIndicator() - - # Determine and display score in dialog box. - contract = self.table.game.bidding.getContract() - if contract: - trickCount = self.table.game.getTrickCount() - offset = trickCount['declarerWon'] - trickCount['required'] - score = self.table.game.score() - self.addScore(contract, trickCount['declarerWon'], score) - - textContract = _('Contract %s') % self.formatContract(contract) - textTrick = (offset > 0 and _('made by %s tricks') % offset) or \ - (offset < 0 and _('failed by %s tricks') % abs(offset)) or \ - _('made exactly') - scorer = (score >= 0 and _('declarer')) or _('defence') - textScore = _('Score %s points for %s') % (abs(score), scorer) - - message = '%s %s.\n\n%s.' % (textContract, textTrick, textScore) - else: - message = _('Bidding passed out.') - - dialog = self.children.open('dialog_gameresult', parent=self) - dialog.setup(message) - - def event_revealHand(self, hand, position): self.redrawHand(position) @@ -519,10 +536,17 @@ d.addErrback(self.errback) + def on_hand_clicked(self, position): + if not self.player and not self.table.players.get(position): + # Join game at position. + self.on_seat_activated(self.cardarea, position) + + def on_card_clicked(self, card, position): if self.player: - d = self.player.callRemote('playCard', card) - d.addErrback(self.errback) + if self.table.game.inProgress() and self.table.game.play: + d = self.player.callRemote('playCard', card) + d.addErrback(self.errback) def on_seat_activated(self, widget, position): @@ -531,8 +555,8 @@ self.player = player # RemoteReference to BridgePlayer object. self.position = position - self.takeseat.set_property('sensitive', False) - self.leaveseat.set_property('sensitive', True) + self.takeseat.set_property('visible', False) + self.leaveseat.set_property('visible', True) # If game is running and bidding is active, open bidding box. if self.table.game.inProgress(): d = self.player.callRemote('getHand') @@ -559,8 +583,8 @@ def success(r): self.player = None self.position = None - self.takeseat.set_property('sensitive', True) - self.leaveseat.set_property('sensitive', False) + self.takeseat.set_property('visible', True) + self.leaveseat.set_property('visible', False) if self.children.get(WindowBidbox): self.children.close(self.children[WindowBidbox]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-04-09 11:56:26
|
Revision: 409 http://svn.sourceforge.net/pybridge/?rev=409&view=rev Author: umgangee Date: 2007-04-09 04:56:19 -0700 (Mon, 09 Apr 2007) Log Message: ----------- Add __hash__() method to facilitate Card keys in dicts, replace __str__() with __repr__(). Modified Paths: -------------- trunk/pybridge/pybridge/bridge/card.py Modified: trunk/pybridge/pybridge/bridge/card.py =================================================================== --- trunk/pybridge/pybridge/bridge/card.py 2007-04-08 20:17:02 UTC (rev 408) +++ trunk/pybridge/pybridge/bridge/card.py 2007-04-09 11:56:19 UTC (rev 409) @@ -64,10 +64,14 @@ return cmp(selfIndex, otherIndex) - def __str__(self): - return "%s of %ss" % (self.rank, self.suit) + def __hash__(self): + return hash((self.rank, self.suit)) + def __repr__(self): + return "Card(%s, %s)" % (self.rank, self.suit) + + def getStateToCopy(self): return self.rank, self.suit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-04-08 20:17:04
|
Revision: 408 http://svn.sourceforge.net/pybridge/?rev=408&view=rev Author: umgangee Date: 2007-04-08 13:17:02 -0700 (Sun, 08 Apr 2007) Log Message: ----------- Remove unused IBridgeTable and IServerState interfaces. Modified Paths: -------------- trunk/pybridge/tests/monkey.py Removed Paths: ------------- trunk/pybridge/pybridge/interfaces/bridgetable.py trunk/pybridge/pybridge/interfaces/serverstate.py Deleted: trunk/pybridge/pybridge/interfaces/bridgetable.py =================================================================== --- trunk/pybridge/pybridge/interfaces/bridgetable.py 2007-04-07 20:56:08 UTC (rev 407) +++ trunk/pybridge/pybridge/interfaces/bridgetable.py 2007-04-08 20:17:02 UTC (rev 408) @@ -1,91 +0,0 @@ -# PyBridge -- online contract bridge made easy. -# Copyright (C) 2004-2006 PyBridge Project. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - -from zope.interface import Interface - - -class IBridgeTable(Interface): - """IBridgeTable defines methods specific to bridge tables.""" - - - def gameMakeCall(self, call, position): - """Add call from player (at position) to bidding.""" - - - def gamePlayCard(self, card, position): - """Add card from player (at position) to current trick.""" - - - def requestNextGame(self, ready, player): - """Indicates that player is ready (or not ready) to commence next game.""" - - - - -class IBridgeTableEvents(Interface): - """IBridgeTableEvents defines the events which may be generated by IBridgeTable. - - """ - - - def gameStarted(self, table, dealer, vulnNS, vulnEW): - """Called when a game is started. - - @param table: reference to table. - @param dealer: - @param vulnNS: - @param vulnEW: - """ - - - def gameFinished(self, table): - """Called when a game is finished. - - A game is finished if trick play is complete, or bidding is passed out, - or it has been aborted. - - @param table: reference to table. - """ - - - def gameCallMade(self, table, call, position): - """Called when a player (at position) makes a call. - - @param table: reference to table. - @param call: - @param position: - """ - - - def gameCardPlayed(self, table, card, position): - """Called when a player (at position) plays a card. - - @param table: reference to table. - @param card: - @param position: - """ - - - def gameHandRevealed(self, table, hand, position): - """Called when a player's hand becomes visible. - - @param table: reference to table. - @param hand: - @param position: - """ - Deleted: trunk/pybridge/pybridge/interfaces/serverstate.py =================================================================== --- trunk/pybridge/pybridge/interfaces/serverstate.py 2007-04-07 20:56:08 UTC (rev 407) +++ trunk/pybridge/pybridge/interfaces/serverstate.py 2007-04-08 20:17:02 UTC (rev 408) @@ -1,28 +0,0 @@ - - -from zope.interface import Interface - - -class IServerEvents(Interface): - """IServerEvents defines methods to track the state of a server.""" - - - def connectionLost(self, connector, reason): - """Called when connection to a server is lost.""" - - - def tableOpened(self, table): - """Called when a new table is opened.""" - - - def tableClosed(self, table): - """Called when an existing table is closed.""" - - - def userLoggedIn(self, user): - """Called when a user has connected and logged in.""" - - - def userLoggedOut(self, user): - """Called when a user has logged out.""" - Modified: trunk/pybridge/tests/monkey.py =================================================================== --- trunk/pybridge/tests/monkey.py 2007-04-07 20:56:08 UTC (rev 407) +++ trunk/pybridge/tests/monkey.py 2007-04-08 20:17:02 UTC (rev 408) @@ -41,7 +41,6 @@ from zope.interface import implements from pybridge.interfaces.observer import IListener -from pybridge.interfaces.serverstate import IServerEvents from pybridge.network.client import NetworkClient from pybridge.network.error import GameError @@ -86,9 +85,7 @@ http://folklore.org/StoryView.py?project=Macintosh&story=Monkey_Lives.txt """ - implements(IServerEvents) - def __init__(self, client): self.client = client self.table = None # RemoteTable. @@ -115,7 +112,7 @@ def joinTable(self): print "Looking for a table to join..." - if self.client.tablesAvailable.get('Monkey'): + if self.client.tableRoster.get('Monkey'): d = self.client.joinTable('Monkey') else: d = self.client.joinTable('Monkey', host=True) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |