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-02-28 18:33:23
|
Revision: 357 http://svn.sourceforge.net/pybridge/?rev=357&view=rev Author: umgangee Date: 2007-02-28 10:33:16 -0800 (Wed, 28 Feb 2007) Log Message: ----------- Upgrade the Enum class to version 0.4.2. Modified Paths: -------------- trunk/pybridge/pybridge/enum.py Modified: trunk/pybridge/pybridge/enum.py =================================================================== --- trunk/pybridge/pybridge/enum.py 2007-02-28 18:29:54 UTC (rev 356) +++ trunk/pybridge/pybridge/enum.py 2007-02-28 18:33:16 UTC (rev 357) @@ -3,7 +3,7 @@ # enum.py # Part of enum, a package providing enumerated types for Python. # -# Copyright © 2005 Ben Finney +# Copyright © 2006 Ben Finney # This is free software; you may copy, modify and/or distribute this work # under the terms of the GNU General Public License, version 2 or later # or, at your option, the terms of the Python license. @@ -50,13 +50,13 @@ __author_name__ = "Ben Finney" __author_email__ = "ben...@be..." __author__ = "%s <%s>" % (__author_name__, __author_email__) -__date__ = "2005-12-20" +__date__ = "2006-10-13" __copyright__ = "Copyright © %s %s" % ( __date__.split('-')[0], __author_name__ ) __license__ = "Choice of GPL or Python license" __url__ = "http://cheeseshop.python.org/pypi/enum/" -__version__ = "0.4.1" +__version__ = "0.4.2" class EnumException(Exception): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-02-28 18:29:54
|
Revision: 356 http://svn.sourceforge.net/pybridge/?rev=356&view=rev Author: umgangee Date: 2007-02-28 10:29:54 -0800 (Wed, 28 Feb 2007) Log Message: ----------- Fold the pybridge.environment.Environment class into pybridge.environment module. Make appropriate changes to UI code. Modified Paths: -------------- trunk/pybridge/pybridge/environment.py trunk/pybridge/pybridge/ui/__init__.py trunk/pybridge/pybridge/ui/canvas.py trunk/pybridge/pybridge/ui/cardarea.py trunk/pybridge/pybridge/ui/dialog_preferences.py trunk/pybridge/pybridge/ui/utils.py trunk/pybridge/pybridge/ui/window_main.py trunk/pybridge/pybridge/ui/wrapper.py Modified: trunk/pybridge/pybridge/environment.py =================================================================== --- trunk/pybridge/pybridge/environment.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/environment.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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 @@ -20,76 +20,95 @@ import sys -class Environment: - """This module provides path location services for PyBridge.""" +""" +This module provides path location services for PyBridge. +Note to PyBridge packagers: - def __init__(self): - # Locate base directory. - if hasattr(sys, 'frozen'): # If py2exe distribution. - currentdir = os.path.dirname(sys.executable) - self.basedir = os.path.abspath(currentdir) - else: # Typically /usr/ or root of source distribution. - currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) - self.basedir = os.path.normpath(os.path.join(currentdir, '..')) - - # Locate shared resources directory, typically /usr/share/. - if os.path.exists(os.path.join(self.basedir, 'share')): - self.sharedir = os.path.join(self.basedir, 'share') - else: # Root of source distribution. - self.sharedir = self.basedir - - # Locate config directory. - self.configdir = os.path.join(os.path.expanduser('~'), '.pybridge') - if not os.path.exists(self.configdir): - os.mkdir(self.configdir) # Create directory. +The packaging policy of your distribution may specify a filesystem organisation +standard, which conflicts with the directory structure defined in this module. +This is the only module that you should need to modify to make PyBridge +compliant with distribution policy. +""" - def find_configfile(self, name): - """A config file is located in <configdir>/""" - return os.path.join(self.configdir, name) +# Locate base directory. +if hasattr(sys, 'frozen'): # If py2exe distribution. + currentdir = os.path.dirname(sys.executable) + basedir = os.path.abspath(currentdir) +else: # Typically /usr/ (if installed) or root of source distribution. + currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) + basedir = os.path.normpath(os.path.join(currentdir, '..')) - def find_doc(self, name): - """A documentation file may be located in: - - <sharedir>/doc/pybridge/ (installed) - <basedir>/ (source) - """ - if self.sharedir == self.basedir: - return os.path.join(self.basedir, name) - else: - return os.path.join(self.sharedir, 'doc', 'pybridge', name) +# Locate shared resources directory, typically /usr/share/. +if os.path.exists(os.path.join(basedir, 'share')): + sharedir = os.path.join(basedir, 'share') +else: # Root of source distribution. + sharedir = basedir +# Locate client configuration directory, typically ~/.pybridge/. +clientconfigdir = os.path.join(os.path.expanduser('~'), '.pybridge') +if not os.path.exists(clientconfigdir): + os.mkdir(clientconfigdir) # Create directory. - def find_glade(self, name): - """A Glade interface file may be located in: - - <sharedir>/pybridge/glade/ (installed) - <basedir>/glade/ (source) - """ - if self.sharedir == self.basedir: - return os.path.join(self.basedir, 'glade', name) - else: - return os.path.join(self.sharedir, 'pybridge', 'glade', name) +# Locate server configuration directory. +serverconfigdir = clientconfigdir - def find_pixmap(self, name): - """A pixmap file may be located in: - - <sharedir>/pybridge/pixmaps/ (installed) - <basedir>/pixmaps/ (source) - """ - if self.sharedir == self.basedir: - return os.path.join(self.basedir, 'pixmaps', name) - else: - return os.path.join(self.sharedir, 'pybridge', 'pixmaps', name) +def find_config_client(name): + """A client configuration file is located in: + + <clientconfigdir>/ + """ + return os.path.join(clientconfigdir, name) - def get_localedir(self): - """Returns the path of the locale directory.""" - return os.path.join(self.sharedir, 'locale') +def find_config_server(name): + """A server configuration file is located in: + <serverconfigdir>/ + """ + return os.path.join(serverconfigdir, name) -environment = Environment() +def find_doc(name): + """A documentation file may be located in: + + <sharedir>/doc/pybridge/ (installed) + <basedir>/ (source) + """ + if sharedir == basedir: + return os.path.join(basedir, name) + else: + return os.path.join(sharedir, 'doc', 'pybridge', name) + + +def find_glade(name): + """A Glade interface file may be located in: + + <sharedir>/pybridge/glade/ (installed) + <basedir>/glade/ (source) + """ + if sharedir == basedir: + return os.path.join(basedir, 'glade', name) + else: + return os.path.join(sharedir, 'pybridge', 'glade', name) + + +def find_pixmap(name): + """A pixmap file may be located in: + + <sharedir>/pybridge/pixmaps/ (installed) + <basedir>/pixmaps/ (source) + """ + if sharedir == basedir: + return os.path.join(basedir, 'pixmaps', name) + else: + return os.path.join(sharedir, 'pybridge', 'pixmaps', name) + + +def get_localedir(): + """Returns the path of the locale directory.""" + return os.path.join(sharedir, 'locale') + Modified: trunk/pybridge/pybridge/ui/__init__.py =================================================================== --- trunk/pybridge/pybridge/ui/__init__.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/__init__.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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,14 +10,12 @@ # 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 pybridge.environment import environment - def run(): """""" from twisted.internet import gtk2reactor @@ -28,8 +26,9 @@ import locale import gettext + import pybridge.environment as env locale.setlocale(locale.LC_ALL, '') - gettext.bindtextdomain('pybridge', environment.get_localedir()) + gettext.bindtextdomain('pybridge', env.get_localedir()) gettext.textdomain('pybridge') gettext.install('pybridge') Modified: trunk/pybridge/pybridge/ui/canvas.py =================================================================== --- trunk/pybridge/pybridge/ui/canvas.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/canvas.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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. @@ -19,7 +19,7 @@ import gtk import cairo -from pybridge.environment import environment +import pybridge.environment as env class CairoCanvas(gtk.DrawingArea): @@ -28,7 +28,7 @@ Overlapping items. """ - background_path = environment.find_pixmap('baize.png') + background_path = env.find_pixmap('baize.png') background = cairo.ImageSurface.create_from_png(background_path) pattern = cairo.SurfacePattern(background) pattern.set_extend(cairo.EXTEND_REPEAT) Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/cardarea.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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. @@ -21,7 +21,7 @@ import pango import pangocairo -from pybridge.environment import environment +import pybridge.environment as env from canvas import CairoCanvas from pybridge.bridge.card import Card, Rank, Suit @@ -44,7 +44,7 @@ """ # Load card mask. - card_mask_path = environment.find_pixmap('bonded.png') + card_mask_path = env.find_pixmap('bonded.png') card_mask = cairo.ImageSurface.create_from_png(card_mask_path) font_description = pango.FontDescription('Sans Bold 10') Modified: trunk/pybridge/pybridge/ui/dialog_preferences.py =================================================================== --- trunk/pybridge/pybridge/ui/dialog_preferences.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/dialog_preferences.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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. @@ -20,7 +20,7 @@ import os from wrapper import GladeWrapper -from pybridge.environment import environment +import pybridge.environment as env import utils @@ -36,7 +36,7 @@ self.carddeck.pack_start(cell, True) self.carddeck.add_attribute(cell, 'text', 0) # Populate list of card decks. - path = environment.find_pixmap('') + path = env.find_pixmap('') for filename in os.listdir(path): if filename.endswith('.png'): iter = model.append((filename,)) Modified: trunk/pybridge/pybridge/ui/utils.py =================================================================== --- trunk/pybridge/pybridge/ui/utils.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/utils.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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,13 +10,13 @@ # 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 pybridge.environment import environment +import pybridge.environment as env # Set up client with UI event handler. from pybridge.network.client import client @@ -49,21 +49,27 @@ self.config.read(self.filename) # Create sections if they do not exist. - if not self.config.has_section('Connection'): - self.config.add_section('Connection') - self.write() + for section in ('Connection', 'General'): + if not self.config.has_section(section): + self.config.add_section(section) + self.write() + for key, value in self.config.items('Connection'): self.connection[key] = value + for key, value in self.config.items('General'): + self.general[key] = value def write(self): """""" for key, value in self.connection.items(): self.config.set('Connection', key, value) + for key, value in self.general.items(): + self.config.set('General', key, value) self.config.write(file(self.filename, 'w')) -settings = Settings(environment.find_configfile('client.cfg')) +settings = Settings(env.find_config_client('client.cfg')) Modified: trunk/pybridge/pybridge/ui/window_main.py =================================================================== --- trunk/pybridge/pybridge/ui/window_main.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/window_main.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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. @@ -21,15 +21,15 @@ import webbrowser -from pybridge import __version__ -from pybridge.environment import environment +from pybridge import __version__ as version +import pybridge.environment as env from pybridge.network.client import client from eventhandler import eventhandler import utils -TABLE_ICON = environment.find_pixmap("table.png") -USER_ICON = environment.find_pixmap("user.png") +TABLE_ICON = env.find_pixmap("table.png") +USER_ICON = env.find_pixmap("user.png") class WindowMain(GladeWrapper): @@ -209,16 +209,16 @@ def on_about_activate(self, widget, *args): about = gtk.AboutDialog() about.set_name('PyBridge') - about.set_version(__version__) - about.set_copyright('Copyright (C) 2004-2006 Michael Banks') + about.set_version(version) + about.set_copyright('Copyright (C) 2004-2007 Michael Banks') about.set_comments(_('A free online bridge game.')) about.set_website('http://pybridge.sourceforge.net/') - license = file(environment.find_doc('COPYING')).read() + license = file(env.find_doc('COPYING')).read() about.set_license(license) - authorsfile = file(environment.find_doc('AUTHORS')) + authorsfile = file(env.find_doc('AUTHORS')) authors = [author.strip() for author in authorsfile] about.set_authors(authors) - logo_path = environment.find_pixmap('pybridge.png') + logo_path = env.find_pixmap('pybridge.png') logo = gtk.gdk.pixbuf_new_from_file(logo_path) about.set_logo(logo) Modified: trunk/pybridge/pybridge/ui/wrapper.py =================================================================== --- trunk/pybridge/pybridge/ui/wrapper.py 2007-02-28 18:21:26 UTC (rev 355) +++ trunk/pybridge/pybridge/ui/wrapper.py 2007-02-28 18:29:54 UTC (rev 356) @@ -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. @@ -21,13 +21,13 @@ import gtk.glade import sys -from pybridge.environment import environment +import pybridge.environment as env -GLADE_PATH = environment.find_glade("pybridge.glade") +GLADE_PATH = env.find_glade("pybridge.glade") if sys.platform == 'win32': # Win32 should use the ICO icon. - ICON_PATH = environment.find_pixmap("pybridge.ico") + ICON_PATH = env.find_pixmap("pybridge.ico") else: # All other platforms should use the PNG icon. - ICON_PATH = environment.find_pixmap("pybridge.png") + ICON_PATH = env.find_pixmap("pybridge.png") class GladeWrapper: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-02-28 18:21:38
|
Revision: 355 http://svn.sourceforge.net/pybridge/?rev=355&view=rev Author: umgangee Date: 2007-02-28 10:21:26 -0800 (Wed, 28 Feb 2007) Log Message: ----------- New SQLObject object-relational database model, replacing flat-file user account store. Modified Paths: -------------- trunk/pybridge/pybridge/server/checker.py trunk/pybridge/pybridge/server/database.py trunk/pybridge/pybridge/server/server.py trunk/pybridge/pybridge/server/user.py Modified: trunk/pybridge/pybridge/server/checker.py =================================================================== --- trunk/pybridge/pybridge/server/checker.py 2007-02-28 18:11:30 UTC (rev 354) +++ trunk/pybridge/pybridge/server/checker.py 2007-02-28 18:21:26 UTC (rev 355) @@ -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. @@ -21,7 +21,7 @@ from twisted.python import failure, log from zope.interface import implements -from database import database +import database as db class Checker: @@ -34,35 +34,33 @@ def __init__(self): - self.database = database self.users = {} # Users online, from Server object. def requestAvatarId(self, credentials): - - def gotUser(user): - password = user.get('password', '') - d = defer.maybeDeferred(credentials.checkPassword, password) - d.addCallback(passwordMatch) - return d - + + def unauthorized(reason): + log.msg("Login failed for %s: %s" % (credentials.username, reason)) + return failure.Failure(error.UnauthorizedLogin(reason)) + def passwordMatch(matched): if matched: - if credentials.username in self.users.keys(): - raise unauthorized('Already logged in') + if credentials.username in self.users: + # TODO: delete old session and use this one instead? + return unauthorized("User is already logged in") else: return credentials.username else: - return unauthorized('Incorrect password') - - def unauthorized(reason): - log.msg('Login failed for %s: %s' % (credentials.username, reason)) - return failure.Failure(error.UnauthorizedLogin(reason)) - + return unauthorized("Incorrect password for user") + if credentials.username == '': - return checkers.ANONYMOUS - else: - d = self.database.getUser(credentials.username) - d.addCallbacks(gotUser, lambda e: unauthorized('No user account')) - return d + return checkers.ANONYMOUS # TODO: if allowAnonymousRegistration. + users = db.UserAccount.selectBy(username=credentials.username) + if users.count() is 0: + return unauthorized("User not known on server") + + d = defer.maybeDeferred(credentials.checkPassword, users[0].password) + d.addCallback(passwordMatch) + return d + Modified: trunk/pybridge/pybridge/server/database.py =================================================================== --- trunk/pybridge/pybridge/server/database.py 2007-02-28 18:11:30 UTC (rev 354) +++ trunk/pybridge/pybridge/server/database.py 2007-02-28 18:21:26 UTC (rev 355) @@ -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,81 +10,141 @@ # 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. -import shelve, anydbm, dbhash -from twisted.internet import defer -from twisted.python import failure +import os, re +from datetime import datetime +from sqlobject import * +from sqlobject.inheritance import InheritableSQLObject -from pybridge.environment import environment +import pybridge.environment as env +from pybridge.bridge.deck import Seat -class DuplicateError(Exception): - pass +backend = "sqlite" -class UnknownError(Exception): - pass +# 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. +connection = connectionForURI(connection_string) +sqlhub.processConnection = connection # Set all classes to use connection. -class UserDatabase: - """A simple database of user accounts.""" +class UserAccount(SQLObject): + """A store of user information. + + A user account is created when a user is registered. + """ - def __init__(self): - # Open the database file. - dbfile = environment.find_configfile('users.db') - self.accounts = shelve.open(dbfile, 'c', writeback=True) + username = StringCol(length=20, notNone=True, unique=True, alternateID=True) + password = StringCol(length=40, notNone=True) # Store SHA-1 hex hashes. + allowLogin = BoolCol(default=True) # If False, account login is disabled. + email = StringCol(default=None, length=320) # See RFC 2821 section 4.5.3.1. + realname = UnicodeCol(default=None, length=40) + profile = UnicodeCol(default=None) + created = DateTimeCol(default=datetime.now) + lastLogin = DateTimeCol(default=None) + # friends = MultipleJoin('UserFriend', joinColumn='from_user') + def _set_username(self, value): + if not isinstance(value, str) or not(1 <= len(value) <= 20): + raise ValueError, "Invalid specification of username" + if re.search("[^A-z0-9_]", value): + raise ValueError, "Username can only contain alphanumeric characters" + self._SO_set_username(value) - def addUser(self, username, **attrs): - """Adds a new user.""" - if self.accounts.has_key(username): - f = failure.Failure(DuplicateError()) - return defer.fail(f) - - profile = attrs.copy() - profile['username'] = username - self.accounts[username] = profile - - return defer.succeed(username) + def _set_password(self, value): + if not isinstance(value, str) or not(1 <= len(value) <= 40): + raise ValueError, "Invalid specification of password" + self._SO_set_password(value) + def _set_email(self, value): + # This regexp matches virtually all well-formatted email addresses. + if value and not re.match("^[A-z0-9_.+-]+@([A-z0-9-]+\.)+[A-z]{2,6}$", value): + raise ValueError, "Invalid or ill-formatted email address" + self._SO_set_email(value) - def removeUser(self, username): - """Removes an existing user.""" - if not self.accounts.has_key(username): - f = failure.Failure(UnknownError()) - return defer.fail(f) - - del self.accounts[username] - - return defer.succeed(username) - - def updateUser(self, username, **attrs): - """Updates attributes for an existing user.""" - if not self.accounts.has_key(username): - f = failure.Failure(UnknownError()) - return defer.fail(f) - - self.accounts[username].update(attrs) - - return defer.succeed(username) +for table in [UserAccount]: + table.createTable(ifNotExists=True) - def getUser(self, username): - """Returns a dict of information for an existing user.""" - if not self.accounts.has_key(username): - f = failure.Failure(UnknownError()) - return defer.fail(f) - - info = self.accounts[username] - - return defer.succeed(info) +# The following tables are not used by PyBridge 0.3. +# They will be enhanced and used in future releases. -database = UserDatabase() +class UserFriend(SQLObject): + """Models the social interconnections that exist between users. + + Client software may use this information to provide visual clues to users + that members of their "social circle" are online. + + Users may specify the nature of their relationships: this takes inspiration + from the XFN (XHTML Friend Network) model: see http://gmpg.org/xfn/. The + symmetry arising from some types of relationship is eschewed for simplicity. + + This relation is irreflexive: no user can form a friendship with themselves! + """ + fromUser = ForeignKey('UserAccount') # The creator of the relationship. + toUser = ForeignKey('UserAccount') # The subject of the relationship. + fromToIndex = DatabaseIndex('fromUser', 'toUser', unique=True) + + # XFN attributes. + friendship = EnumCol(default=None, enumValues=['friend', 'acquaintance', 'contact']) + physical = BoolCol(default=False) # Having met in person. + professional = EnumCol(default=None, enumValues=['co-worker', 'colleague']) + geographical = EnumCol(default=None, enumValues=['co-resident', 'neighbour']) + family = EnumCol(default=None, enumValues=['child', 'parent', 'sibling', 'spouse', 'kin']) + romantic = EnumCol(default=None, enumValues=['muse', 'crush', 'date', 'sweetheart']) + + +class Game(InheritableSQLObject): + """Captures game attributes common to all games. + + Implementations of specific games should inherit from this class. + """ + + start = DateTimeCol() + complete = DateTimeCol() + + +class BridgeGame(Game): + """Captures game attributes specific to bridge games. + + """ + + board = ForeignKey('BridgeBoard') + + declarer = EnumCol(enumValues=list(Seat)) +# contract = + trickCount = IntCol() # Number of tricks won by + score = IntCol() + + # Although key attributes of games are stored in fields (for searching), + # the complete game is represented in PBN format. + pbn = StringCol() + + # Players: no player may occupy more than one position. + north = ForeignKey('UserAccount') + east = ForeignKey('UserAccount') + south = ForeignKey('UserAccount') + west = ForeignKey('UserAccount') + + +class BridgeBoard(SQLObject): + """Encapsulates the attributes which may be common to multiple bridge games. + + Separating board attributes from . + """ + + deal = IntCol() + dealer = EnumCol(enumValues=list(Seat)) + vuln = EnumCol(enumValues=['none', 'ns', 'ew', 'all']) + Modified: trunk/pybridge/pybridge/server/server.py =================================================================== --- trunk/pybridge/pybridge/server/server.py 2007-02-28 18:11:30 UTC (rev 354) +++ trunk/pybridge/pybridge/server/server.py 2007-02-28 18:21:26 UTC (rev 355) @@ -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,16 +10,19 @@ # 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 datetime import datetime from twisted.python import log -from database import database -import pybridge +import database as db +from pybridge import __version__ + +from pybridge.network.error import DeniedRequest, IllegalRequest from pybridge.network.tablemanager import LocalTableManager from pybridge.network.usermanager import LocalUserManager @@ -32,13 +35,14 @@ def __init__(self): self.tables = LocalTableManager() self.users = LocalUserManager() - self.version = pybridge.__version__ + self.version = __version__ self.supported = ['bridge'] def userConnects(self, user): """""" self.users.userLoggedIn(user) + db.UserAccount.byUsername(user.name).set(lastLogin=datetime.now()) log.msg("User %s connected" % user.name) @@ -51,11 +55,26 @@ # Methods invoked by user perspectives. - def userRegister(self, username, password): + def registerUser(self, username, password): + """Registers a new user account in the database. + + @param username: the unique username requested by user. + @param password: the password to be associated with the account. + """ + # Check that username has not already been registered. + if db.UserAccount.selectBy(username=username).count() > 0: + raise DeniedRequest, "Username already registered" + try: + # Create user account. + db.UserAccount(username=username, password=password, allowLogin=True) + log.msg("New user %s registered" % username) + except ValueError, err: + raise IllegalRequest, err + + + def userChangePassword(self, user, password): """""" - d = database.addUser(username, password=password) - log.msg("New user %s registered" % username) - return d + pass def createTable(self, tableid, tabletype): Modified: trunk/pybridge/pybridge/server/user.py =================================================================== --- trunk/pybridge/pybridge/server/user.py 2007-02-28 18:11:30 UTC (rev 354) +++ trunk/pybridge/pybridge/server/user.py 2007-02-28 18:21:26 UTC (rev 355) @@ -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,13 +10,15 @@ # 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. import re +#from twisted.internet import defer +#from twisted.python import failure from twisted.spread import pb from pybridge.network.error import DeniedRequest, IllegalRequest @@ -73,13 +75,13 @@ def perspective_hostTable(self, tableid, tabletype): """Creates a new table.""" if not isinstance(tableid, str): - raise IllegalRequest, 'Invalid parameter for table identifier' + raise IllegalRequest, "Invalid parameter for table identifier" elif not(0 < len(tableid) < 21) or re.search("[^A-Za-z0-9_ ]", tableid): - raise IllegalRequest, 'Invalid table identifier format' + raise IllegalRequest, "Invalid table identifier format" elif tableid in self.server.tables: - raise DeniedRequest, 'Table name exists' + raise DeniedRequest, "Table name exists" elif tabletype not in self.server.supported: - raise DeniedRequest, 'Table type not suppported by this server' + raise DeniedRequest, "Table type not suppported by this server" self.server.createTable(tableid, tabletype) return self.perspective_joinTable(tableid) # Force join to table. @@ -88,11 +90,11 @@ def perspective_joinTable(self, tableid): """Joins an existing table.""" if not isinstance(tableid, str): - raise IllegalRequest, 'Invalid parameter for table name' + raise IllegalRequest, "Invalid parameter for table name" elif tableid not in self.server.tables: - raise DeniedRequest, 'No such table' + raise DeniedRequest, "No such table" elif tableid in self.tables: - raise DeniedRequest, 'Already joined table' + raise DeniedRequest, "Already joined table" table = self.server.tables[tableid] self.tables[tableid] = table @@ -103,11 +105,11 @@ def perspective_leaveTable(self, tableid): """Leaves a table.""" if not isinstance(tableid, str): - raise IllegalRequest, 'Invalid parameter for table name' + raise IllegalRequest, "Invalid parameter for table name" elif tableid not in self.tables: - raise DeniedRequest, 'Not joined to table' + raise DeniedRequest, "Not joined to table" - del self.tables[tableid] + del self.tables[tableid] # Implicitly removes user from table. @@ -116,11 +118,7 @@ def perspective_register(self, username, password): - """Register a user account with given username and password.""" - if not isinstance(username, str): - raise IllegalRequest, 'Invalid parameter for user name' - elif not isinstance(password, str): - raise IllegalRequest, 'Invalid parameter for password' - - self.server.userRegister(username, password) + """Create a user account with specified username and password.""" + # TODO: consider defer.succeed, defer.fail, failure.Failure + self.server.registerUser(username, password) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-02-28 18:11:34
|
Revision: 354 http://svn.sourceforge.net/pybridge/?rev=354&view=rev Author: umgangee Date: 2007-02-28 10:11:30 -0800 (Wed, 28 Feb 2007) Log Message: ----------- Expanded docstrings of error classes. Modified Paths: -------------- trunk/pybridge/pybridge/network/error.py Modified: trunk/pybridge/pybridge/network/error.py =================================================================== --- trunk/pybridge/pybridge/network/error.py 2007-02-21 19:09:09 UTC (rev 353) +++ trunk/pybridge/pybridge/network/error.py 2007-02-28 18:11:30 UTC (rev 354) @@ -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. @@ -19,11 +19,17 @@ from twisted.spread import pb -# Base errors. - class DeniedRequest(pb.Error): - """Raised in response to an unsatisfiable request.""" + """Raised by server in response to an unsatisfiable request from client.""" + class IllegalRequest(pb.Error): - """Raised in response to an erroneous request.""" + """Raised by server in response to an erroneous request from client. + + The propagation of this error from server to client suggests there is a bug + in the client code (ie. sending invalid or ill-formatted data to the server) + or in the server code (ie. mishandling data). + + Please report any bugs which you discover in PyBridge! + """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-02-21 19:09:14
|
Revision: 353 http://svn.sourceforge.net/pybridge/?rev=353&view=rev Author: umgangee Date: 2007-02-21 11:09:09 -0800 (Wed, 21 Feb 2007) Log Message: ----------- In indexToDeal, make initial n = k-1 instead of 0, to eliminate a few unnecessary calls to comb. Modified Paths: -------------- trunk/pybridge/pybridge/bridge/deck.py Modified: trunk/pybridge/pybridge/bridge/deck.py =================================================================== --- trunk/pybridge/pybridge/bridge/deck.py 2007-02-18 21:51:28 UTC (rev 352) +++ trunk/pybridge/pybridge/bridge/deck.py 2007-02-21 19:09:09 UTC (rev 353) @@ -141,9 +141,14 @@ deal[seat] = [] for k in range(13, 0, -1): # Find the largest n such that comb(n, k) <= indexes[seat]. - n = 0 + n = k-1 # n < k implies comb(n, k) = 0 + + # comb(n+1, k) = + # n-k = -1 => comb(n, k) * (n+1) + # otherwise => (comb(n, k) * (n+1)) / (n+1 - k) while comb(n+1, k) <= indexes[seat]: n += 1 + # Remove card index from indices, add card to hand. indexes[seat] -= comb(n, k) card = cardSeq[n] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2007-02-18 21:51:42
|
Revision: 352 http://svn.sourceforge.net/pybridge/?rev=352&view=rev Author: umgangee Date: 2007-02-18 13:51:28 -0800 (Sun, 18 Feb 2007) Log Message: ----------- Implemented two-way conversion between deals and deal indexes, based on the "Impossible Bridge Book" algorithm (see http://bridge.thomasoandrews.com/impossible/). Modified Paths: -------------- trunk/pybridge/pybridge/bridge/deck.py Modified: trunk/pybridge/pybridge/bridge/deck.py =================================================================== --- trunk/pybridge/pybridge/bridge/deck.py 2006-12-01 15:21:18 UTC (rev 351) +++ trunk/pybridge/pybridge/bridge/deck.py 2007-02-18 21:51:28 UTC (rev 352) @@ -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,13 +10,15 @@ # 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. -import random # To shuffle a deck. +from copy import copy +from operator import mul +from random import shuffle from card import Card, Rank, Suit @@ -25,21 +27,55 @@ Seat = Enum('North', 'East', 'South', 'West') # Clockwise. +# See http://mail.python.org/pipermail/edu-sig/2001-May/001288.html for details. +comb = lambda n, k: reduce(mul, range(n, n-k, -1)) / reduce(mul, range(1, k+1)) + + +# TODO: consider making Hand a subclass of List, with additional constraints. + class Deck: - """A Deck consists of 52 Card objects.""" + """A Deck object provides operations for dealing Card objects. + + A hand is a collection of 13 cards from the deck. + A deal is a distribution of all 52 cards to four hands. + + A deal is represented as a dictionary, mapping Seat labels to lists (hands) + of Card objects. + + There are exactly 52! / (13!)**4 (comb(52,13) * comb(39,13) * comb(26,13)) + distinct deals of 13 cards to 4 players from a standard 52-card deck. + """ - def __init__(self): - self.cards = [Card(r, s) for r in Rank for s in Suit] + cards = [Card(r, s) for r in Rank for s in Suit] + cardSeq = copy(cards) + cardSeq.sort(reverse=True) # Required order: Ace of Spades -> Two of Clubs. + Nmax = comb(52, 13) + Emax = comb(39, 13) + Smax = comb(26, 13) + D = Nmax * Emax * Smax - def dealOrdered(self, combination): - """Returns a deal, ordered by combination.""" - pass # Not implemented yet. + def isValidDeal(self, deal): + """Checks that structure of deal conforms to requirements: - def dealRandom(self): - """Returns a deal, from a shuffled deck.""" - random.shuffle(self.cards) + * 4-element dict, mapping Seat objects to hand lists. + * Hand lists contain exactly 13 Card objects. + * No card may be repeated in the same hand, or between hands. + * The cards in hands may be in any order. + + @param deal: a deal dict. + @return: True if deal is valid, False otherwise. + """ + return True # TODO + + + def dealRandom(self): # randomDeal + """Shuffles the deck and generates a random deal of hands. + + @return: a deal dictionary. + """ + shuffle(self.cards) hands = {} for seat in Seat: hands[seat] = [] @@ -49,3 +85,71 @@ hand.sort() return hands + + def dealToIndex(self, deal): + """Computes the index which corresponds to the specified deal. + + This implements the "impossible bridge book" encoding algorithm by + Thomas Andrews, see http://bridge.thomasoandrews.com/impossible/. + + @param deal: dict representing a valid deal. + @return: integer in range 0..D-1 + """ + assert self.isValidDeal(deal) + + cardSeq = copy(self.cardSeq) # Make a copy for modification. + indexes = {} + + # For each hand, compute indexes of cards in cardSeq. + for seat in (Seat.North, Seat.East, Seat.South): + indexes[seat] = 0 + deal[seat].sort(reverse=False) + # It is desirable to remove cards from cardSeq when adding their + # indexes, instead of doing so in an extra step. + # Removing cards backwards preserves the indexes of later cards. + for i, card in enumerate(deal[seat]): + indexes[seat] += comb(cardSeq.index(card), 13-i) + cardSeq.remove(card) + + # Deal index = (Nindex * Emax * Smax) + (Eindex * Smax) + Sindex + indexes[Seat.North] *= self.Emax * self.Smax + indexes[Seat.East] *= self.Smax + return sum(indexes.values()) + + + def indexToDeal(self, num): + """Generates the deal which corresponds to the specified index. + + This implements the "impossible bridge book" decoding algorithm by + Thomas Andrews, see http://bridge.thomasoandrews.com/impossible/. + + @param num: integer in range 0..D-1. + @return: dict representing a valid deal. + """ + assert type(num) in (int, long), "index must be an integer" + assert 0 <= num < self.D, "index not in required range" + + cardSeq = copy(self.cardSeq) # Make a copy for modification. + deal = {} + + # Split index into hand indexes. + indexes = {Seat.North : (num / self.Smax) / self.Emax, + Seat.East : (num / self.Smax) % self.Emax, + Seat.South : (num % self.Smax) } + + for seat in (Seat.North, Seat.East, Seat.South): + deal[seat] = [] + for k in range(13, 0, -1): + # Find the largest n such that comb(n, k) <= indexes[seat]. + n = 0 + while comb(n+1, k) <= indexes[seat]: + n += 1 + # Remove card index from indices, add card to hand. + indexes[seat] -= comb(n, k) + card = cardSeq[n] + deal[seat].append(card) + cardSeq.remove(card) + + deal[Seat.West] = cardSeq # South has the remaining cards. + return deal + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-12-01 15:21:25
|
Revision: 351 http://svn.sourceforge.net/pybridge/?rev=351&view=rev Author: umgangee Date: 2006-12-01 07:21:18 -0800 (Fri, 01 Dec 2006) Log Message: ----------- Changed play of cards by single-clicking to double-clicking, as a confirmation check. Modified Paths: -------------- trunk/pybridge/pybridge/ui/cardarea.py Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2006-10-09 17:44:51 UTC (rev 350) +++ trunk/pybridge/pybridge/ui/cardarea.py 2006-12-01 15:21:18 UTC (rev 351) @@ -66,8 +66,8 @@ self.trick = None self.set_seat_mapping(Seat.South) - self.connect('button_release_event', self.button_release) - self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK) + self.connect('button_press_event', self.button_press) + self.add_events(gtk.gdk.BUTTON_PRESS_MASK) def draw_card(self, context, pos_x, pos_y, card): @@ -270,8 +270,8 @@ def set_turn(self, turn): """Sets the turn indicator. - The turn indicator is displayed as a rounded rectangle around - the hand matching the specified seat. + The hand of the player on turn is drawn opaque; + the other hands are drawn translucent. @param turn: a member of Seat, or None. """ @@ -282,25 +282,10 @@ opacity = (seat is turn) and 1 or 0.5 self.update_item('hand-%s' % seat, opacity=opacity) -# # TODO: select colours that don't clash with the background. -# # TODO: one colour if user can play card from hand, another if not. -# width = self.hands[turn]['surface'].get_width() + 20 -# height = self.hands[turn]['surface'].get_height() + 20 -# surface, context = self.new_surface(width, height) -# context.set_source_rgb(0.3, 0.6, 0) # Green. -# context.paint_with_alpha(0.5) -# -# xy = self.items['hand-%s' % turn]['xy'] # Use same xy as hand. -# -# if id in self.items: -# self.update_item(id, source=surface, xy=xy) -# else: -# self.add_item(id, surface, xy, -1) - - def button_release(self, widget, event): + def button_press(self, widget, event): """Determines if a card was clicked: if so, calls card_selected.""" - if event.button == 1: + if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: found_hand = False # Determine the hand which was clicked. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-10-09 17:45:29
|
Revision: 350 http://svn.sourceforge.net/pybridge/?rev=350&view=rev Author: umgangee Date: 2006-10-09 10:44:51 -0700 (Mon, 09 Oct 2006) Log Message: ----------- Add DialogPreferences window class. Modified Paths: -------------- trunk/pybridge/pybridge/ui/window_main.py Added Paths: ----------- trunk/pybridge/pybridge/ui/dialog_preferences.py Added: trunk/pybridge/pybridge/ui/dialog_preferences.py =================================================================== --- trunk/pybridge/pybridge/ui/dialog_preferences.py (rev 0) +++ trunk/pybridge/pybridge/ui/dialog_preferences.py 2006-10-09 17:44:51 UTC (rev 350) @@ -0,0 +1,62 @@ +# 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. + + +import gtk +import os +from wrapper import GladeWrapper + +from pybridge.environment import environment +import utils + + +class DialogPreferences(GladeWrapper): + + glade_name = 'dialog_preferences' + + + def new(self): + model = gtk.ListStore(str) + self.carddeck.set_model(model) + cell = gtk.CellRendererText() + self.carddeck.pack_start(cell, True) + self.carddeck.add_attribute(cell, 'text', 0) + # Populate list of card decks. + path = environment.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) + + +# Signal handlers. + + + def on_carddeck_changed(self, widget, *args): + print "changed" + + + def on_cancelbutton_clicked(self, widget, *args): + print "cancel" + utils.windows.close(self.glade_name) + + + def on_okbutton_clicked(self, widget, *args): + print "ok" + utils.windows.close(self.glade_name) + Modified: trunk/pybridge/pybridge/ui/window_main.py =================================================================== --- trunk/pybridge/pybridge/ui/window_main.py 2006-10-09 17:41:57 UTC (rev 349) +++ trunk/pybridge/pybridge/ui/window_main.py 2006-10-09 17:44:51 UTC (rev 350) @@ -172,9 +172,7 @@ self.frame_personinfo.set_property('sensitive', False) self.label_personname.set_text('') - - def on_window_main_delete_event(self, widget, *args): utils.quit() # return True @@ -200,6 +198,10 @@ utils.quit() + def on_preferences_activate(self, widget, *args): + utils.windows.open('dialog_preferences') + + def on_homepage_activate(self, widget, *args): webbrowser.open('http://pybridge.sourceforge.net/') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-10-09 17:43:49
|
Revision: 349 http://svn.sourceforge.net/pybridge/?rev=349&view=rev Author: umgangee Date: 2006-10-09 10:41:57 -0700 (Mon, 09 Oct 2006) Log Message: ----------- New dialog_preferences window. Switch from Glade 2 to Glade 3, yay! Modified Paths: -------------- trunk/pybridge/glade/pybridge.glade Modified: trunk/pybridge/glade/pybridge.glade =================================================================== --- trunk/pybridge/glade/pybridge.glade 2006-10-08 20:07:52 UTC (rev 348) +++ trunk/pybridge/glade/pybridge.glade 2006-10-09 17:41:57 UTC (rev 349) @@ -1,3720 +1,2552 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> -<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> - +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> <glade-interface> - -<widget class="GtkWindow" id="window_main"> - <property name="visible">True</property> - <property name="title" translatable="yes">PyBridge</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - <signal name="delete_event" handler="on_window_main_delete_event" last_modification_time="Mon, 27 Mar 2006 14:07:43 GMT"/> - - <child> - <widget class="GtkVBox" id="vbox1"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkMenuBar" id="menubar_main"> - <property name="visible">True</property> - <property name="pack_direction">GTK_PACK_DIRECTION_LTR</property> - <property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property> - - <child> - <widget class="GtkMenuItem" id="menu_server"> - <property name="visible">True</property> - <property name="label" translatable="yes">_File</property> - <property name="use_underline">True</property> - - <child> - <widget class="GtkMenu" id="menu_server_menu"> - - <child> - <widget class="GtkImageMenuItem" id="menu_newtable"> - <property name="visible">True</property> - <property name="label" translatable="yes">_New Table...</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_newtable_clicked" last_modification_time="Tue, 08 Aug 2006 16:22:07 GMT"/> - - <child internal-child="image"> - <widget class="GtkImage" id="image340"> - <property name="visible">True</property> - <property name="stock">gtk-new</property> - <property name="icon_size">1</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkImageMenuItem" id="menu_opengame"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">_Open Game...</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_opengame_activate" last_modification_time="Mon, 07 Aug 2006 13:57:54 GMT"/> - - <child internal-child="image"> - <widget class="GtkImage" id="image341"> - <property name="visible">True</property> - <property name="stock">gtk-open</property> - <property name="icon_size">1</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkSeparatorMenuItem" id="menu_separator"> - <property name="visible">True</property> - </widget> - </child> - - <child> - <widget class="GtkImageMenuItem" id="menu_disconnect"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Disconnect</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_disconnect_activate" last_modification_time="Mon, 19 Sep 2005 09:26:13 GMT"/> - - <child internal-child="image"> - <widget class="GtkImage" id="image342"> - <property name="visible">True</property> - <property name="stock">gtk-disconnect</property> - <property name="icon_size">1</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkImageMenuItem" id="menu_quit"> - <property name="visible">True</property> - <property name="label">gtk-quit</property> - <property name="use_stock">True</property> - <signal name="activate" handler="on_quit_activate" last_modification_time="Sat, 02 Apr 2005 15:32:19 GMT"/> - </widget> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkMenuItem" id="menu_help"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Help</property> - <property name="use_underline">True</property> - - <child> - <widget class="GtkMenu" id="menu_help_menu"> - - <child> - <widget class="GtkImageMenuItem" id="menu_homepage"> - <property name="visible">True</property> - <property name="label" translatable="yes">PyBridge _Home Page</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_homepage_activate" last_modification_time="Mon, 07 Aug 2006 13:48:07 GMT"/> - - <child internal-child="image"> - <widget class="GtkImage" id="image343"> - <property name="visible">True</property> - <property name="stock">gtk-home</property> - <property name="icon_size">1</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkSeparatorMenuItem" id="menu_separator"> - <property name="visible">True</property> - </widget> - </child> - - <child> - <widget class="GtkImageMenuItem" id="menu_about"> - <property name="visible">True</property> - <property name="label" translatable="yes">_About PyBridge</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_about_activate" last_modification_time="Wed, 16 Feb 2005 20:18:12 GMT"/> - - <child internal-child="image"> - <widget class="GtkImage" id="image344"> - <property name="visible">True</property> - <property name="stock">gtk-about</property> - <property name="icon_size">1</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - </child> - </widget> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkNotebook" id="notebook"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="show_tabs">True</property> - <property name="show_border">True</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">False</property> - <property name="enable_popup">False</property> - <signal name="switch_page" handler="on_notebook_switch_page" last_modification_time="Thu, 03 Aug 2006 11:43:33 GMT"/> - - <child> - <widget class="GtkHBox" id="hbox22"> - <property name="border_width">8</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">8</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow5"> - <property name="width_request">320</property> - <property name="height_request">240</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkIconView" id="tableview"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="selection_mode">GTK_SELECTION_SINGLE</property> - <property name="orientation">GTK_ORIENTATION_VERTICAL</property> - <property name="reorderable">False</property> - <signal name="item_activated" handler="on_tableview_item_activated" last_modification_time="Mon, 31 Jul 2006 15:12:34 GMT"/> - <signal name="selection_changed" handler="on_tableview_selection_changed" last_modification_time="Tue, 08 Aug 2006 16:39:09 GMT"/> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox16"> - <property name="width_request">160</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">4</property> - - <child> - <widget class="GtkButton" id="newtable"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_newtable_clicked" last_modification_time="Tue, 08 Aug 2006 16:15:48 GMT"/> - - <child> - <widget class="GtkAlignment" id="alignment19"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox24"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image322"> - <property name="visible">True</property> - <property name="stock">gtk-new</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label55"> - <property name="visible">True</property> - <property name="label" translatable="yes">New Table...</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="jointable"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_jointable_clicked" last_modification_time="Tue, 08 Aug 2006 16:15:56 GMT"/> - - <child> - <widget class="GtkAlignment" id="alignment20"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox25"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image323"> - <property name="visible">True</property> - <property name="stock">gtk-jump-to</property> - <property name="icon_size">4</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label56"> - <property name="visible">True</property> - <property name="label" translatable="yes">Join This Table</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkFrame" id="frame_tableinfo"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label_xalign">0.5</property> - <property name="label_yalign">0.5</property> - <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> - - <child> - <widget class="GtkAlignment" id="alignment21"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">1</property> - <property name="yscale">1</property> - <property name="top_padding">4</property> - <property name="bottom_padding">4</property> - <property name="left_padding">4</property> - <property name="right_padding">4</property> - - <child> - <widget class="GtkTable" id="table_tableinfo"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">8</property> - - <child> - <widget class="GtkLabel" id="label63"> - <property name="visible">True</property> - <property name="label" translatable="yes">ID:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label_tableid"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label65"> - <property name="visible">True</property> - <property name="label" translatable="yes">Type:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label_tabletype"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</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">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkLabel" id="label57"> - <property name="visible">True</property> - <property name="label" translatable="yes">Table Information</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="tab_tables"> - <property name="visible">True</property> - <property name="label" translatable="yes">Available Tables</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox23"> - <property name="border_width">8</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">8</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow9"> - <property name="width_request">320</property> - <property name="height_request">240</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkIconView" id="peopleview"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="selection_mode">GTK_SELECTION_SINGLE</property> - <property name="orientation">GTK_ORIENTATION_VERTICAL</property> - <property name="reorderable">False</property> - <signal name="item_activated" handler="on_peopleview_item_activated" last_modification_time="Mon, 07 Aug 2006 19:21:22 GMT"/> - <signal name="selection_changed" handler="on_peopleview_selection_changed" last_modification_time="Sun, 13 Aug 2006 19:13:43 GMT"/> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox17"> - <property name="width_request">160</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">4</property> - - <child> - <widget class="GtkFrame" id="frame_personinfo"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label_xalign">0.5</property> - <property name="label_yalign">0.5</property> - <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> - - <child> - <widget class="GtkAlignment" id="alignment22"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">1</property> - <property name="yscale">1</property> - <property name="top_padding">4</property> - <property name="bottom_padding">4</property> - <property name="left_padding">4</property> - <property name="right_padding">4</property> - - <child> - <widget class="GtkTable" id="table_personinfo"> - <property name="visible">True</property> - <property name="n_rows">1</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">2</property> - <property name="column_spacing">8</property> - - <child> - <widget class="GtkLabel" id="label67"> - <property name="visible">True</property> - <property name="label" translatable="yes">Name:</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label_personname"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GtkLabel" id="label58"> - <property name="visible">True</property> - <property name="label" translatable="yes">Person Information</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label_people"> - <property name="visible">True</property> - <property name="label" translatable="yes">People Online</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - -<widget class="GtkWindow" id="window_bidbox"> - <property name="visible">True</property> - <property name="title" translatable="yes">Bidding Box</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">False</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">True</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_EAST</property> - <property name="focus_on_map">False</property> - <property name="urgency_hint">False</property> - <signal name="delete_event" handler="on_window_bidbox_delete_event" last_modification_time="Tue, 28 Mar 2006 11:28:01 GMT"/> - - <child> - <widget class="GtkVBox" id="calls"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkButton" id="button_pass"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">Pass</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:32:29 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHSeparator" id="hseparator2"> - <property name="visible">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table_bids"> - <property name="visible">True</property> - <property name="n_rows">7</property> - <property name="n_columns">5</property> - <property name="homogeneous">False</property> - <property name="row_spacing">0</property> - <property name="column_spacing">0</property> - - <child> - <widget class="GtkButton" id="button_bid_1_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">1NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:35:34 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_1_spade"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">1♠</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:33:17 GMT"/> - </widget> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_1_heart"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">1♥</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:33:03 GMT"/> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_1_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">1♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:32:45 GMT"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_1_club"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">1♣</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:26:19 GMT"/> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_3_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">3♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:34:39 GMT"/> - </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="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_2_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">2♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:33:56 GMT"/> - </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="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_2_club"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">2♣</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:33:47 GMT"/> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_2_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">2NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:34:18 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_3_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">3NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:35:20 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_4_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">4NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:13 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_5_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">5NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:42 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_6_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">6NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:08 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_7_nt"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">7NT</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:39 GMT"/> - </widget> - <packing> - <property name="left_attach">4</property> - <property name="right_attach">5</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_7_spade"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">7♠</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:34 GMT"/> - </widget> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_7_heart"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">7♥</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:29 GMT"/> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_7_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">7♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:24 GMT"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_7_club"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">7♣</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:19 GMT"/> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">6</property> - <property name="bottom_attach">7</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_6_club"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">6♣</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:47 GMT"/> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_6_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">6♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:54 GMT"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_6_heart"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">6♥</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:58 GMT"/> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_6_spade"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">6♠</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:37:03 GMT"/> - </widget> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">5</property> - <property name="bottom_attach">6</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_5_heart"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">5♥</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:32 GMT"/> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_5_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">5♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:28 GMT"/> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_5_club"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">5♣</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:22 GMT"/> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">4</property> - <property name="bottom_attach">5</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_4_club"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">4♣</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:35:53 GMT"/> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_4_diamond"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">4♦</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:35:58 GMT"/> - </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="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_4_heart"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">4♥</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:02 GMT"/> - </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="GtkButton" id="button_bid_4_spade"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">4♠</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:36:08 GMT"/> - </widget> - <packing> - <property name="left_attach">3</property> - <property name="right_attach">4</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button_bid_3_heart"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">3♥</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NONE</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_call_clicked" last_modification_time="Tue, 28 Mar 2006 11:34:45 GMT"/> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <pro... [truncated message content] |
From: <umg...@us...> - 2006-10-08 20:07:56
|
Revision: 348 http://svn.sourceforge.net/pybridge/?rev=348&view=rev Author: umgangee Date: 2006-10-08 13:07:52 -0700 (Sun, 08 Oct 2006) Log Message: ----------- Fix logic error in __eq__, which was triggered when comparing hands. Modified Paths: -------------- trunk/pybridge/pybridge/bridge/card.py Modified: trunk/pybridge/pybridge/bridge/card.py =================================================================== --- trunk/pybridge/pybridge/bridge/card.py 2006-10-08 15:01:55 UTC (rev 347) +++ trunk/pybridge/pybridge/bridge/card.py 2006-10-08 20:07:52 UTC (rev 348) @@ -41,8 +41,9 @@ def __eq__(self, other): """Two cards are equivalent if their ranks and suits match.""" - assert isinstance(other, Card) - return self.suit == other.suit and self.rank == other.rank + if isinstance(other, Card): + return self.suit == other.suit and self.rank == other.rank + return False def __cmp__(self, other): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-10-08 15:02:05
|
Revision: 347 http://svn.sourceforge.net/pybridge/?rev=347&view=rev Author: umgangee Date: 2006-10-08 08:01:55 -0700 (Sun, 08 Oct 2006) Log Message: ----------- Enable border around player labels, draw individual cards in trick with canvas code, indicate turn by setting transparency on inactive hands. Modified Paths: -------------- trunk/pybridge/pybridge/ui/canvas.py trunk/pybridge/pybridge/ui/cardarea.py Modified: trunk/pybridge/pybridge/ui/canvas.py =================================================================== --- trunk/pybridge/pybridge/ui/canvas.py 2006-10-06 16:25:53 UTC (rev 346) +++ trunk/pybridge/pybridge/ui/canvas.py 2006-10-08 15:01:55 UTC (rev 347) @@ -58,18 +58,19 @@ self.window.invalidate_rect((0, 0, width, height), False) - def add_item(self, id, source, xy, z_index): + def add_item(self, id, source, xy, z_index, opacity=1): """Places source item into items list. @param id: unique identifier for source. @param source: ImageSurface. @param xy: tuple providing (x, y) coords for source in backing. @param z_index: integer. + @param opacity: integer in range 0 to 1. """ # Calculate and cache the on-screen area of the item. area = self.get_area(source, xy) self.items[id] = {'source': source, 'area': area, 'xy': xy, - 'z-index': z_index, } + 'z-index': z_index, 'opacity' : opacity, } self.redraw(*area) @@ -84,12 +85,17 @@ self.redraw(*area) - def update_item(self, id, source=None, xy=None, z_index=0): + def update_item(self, id, source=None, xy=None, z_index=0, opacity=0): """ - + @param id: unique identifier for source. + @param source: if specified, ImageSurface. + @param xy: if specified, tuple providing (x, y) coords for source in backing. + @param z_index: if specified, integer. + @param opacity: if specified, integer in range 0 to 1. """ # If optional parameters are not specified, use stored values. z_index = z_index or self.items[id]['z-index'] + opacity = opacity or self.items[id]['opacity'] if source or xy: # If source or xy coords changed, recalculate on-screen area. source = source or self.items[id]['source'] @@ -106,7 +112,7 @@ area = self.items[id]['area'] self.items[id] = {'source': source, 'area': area, 'xy' : xy, - 'z-index': z_index, } + 'z-index': z_index, 'opacity' : opacity, } self.redraw(*area) @@ -135,7 +141,8 @@ for item in items: pos_x, pos_y = item['area'][0:2] context.set_source_surface(item['source'], pos_x, pos_y) - context.paint() +# context.paint() + context.paint_with_alpha(item['opacity']) context.reset_clip() self.window.invalidate_rect((x, y, width, height), False) # Expose. Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2006-10-06 16:25:53 UTC (rev 346) +++ trunk/pybridge/pybridge/ui/cardarea.py 2006-10-08 15:01:55 UTC (rev 347) @@ -196,26 +196,26 @@ layout.set_text(name) # Create an ImageSurface respective to dimensions of text. width, height = layout.get_pixel_size() + width += 8; height += 4 surface, context = self.new_surface(width, height) context = pangocairo.CairoContext(context) -# context.set_line_width(4) -# context.rectangle(0, 0, width, height) -# context.set_source_rgb(0, 0.5, 0) -# context.fill_preserve() -# context.set_source_rgb(0, 0.25, 0) -# context.stroke() -# context.move_to(4, 2) + # Draw background box, text to ImageSurface. + context.set_line_width(4) + context.rectangle(0, 0, width, height) + context.set_source_rgb(0, 0.5, 0) + context.fill_preserve() + context.set_source_rgb(0, 0.25, 0) + context.stroke() + context.move_to(4, 2) context.set_source_rgb(1, 1, 1) context.show_layout(layout) if id in self.items: self.update_item(id, source=surface) else: - xy = {self.TOP : (0.5, 0.05), self.BOTTOM : (0.5, 0.95), - self.LEFT : (0.15, 0.7), self.RIGHT : (0.85, 0.7), } -# xy = {self.TOP : (0.5, 0.3), self.BOTTOM : (0.5, 0.7), -# self.LEFT : (0.15, 0.7), self.RIGHT : (0.85, 0.7), } + xy = {self.TOP : (0.5, 0.15), self.BOTTOM : (0.5, 0.85), + self.LEFT : (0.15, 0.6), self.RIGHT : (0.85, 0.6), } self.add_item(id, surface, xy[seat], 2) @@ -237,35 +237,34 @@ @param trick: a (leader, cards_played) pair, or None. """ - id = 'trick' - self.trick = trick - if trick is None: - self.remove_item(id) - return + xy = {self.TOP : (0.5, 0.425), self.BOTTOM : (0.5, 0.575), + self.LEFT : (0.425, 0.5), self.RIGHT : (0.575, 0.5), } - width, height = 200, 200 - # (x, y) positions to fit within (width, height) bound box. - pos = {Seat.North : ((width - self.card_width)/2, 0 ), - Seat.East : ((width - self.card_width), (height - self.card_height)/2 ), - Seat.South : ((width - self.card_width)/2, (height - self.card_height) ), - Seat.West : (0, (height - self.card_height)/2 ), } - - surface, context = self.new_surface(width, height) - if trick: - leader, cards_played = trick # The order of play is the leader, then clockwise around Seat. - for seat in Seat[leader.index:] + Seat[:leader.index]: - card = cards_played.get(seat) - if card: - pos_x, pos_y = pos[seat] - self.draw_card(context, pos_x, pos_y, card) + leader = trick[0] + order = Seat[leader.index:] + Seat[:leader.index] + for i, seat in enumerate(order): + id = 'trick-%s' % seat + old_card = self.trick and self.trick[1].get(seat) or None + new_card = trick[1].get(seat) + # 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[seat], z_index=i+1) + elif new_card is None and old_card is not None: + self.remove_item(id) + elif old_card != new_card: + surface, context = self.new_surface(self.card_width, self.card_height) + self.draw_card(context, 0, 0, new_card) + self.update_item(id, surface, z_index=i+1) - if id in self.items: - self.update_item(id, source=surface) - else: - xy = (0.5, 0.5) - self.add_item(id, surface, xy, 0) + elif self.trick: # Remove all cards from previous trick. + for seat in self.trick[1]: + self.remove_item('trick-%s' % seat) + + self.trick = trick # Save trick and return. def set_turn(self, turn): @@ -276,27 +275,29 @@ @param turn: a member of Seat, or None. """ - id = 'turn' if turn is None: - self.remove_item(id) return - # TODO: select colours that don't clash with the background. - # TODO: one colour if user can play card from hand, another if not. - width = self.hands[turn]['surface'].get_width() + 20 - height = self.hands[turn]['surface'].get_height() + 20 - surface, context = self.new_surface(width, height) - context.set_source_rgb(0.3, 0.6, 0) # Green. - context.paint_with_alpha(0.5) - - xy = self.items['hand-%s' % turn]['xy'] # Use same xy as hand. - - if id in self.items: - self.update_item(id, source=surface, xy=xy) - else: - self.add_item(id, surface, xy, -1) + for seat in Seat: + opacity = (seat is turn) and 1 or 0.5 + self.update_item('hand-%s' % seat, opacity=opacity) +# # TODO: select colours that don't clash with the background. +# # TODO: one colour if user can play card from hand, another if not. +# width = self.hands[turn]['surface'].get_width() + 20 +# height = self.hands[turn]['surface'].get_height() + 20 +# surface, context = self.new_surface(width, height) +# context.set_source_rgb(0.3, 0.6, 0) # Green. +# context.paint_with_alpha(0.5) +# +# xy = self.items['hand-%s' % turn]['xy'] # Use same xy as hand. +# +# if id in self.items: +# self.update_item(id, source=surface, xy=xy) +# else: +# self.add_item(id, surface, xy, -1) + def button_release(self, widget, event): """Determines if a card was clicked: if so, calls card_selected.""" if event.button == 1: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-10-06 16:26:04
|
Revision: 346 http://svn.sourceforge.net/pybridge/?rev=346&view=rev Author: umgangee Date: 2006-10-06 09:25:53 -0700 (Fri, 06 Oct 2006) Log Message: ----------- xy positioning of items in cardarea now uses (0..1, 0..1) values scaled by cardarea's width/height; replaces lambda positioning. Addition of set_player_name(). Modified Paths: -------------- trunk/pybridge/pybridge/ui/canvas.py trunk/pybridge/pybridge/ui/cardarea.py trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/canvas.py =================================================================== --- trunk/pybridge/pybridge/ui/canvas.py 2006-09-20 15:59:34 UTC (rev 345) +++ trunk/pybridge/pybridge/ui/canvas.py 2006-10-06 16:25:53 UTC (rev 346) @@ -54,7 +54,8 @@ context.rectangle(0, 0, width, height) context.set_source(self.pattern) context.paint() - self.window.invalidate_rect((0, 0, width, height), False) # Expose. + # Trigger a call to self.expose(). + self.window.invalidate_rect((0, 0, width, height), False) def add_item(self, id, source, xy, z_index): @@ -62,13 +63,13 @@ @param id: unique identifier for source. @param source: ImageSurface. - @param xy: function providing (x, y) coords for source in backing. + @param xy: tuple providing (x, y) coords for source in backing. @param z_index: integer. """ - pos_x, pos_y = xy(*self.window.get_size()) - area = (pos_x, pos_y, source.get_width(), source.get_height()) - self.items[id] = {'source': source, 'area': area, - 'xy' : xy, 'z-index': z_index, } + # Calculate and cache the on-screen area of the item. + area = self.get_area(source, xy) + self.items[id] = {'source': source, 'area': area, 'xy': xy, + 'z-index': z_index, } self.redraw(*area) @@ -87,29 +88,35 @@ """ """ - # If optional parameters are not specified, use previous values. - source = source or self.items[id]['source'] - xy = xy or self.items[id]['xy'] + # If optional parameters are not specified, use stored values. z_index = z_index or self.items[id]['z-index'] + if source or xy: + # If source or xy coords changed, recalculate on-screen area. + source = source or self.items[id]['source'] + xy = xy or self.items[id]['xy'] + area = self.get_area(source, xy) + # If area of item has changed, clear item from previous area. + oldarea = self.items[id]['area'] + if area != oldarea: + del self.items[id] + self.redraw(*oldarea) + else: + source = self.items[id]['source'] + xy = self.items[id]['xy'] + area = self.items[id]['area'] - oldarea = self.items[id]['area'] # Current position of item. - pos_x, pos_y = xy(*self.window.get_size()) - area = (pos_x, pos_y, source.get_width(), source.get_height()) - if area != oldarea: # If position has changed, clear previous area. - del self.items[id] - self.redraw(*oldarea) - self.items[id] = {'source': source, 'area': area, - 'xy' : xy, 'z-index': z_index, } + self.items[id] = {'source': source, 'area': area, 'xy' : xy, + 'z-index': z_index, } self.redraw(*area) def redraw(self, x, y, width, height): """Redraws sources in area (x, y, width, height) to backing canvas. - @param x: - @param y: - @param width: - @param height: + @param x: start x-coordinate of area to be redrawn. + @param y: start y-coordinate of area to be redrawn. + @param width: the width of area to be redrawn. + @param height: the height of area to be redrawn. """ context = cairo.Context(self.backing) context.rectangle(x, y, width, height) @@ -134,16 +141,55 @@ self.window.invalidate_rect((x, y, width, height), False) # Expose. + def get_area(self, source, xy): + """Calculates the on-screen area of the specified source centred at xy. + + @param source: + @param xy: + @return: a tuple (x, y, width, height) + """ + win_w, win_h = self.window.get_size() # Window width and height. + width, height = source.get_width(), source.get_height() + x = int((xy[0] * win_w) - width/2) # Round to integer. + y = int((xy[1] * win_h) - height/2) + # Ensure that source coordinates fit inside dimensions of backing. + if x < self.border_x: + x = self.border_x + elif x + width > win_w - self.border_x: + x = win_w - self.border_x - width + if y < self.border_y: + y = self.border_y + elif y + height > win_h - self.border_y: + y = win_h - self.border_y - height + return x, y, width, height + + def new_surface(self, width, height): + """Creates a new ImageSurface of dimensions (width, height) + and ensures that the ImageSurface is cleared. + + @param width: the expected width of the ImageSurface. + @param height: the expected height of the ImageSurface. + @return: tuple (surface, context) + """ + # Create new ImageSurface for hand. + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + # Clear ImageSurface - in Cairo 1.2+, this is done automatically. + if cairo.version_info < (1, 2): + context.set_operator(cairo.OPERATOR_CLEAR) + context.paint() + context.set_operator(cairo.OPERATOR_OVER) # Restore. + return surface, context + + def configure(self, widget, event): width, height = self.window.get_size() self.backing = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) # Recalculate position of all items. - for id, item in self.items.items(): - pos_x, pos_y = item['xy'](width, height) - area = (pos_x, pos_y, item['area'][2], item['area'][3]) - self.items[id]['area'] = area + for id, item in self.items.iteritems(): + self.items[id]['area'] = self.get_area(item['source'], item['xy']) self.redraw(0, 0, width, height) # Full redraw required. return True # Expected to return True. Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2006-09-20 15:59:34 UTC (rev 345) +++ trunk/pybridge/pybridge/ui/cardarea.py 2006-10-06 16:25:53 UTC (rev 346) @@ -18,6 +18,8 @@ import gtk import cairo +import pango +import pangocairo from pybridge.environment import environment from canvas import CairoCanvas @@ -45,6 +47,8 @@ card_mask_path = environment.find_pixmap('bonded.png') card_mask = cairo.ImageSurface.create_from_png(card_mask_path) + font_description = pango.FontDescription('Sans Bold 10') + border_x = border_y = 10 card_width = card_mask.get_width() / 13 card_height = card_mask.get_height() / 5 @@ -110,10 +114,10 @@ pos_x = index * self.spacing_x coords.append((card, pos_x, pos_y)) else: # Insert a space between each suit. - spaces = sum([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 + spaces = len([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 for index, card in enumerate(hand): # Insert a space for each suit in hand which appears before this card's suit. - insert = sum([1 for suit, suitcards in suits.items() if len(suitcards) > 0 + 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)) @@ -156,14 +160,7 @@ # 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 - # Create new ImageSurface for hand. - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - # Clear ImageSurface - in Cairo 1.2+, this is done automatically. - if cairo.version_info < (1, 2): - context.set_operator(cairo.OPERATOR_CLEAR) - context.paint() - context.set_operator(cairo.OPERATOR_OVER) # Restore. + 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] @@ -175,23 +172,53 @@ self.hands[seat] = {'hand' : hand, 'visible' : visible, 'surface' : surface, 'coords' : coords, } - # - if seat is self.TOP: - xy = lambda w, h: ((w - width)/2, self.border_y) - elif seat is self.RIGHT: - xy = lambda w, h: ((w - width - self.border_x), (h - height)/2) - elif seat is self.BOTTOM: - xy = lambda w, h: ((w - width)/2, (h - height - self.border_y)) - elif seat is self.LEFT: - xy = lambda w, h: (self.border_x, (h - height)/2) - id = 'hand-%s' % seat # Identifier for this item. if id in self.items: - self.update_item(id, source=surface, xy=xy) - else: - self.add_item(id, surface, xy, 0) + 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[seat], 0) + def set_player_name(self, seat, name=None): + """ + + @param name: the name of the player, or None. + """ + id = 'player-%s' % seat + 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(name) + # Create an ImageSurface respective to dimensions of text. + width, height = layout.get_pixel_size() + surface, context = self.new_surface(width, height) + context = pangocairo.CairoContext(context) + +# context.set_line_width(4) +# context.rectangle(0, 0, width, height) +# context.set_source_rgb(0, 0.5, 0) +# context.fill_preserve() +# context.set_source_rgb(0, 0.25, 0) +# context.stroke() +# context.move_to(4, 2) + context.set_source_rgb(1, 1, 1) + context.show_layout(layout) + + if id in self.items: + self.update_item(id, source=surface) + else: + xy = {self.TOP : (0.5, 0.05), self.BOTTOM : (0.5, 0.95), + self.LEFT : (0.15, 0.7), self.RIGHT : (0.85, 0.7), } +# xy = {self.TOP : (0.5, 0.3), self.BOTTOM : (0.5, 0.7), +# self.LEFT : (0.15, 0.7), self.RIGHT : (0.85, 0.7), } + self.add_item(id, surface, xy[seat], 2) + + def set_seat_mapping(self, focus=Seat.South): """Sets the mapping between seats at table and positions of hands. @@ -223,14 +250,7 @@ Seat.South : ((width - self.card_width)/2, (height - self.card_height) ), Seat.West : (0, (height - self.card_height)/2 ), } - # Create new ImageSurface for trick. - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - # Clear ImageSurface - in Cairo 1.2+, this is done automatically. - if cairo.version_info < (1, 2): - context.set_operator(cairo.OPERATOR_CLEAR) - context.paint() - context.set_operator(cairo.OPERATOR_OVER) # Restore. + surface, context = self.new_surface(width, height) if trick: leader, cards_played = trick @@ -244,11 +264,10 @@ if id in self.items: self.update_item(id, source=surface) else: - xy = lambda w, h: ((w - width)/2, (h - height)/2) + xy = (0.5, 0.5) self.add_item(id, surface, xy, 0) - def set_turn(self, turn): """Sets the turn indicator. @@ -262,19 +281,16 @@ self.remove_item(id) return - def xy(w, h): - x, y = self.items['hand-%s' % turn]['xy'](w, h) - return x-10, y-10 - # TODO: select colours that don't clash with the background. - # TODO: one colour if user can click card, another if not. + # TODO: one colour if user can play card from hand, another if not. width = self.hands[turn]['surface'].get_width() + 20 height = self.hands[turn]['surface'].get_height() + 20 - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) + surface, context = self.new_surface(width, height) context.set_source_rgb(0.3, 0.6, 0) # Green. context.paint_with_alpha(0.5) + xy = self.items['hand-%s' % turn]['xy'] # Use same xy as hand. + if id in self.items: self.update_item(id, source=surface, xy=xy) else: Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-09-20 15:59:34 UTC (rev 345) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-10-06 16:25:53 UTC (rev 346) @@ -353,6 +353,7 @@ def event_playerAdded(self, table, player, position): if table == self.table: + self.cardarea.set_player_name(position, player) # Disable menu item corresponding to position. widget = self.takeseat_items[position] widget.set_property('sensitive', False) @@ -367,6 +368,7 @@ def event_playerRemoved(self, table, player, position): if table == self.table: + self.cardarea.set_player_name(position, None) # Enable menu item corresponding to position. widget = self.takeseat_items[position] widget.set_property('sensitive', True) @@ -384,13 +386,14 @@ self.children.close('dialog_gameresult') self.resetGame() + self.redrawTrick() # Clear trick. + for position in table.game.deal: + self.redrawHand(position) + self.setTurnIndicator() self.setDealer(table.dealer) self.setVuln(table.game.vulnNS, table.game.vulnEW) - self.redrawTrick() # Clear trick. - for position in table.game.deal: - self.redrawHand(position) if table.seated: self.children.open('window_bidbox', parent=self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-09-20 15:59:46
|
Revision: 345 http://svn.sourceforge.net/pybridge/?rev=345&view=rev Author: umgangee Date: 2006-09-20 08:59:34 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Added turn indicator to CardArea. Fixed a couple of bugs. Modified Paths: -------------- trunk/pybridge/pybridge/ui/canvas.py trunk/pybridge/pybridge/ui/cardarea.py trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/canvas.py =================================================================== --- trunk/pybridge/pybridge/ui/canvas.py 2006-09-20 11:00:26 UTC (rev 344) +++ trunk/pybridge/pybridge/ui/canvas.py 2006-09-20 15:59:34 UTC (rev 345) @@ -79,7 +79,7 @@ """ if self.items.get(id): area = self.items[id]['area'] - del self.item[id] + del self.items[id] self.redraw(*area) @@ -123,7 +123,7 @@ # TODO: Find sources which intersect with area. area = gtk.gdk.Rectangle(x, y, width, height) items = self.items.values() - items.sort(lambda i, j : cmp(i['z-index'], j['z-index']), reverse=True) + items.sort(lambda i, j : cmp(i['z-index'], j['z-index'])) for item in items: pos_x, pos_y = item['area'][0:2] Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2006-09-20 11:00:26 UTC (rev 344) +++ trunk/pybridge/pybridge/ui/cardarea.py 2006-09-20 15:59:34 UTC (rev 345) @@ -208,8 +208,14 @@ """Sets the current trick. Draws representation of current trick to context. - @param trick: a (leader, cards_played) pair. + @param trick: a (leader, cards_played) pair, or None. """ + id = 'trick' + self.trick = trick + if trick is None: + self.remove_item(id) + return + width, height = 200, 200 # (x, y) positions to fit within (width, height) bound box. pos = {Seat.North : ((width - self.card_width)/2, 0 ), @@ -235,7 +241,6 @@ pos_x, pos_y = pos[seat] self.draw_card(context, pos_x, pos_y, card) - id = 'trick' if id in self.items: self.update_item(id, source=surface) else: @@ -244,21 +249,36 @@ - def set_turn(self, seat): + def set_turn(self, turn): + """Sets the turn indicator. + + The turn indicator is displayed as a rounded rectangle around + the hand matching the specified seat. + + @param turn: a member of Seat, or None. """ + id = 'turn' + if turn is None: + self.remove_item(id) + return - @param seat: a member of Seat. - """ -# hand_surface = self.hands[seat]['surface'] -# x = self.hands[seat]['xy'] - 10 -# y = self.hands[seat]['xy'] - 10 -# width = surface.get_width() + 20 -# height = surface.get_height() + 20 -# args = ('turn', surface, pos_x, pos_y, -1) -# if self.items.get('turn'): -# self.update_item(*args) -# else: -# self.add_item(*args) + def xy(w, h): + x, y = self.items['hand-%s' % turn]['xy'](w, h) + return x-10, y-10 + + # TODO: select colours that don't clash with the background. + # TODO: one colour if user can click card, another if not. + width = self.hands[turn]['surface'].get_width() + 20 + height = self.hands[turn]['surface'].get_height() + 20 + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + context.set_source_rgb(0.3, 0.6, 0) # Green. + context.paint_with_alpha(0.5) + + if id in self.items: + self.update_item(id, source=surface, xy=xy) + else: + self.add_item(id, surface, xy, -1) def button_release(self, widget, event): Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-09-20 11:00:26 UTC (rev 344) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-09-20 15:59:34 UTC (rev 345) @@ -283,9 +283,12 @@ def setTurnIndicator(self): """Sets the statusbar text to indicate which player is on turn.""" - turn = self.table.game and not self.table.game.isComplete() \ - and self.table.game.whoseTurn() + turn = None + if self.table.game and not self.table.game.isComplete(): + turn = self.table.game.whoseTurn() + self.cardarea.set_turn(turn) + context = self.statusbar.get_context_id('turn') self.statusbar.pop(context) if turn: @@ -385,7 +388,7 @@ self.setDealer(table.dealer) self.setVuln(table.game.vulnNS, table.game.vulnEW) - self.redrawTrick() + self.redrawTrick() # Clear trick. for position in table.game.deal: self.redrawHand(position) if table.seated: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-09-20 11:00:30
|
Revision: 344 http://svn.sourceforge.net/pybridge/?rev=344&view=rev Author: umgangee Date: 2006-09-20 04:00:26 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Force import of pybridge package, after path to pybridge has been inserted in sys.path. Running "pybridge-server -v" on local (not installed) PyBridge setups will now work. Modified Paths: -------------- trunk/pybridge/bin/pybridge trunk/pybridge/bin/pybridge-server Modified: trunk/pybridge/bin/pybridge =================================================================== --- trunk/pybridge/bin/pybridge 2006-09-20 10:56:47 UTC (rev 343) +++ trunk/pybridge/bin/pybridge 2006-09-20 11:00:26 UTC (rev 344) @@ -56,6 +56,7 @@ else: pythonpath = basedir sys.path.insert(0, pythonpath) # Place PyBridge package in PYTHONPATH. + import pybridge import pybridge.ui Modified: trunk/pybridge/bin/pybridge-server =================================================================== --- trunk/pybridge/bin/pybridge-server 2006-09-20 10:56:47 UTC (rev 343) +++ trunk/pybridge/bin/pybridge-server 2006-09-20 11:00:26 UTC (rev 344) @@ -52,6 +52,7 @@ else: pythonpath = basedir sys.path.insert(0, pythonpath) # Place PyBridge package in PYTHONPATH. + import pybridge for opt, arg in opts: if opt in ('-h', '--help'): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-09-20 10:56:56
|
Revision: 343 http://svn.sourceforge.net/pybridge/?rev=343&view=rev Author: umgangee Date: 2006-09-20 03:56:47 -0700 (Wed, 20 Sep 2006) Log Message: ----------- Rewritten CardArea widget for Cairo. Introduction of a "canvas" layer, which manages positioning and redrawing of graphics. Modifications to WindowBridgetable in line with CardArea. Modified Paths: -------------- trunk/pybridge/pybridge/ui/cardarea.py trunk/pybridge/pybridge/ui/window_bridgetable.py Added Paths: ----------- trunk/pybridge/pybridge/ui/canvas.py Added: trunk/pybridge/pybridge/ui/canvas.py =================================================================== --- trunk/pybridge/pybridge/ui/canvas.py (rev 0) +++ trunk/pybridge/pybridge/ui/canvas.py 2006-09-20 10:56:47 UTC (rev 343) @@ -0,0 +1,160 @@ +# 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. + + +import gtk +import cairo + +from pybridge.environment import environment + + +class CairoCanvas(gtk.DrawingArea): + """Provides a simple canvas layer for . + + Overlapping items. + """ + + background_path = environment.find_pixmap('baize.png') + background = cairo.ImageSurface.create_from_png(background_path) + pattern = cairo.SurfacePattern(background) + pattern.set_extend(cairo.EXTEND_REPEAT) + + + def __init__(self): + super(CairoCanvas, self).__init__() # Initialise parent. + + self.items = {} + + # Set up gtk.Widget signals. + self.connect('configure_event', self.configure) + self.connect('expose_event', self.expose) + + + def clear(self): + """Clears all items from canvas.""" + self.items = {} # Remove all item references. + + # Redraw background pattern on backing. + width, height = self.window.get_size() + context = cairo.Context(self.backing) + context.rectangle(0, 0, width, height) + context.set_source(self.pattern) + context.paint() + self.window.invalidate_rect((0, 0, width, height), False) # Expose. + + + def add_item(self, id, source, xy, z_index): + """Places source item into items list. + + @param id: unique identifier for source. + @param source: ImageSurface. + @param xy: function providing (x, y) coords for source in backing. + @param z_index: integer. + """ + pos_x, pos_y = xy(*self.window.get_size()) + area = (pos_x, pos_y, source.get_width(), source.get_height()) + self.items[id] = {'source': source, 'area': area, + 'xy' : xy, 'z-index': z_index, } + self.redraw(*area) + + + def remove_item(self, id): + """Removes source item with identifier from items list. + + @param id: unique identifier for source. + """ + if self.items.get(id): + area = self.items[id]['area'] + del self.item[id] + self.redraw(*area) + + + def update_item(self, id, source=None, xy=None, z_index=0): + """ + + """ + # If optional parameters are not specified, use previous values. + source = source or self.items[id]['source'] + xy = xy or self.items[id]['xy'] + z_index = z_index or self.items[id]['z-index'] + + oldarea = self.items[id]['area'] # Current position of item. + pos_x, pos_y = xy(*self.window.get_size()) + area = (pos_x, pos_y, source.get_width(), source.get_height()) + if area != oldarea: # If position has changed, clear previous area. + del self.items[id] + self.redraw(*oldarea) + self.items[id] = {'source': source, 'area': area, + 'xy' : xy, 'z-index': z_index, } + self.redraw(*area) + + + def redraw(self, x, y, width, height): + """Redraws sources in area (x, y, width, height) to backing canvas. + + @param x: + @param y: + @param width: + @param height: + """ + context = cairo.Context(self.backing) + context.rectangle(x, y, width, height) + context.clip() # Set clip region. + + # Redraw background pattern in area. + context.set_source(self.pattern) + context.paint() + + # Build list of sources to redraw in area, in order of z-index. + # TODO: Find sources which intersect with area. + area = gtk.gdk.Rectangle(x, y, width, height) + items = self.items.values() + items.sort(lambda i, j : cmp(i['z-index'], j['z-index']), reverse=True) + + for item in items: + pos_x, pos_y = item['area'][0:2] + context.set_source_surface(item['source'], pos_x, pos_y) + context.paint() + + context.reset_clip() + self.window.invalidate_rect((x, y, width, height), False) # Expose. + + + + def configure(self, widget, event): + width, height = self.window.get_size() + self.backing = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + + # Recalculate position of all items. + for id, item in self.items.items(): + pos_x, pos_y = item['xy'](width, height) + area = (pos_x, pos_y, item['area'][2], item['area'][3]) + self.items[id]['area'] = area + + self.redraw(0, 0, width, height) # Full redraw required. + return True # Expected to return True. + + + def expose(self, widget, event): + context = widget.window.cairo_create() + context.rectangle(*event.area) + context.clip() # Only redraw the exposed area. + context.set_source_surface(self.backing, 0, 0) + context.paint() + context.reset_clip() + return False # Expected to return False. + Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2006-08-16 14:02:03 UTC (rev 342) +++ trunk/pybridge/pybridge/ui/cardarea.py 2006-09-20 10:56:47 UTC (rev 343) @@ -16,13 +16,12 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import gc, gtk +import gtk +import cairo from pybridge.environment import environment +from canvas import CairoCanvas -BACKGROUND_PATH = environment.find_pixmap("baize.png") -CARD_MASK_PATH = environment.find_pixmap("bonded.png") - from pybridge.bridge.card import Card, Rank, Suit from pybridge.bridge.deck import Seat @@ -35,73 +34,108 @@ # The red-black-red-black ordering convention. RED_BLACK = [Suit.Diamond, Suit.Club, Suit.Heart, Suit.Spade] -BORDER_X = BORDER_Y = 12 +class CardArea(CairoCanvas): + """This widget. -class CardArea(gtk.DrawingArea): + This widget uses Cairo and requires >= GTK 2.8. + """ - # TODO: when PyGTK 2.8 becomes widespread, adapt this module to Cairo. + # Load card mask. + card_mask_path = environment.find_pixmap('bonded.png') + card_mask = cairo.ImageSurface.create_from_png(card_mask_path) + + border_x = border_y = 10 + card_width = card_mask.get_width() / 13 + card_height = card_mask.get_height() / 5 + spacing_x = int(card_width * 0.4) + spacing_y = int(card_height * 0.2) - # Load table background and card pixbufs. - background = gtk.gdk.pixbuf_new_from_file(BACKGROUND_PATH).render_pixmap_and_mask()[0] - card_mask = gtk.gdk.pixbuf_new_from_file_at_size(CARD_MASK_PATH, 1028, 615) - def __init__(self): - gtk.DrawingArea.__init__(self) + super(CardArea, self).__init__() # Initialise parent. - self.backing = None # Placeholder for backing pixbuf. - self.hand_pixbufs = {} # Hand pixbufs, keyed by seat. - self.hand_coords = {} # Positions of hand pixbufs on backing. - self.card_coords = {} # Positions of cards on hand pixbufs. - self.trick_pixbuf = None # + # To receive card clicked events, override this with external method. + self.on_card_clicked = lambda card, seat: True - # Expect cards of unit size 13 x 5. - self.card_width = self.card_mask.get_width() / 13 - self.card_height = self.card_mask.get_height() / 5 - self.spacing_x = int(self.card_width * 0.4) - self.spacing_y = int(self.card_height * 0.2) + self.hands = {} + self.trick = None + self.set_seat_mapping(Seat.South) - # Method to call when a card is clicked. - self.on_card_clicked = None - - # Set up events. - self.connect('configure_event', self.configure) - self.connect('expose_event', self.expose) - self.connect('button_press_event', self.button_press) - self.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self.connect('button_release_event', self.button_release) + self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK) - def draw_card(self, dest_pixbuf, pos_x, pos_y, card): - """Draws graphic of specified card to dest_pixbuf at (pos_x, pos_y).""" - if isinstance(card, Card): # Determine coordinates of graphic in card_mask. + def draw_card(self, context, pos_x, pos_y, card): + """Draws graphic of specified card to context at (pos_x, pos_y). + + @param context: a cairo.Context + @param pos_x: + @param pos_y: + @param card: the Card to draw. + """ + if isinstance(card, Card): # Determine coordinates of card graphic. src_x = CARD_MASK_RANKS.index(card.rank) * self.card_width src_y = CARD_MASK_SUITS.index(card.suit) * self.card_height else: # Draw a face-down card. src_x, src_y = self.card_width*2, self.card_height*4 - self.card_mask.copy_area(src_x, src_y, self.card_width, self.card_height, - dest_pixbuf, pos_x, pos_y) + context.rectangle(pos_x, pos_y, self.card_width, self.card_height) + context.clip() + context.set_source_surface(self.card_mask, pos_x-src_x, pos_y-src_y) + context.paint() + context.reset_clip() - def build_hand(self, seat, hand, facedown=False, omit=[]): - """Builds and saves a pixbuf of card images. + def set_hand(self, hand, seat, facedown=False, omit=[]): + """Sets the hand of player at seat. + Draws representation of cards in hand to context. - @param seat: the seat of player holding hand. - @param hand: a list of Card objects representing the hand. - @param facedown: if True, card elements of hand are drawn face down. - @param omit: a list of Card objects in hand not to draw. + 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 seat: a member of Seat. + @param facedown: if True, cards are drawn face-down. + @param omit: a list of elements of hand not to draw. """ - # Filters out cards in hand that appear in omit. - ef = lambda hand: [(i, c) for i, c in enumerate(hand) if c not in omit] - - coords = [] + # TODO: coords should be dict (card : (pos_x, pos_y)), but this breaks when hashing. + def get_coords_for_hand(): + coords = [] + if seat 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)) + else: # Insert a space between each suit. + spaces = sum([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 + for index, card in enumerate(hand): + # Insert a space for each suit in hand which appears before this card's suit. + insert = sum([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)) + else: # LEFT or RIGHT. + if facedown is True: # Wrap cards to a 4x4 grid. + for index, card in enumerate(hand): + adjust = seat is 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)) + else: + longest = max([len(cards) for cards in suits.values()]) + for index, card in enumerate(hand): + adjust = seat is 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)) + return coords + if facedown is False: # Split hand into suits. - suits = {} - for suit in Suit: - suits[suit] = [] + suits = dict([(suit, []) for suit in Suit]) for card in hand: suits[card.suit].append(card) # Sort suits. @@ -111,178 +145,147 @@ hand = [] for suit in RED_BLACK: hand.extend(suits[suit]) + + saved = self.hands.get(seat) + if saved and saved['hand'] == hand: + # If hand has been set previously, do not recalculate coords. + coords = saved['coords'] + else: + coords = get_coords_for_hand() - if seat in (Seat.North, Seat.South): - height = self.card_height # Draw cards in one continuous row. - pos_y = 0 - - if facedown is True: - width = self.card_width + (self.spacing_x * 12) - for index, card in ef(hand): - pos_x = index * self.spacing_x - coords.append((card, pos_x, pos_y)) - - else: # Insert a space between each suit. - spaces = sum([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 - width = self.card_width + (self.spacing_x * (12 + spaces)) - for index, card in ef(hand): - # Insert a space for each suit in hand which appears before this card's suit. - insert = sum([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)) + # 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 + # Create new ImageSurface for hand. + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + # Clear ImageSurface - in Cairo 1.2+, this is done automatically. + if cairo.version_info < (1, 2): + context.set_operator(cairo.OPERATOR_CLEAR) + context.paint() + context.set_operator(cairo.OPERATOR_OVER) # Restore. - else: # West or East. - if facedown is True: # Wrap cards to a 4x4 grid. - width = self.card_width + (self.spacing_x * 3) - height = self.card_height + (self.spacing_y * 3) - for index, card in ef(hand): - adjust = seat is Seat.East 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)) - - else: - longest = max([len(cards) for cards in suits.values()]) - width = self.card_width + (self.spacing_x * (longest - 1)) - height = self.card_height + (self.spacing_y * (len(suits) - 1)) - for index, card in ef(hand): - adjust = seat is Seat.East 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)) + # 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:] + self.draw_card(context, pos_x, pos_y, card) - self.hand_pixbufs[seat] = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height) - self.hand_pixbufs[seat].fill(0x00000000) # Clear pixbuf. + # Save + self.hands[seat] = {'hand' : hand, 'visible' : visible, + 'surface' : surface, 'coords' : coords, } - # Draw cards to pixbuf. - for card, pos_x, pos_y in coords: - self.draw_card(self.hand_pixbufs[seat], pos_x, pos_y, card) - self.card_coords[seat] = coords - - - def draw_hand(self, seat): - """""" - x, y, width, height = self.get_allocation() + # + if seat is self.TOP: + xy = lambda w, h: ((w - width)/2, self.border_y) + elif seat is self.RIGHT: + xy = lambda w, h: ((w - width - self.border_x), (h - height)/2) + elif seat is self.BOTTOM: + xy = lambda w, h: ((w - width)/2, (h - height - self.border_y)) + elif seat is self.LEFT: + xy = lambda w, h: (self.border_x, (h - height)/2) - # Determine coordinates in backing pixmap to draw hand pixbuf. - hand_pixbuf = self.hand_pixbufs[seat] - hand_width = hand_pixbuf.get_width() - hand_height = hand_pixbuf.get_height() - - if seat is Seat.North: - pos_x = (width - hand_width) / 2 - pos_y = BORDER_Y - elif seat is Seat.East: - pos_x = width - hand_width - BORDER_X - pos_y = (height - hand_height) / 2 - elif seat is Seat.South: - pos_x = (width - hand_width) / 2 - pos_y = height - hand_height - BORDER_Y - elif seat is Seat.West: - pos_x = BORDER_X - pos_y = (height - hand_height) / 2 - - # Draw hand pixbuf and save hand coordinates. - self.backing.draw_rectangle(self.backingGC, True, pos_x, pos_y, hand_width, hand_height) - self.backing.draw_pixbuf(self.backingGC, hand_pixbuf, 0, 0, pos_x, pos_y) - self.hand_coords[seat] = (pos_x, pos_y, pos_x+hand_width, pos_y+hand_height) - - # Redraw modified area of backing pixbuf. - self.window.invalidate_rect((pos_x, pos_y, hand_width, hand_height), False) + id = 'hand-%s' % seat # Identifier for this item. + if id in self.items: + self.update_item(id, source=surface, xy=xy) + else: + self.add_item(id, surface, xy, 0) - def build_trick(self, trick): - """Builds and saves a pixbuf of trick.""" - width = self.card_width + self.spacing_x*2 - height = self.card_height + self.spacing_y*2 - self.trick_pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height) - self.trick_pixbuf.fill(0x00000000) # Clear pixbuf. - - # When called, returns (x, y) start point to draw card. - coords = {Seat.North : lambda: ((width-self.card_width)/2, 0), - Seat.East : lambda: (width-self.card_width, (height-self.card_height)/2), - Seat.South : lambda: ((width-self.card_width)/2, height-self.card_height), - Seat.West : lambda: (0, (height-self.card_height)/2), } + def set_seat_mapping(self, focus=Seat.South): + """Sets the mapping between seats at table and positions of hands. - # Draw cards in order of play, to permit overlapping of cards. - leader, cards = trick - seatorder = Seat[leader.index:] + Seat[:leader.index] - for seat in [s for s in seatorder if s in cards]: - pos_x, pos_y = coords[seat]() - self.draw_card(self.trick_pixbuf, pos_x, pos_y, cards[seat]) + @param focus: the Seat to be drawn "closest" to the observer. + """ + # Assumes Seat elements are ordered clockwise from North. + order = Seat[focus.index:] + Seat[:focus.index] + for seat, attr in zip(order, ('BOTTOM', 'LEFT', 'TOP', 'RIGHT')): + setattr(self, attr, seat) + # TODO: set seat labels. - def draw_trick(self): - """""" - x, y, width, height = self.get_allocation() + def set_trick(self, trick): + """Sets the current trick. + Draws representation of current trick to context. - trick_width = self.trick_pixbuf.get_width() - trick_height = self.trick_pixbuf.get_height() - pos_x = (width - trick_width) / 2 - pos_y = (height - trick_height) / 2 - self.backing.draw_rectangle(self.backingGC, True, pos_x, pos_y, trick_width, trick_height) - self.backing.draw_pixbuf(self.backingGC, self.trick_pixbuf, 0, 0, pos_x, pos_y) + @param trick: a (leader, cards_played) pair. + """ + width, height = 200, 200 + # (x, y) positions to fit within (width, height) bound box. + pos = {Seat.North : ((width - self.card_width)/2, 0 ), + Seat.East : ((width - self.card_width), (height - self.card_height)/2 ), + Seat.South : ((width - self.card_width)/2, (height - self.card_height) ), + Seat.West : (0, (height - self.card_height)/2 ), } - # Redraw modified area of backing pixbuf. - self.window.invalidate_rect((pos_x, pos_y, trick_width, trick_height), False) + # Create new ImageSurface for trick. + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + # Clear ImageSurface - in Cairo 1.2+, this is done automatically. + if cairo.version_info < (1, 2): + context.set_operator(cairo.OPERATOR_CLEAR) + context.paint() + context.set_operator(cairo.OPERATOR_OVER) # Restore. + + if trick: + leader, cards_played = trick + # The order of play is the leader, then clockwise around Seat. + for seat in Seat[leader.index:] + Seat[:leader.index]: + card = cards_played.get(seat) + if card: + pos_x, pos_y = pos[seat] + self.draw_card(context, pos_x, pos_y, card) + + id = 'trick' + if id in self.items: + self.update_item(id, source=surface) + else: + xy = lambda w, h: ((w - width)/2, (h - height)/2) + self.add_item(id, surface, xy, 0) - def clear(self): - """Clears backing pixmap and pixbufs.""" - self.hand_pixbufs = {} - self.trick_pixbuf = None - x, y, width, height = self.get_allocation() - self.backing.draw_rectangle(self.backingGC, True, 0, 0, width, height) - self.window.invalidate_rect((0, 0, width, height), False) - - def configure(self, widget, event): - """Creates backing pixmap of the appropriate size, containing pixbufs.""" - x, y, width, height = widget.get_allocation() - self.backing = gtk.gdk.Pixmap(widget.window, width, height) - self.backingGC = gtk.gdk.GC(self.backing, fill=gtk.gdk.TILED, tile=self.background) - self.backing.draw_rectangle(self.backingGC, True, 0, 0, width, height) + def set_turn(self, seat): + """ - for seat in self.hand_pixbufs: - self.draw_hand(seat) - if self.trick_pixbuf: - self.draw_trick() + @param seat: a member of Seat. + """ +# hand_surface = self.hands[seat]['surface'] +# x = self.hands[seat]['xy'] - 10 +# y = self.hands[seat]['xy'] - 10 +# width = surface.get_width() + 20 +# height = surface.get_height() + 20 +# args = ('turn', surface, pos_x, pos_y, -1) +# if self.items.get('turn'): +# self.update_item(*args) +# else: +# self.add_item(*args) - gc.collect() # Manual garbage collection. See PyGTK FAQ, section 8.4. - return True # Configure event is expected to return true. - - def expose(self, widget, event): - """Redraws card table widget from the backing pixmap.""" - x, y, width, height = event.area - gc = widget.get_style().bg_gc[gtk.STATE_NORMAL] - widget.window.draw_drawable(gc, self.backing, x, y, x, y, width, height) - return False # Expose event is expected to return false. - - - def button_press(self, widget, event): - """Determines which card was clicked, then calls external handler method.""" + def button_release(self, widget, event): + """Determines if a card was clicked: if so, calls card_selected.""" + if event.button == 1: + found_hand = False + + # Determine the hand which was clicked. + for seat in self.hands: + card_coords = self.hands[seat]['coords'] + surface = self.hands[seat]['surface'] + hand_x, hand_y = self.items['hand-%s' % seat]['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: + # 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[seat]['visible'][::-1]: + x, y = card_coords[i][1:] + if (x <= pos_x <= x + self.card_width) and \ + (y <= pos_y <= y + self.card_height): + self.on_card_clicked(card, seat) + break - def get_hand_xy(): - for seat, hand in self.hand_coords.items(): - start_x, start_y, finish_x, finish_y = hand - if (start_x <= event.x <= finish_x) and (start_y <= event.y <= finish_y): - return seat, start_x, start_y - - def get_card_in_hand(seat, start_x, start_y): - pos_x = event.x - start_x - pos_y = event.y - start_y - for card, x, y in self.card_coords[seat][::-1]: # Iterate backwards. - if (x <= pos_x <= x+self.card_width) and (y <= pos_y <= y+self.card_height): - return card - - if event.button == 1 and self.on_card_clicked: - hand_xy = get_hand_xy() - if hand_xy: - card = get_card_in_hand(*hand_xy) - if isinstance(card, Card): - self.on_card_clicked(card, hand_xy[0]) # External handler. - - return True # Button press event is expected to return true. + return True # Expected to return True. Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-08-16 14:02:03 UTC (rev 342) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-09-20 10:56:47 UTC (rev 343) @@ -35,7 +35,7 @@ CALLTYPE_SYMBOLS = {Pass : _('pass'), Double : _('dbl'), Redouble : _('rdbl') } -LEVEL_SYMBOLS = {Level.One : _('1'), Level.Two : _('2'), Level.Three : _('3'), +LEVEL_SYMBOLS = {Level.One : _('1'), Level.Two : _('2'), Level.Three : _('3'), Level.Four : _('4'), Level.Five : _('5'), Level.Six : _('6'), Level.Seven : _('7'), } @@ -191,7 +191,7 @@ def resetGame(self): """Clears bidding history, contract, trick counts.""" - self.cardarea.clear() +# self.cardarea.clear() self.call_store.clear() # Reset bidding history. self.trick_store.clear() # Reset trick history. self.setContract(None) # Reset contract. @@ -263,28 +263,22 @@ if hand: # Own or known hand. if all is True: # Show all cards. played = [] - self.cardarea.build_hand(position, hand, omit=played) + self.cardarea.set_hand(hand, position, omit=played) else: # Unknown hand: draw cards face down, use integer placeholders. - cards = range(13) - played = range(len(played)) - self.cardarea.build_hand(position, cards, facedown=True, omit=played) - - self.cardarea.draw_hand(position) + cards, played = range(13), range(len(played)) + self.cardarea.set_hand(cards, position, facedown=True, omit=played) - def redrawTrick(self, trick=None): + def redrawTrick(self): """Redraws trick. @param table: @param trick: """ - # TODO: this cannot be called until playing in progress - # perhaps put a clear() method in cardarea? - if trick is None: + trick = None + if self.table.game.playing: trick = self.table.game.playing.getCurrentTrick() - - self.cardarea.build_trick(trick) - self.cardarea.draw_trick() + self.cardarea.set_trick(trick) def setTurnIndicator(self): @@ -391,6 +385,7 @@ self.setDealer(table.dealer) self.setVuln(table.game.vulnNS, table.game.vulnEW) + self.redrawTrick() for position in table.game.deal: self.redrawHand(position) if table.seated: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-08-16 14:02:09
|
Revision: 342 Author: umgangee Date: 2006-08-16 07:02:03 -0700 (Wed, 16 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=342&view=rev Log Message: ----------- Tagged trunk as release 0.2.1. Added Paths: ----------- tags/0.2.1/ Copied: tags/0.2.1 (from rev 341, trunk) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-08-16 13:06:53
|
Revision: 341 Author: umgangee Date: 2006-08-16 06:06:42 -0700 (Wed, 16 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=341&view=rev Log Message: ----------- Update doc files. Bump version number to 0.2.1. Modified Paths: -------------- trunk/pybridge/INSTALL trunk/pybridge/NEWS trunk/pybridge/README trunk/pybridge/pybridge/__init__.py Modified: trunk/pybridge/INSTALL =================================================================== --- trunk/pybridge/INSTALL 2006-08-16 12:45:36 UTC (rev 340) +++ trunk/pybridge/INSTALL 2006-08-16 13:06:42 UTC (rev 341) @@ -18,12 +18,9 @@ - Python (>= 2.3) - http://www.python.org/ - Twisted Core (>= 1.3) - http://twistedmatrix.com/trac/wiki/TwistedCore -- Zope Interface (>= 3.0) http://www.zope.org/Products/ZopeInterface -- GTK+ (>= 2.6) - http://www.gtk.org/ -- PyGTK (>= 2.6) - http://www.pygtk.org/ +- Zope Interface (>= 3.0) - http://www.zope.org/Products/ZopeInterface +- GTK+ (>= 2.6, >= 2.8 recommended) - http://www.gtk.org/ +- PyGTK (>= 2.6, >= 2.8 recommended) - http://www.pygtk.org/ (The GTK+ and PyGTK libraries are not necessary to run the standalone server.) - -Michael Banks (mi...@ba...), 14 August 2006 - Modified: trunk/pybridge/NEWS =================================================================== --- trunk/pybridge/NEWS 2006-08-16 12:45:36 UTC (rev 340) +++ trunk/pybridge/NEWS 2006-08-16 13:06:42 UTC (rev 341) @@ -1,7 +1,23 @@ +====================== +0.2.1 (16 August 2006) +====================== + +Bug fixes +========= + +- Fixed setup.py script to install source package and supporting files in the + standard /usr/ directories. + +- Updated pybridge.environment and bin/* scripts to work with both the source + and installation directory layouts. + + +====================== 0.2.0 (14 August 2006) ====================== -Features: +New Features +============ - Substantial rewrite of network code. Focus on splitting discrete services into separate components and making full use of Twisted's pb.Cacheable. @@ -19,6 +35,7 @@ - Initial support for internationalization and localization via gettext. +==================== 0.1.0 (19 July 2006) ==================== Modified: trunk/pybridge/README =================================================================== --- trunk/pybridge/README 2006-08-16 12:45:36 UTC (rev 340) +++ trunk/pybridge/README 2006-08-16 13:06:42 UTC (rev 341) @@ -1,4 +1,4 @@ -PyBridge 0.2.0 - a free online bridge game +PyBridge 0.2.1 - a free online bridge game http://pybridge.sourceforge.net/ http://sourceforge.net/projects/pybridge/ @@ -42,6 +42,3 @@ PyBridge is released under the GNU General Public License, version 2 or later. A copy of the license is provided in the COPYING file. - -Michael Banks (mi...@ba...), 14 August 2006 - Modified: trunk/pybridge/pybridge/__init__.py =================================================================== --- trunk/pybridge/pybridge/__init__.py 2006-08-16 12:45:36 UTC (rev 340) +++ trunk/pybridge/pybridge/__init__.py 2006-08-16 13:06:42 UTC (rev 341) @@ -1 +1 @@ -__version__ = '0.2.0' +__version__ = '0.2.1' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-08-16 12:45:43
|
Revision: 340 Author: umgangee Date: 2006-08-16 05:45:36 -0700 (Wed, 16 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=340&view=rev Log Message: ----------- Packages should include locale *.mo and all pixmap files. Modified Paths: -------------- trunk/pybridge/MANIFEST.in Modified: trunk/pybridge/MANIFEST.in =================================================================== --- trunk/pybridge/MANIFEST.in 2006-08-16 12:03:20 UTC (rev 339) +++ trunk/pybridge/MANIFEST.in 2006-08-16 12:45:36 UTC (rev 340) @@ -1,6 +1,6 @@ include MANIFEST.in include AUTHORS COPYING INSTALL NEWS README - include glade/*.glade -include pixmaps/*.png +recursive-include locale *.mo +recursive-include pixmaps *.ico *.png *.svg This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-08-16 12:03:24
|
Revision: 339 Author: umgangee Date: 2006-08-16 05:03:20 -0700 (Wed, 16 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=339&view=rev Log Message: ----------- Win32 should use the ICO icon, everything else should use the PNG icon. Modified Paths: -------------- trunk/pybridge/pybridge/ui/wrapper.py Modified: trunk/pybridge/pybridge/ui/wrapper.py =================================================================== --- trunk/pybridge/pybridge/ui/wrapper.py 2006-08-15 15:11:51 UTC (rev 338) +++ trunk/pybridge/pybridge/ui/wrapper.py 2006-08-16 12:03:20 UTC (rev 339) @@ -19,10 +19,15 @@ import gettext import gtk import gtk.glade +import sys from pybridge.environment import environment -ICON_PATH = environment.find_pixmap("pybridge.png") + GLADE_PATH = environment.find_glade("pybridge.glade") +if sys.platform == 'win32': # Win32 should use the ICO icon. + ICON_PATH = environment.find_pixmap("pybridge.ico") +else: # All other platforms should use the PNG icon. + ICON_PATH = environment.find_pixmap("pybridge.png") class GladeWrapper: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-08-15 15:12:04
|
Revision: 338 Author: umgangee Date: 2006-08-15 08:11:51 -0700 (Tue, 15 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=338&view=rev Log Message: ----------- Revised environment class to differentiate between installed paths (/usr/bin/, /usr/share/pybridge/glade/ etc) and source dist paths (pybridge/bin/, pybridge/glade/ etc). Modified Paths: -------------- trunk/pybridge/pybridge/environment.py trunk/pybridge/pybridge/server/database.py trunk/pybridge/pybridge/ui/__init__.py trunk/pybridge/pybridge/ui/utils.py Modified: trunk/pybridge/pybridge/environment.py =================================================================== --- trunk/pybridge/pybridge/environment.py 2006-08-15 15:02:10 UTC (rev 337) +++ trunk/pybridge/pybridge/environment.py 2006-08-15 15:11:51 UTC (rev 338) @@ -16,50 +16,80 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import os, sys +import os +import sys -HOME = os.path.expanduser('~') -if hasattr(sys, 'frozen'): # For py2exe distribution. - CURRENTDIR = os.path.dirname(sys.executable) - BASEDIR = os.path.abspath(CURRENTDIR) -else: - CURRENTDIR = os.path.dirname(os.path.abspath(sys.argv[0])) - BASEDIR = os.path.abspath(os.path.join(CURRENTDIR, '..')) +class Environment: + """This module provides path location services for PyBridge.""" -if os.path.exists(os.path.join(BASEDIR, 'share', 'pybridge')): - DATADIR = os.path.join(BASEDIR, 'share', 'pybridge') -else: - DATADIR = BASEDIR -CONFIG_DIR = os.path.join(HOME, '.pybridge') -CLIENT_SETTINGS_PATH = os.path.join(CONFIG_DIR, 'client.cfg') -USER_DB = os.path.join(CONFIG_DIR, 'users.db') + def __init__(self): + # Locate base directory. + if hasattr(sys, 'frozen'): # If py2exe distribution. + currentdir = os.path.dirname(sys.executable) + self.basedir = os.path.abspath(currentdir) + else: # Typically /usr/ or root of source distribution. + currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) + self.basedir = os.path.normpath(os.path.join(currentdir, '..')) + + # Locate shared resources directory, typically /usr/share/. + if os.path.exists(os.path.join(self.basedir, 'share')): + self.sharedir = os.path.join(self.basedir, 'share') + else: # Root of source distribution. + self.sharedir = self.basedir + + # Locate config directory. + self.configdir = os.path.join(os.path.expanduser('~'), '.pybridge') + if not os.path.exists(self.configdir): + os.mkdir(self.configdir) # Create directory. -if not os.path.isdir(CONFIG_DIR): - os.makedirs(CONFIG_DIR) -LOCALE_DIR = os.path.join(BASEDIR, 'locale') + def find_configfile(self, name): + """A config file is located in <configdir>/""" + return os.path.join(self.configdir, name) -DOCS_DIR = '.' -GLADE_DIR = 'glade' -PIXMAPS_DIR = 'pixmaps' + def find_doc(self, name): + """A documentation file may be located in: + + <sharedir>/doc/pybridge/ (installed) + <basedir>/ (source) + """ + if self.sharedir == self.basedir: + return os.path.join(self.basedir, name) + else: + return os.path.join(self.sharedir, 'doc', 'pybridge', name) -class Environment: - def find_datafile(self, name): - return os.path.join(CONFIG_DIR, name) + def find_glade(self, name): + """A Glade interface file may be located in: + + <sharedir>/pybridge/glade/ (installed) + <basedir>/glade/ (source) + """ + if self.sharedir == self.basedir: + return os.path.join(self.basedir, 'glade', name) + else: + return os.path.join(self.sharedir, 'pybridge', 'glade', name) - def find_doc(self, name): - return os.path.join(DATADIR, DOCS_DIR, name) - def find_glade(self, name): - return os.path.join(DATADIR, GLADE_DIR, name) - def find_pixmap(self, name): - return os.path.join(DATADIR, PIXMAPS_DIR, name) + """A pixmap file may be located in: + + <sharedir>/pybridge/pixmaps/ (installed) + <basedir>/pixmaps/ (source) + """ + if self.sharedir == self.basedir: + return os.path.join(self.basedir, 'pixmaps', name) + else: + return os.path.join(self.sharedir, 'pybridge', 'pixmaps', name) + def get_localedir(self): + """Returns the path of the locale directory.""" + return os.path.join(self.sharedir, 'locale') + + environment = Environment() Modified: trunk/pybridge/pybridge/server/database.py =================================================================== --- trunk/pybridge/pybridge/server/database.py 2006-08-15 15:02:10 UTC (rev 337) +++ trunk/pybridge/pybridge/server/database.py 2006-08-15 15:11:51 UTC (rev 338) @@ -20,7 +20,7 @@ from twisted.internet import defer from twisted.python import failure -from pybridge.environment import USER_DB +from pybridge.environment import environment class DuplicateError(Exception): @@ -36,7 +36,8 @@ def __init__(self): # Open the database file. - self.accounts = shelve.open(USER_DB, 'c', writeback=True) + dbfile = environment.find_configfile('users.db') + self.accounts = shelve.open(dbfile, 'c', writeback=True) def addUser(self, username, **attrs): Modified: trunk/pybridge/pybridge/ui/__init__.py =================================================================== --- trunk/pybridge/pybridge/ui/__init__.py 2006-08-15 15:02:10 UTC (rev 337) +++ trunk/pybridge/pybridge/ui/__init__.py 2006-08-15 15:11:51 UTC (rev 338) @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from pybridge.environment import LOCALE_DIR +from pybridge.environment import environment def run(): """""" @@ -29,7 +29,7 @@ import locale import gettext locale.setlocale(locale.LC_ALL, '') - gettext.bindtextdomain('pybridge', LOCALE_DIR) + gettext.bindtextdomain('pybridge', environment.get_localedir()) gettext.textdomain('pybridge') gettext.install('pybridge') Modified: trunk/pybridge/pybridge/ui/utils.py =================================================================== --- trunk/pybridge/pybridge/ui/utils.py 2006-08-15 15:02:10 UTC (rev 337) +++ trunk/pybridge/pybridge/ui/utils.py 2006-08-15 15:11:51 UTC (rev 338) @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from pybridge.environment import CLIENT_SETTINGS_PATH +from pybridge.environment import environment # Set up client with UI event handler. from pybridge.network.client import client @@ -38,7 +38,7 @@ general = {} - def __init__(self, filename=CLIENT_SETTINGS_PATH): + def __init__(self, filename): self.config = ConfigParser.SafeConfigParser() self.filename = filename self.read() @@ -63,7 +63,7 @@ self.config.write(file(self.filename, 'w')) -settings = Settings() +settings = Settings(environment.find_configfile('client.cfg')) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <umg...@us...> - 2006-08-15 15:02:16
|
Revision: 337 Author: umgangee Date: 2006-08-15 08:02:10 -0700 (Tue, 15 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=337&view=rev Log Message: ----------- Add detection of lib/python/pybridge/ package. Removed detection of lib/python2.X/site-packages/pybridge, since "import pybridge" does that automatically! Modified Paths: -------------- trunk/pybridge/bin/pybridge trunk/pybridge/bin/pybridge-server Modified: trunk/pybridge/bin/pybridge =================================================================== --- trunk/pybridge/bin/pybridge 2006-08-14 20:12:33 UTC (rev 336) +++ trunk/pybridge/bin/pybridge 2006-08-15 15:02:10 UTC (rev 337) @@ -18,7 +18,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import os, sys +import os +import sys PYTHON_VERSION = sys.version_info[:2] @@ -44,19 +45,19 @@ raise SystemExit("Error: Twisted Core %s or higher required" % TWISTED_REQUIRED) -# Determine the base directory. -currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) -basedir = os.path.abspath(os.path.join(currentdir, '..')) +try: # If PyBridge is installed system-wide, this finds it automatically. + import pybridge +except ImportError: # Locate the PyBridge package. + currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) + basedir = os.path.abspath(os.path.join(currentdir, '..')) + # The package path should be relative to the base directory. + if os.path.exists(os.path.join(basedir, 'lib', 'python')): + pythonpath = os.path.join(basedir, 'lib', 'python') + else: + pythonpath = basedir + sys.path.insert(0, pythonpath) # Place PyBridge package in PYTHONPATH. -# Find the Python module path, relative to the base directory. -if os.path.exists(os.path.join(basedir, 'lib')): - pythonpath = os.path.join(basedir, 'lib', 'python%d.%d' % PYTHON_VERSION, 'site-packages') -else: - pythonpath = basedir -sys.path.insert(0, pythonpath) - - import pybridge.ui pybridge.ui.run() Modified: trunk/pybridge/bin/pybridge-server =================================================================== --- trunk/pybridge/bin/pybridge-server 2006-08-14 20:12:33 UTC (rev 336) +++ trunk/pybridge/bin/pybridge-server 2006-08-15 15:02:10 UTC (rev 337) @@ -41,6 +41,18 @@ print "\nError: %s" % error sys.exit(2) + try: # If PyBridge is installed system-wide, this finds it automatically. + import pybridge + except ImportError: # Locate the PyBridge package. + currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) + basedir = os.path.abspath(os.path.join(currentdir, '..')) + # The package path should be relative to the base directory. + if os.path.exists(os.path.join(basedir, 'lib', 'python')): + pythonpath = os.path.join(basedir, 'lib', 'python') + else: + pythonpath = basedir + sys.path.insert(0, pythonpath) # Place PyBridge package in PYTHONPATH. + for opt, arg in opts: if opt in ('-h', '--help'): usage() @@ -53,30 +65,16 @@ print "\nError: invalid value %s specified for %s" % (arg, opt) sys.exit(2) elif opt in ('-v', '--version'): - import pybridge print "PyBridge Server version %s" % pybridge.__version__ sys.exit(0) - # Determine the base directory. - currentdir = os.path.dirname(os.path.abspath(sys.argv[0])) - basedir = os.path.abspath(os.path.join(currentdir, '..')) - - # Find the Python module path, relative to the base directory. - if os.path.exists(os.path.join(basedir, 'lib')): - pythonver = 'python%d.%d' % sys.version_info[:2] - pythonpath = os.path.join(basedir, 'lib', pythonver, 'site-packages') - else: - pythonpath = basedir - - sys.path.insert(0, pythonpath) - from twisted.internet import reactor from twisted.python import log from pybridge.server import factory # TODO: replace with a service. log.startLogging(sys.stdout) # Log to stdout. - reactor.listenTCP(PORT, factory) # Default PyBridge port. + 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...> - 2006-08-14 20:12:40
|
Revision: 336 Author: umgangee Date: 2006-08-14 13:12:33 -0700 (Mon, 14 Aug 2006) ViewCVS: http://svn.sourceforge.net/pybridge/?rev=336&view=rev Log Message: ----------- Fixed data_files entries to point at UNIX standard pathnames. The program scripts and pybridge.environment need work to adjust to the appropriate data file paths. Modified Paths: -------------- trunk/pybridge/setup.py Modified: trunk/pybridge/setup.py =================================================================== --- trunk/pybridge/setup.py 2006-08-14 15:19:07 UTC (rev 335) +++ trunk/pybridge/setup.py 2006-08-14 20:12:33 UTC (rev 336) @@ -21,16 +21,16 @@ url = 'http://sourceforge.net/projects/pybridge/', description = 'A free online bridge game.', download_url = 'http://sourceforge.net/project/showfiles.php?group_id=114287', - packages = ['pybridge', 'pybridge.bridge', 'pybridge.interfaces', 'pybridge.network', 'pybridge.server', 'pybridge.ui'], - package_data = {'pybridge' : ['glade/pybridge.glade', 'locale', 'pixmaps/*']}, + packages = ['pybridge', 'pybridge.bridge', 'pybridge.interfaces', + 'pybridge.network', 'pybridge.server', 'pybridge.ui'], scripts = ['bin/pybridge', 'bin/pybridge-server'], + data_files = [('share/doc/pybridge', ['AUTHORS', 'COPYING', 'INSTALL', 'NEWS', 'README']), + ('share/pybridge/glade', glob.glob('glade/*.glade')), + ('share/pybridge/pixmaps', glob.glob('pixmaps/*')), ], # py2exe console = ['bin/pybridge-server'], windows = [{'script' : 'bin/pybridge', 'icon_resources' : [(1, 'pixmaps/pybridge.ico')]}], - data_files = [('.', ['AUTHORS', 'COPYING', 'INSTALL', 'NEWS', 'README']), - ('glade', glob.glob('glade/*.glade')), - ('pixmaps', glob.glob('pixmaps/*')), ], options = {'py2exe': {'packages' : 'encodings', 'includes' : 'cairo, pango, pangocairo, atk, gobject, gtk.glade' } }, ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: guido d. <gui...@gm...> - 2006-08-12 15:52:01
|
Hello I installed -by following the INSTALL instructions - pybridge (in ubuntu 6.06), but what then? How do I start pybridge? Thanx -- Tel:+32 (0)58 239804 +32 (0)497 538736 Nog een mooie dag toegewenst. Guido (dompie) Dom |