Merge branch 'master' of git://git.assembla.com/fpdboz.git
This commit is contained in:
@@ -648,7 +648,7 @@ class Config:
|
||||
# Allow to change the menu appearance
|
||||
def get_hud_ui_parameters(self):
|
||||
hui = {}
|
||||
|
||||
|
||||
default_text = 'FPDB Menu - Right click\nLeft-Drag to Move'
|
||||
try:
|
||||
hui['label'] = self.ui.label
|
||||
|
||||
+59
-57
@@ -1145,6 +1145,7 @@ class Database:
|
||||
c.execute("INSERT INTO Sites (name,currency) VALUES ('Betfair', 'USD')")
|
||||
c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')")
|
||||
c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')")
|
||||
c.execute("INSERT INTO Sites (name,currency) VALUES ('Partouche', 'EUR')")
|
||||
if self.backend == self.SQLITE:
|
||||
c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);")
|
||||
elif self.backend == self.PGSQL:
|
||||
@@ -1264,63 +1265,6 @@ class Database:
|
||||
print "Error during fdb.lock_for_insert:", str(sys.exc_value)
|
||||
#end def lock_for_insert
|
||||
|
||||
def getGameTypeId(self, siteid, game):
|
||||
c = self.get_cursor()
|
||||
#FIXME: Fixed for NL at the moment
|
||||
c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'],
|
||||
int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100)))
|
||||
tmp = c.fetchone()
|
||||
if (tmp == None):
|
||||
hilo = "h"
|
||||
if game['category'] in ['studhilo', 'omahahilo']:
|
||||
hilo = "s"
|
||||
elif game['category'] in ['razz','27_3draw','badugi']:
|
||||
hilo = "l"
|
||||
tmp = self.insertGameTypes( (siteid, game['type'], game['base'], game['category'], game['limitType'], hilo,
|
||||
int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), 0, 0) )
|
||||
return tmp[0]
|
||||
|
||||
def getSqlPlayerIDs(self, pnames, siteid):
|
||||
result = {}
|
||||
if(self.pcache == None):
|
||||
self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid))
|
||||
|
||||
for player in pnames:
|
||||
result[player] = self.pcache[player]
|
||||
# NOTE: Using the LambdaDict does the same thing as:
|
||||
#if player in self.pcache:
|
||||
# #print "DEBUG: cachehit"
|
||||
# pass
|
||||
#else:
|
||||
# self.pcache[player] = self.insertPlayer(player, siteid)
|
||||
#result[player] = self.pcache[player]
|
||||
|
||||
return result
|
||||
|
||||
def insertPlayer(self, name, site_id):
|
||||
result = None
|
||||
c = self.get_cursor()
|
||||
q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s"
|
||||
q = q.replace('%s', self.sql.query['placeholder'])
|
||||
|
||||
#print "DEBUG: name: %s site: %s" %(name, site_id)
|
||||
|
||||
c.execute (q, (site_id, name))
|
||||
|
||||
tmp = c.fetchone()
|
||||
if (tmp == None): #new player
|
||||
c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder'])
|
||||
,(name, site_id))
|
||||
#Get last id might be faster here.
|
||||
#c.execute ("SELECT id FROM Players WHERE name=%s", (name,))
|
||||
tmp = [self.get_last_insert_id(c)]
|
||||
return tmp[0]
|
||||
|
||||
def insertGameTypes(self, row):
|
||||
c = self.get_cursor()
|
||||
c.execute( self.sql.query['insertGameTypes'], row )
|
||||
return [self.get_last_insert_id(c)]
|
||||
|
||||
def store_the_hand(self, h):
|
||||
"""Take a HandToWrite object and store it in the db"""
|
||||
|
||||
@@ -1668,6 +1612,64 @@ class Database:
|
||||
# street4CheckCallRaiseChance,
|
||||
# street4CheckCallRaiseDone)
|
||||
|
||||
def getGameTypeId(self, siteid, game):
|
||||
c = self.get_cursor()
|
||||
#FIXME: Fixed for NL at the moment
|
||||
c.execute(self.sql.query['getGametypeNL'], (siteid, game['type'], game['category'], game['limitType'],
|
||||
int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100)))
|
||||
tmp = c.fetchone()
|
||||
if (tmp == None):
|
||||
hilo = "h"
|
||||
if game['category'] in ['studhilo', 'omahahilo']:
|
||||
hilo = "s"
|
||||
elif game['category'] in ['razz','27_3draw','badugi']:
|
||||
hilo = "l"
|
||||
tmp = self.insertGameTypes( (siteid, game['type'], game['base'], game['category'], game['limitType'], hilo,
|
||||
int(Decimal(game['sb'])*100), int(Decimal(game['bb'])*100), 0, 0) )
|
||||
return tmp[0]
|
||||
|
||||
def getSqlPlayerIDs(self, pnames, siteid):
|
||||
result = {}
|
||||
if(self.pcache == None):
|
||||
self.pcache = LambdaDict(lambda key:self.insertPlayer(key, siteid))
|
||||
|
||||
for player in pnames:
|
||||
result[player] = self.pcache[player]
|
||||
# NOTE: Using the LambdaDict does the same thing as:
|
||||
#if player in self.pcache:
|
||||
# #print "DEBUG: cachehit"
|
||||
# pass
|
||||
#else:
|
||||
# self.pcache[player] = self.insertPlayer(player, siteid)
|
||||
#result[player] = self.pcache[player]
|
||||
|
||||
return result
|
||||
|
||||
def insertPlayer(self, name, site_id):
|
||||
result = None
|
||||
c = self.get_cursor()
|
||||
q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s"
|
||||
q = q.replace('%s', self.sql.query['placeholder'])
|
||||
|
||||
#print "DEBUG: name: %s site: %s" %(name, site_id)
|
||||
|
||||
c.execute (q, (site_id, name))
|
||||
|
||||
tmp = c.fetchone()
|
||||
if (tmp == None): #new player
|
||||
c.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)".replace('%s',self.sql.query['placeholder'])
|
||||
,(name, site_id))
|
||||
#Get last id might be faster here.
|
||||
#c.execute ("SELECT id FROM Players WHERE name=%s", (name,))
|
||||
tmp = [self.get_last_insert_id(c)]
|
||||
return tmp[0]
|
||||
|
||||
def insertGameTypes(self, row):
|
||||
c = self.get_cursor()
|
||||
c.execute( self.sql.query['insertGameTypes'], row )
|
||||
return [self.get_last_insert_id(c)]
|
||||
|
||||
|
||||
|
||||
#################################
|
||||
# Finish of NEWIMPORT CODE
|
||||
|
||||
@@ -0,0 +1,562 @@
|
||||
|
||||
import os
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
|
||||
#*******************************************************************************************************
|
||||
class DatabaseManager(object):
|
||||
DatabaseTypes = {}
|
||||
|
||||
@classmethod
|
||||
def from_fpdb(klass, data, defaultDatabaseType=None):
|
||||
#TODO: parse whatever data is
|
||||
#TODO: sort out unsupported databases passed by user and log
|
||||
databases = (
|
||||
DatabaseTypeSqLite(name='myDb'),
|
||||
DatabaseTypeSqLite(name='myDb2'),
|
||||
|
||||
)
|
||||
return klass(databases=databases, defaultDatabaseType=defaultDatabaseType)
|
||||
|
||||
|
||||
def __init__(self, databases=None, defaultDatabaseType=None):
|
||||
self._defaultDatabaseType = defaultDatabaseType
|
||||
self._databases = [] if databases is None else list(databases)
|
||||
def __iter__(self):
|
||||
return iter(self._databases)
|
||||
def set_default_database_type(self, databaseType):
|
||||
self._defaultDatabaseType = defaultDatabaseType
|
||||
def get_default_database_type(self):
|
||||
return self._defaultDatabaseType
|
||||
def database_from_id(self, idDatabase):
|
||||
for database in self._databases:
|
||||
if idDatabase == id(database):
|
||||
return database
|
||||
def database_id(self, database):
|
||||
return id(database)
|
||||
def add_database(self, database):
|
||||
if database in self._databases:
|
||||
raise ValueError('database already registered')
|
||||
self._databases.append(database)
|
||||
def remove_database(self, database):
|
||||
self._databases.remove(database)
|
||||
def init_database(self, database):
|
||||
pass
|
||||
|
||||
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
|
||||
Params = ()
|
||||
|
||||
class DatabaseTypePostgres(DatabaseTypeBase):
|
||||
Type = 'postgres'
|
||||
@classmethod
|
||||
def display_name(klass):
|
||||
return 'Postgres'
|
||||
def __init__(self, name='', host='localhost', port=5432, user='postgres', password='', database='fpdb'):
|
||||
self.name = name
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.database = database
|
||||
|
||||
class DatabaseTypeMysql(DatabaseTypeBase):
|
||||
Type = 'mysql'
|
||||
@classmethod
|
||||
def display_name(klass):
|
||||
return 'MySql'
|
||||
def __init__(self, name='', host='localhost', port=3306, user='root', password='', database='fpdb'):
|
||||
self.name = name
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.database = database
|
||||
|
||||
class DatabaseTypeSqLite(DatabaseTypeBase):
|
||||
Type = 'sqlite'
|
||||
@classmethod
|
||||
def display_name(klass):
|
||||
return 'SqLite'
|
||||
def __init__(self, name='', host='', file='', database='fpdb'):
|
||||
self.name = name
|
||||
self.file = file
|
||||
self.database = database
|
||||
|
||||
#TODO: how do we want to handle unsupported database types?
|
||||
# ..uncomment to remove unsupported database types
|
||||
#try: import psycopg2
|
||||
#except ImportError: del DatabaseManager.DatabaseTypes['postgres']
|
||||
#try: import MySQLdb
|
||||
#except ImportError: del DatabaseManager.DatabaseTypes['mysql']
|
||||
#try: import sqlite3
|
||||
#except ImportError: del DatabaseManager.DatabaseTypes['sqlite']
|
||||
|
||||
#***************************************************************************************************************************
|
||||
#TODO: derrive from gtk.VBox?
|
||||
class WidgetDatabaseProperties(gtk.VBox):
|
||||
|
||||
ModeNew = 0
|
||||
ModeEdit = 1
|
||||
ModeAdd = 2
|
||||
|
||||
class SqLiteFileChooserButton(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, widgetDatabaseProperties, parentWidget):
|
||||
gtk.HBox.__init__(self)
|
||||
self.set_homogeneous(False)
|
||||
|
||||
self.parentWidget = parentWidget
|
||||
self.widgetDatabaseProperties = widgetDatabaseProperties
|
||||
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):
|
||||
if self.widgetDatabaseProperties.mode == WidgetDatabaseProperties.ModeAdd:
|
||||
action = gtk.FILE_CHOOSER_ACTION_OPEN
|
||||
elif self.widgetDatabaseProperties.mode == WidgetDatabaseProperties.ModeNew:
|
||||
action = gtk.FILE_CHOOSER_ACTION_SAVE
|
||||
else:
|
||||
raise ValueError('unsupported dialog mode')
|
||||
dlg = gtk.FileChooserDialog(
|
||||
title='Choose an exiting database file or type in name of a new one',
|
||||
parent=self.parentWidget,
|
||||
action=action,
|
||||
buttons=(
|
||||
gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
|
||||
gtk.STOCK_OK, gtk.RESPONSE_OK,
|
||||
),
|
||||
backend=None
|
||||
)
|
||||
dlg.set_default_response(gtk.RESPONSE_OK)
|
||||
dlg.set_do_overwrite_confirmation(True)
|
||||
if dlg.run() == gtk.RESPONSE_OK:
|
||||
fileName = dlg.get_filename()
|
||||
self.set_filename(fileName)
|
||||
dlg.destroy()
|
||||
|
||||
|
||||
|
||||
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, mode=ModeEdit, parentWidget=None):
|
||||
gtk.VBox.__init__(self)
|
||||
|
||||
self.databaseManager = databaseManager
|
||||
self.database = database
|
||||
self.mode = mode
|
||||
self.parentWidget = parentWidget
|
||||
self.fieldWidgets = (
|
||||
self.FieldWidget(
|
||||
text='Name:',
|
||||
attrDatabase='name',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=True,
|
||||
tooltip='Any name you like to name the database '
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Db:',
|
||||
attrDatabase='database',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip='Name of the database to create'
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='File:',
|
||||
attrDatabase='file',
|
||||
widget=self.SqLiteFileChooserButton(self, self.parentWidget),
|
||||
defaultValue='',
|
||||
attrGet='get_filename',
|
||||
attrSet='set_filename',
|
||||
canEdit=False,
|
||||
tooltip='Fully qualified path of the file to hold the database '
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Host:',
|
||||
attrDatabase='host',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip='Host the database is located at'
|
||||
),
|
||||
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='Port to use to connect to the host'
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='User:',
|
||||
attrDatabase='user',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip='User name used to login to the host'
|
||||
),
|
||||
self.FieldWidget(
|
||||
text='Pwd:',
|
||||
attrDatabase='password',
|
||||
widget=gtk.Entry(),
|
||||
defaultValue='',
|
||||
attrGet='get_text',
|
||||
attrSet='set_text',
|
||||
canEdit=False,
|
||||
tooltip='Password used to login to the host'
|
||||
),
|
||||
)
|
||||
|
||||
# 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)
|
||||
self.comboType.connect('changed', self.on_combo_type_changed)
|
||||
|
||||
# fill database type combo with available database klasses. we store (databaseDisplayName, databaseType) in our model for later lookup
|
||||
iCurrentDatabase = 0
|
||||
databaseTypes = [(klass.display_name(), klass.Type) for klass in databaseManager.DatabaseTypes.values()]
|
||||
databaseTypes.sort()
|
||||
for i, (databaseDisplayName, databaseType) in enumerate(databaseTypes):
|
||||
listStore.append( (databaseDisplayName, databaseType) )
|
||||
if databaseType == self.database.Type:
|
||||
iCurrentDatabase = i
|
||||
if self.mode == self.ModeEdit or len(databaseTypes) < 2:
|
||||
self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF)
|
||||
|
||||
# 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
|
||||
self.comboType.set_active(iCurrentDatabase)
|
||||
self._adjust_widgets(self.database)
|
||||
|
||||
def _adjust_widgets(self, database):
|
||||
for fieldWidget in self.fieldWidgets:
|
||||
isSensitive = fieldWidget.is_sensitive(database)
|
||||
if isSensitive:
|
||||
fieldWidget.value_from_database(database)
|
||||
else:
|
||||
fieldWidget.reset_value()
|
||||
if self.mode == self.ModeEdit:
|
||||
isSensitive = isSensitive and fieldWidget.can_edit()
|
||||
fieldWidget.set_sensitive(isSensitive)
|
||||
|
||||
|
||||
def on_combo_type_changed(self, combo):
|
||||
i = self.comboType.get_active()
|
||||
if i < 0:
|
||||
return
|
||||
|
||||
# check if we need to init a new database
|
||||
currentDatabaseType = self.comboType.get_model()[i][1]
|
||||
if currentDatabaseType == self.database.Type:
|
||||
return
|
||||
|
||||
# create new empty database
|
||||
#NOTE: we dont register it in DatabaseManager
|
||||
self.database = self.databaseManager.DatabaseTypes[currentDatabaseType]()
|
||||
self._adjust_widgets(self.database)
|
||||
|
||||
|
||||
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, parent=None, mode=WidgetDatabaseProperties.ModeEdit, title=''):
|
||||
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.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database, mode=mode, parentWidget=self)
|
||||
self.vbox.pack_start(self.widgetDatabaseProperties, True, True)
|
||||
self.show_all()
|
||||
|
||||
def get_widget_database_properties(self):
|
||||
return self.widgetDatabaseProperties
|
||||
|
||||
def on_dialog_response(self, dlg, responseId):
|
||||
if responseId == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
elif responseId == gtk.RESPONSE_ACCEPT:
|
||||
pass
|
||||
|
||||
|
||||
#TODO: derrive from gtk.VBox?
|
||||
# ..is there a way to derrive from gtk.Widget or similar? this would make parentWidget kw obsolete
|
||||
class WidgetDatabaseManager(gtk.VBox):
|
||||
def __init__(self, databaseManager, parentWidget=None):
|
||||
gtk.VBox.__init__(self)
|
||||
|
||||
self.databaseManager = databaseManager
|
||||
self.parentWidget = parentWidget
|
||||
|
||||
#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)
|
||||
|
||||
# init database tree
|
||||
self.treeDatabases = gtk.TreeView()
|
||||
self.treeDatabaseColumns = ( #NOTE: column names starting with '_' will be hidden
|
||||
'Name',
|
||||
'Status',
|
||||
'Type',
|
||||
'_id',
|
||||
)
|
||||
|
||||
store = gtk.ListStore(str, str, str, int)
|
||||
self.treeDatabases.set_model(store)
|
||||
columns = ('Name', 'Status', 'Type', '_id')
|
||||
for i, column in enumerate(columns):
|
||||
col = gtk.TreeViewColumn(column, gtk.CellRendererText(), text=i)
|
||||
self.treeDatabases.append_column(col)
|
||||
if column.startswith('_'):
|
||||
col.set_visible(False)
|
||||
|
||||
self.treeDatabaseColumns = dict([(name, i) for (i, name) in enumerate(self.treeDatabaseColumns)])
|
||||
self.treeDatabases.get_selection().connect('changed', self.on_tree_databases_selection_changed)
|
||||
|
||||
# layout widgets
|
||||
vbox = gtk.VBox(self)
|
||||
vbox.pack_start(self.labelInfo, False, False, 2)
|
||||
vbox.pack_start(gtk.HSeparator(), False, False, 2)
|
||||
hbox = gtk.HBox()
|
||||
self.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()
|
||||
|
||||
# init widget
|
||||
for database in self.databaseManager:
|
||||
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
|
||||
|
||||
#TODO: for some reason i have to click OK/Cancel twice to close the dialog
|
||||
def on_button_database_new_clicked(self, button):
|
||||
databaseType = self.databaseManager.get_default_database_type()
|
||||
if databaseType is None:
|
||||
raise ValueError('no defult database type set')
|
||||
dlg = DialogDatabaseProperties(
|
||||
self.databaseManager,
|
||||
databaseType(),
|
||||
parent=self.parentWidget,
|
||||
mode=WidgetDatabaseProperties.ModeNew,
|
||||
title='[New database] - database properties'
|
||||
)
|
||||
if dlg.run() == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
if dlg.run() == gtk.RESPONSE_ACCEPT:
|
||||
database = dlg.get_widget_database_properties().get_database()
|
||||
#TODO: sanity checks + init databse if necessary
|
||||
self.databaseManager.add_database(database)
|
||||
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
|
||||
dlg.destroy()
|
||||
|
||||
def on_button_database_add_clicked(self, button):
|
||||
databaseType = self.databaseManager.get_default_database_type()
|
||||
if databaseType is None:
|
||||
raise ValueError('no defult database type set')
|
||||
dlg = DialogDatabaseProperties(
|
||||
self.databaseManager,
|
||||
databaseType(),
|
||||
parent=self.parentWidget,
|
||||
mode=WidgetDatabaseProperties.ModeAdd,
|
||||
title='[Add database] - database properties'
|
||||
)
|
||||
if dlg.run() == gtk.RESPONSE_REJECT:
|
||||
pass
|
||||
if dlg.run() == gtk.RESPONSE_ACCEPT:
|
||||
database = dlg.get_widget_database_properties().get_database()
|
||||
#TODO: sanity checks
|
||||
self.databaseManager.add_database(database)
|
||||
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
|
||||
dlg.destroy()
|
||||
|
||||
def on_button_database_edit_clicked(self, button):
|
||||
selection = self.treeDatabases.get_selection()
|
||||
if selection is None:
|
||||
return
|
||||
|
||||
model, iter = selection.get_selected()
|
||||
idDatabase = model.get_value(iter, self.treeDatabaseColumns['_id'])
|
||||
database = self.databaseManager.database_from_id(idDatabase)
|
||||
dlg = DialogDatabaseProperties(
|
||||
self.databaseManager,
|
||||
database=database,
|
||||
parent=self.parentWidget,
|
||||
mode=WidgetDatabaseProperties.ModeEdit,
|
||||
title='[Edit database] - database properties'
|
||||
)
|
||||
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)
|
||||
|
||||
|
||||
class DialogDatabaseManager(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.widgetDatabaseManager = WidgetDatabaseManager(databaseManager, parentWidget=self)
|
||||
self.vbox.pack_start(self.widgetDatabaseManager, True, True)
|
||||
self.show_all()
|
||||
|
||||
#**************************************************************************************************
|
||||
if __name__ == '__main__':
|
||||
databaseManager = DatabaseManager.from_fpdb('', defaultDatabaseType=DatabaseTypeSqLite)
|
||||
|
||||
#d = DialogDatabaseProperties(
|
||||
# DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite),
|
||||
#database=DatabaseTypePostgres(),
|
||||
# database=None,
|
||||
# )
|
||||
d = DialogDatabaseManager(databaseManager)
|
||||
d.connect("destroy", gtk.main_quit)
|
||||
d.run()
|
||||
#gtk.main()
|
||||
|
||||
|
||||
+6
-16
@@ -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)
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
<import callFpdbHud = "True" interval = "10" fastStoreHudCache="False" hhArchiveBase="~/.fpdb/HandHistories/" saveActions="True"></import>
|
||||
|
||||
|
||||
<!-- These values need some explaining
|
||||
|
||||
aggregate_ring_game_stats :
|
||||
@@ -567,6 +566,7 @@ Left-Drag to Move"
|
||||
<hhc site="Absolute" converter="AbsoluteToFpdb"/>
|
||||
<hhc site="PartyPoker" converter="PartyPokerToFpdb"/>
|
||||
<hhc site="Betfair" converter="BetfairToFpdb"/>
|
||||
<hhc site="Partouche" converter="PartoucheToFpdb"/>
|
||||
</hhcs>
|
||||
|
||||
<supported_databases>
|
||||
|
||||
+14
-3
@@ -626,7 +626,12 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||
self.load_profile()
|
||||
|
||||
self.statusIcon = gtk.StatusIcon()
|
||||
self.statusIcon.set_from_stock(gtk.STOCK_HOME)
|
||||
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)
|
||||
self.statusMenu = gtk.Menu()
|
||||
@@ -673,8 +678,14 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
||||
pass
|
||||
|
||||
def statusicon_activate(self, widget, data = None):
|
||||
self.window.show()
|
||||
self.window.present()
|
||||
# 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()
|
||||
|
||||
def warning_box(self, str, diatitle="FPDB WARNING"):
|
||||
diaWarning = gtk.Dialog(title=diatitle, parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
|
||||
|
||||
Reference in New Issue
Block a user