Merge branch 'master' of git://git.assembla.com/fpdboz
This commit is contained in:
commit
faa95ca26e
BIN
gfx/fpdb-cards.png
Normal file
BIN
gfx/fpdb-cards.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
92
gfx/img-PokerStars-Small.xpm
Normal file
92
gfx/img-PokerStars-Small.xpm
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* XPM */
|
||||
/* C:\Program Files\PokerStars\PokerStarsUpdate.exe */
|
||||
static char *icon[] = {
|
||||
"48 48 40 2",
|
||||
"01 c #800000",
|
||||
"08 c #C0DCC0",
|
||||
"4C c #7F1F00",
|
||||
"6C c #AA0000",
|
||||
"6D c #AA0055",
|
||||
"70 c #AA1F00",
|
||||
"90 c #D40000",
|
||||
"91 c #D40055",
|
||||
"94 c #D41F00",
|
||||
"95 c #D41F55",
|
||||
"99 c #D43F55",
|
||||
"9D c #D45F55",
|
||||
"9E c #D45FAA",
|
||||
"A1 c #D47F55",
|
||||
"A2 c #D47FAA",
|
||||
"A5 c #D49F55",
|
||||
"A6 c #D49FAA",
|
||||
"AA c #D4BFAA",
|
||||
"AE c #D4DFAA",
|
||||
"AF c #D4DFFF",
|
||||
"B4 c #FF0055",
|
||||
"B6 c #FF1F00",
|
||||
"B7 c #FF1F55",
|
||||
"BA c #FF3F00",
|
||||
"BB c #FF3F55",
|
||||
"BE c #FF5F00",
|
||||
"BF c #FF5F55",
|
||||
"C3 c #FF7F55",
|
||||
"C4 c #FF7FAA",
|
||||
"C7 c #FF9F55",
|
||||
"C8 c #FF9FAA",
|
||||
"CC c #FFBFAA",
|
||||
"CD c #FFBFFF",
|
||||
"D0 c #FFDFAA",
|
||||
"D1 c #FFDFFF",
|
||||
"D5 c #FFCCFF",
|
||||
"F6 c #FFFBF0",
|
||||
"F9 c #FF0000",
|
||||
"FF c #FFFFFF",
|
||||
" c None",
|
||||
"707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAD1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6949DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6BFBBF999F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A6A2C7B6F9F99DD1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A2C8CCBFB6B4F99099F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6C8CCC3BEB7F9F9F99099F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2C8D0C7BFBBB6F9B4F9F99099F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A6AAD0C8C3C3BBF9F9F9F9B4F99099D1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFA6C8D0CCC7C3BFBAB6B4F9F9F99090909DF6FFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFA2CCF6CCC8C3BFBEBBF9F9F9B4F9F9B4909099F6FFFFFFFFFFFFFFFFFFFFFFFFFF6C",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFA6CCD1CCC7C3C3BFBAB6B7F9F9F9B490F990906C99FFFFFFD1FFFFFFD1FFFFFFD1FF70",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFAAC8F6CCC7C8C3BFBFBFB6C4B7F9F9F9F9F99190906C9DFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFD1FFFFFFD1FFFFFFAAC8F6CCCCC8C3C3C3BEBBB6F6BFF9B4F9B490F99091906CA2FFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFD1A6F6CCCCC7C7C3C3BFBBBABFFFC8F9F9F990F9909090906C90AAFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFF6A6D0D1CCC8C7C3C3BFBEBFB6CCFFF6F9F9F9B4F9B49090906C6C95F6FFFFFFFFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFFFFFFFAACCF6CCCCC7C4C3BFBEBBBABBD1FFFFBFF9F9F990F9F99190956C6C99FFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFD1C8F6CCCCC8C7C7C8C7C8C7C3C8F6FFF6CDBFBBBFBBBFBF9090906C6C6CA6FFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFAAF6D0CCC8C7C3C4D0FFFFFFFFF6F6FFFFF6FFFFFFFFD199F9909090706C99F6FFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFD5CCD1CCCCC7C3C3C3BFC8F6FFFFFFFFFFFFFFFFFFFFC895F990B490916C016CA2FFFFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFF6AAD1D0CCC7C8C3C3C3BFBEBFD1FFFFFFFFFFFFFFFFA1F9F990F9909090906C0170F6FFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFD1CCD0CCC8C8C3C3BFBFBFBABBBACCFFFFFFFFFFD1BBF9F990B490B490906D6C6C6CA6FFFFFFFFFFFF70",
|
||||
"70FFFFFFFFF6AACCD1CCC7C7C3C3BFBEBFBABABBD1FFFFFFFFFFF699F990B4F990F99090906C700199FFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFA6D0CCC8C7C3C3BFBFBFBABBB6BFF6FFFFFFFFFFFFC8F9F990F99091F99190906C0194D1FFFFFFFFFF6C",
|
||||
"6CFFFFFFFFF6C8CCCCC7C4C3BFBFBEBFBABBB6C8FFFFCCBBC4FFFFD091F9F991F9F990F9906C6D016CAAFFFFFFFFFF70",
|
||||
"70FFFFFFF6D5A5CCC8C7C3C3BFBEBBBABBBAB6F6F6C4F9F9F9BBD1FFBBF990F9F991F99091906C016CA2FFFFFFFFFF70",
|
||||
"70FFFFFFFFAEC4C7C7C3BFBFBEBFBABBB6B6BBD1BBF9F9F9F9F9B6CCC8F9B4F990F990909090706C6CA2F6FFFFFFFF70",
|
||||
"70FFFFFFFFCCC3C8C3C3BFBEBBBABBBAB6B7BBB6F9F9F9B4F9F9F9B4BBB690F9B490B49090916C016CA1FFFFFFFFFF6C",
|
||||
"6CFFFFFFFFD19DC3BFBFBFBBBABBB6B7B6F9F9F9F9B4F9F9F9B4F9F9F9B4F9F9F9F990B4906C6C016CC8FFFFFFFFFF70",
|
||||
"70FFFFFFFFF69DBEBFBEBABABBB6B6B6F9F9F9B4F990F9B4F9F9F9F9F9F9F991F990F99090706C016CAAFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFA2B6BBBAB7B6B6B6B4F9B4F991909090F9F9F990B4F9B4F9F9F9F9B49090906D6C0199FFFFFFFFFFFF70",
|
||||
"70FFFFFFFFF6F694F9B6B6B4F9F9F9F990F9909090C8A2F999CC95F9F9F9B4F9909090916C6C0190A6FFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFFFCC91F990F9B4F991F991906C909DFFCCF9BFFFCCF9F9F990F9F991906C70016CA2FFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFC895909090909090906C909EFFFFA2F995FFFFA6B790F99190906C6C6C6CC4F6F6FFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFAEBF9590906C906C99C8FFF6FFBFB69008FFFFF69DB7906C6C6C9499D5F6F6FFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFD0A6A2C3A6CCFFFFFFFF08BBF990A2F6FFFFFFF6CCC8C8CCAFFFF6FFFFFFFFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6BFF99095F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D1A1BFF9906CA6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2C3BBF9F96C95F6F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6A1C3B6F9B4906C99FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAC3C3BAB4F9F990906C9DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD19DBBBBB6F9F9F990F990909099AAFFFFFFFFFFFFFFFFFFF6FFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A2A1BF9D9EBFA2BFA2BFA29DA2BFA2CCFFFFFFFFF6FFFFFFFFFFFFFFFFFFFF70",
|
||||
"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFF6FFFFFFFFFFFFFFFFFFFFFFFFF6FFF6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C",
|
||||
"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70",
|
||||
"704C706C7001706C7001706C70706C7070707070707070706C7070707070704C707001707001706C704C6C7070017070"};
|
|
@ -1,3 +1,9 @@
|
|||
free-poker-tools (0.12-1) unstable; urgency=low
|
||||
|
||||
* New release
|
||||
|
||||
-- Mika Bostrom <bostik+fpdb@bostik.iki.fi> Mon, 26 Oct 2009 17:49:07 +0200
|
||||
|
||||
free-poker-tools (0.11.3+git20091023) unstable; urgency=low
|
||||
|
||||
* Snapshot release
|
||||
|
|
484
pyfpdb/DatabaseManager.py
Normal file
484
pyfpdb/DatabaseManager.py
Normal file
|
@ -0,0 +1,484 @@
|
|||
|
||||
import os
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
|
||||
#*******************************************************************************************************
|
||||
class DatabaseManager(object):
|
||||
DatabaseTypes = {}
|
||||
|
||||
def __init__(self, defaultDatabaseType=None):
|
||||
self._defaultDatabaseType = defaultDatabaseType
|
||||
def set_default_database_type(self, databaseType):
|
||||
self._defaultDatabaseType = defaultDatabaseType
|
||||
def get_default_database_type(self):
|
||||
return self._defaultDatabaseType
|
||||
|
||||
class DatabaseTypeMeta(type):
|
||||
def __new__(klass, name, bases, kws):
|
||||
newKlass = type.__new__(klass, name, bases, kws)
|
||||
if newKlass.Type is not None:
|
||||
if newKlass.Type in DatabaseManager.DatabaseTypes:
|
||||
raise ValueError('data base type already registered for: %s' % newKlass.Type)
|
||||
DatabaseManager.DatabaseTypes[newKlass.Type] = newKlass
|
||||
return newKlass
|
||||
|
||||
class DatabaseTypeBase(object):
|
||||
__metaclass__ = DatabaseTypeMeta
|
||||
Type = None
|
||||
|
||||
class DatabaseTypePostgres(DatabaseTypeBase):
|
||||
Type = 'postgres'
|
||||
def __init__(self, host='localhost', port=5432, user='postgres', password='', database='fpdb', name=''):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.database = database
|
||||
self.name = name
|
||||
|
||||
class DatabaseTypeMysql(DatabaseTypeBase):
|
||||
Type = 'mysql'
|
||||
def __init__(self, host='localhost', port=3306, user='root', password='', database='fpdb', name=''):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.database = database
|
||||
self.name = name
|
||||
|
||||
class DatabaseTypeSqLite(DatabaseTypeBase):
|
||||
Type = 'sqlite'
|
||||
def __init__(self, host='', file='', name=''):
|
||||
self.file = file
|
||||
self.name = name
|
||||
|
||||
#***************************************************************************************************************************
|
||||
class MyFileChooserButton(gtk.HBox):
|
||||
#NOTE: for some weird reason it is impossible to let the user choose a non exiting filename with gtk.FileChooserButton, so impl our own on the fly
|
||||
def __init__(self):
|
||||
gtk.HBox.__init__(self)
|
||||
self.set_homogeneous(False)
|
||||
|
||||
self.entry = gtk.Entry()
|
||||
self.button = gtk.Button('...')
|
||||
self.button.connect('clicked', self.on_button_clicked)
|
||||
|
||||
# layout widgets
|
||||
self.pack_start(self.entry, True, True)
|
||||
self.pack_start(self.button, False, False)
|
||||
|
||||
def get_filename(self):
|
||||
return self.entry.get_text()
|
||||
|
||||
def set_filename(self, name):
|
||||
self.entry.set_text(name)
|
||||
|
||||
def on_button_clicked(self, button):
|
||||
dlg = gtk.FileChooserDialog(
|
||||
title='Choose an exiting database file or type in name of a new one',
|
||||
parent=None,
|
||||
action=gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
buttons=(
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_OK,
|
||||
),
|
||||
backend=None
|
||||
)
|
||||
dlg.connect('confirm-overwrite', self.on_dialog_confirm_overwrite)
|
||||
dlg.set_default_response(gtk.RESPONSE_OK)
|
||||
dlg.set_do_overwrite_confirmation(True)
|
||||
if dlg.run() == gtk.RESPONSE_OK:
|
||||
self.set_filename(dlg.get_filename())
|
||||
dlg.destroy()
|
||||
|
||||
#TODO: when the user selects a sqLite database file we got three possible actions
|
||||
# 1. user types in a new filename. easy one, create the file
|
||||
# 2. user selectes a file with the intention to overwrite it
|
||||
# 3. user selects a file with the intention to plug an existing database file in
|
||||
#IDEA: impl open_existing as plug in, never overwrite, cos we can not guess
|
||||
#PROBLEMS: how to validate an existing file is a database?
|
||||
def on_dialog_confirm_overwrite(self, dlg):
|
||||
print dlg.get_filename()
|
||||
|
||||
gtk.FILE_CHOOSER_CONFIRMATION_CONFIRM
|
||||
#The file chooser will present its stock dialog to confirm overwriting an existing file.
|
||||
|
||||
gtk.FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME
|
||||
#The file chooser will terminate and accept the user's choice of a file name.
|
||||
|
||||
gtk.FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN
|
||||
#
|
||||
|
||||
|
||||
class WidgetDatabaseProperties(gtk.VBox):
|
||||
ModeEdit = 0x1
|
||||
ModeAdd = 0x2
|
||||
ModeNew = 0x4
|
||||
|
||||
class FieldWidget(object):
|
||||
def __init__(self, text='', attrDatabase='', widget=None, attrGet=None, attrSet=None, defaultValue=None, canEdit=False, tooltip=''):
|
||||
"""
|
||||
@param canEdit: True if the user can edit the attr in edit mode, False otherwise
|
||||
"""
|
||||
self._label = gtk.Label(text)
|
||||
self._attrDatabase = attrDatabase
|
||||
self._widget = widget
|
||||
self._defaultValue = defaultValue
|
||||
self._attrGetter=None,
|
||||
self._attrGet = attrGet
|
||||
self._attrSet = attrSet
|
||||
self._canEdit = canEdit
|
||||
|
||||
self._label.set_tooltip_text(tooltip)
|
||||
self._widget.set_tooltip_text(tooltip)
|
||||
|
||||
def widget(self):
|
||||
return self._widget
|
||||
def label(self):
|
||||
return self._label
|
||||
def is_sensitive(self, database):
|
||||
return hasattr(database, self._attrDatabase)
|
||||
def can_edit(self):
|
||||
return self._canEdit
|
||||
def set_sensitive(self, flag):
|
||||
self._label.set_sensitive(flag)
|
||||
self._widget.set_sensitive(flag)
|
||||
def value_from_database(self, database):
|
||||
getattr(self._widget, self._attrSet)( getattr(database, self._attrDatabase) )
|
||||
def value_to_database(self, database):
|
||||
setattr(database, self._attrDatabase, getattr(self._widget, self._attrGet)() )
|
||||
def reset_value(self):
|
||||
getattr(self._widget, self._attrSet)(self._defaultValue)
|
||||
|
||||
def __init__(self, databaseManager, database=None, flags=ModeEdit):
|
||||
gtk.VBox.__init__(self)
|
||||
|
||||
self.flags = flags
|
||||
self.fieldWidgets = ( #fieldName--> fieldHandler
|
||||
self.FieldWidget(
|
||||
text='Name:',
|
||||
attrDatabase='name',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=True,
|
||||
tooltip=''
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='File:',
|
||||
attrDatabase='file',
|
||||
widget=MyFileChooserButton(),
|
||||
defaultValue='',
|
||||
attrGet='get_filename',
|
||||
attrSet='set_filename',
|
||||
canEdit=False,
|
||||
tooltip=''
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Host:',
|
||||
attrDatabase='host',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip=''
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Port:',
|
||||
attrDatabase='port',
|
||||
widget=gtk.SpinButton(adjustment=gtk.Adjustment(value=0, lower=0, upper=999999, step_incr=1, page_incr=10) ),
|
||||
defaultValue=0,
|
||||
attrGet='get_value',
|
||||
attrSet='set_value',
|
||||
canEdit=False,
|
||||
tooltip=''
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='User:',
|
||||
attrDatabase='user',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip=''
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Pwd:',
|
||||
attrDatabase='password',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip=''
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Db:',
|
||||
attrDatabase='database',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip=''
|
||||
),
|
||||
)
|
||||
|
||||
# setup database type combo
|
||||
self.comboType = gtk.ComboBox()
|
||||
listStore= gtk.ListStore(str, str)
|
||||
self.comboType.set_model(listStore)
|
||||
cell = gtk.CellRendererText()
|
||||
self.comboType.pack_start(cell, True)
|
||||
self.comboType.add_attribute(cell, 'text', 0)
|
||||
# fill out combo with database type. we store (displayName, databaseType) in our model for later lookup
|
||||
for dbType, dbDisplayName in sorted([(klass.Type, klass.Type) for klass in databaseManager.DatabaseTypes.values()]):
|
||||
listStore.append( (dbDisplayName, dbType) )
|
||||
self.comboType.connect('changed', self.on_combo_type_changed)
|
||||
|
||||
# init and layout field widgets
|
||||
self.pack_start(self.comboType, False, False, 2)
|
||||
table = gtk.Table(rows=len(self.fieldWidgets) +1, columns=2, homogeneous=False)
|
||||
self.pack_start(table, False, False, 2)
|
||||
for i,fieldWidget in enumerate(self.fieldWidgets):
|
||||
table.attach(fieldWidget.label(), 0, 1, i, i+1, xoptions=gtk.FILL)
|
||||
table.attach(fieldWidget.widget(), 1, 2, i, i+1)
|
||||
|
||||
# init widget
|
||||
|
||||
# if a database has been passed user is not allowed to change database type
|
||||
if database is None:
|
||||
self.comboType.set_button_sensitivity(gtk.SENSITIVITY_ON)
|
||||
else:
|
||||
self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF)
|
||||
|
||||
# set current database
|
||||
self.databaseManager = databaseManager
|
||||
self.database= None
|
||||
if database is None:
|
||||
databaseType = self.databaseManager.get_default_database_type()
|
||||
if databaseType is not None:
|
||||
database = databaseType()
|
||||
if database is not None:
|
||||
self.set_database(database)
|
||||
|
||||
def on_combo_type_changed(self, combo):
|
||||
i = self.comboType.get_active()
|
||||
if i > -1:
|
||||
# change database if necessary
|
||||
currentDatabaseType = self.comboType.get_model()[i][1]
|
||||
if currentDatabaseType != self.database.Type:
|
||||
newDatabase = self.databaseManager.DatabaseTypes[currentDatabaseType]()
|
||||
self.set_database(newDatabase)
|
||||
|
||||
def set_database(self, database):
|
||||
self.database = database
|
||||
|
||||
# adjust database type combo if necessary
|
||||
i = self.comboType.get_active()
|
||||
if i == -1:
|
||||
currentDatabaseType = None
|
||||
else:
|
||||
currentDatabaseType = self.comboType.get_model()[i][1]
|
||||
if currentDatabaseType != self.database.Type:
|
||||
for i, row in enumerate(self.comboType.get_model()):
|
||||
if row[1] == self.database.Type:
|
||||
self.comboType.set_active(i)
|
||||
break
|
||||
else:
|
||||
raise ValueError('unknown database type')
|
||||
|
||||
# adjust field widgets to database
|
||||
for fieldWidget in self.fieldWidgets:
|
||||
isSensitive = fieldWidget.is_sensitive(self.database)
|
||||
if isSensitive:
|
||||
fieldWidget.value_from_database(self.database)
|
||||
else:
|
||||
fieldWidget.reset_value()
|
||||
if self.flags & self.ModeEdit:
|
||||
isSensitive = isSensitive and fieldWidget.can_edit()
|
||||
fieldWidget.set_sensitive(isSensitive)
|
||||
|
||||
def get_database(self):
|
||||
for fieldWidget in self.fieldWidgets:
|
||||
if fieldWidget.is_sensitive(self.database):
|
||||
fieldWidget.value_to_database(self.database)
|
||||
return self.database
|
||||
|
||||
|
||||
class DialogDatabaseProperties(gtk.Dialog):
|
||||
def __init__(self, databaseManager, database=None,parent=None, flags=WidgetDatabaseProperties.ModeEdit):
|
||||
if flags & WidgetDatabaseProperties.ModeEdit:
|
||||
title = '[Edit database] - database properties'
|
||||
elif flags & WidgetDatabaseProperties.ModeAdd:
|
||||
title = '[Add database] - database properties'
|
||||
elif flags & WidgetDatabaseProperties.ModeNew:
|
||||
title = '[New database] - database properties'
|
||||
else:
|
||||
title = 'database properties'
|
||||
|
||||
gtk.Dialog.__init__(self,
|
||||
title=title,
|
||||
parent=parent,
|
||||
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
buttons=(
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
|
||||
)
|
||||
)
|
||||
self.connect('response', self.on_dialog_response)
|
||||
|
||||
# setup widget
|
||||
self.flags = flags
|
||||
self.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database=database, flags=self.flags)
|
||||
self.vbox.pack_start(self.widgetDatabaseProperties, True, True)
|
||||
self.widgetDatabaseProperties.show_all()
|
||||
|
||||
def get_database(self):
|
||||
return self.widgetDatabaseProperties.get_database()
|
||||
|
||||
def on_dialog_response(self, dlg, responseId):
|
||||
if responseId == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
elif responseId == gtk.RESPONSE_ACCEPT:
|
||||
pass
|
||||
|
||||
|
||||
#TODO: just boilerplate code
|
||||
class DialogDatabase(gtk.Dialog):
|
||||
def __init__(self, databaseManager, parent=None):
|
||||
gtk.Dialog.__init__(self,
|
||||
title="My dialog",
|
||||
parent=parent,
|
||||
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
buttons=(
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
|
||||
))
|
||||
#self.set_size_request(260, 250)
|
||||
|
||||
self.databaseManager = databaseManager
|
||||
|
||||
#TODO: dono how to make word wrap work as expected
|
||||
self.labelInfo = gtk.Label('database management')
|
||||
self.labelInfo.set_line_wrap(True)
|
||||
self.labelInfo.set_selectable(True)
|
||||
self.labelInfo.set_single_line_mode(False)
|
||||
self.labelInfo.set_alignment(0, 0)
|
||||
|
||||
# database management buttons
|
||||
|
||||
#TODO: bit messy the distinction New/Add/Edit. we'd have to pass three flags to DialogDatabaseProperties
|
||||
# to handle this. maybe drop Edit (is just a Remove + Add), to keep things simple
|
||||
self.buttonDatabaseNew = gtk.Button("New..")
|
||||
self.buttonDatabaseNew.set_tooltip_text('creates a new database')
|
||||
self.buttonDatabaseNew.connect('clicked', self.on_button_database_new_clicked)
|
||||
self.buttonDatabaseAdd = gtk.Button("Add..")
|
||||
self.buttonDatabaseAdd.set_tooltip_text('adds an existing database')
|
||||
self.buttonDatabaseAdd.connect('clicked', self.on_button_database_add_clicked)
|
||||
self.buttonDatabaseEdit = gtk.Button("Edit..")
|
||||
self.buttonDatabaseEdit.set_tooltip_text('edit database settings')
|
||||
self.buttonDatabaseEdit.connect('clicked', self.on_button_database_edit_clicked)
|
||||
self.buttonDatabaseEdit.set_sensitive(False)
|
||||
self.buttonDatabaseRemove = gtk.Button("Remove")
|
||||
self.buttonDatabaseRemove.set_tooltip_text('removes the database from the list')
|
||||
self.buttonDatabaseRemove.set_sensitive(False)
|
||||
|
||||
#TODO: i dont think we should do any real database management here. maybe drop it
|
||||
self.buttonDatabaseDelete = gtk.Button("Delete")
|
||||
self.buttonDatabaseDelete.set_tooltip_text('removes the database from the list and deletes it')
|
||||
self.buttonDatabaseDelete.set_sensitive(False)
|
||||
|
||||
# database tree
|
||||
self.treeDatabases = gtk.TreeView()
|
||||
store = gtk.ListStore(str, str, str)
|
||||
self.treeDatabases.set_model(store)
|
||||
columns = ('Name', 'Status', 'Type')
|
||||
for i, column in enumerate(columns):
|
||||
col = gtk.TreeViewColumn(column, gtk.CellRendererText(), text=i)
|
||||
self.treeDatabases.append_column(col)
|
||||
self.treeDatabases.get_selection().connect('changed', self.on_tree_databases_selection_changed)
|
||||
|
||||
# layout widgets
|
||||
self.vbox.pack_start(self.labelInfo, False, False, 2)
|
||||
self.vbox.pack_start(gtk.HSeparator(), False, False, 2)
|
||||
|
||||
hbox = gtk.HBox()
|
||||
self.vbox.add(hbox)
|
||||
hbox.set_homogeneous(False)
|
||||
vbox = gtk.VBox()
|
||||
hbox.pack_start(vbox, False, False, 2)
|
||||
vbox.pack_start(self.buttonDatabaseNew, False, False, 2)
|
||||
vbox.pack_start(self.buttonDatabaseAdd, False, False, 2)
|
||||
vbox.pack_start(self.buttonDatabaseEdit, False, False, 2)
|
||||
vbox.pack_start(self.buttonDatabaseRemove, False, False, 2)
|
||||
vbox.pack_start(self.buttonDatabaseDelete, False, False, 2)
|
||||
box = gtk.VBox()
|
||||
vbox.pack_start(box, True, True, 0)
|
||||
|
||||
hbox.pack_start(gtk.VSeparator(), False, False, 2)
|
||||
hbox.pack_end(self.treeDatabases, True, True, 2)
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
#TODO: for some reason i have to click OK/Cancel twice to close the dialog
|
||||
def on_button_database_new_clicked(self, button):
|
||||
dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeNew)
|
||||
if dlg.run() == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
if dlg.run() == gtk.RESPONSE_ACCEPT:
|
||||
database = dlg.get_database()
|
||||
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) )
|
||||
dlg.destroy()
|
||||
|
||||
def on_button_database_add_clicked(self, button):
|
||||
dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeAdd)
|
||||
if dlg.run() == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
if dlg.run() == gtk.RESPONSE_ACCEPT:
|
||||
database = dlg.get_database()
|
||||
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) )
|
||||
dlg.destroy()
|
||||
|
||||
def on_button_database_edit_clicked(self, button):
|
||||
dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeEdit)
|
||||
if dlg.run() == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
if dlg.run() == gtk.RESPONSE_ACCEPT:
|
||||
database = dlg.get_database()
|
||||
selection = self.treeDatabases.get_selection()
|
||||
if selection is not None:
|
||||
model, iter = selection.get_selected()
|
||||
model.set_value(iter, 0, database.name)
|
||||
dlg.destroy()
|
||||
|
||||
def on_tree_databases_selection_changed(self, treeSelection):
|
||||
hasSelection = bool(treeSelection.count_selected_rows())
|
||||
|
||||
# enable/disable selection dependend widgets
|
||||
self.buttonDatabaseEdit.set_sensitive(hasSelection)
|
||||
self.buttonDatabaseRemove.set_sensitive(hasSelection)
|
||||
self.buttonDatabaseDelete.set_sensitive(hasSelection)
|
||||
|
||||
|
||||
|
||||
|
||||
#**************************************************************************************************
|
||||
if __name__ == '__main__':
|
||||
#d = DialogDatabaseProperties(
|
||||
# DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite),
|
||||
#database=DatabaseTypePostgres(),
|
||||
# database=None,
|
||||
# )
|
||||
d = DialogDatabase(DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite))
|
||||
d.connect("destroy", gtk.main_quit)
|
||||
d.run()
|
||||
#gtk.main()
|
||||
|
||||
|
|
@ -56,7 +56,10 @@ class DerivedStats():
|
|||
|
||||
# This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and
|
||||
# those values remain default in stud.
|
||||
boardcards = hand.board['FLOP'] + hand.board['TURN'] + hand.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x']
|
||||
boardcards = []
|
||||
for street in hand.communityStreets:
|
||||
boardcards += hand.board[street]
|
||||
boardcards += [u'0x', u'0x', u'0x', u'0x', u'0x']
|
||||
cards = [Card.encodeCard(c) for c in boardcards[0:5]]
|
||||
self.hands['boardcard1'] = cards[0]
|
||||
self.hands['boardcard2'] = cards[1]
|
||||
|
@ -809,24 +812,11 @@ class DerivedStats():
|
|||
self.hands['playersAtStreet4'] = 0
|
||||
self.hands['playersAtShowdown'] = 0
|
||||
|
||||
for street in hand.actionStreets:
|
||||
for (i, street) in enumerate(hand.actionStreets[2:]):
|
||||
actors = {}
|
||||
for act in hand.actions[street]:
|
||||
actors[act[0]] = 1
|
||||
#print "len(actors.keys(%s)): %s" % ( street, len(actors.keys()))
|
||||
if hand.gametype['base'] in ("hold"):
|
||||
if street in "FLOP": self.hands['playersAtStreet1'] = len(actors.keys())
|
||||
elif street in "TURN": self.hands['playersAtStreet2'] = len(actors.keys())
|
||||
elif street in "RIVER": self.hands['playersAtStreet3'] = len(actors.keys())
|
||||
elif hand.gametype['base'] in ("stud"):
|
||||
if street in "FOURTH": self.hands['playersAtStreet1'] = len(actors.keys())
|
||||
elif street in "FIFTH": self.hands['playersAtStreet2'] = len(actors.keys())
|
||||
elif street in "SIXTH": self.hands['playersAtStreet3'] = len(actors.keys())
|
||||
elif street in "SEVENTH": self.hands['playersAtStreet4'] = len(actors.keys())
|
||||
elif hand.gametype['base'] in ("draw"):
|
||||
if street in "DRAWONE": self.hands['playersAtStreet1'] = len(actors.keys())
|
||||
elif street in "DRAWTWO": self.hands['playersAtStreet2'] = len(actors.keys())
|
||||
elif street in "DRAWTHREE": self.hands['playersAtStreet3'] = len(actors.keys())
|
||||
self.hands['playersAtStreet%s' % str(i+1)] = len(actors.keys())
|
||||
|
||||
#Need playersAtShowdown
|
||||
|
||||
|
|
|
@ -304,5 +304,5 @@ if __name__ == "__main__":
|
|||
LOG_FILENAME = './logging.out'
|
||||
logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity)
|
||||
|
||||
e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True, debugging=True)
|
||||
e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True)
|
||||
|
||||
|
|
|
@ -33,11 +33,12 @@ try:
|
|||
from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar
|
||||
from numpy import arange, cumsum
|
||||
from pylab import *
|
||||
except ImportError:
|
||||
except ImportError as inst:
|
||||
print """Failed to load libs for graphing, graphing will not function. Please in
|
||||
stall numpy and matplotlib if you want to use graphs."""
|
||||
print """This is of no consequence for other parts of the program, e.g. import
|
||||
and HUD are NOT affected by this problem."""
|
||||
print "ImportError: %s" % inst.args
|
||||
|
||||
import fpdb_import
|
||||
import Database
|
||||
|
|
|
@ -37,11 +37,10 @@ try:
|
|||
# from matplotlib.dates import DateFormatter, WeekdayLocator, HourLocator, \
|
||||
# DayLocator, MONDAY, timezone
|
||||
|
||||
except:
|
||||
err = traceback.extract_tb(sys.exc_info()[2])[-1]
|
||||
print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
|
||||
except ImportError as inst:
|
||||
print """Failed to load numpy in Session Viewer"""
|
||||
print """This is of no consequence as the module currently doesn't do anything."""
|
||||
print """This is of no consequence as the page is broken and only of interest to developers."""
|
||||
print "ImportError: %s" % inst.args
|
||||
|
||||
import Card
|
||||
import fpdb_import
|
||||
|
|
|
@ -626,6 +626,11 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
self.load_profile()
|
||||
|
||||
self.statusIcon = gtk.StatusIcon()
|
||||
if os.path.exists('../gfx/fpdb-cards.png'):
|
||||
self.statusIcon.set_from_file('../gfx/fpdb-cards.png')
|
||||
elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'):
|
||||
self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png')
|
||||
else:
|
||||
self.statusIcon.set_from_stock(gtk.STOCK_HOME)
|
||||
self.statusIcon.set_tooltip("Free Poker Database")
|
||||
self.statusIcon.connect('activate', self.statusicon_activate)
|
||||
|
@ -673,6 +678,12 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
pass
|
||||
|
||||
def statusicon_activate(self, widget, data = None):
|
||||
# Let's allow the tray icon to toggle window visibility, the way
|
||||
# most other apps work
|
||||
shown = self.window.get_property('visible')
|
||||
if shown:
|
||||
self.window.hide()
|
||||
else:
|
||||
self.window.show()
|
||||
self.window.present()
|
||||
|
||||
|
|
|
@ -77,10 +77,11 @@ class fpdb_db:
|
|||
import MySQLdb
|
||||
if use_pool:
|
||||
MySQLdb = pool.manage(MySQLdb, pool_size=5)
|
||||
try:
|
||||
# try:
|
||||
self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True)
|
||||
except:
|
||||
raise FpdbMySQLFailedError("MySQL connection failed")
|
||||
#TODO: Add port option
|
||||
# except:
|
||||
# raise FpdbMySQLFailedError("MySQL connection failed")
|
||||
elif backend==fpdb_db.PGSQL:
|
||||
import psycopg2
|
||||
import psycopg2.extensions
|
||||
|
|
6
setup.py
6
setup.py
|
@ -5,7 +5,7 @@ from distutils.core import setup
|
|||
|
||||
setup(name = 'fpdb',
|
||||
description = 'Free Poker Database',
|
||||
version = '0.11.3',
|
||||
version = '0.12',
|
||||
author = 'FPDB team',
|
||||
author_email = 'fpdb-main@lists.sourceforge.net',
|
||||
packages = ['fpdb'],
|
||||
|
@ -15,7 +15,9 @@ setup(name = 'fpdb',
|
|||
['docs/readme.txt', 'docs/release-notes.txt',
|
||||
'docs/tabledesign.html', 'THANKS.txt']),
|
||||
('/usr/share/pixmaps',
|
||||
['gfx/fpdb-icon.png']),
|
||||
['gfx/fpdb-icon.png', 'gfx/fpdb-icon2.png',
|
||||
'gfx/fpdb-cards.png'
|
||||
]),
|
||||
('/usr/share/applications',
|
||||
['files/fpdb.desktop']),
|
||||
('/usr/share/python-fpdb',
|
||||
|
|
Loading…
Reference in New Issue
Block a user