Merge branch 'master' of git://git.assembla.com/fpdb-sql

This commit is contained in:
Worros 2010-08-29 14:05:06 +08:00
commit 93be69858a
8 changed files with 613 additions and 227 deletions

View File

@ -1,6 +1,7 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info and Erki Ferenc, erkiferenc@gmail.com
# $Header: $
EAPI="2"
inherit eutils

View File

@ -1,6 +1,7 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info and Erki Ferenc, erkiferenc@gmail.com
# $Header: $
EAPI="2"
inherit eutils
@ -17,49 +18,53 @@ SLOT="0"
KEYWORDS="~amd64 ~x86"
#note: this should work on other architectures too, please send me your experiences
IUSE="graph mysql postgres sqlite linguas_hu"
IUSE="graph mysql postgres sqlite linguas_hu linguas_it"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib
dev-python/pytz"
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib
dev-python/pytz"
DEPEND="${RDEPEND}"
src_install() {
insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx
doins -r pyfpdb
insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx
doins -r pyfpdb
if use linguas_hu; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/hu/LC_MESSAGES/${PN}.mo /usr/share/locale/hu/LC_MESSAGES/${PN}.mo
fi
if use linguas_hu; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/hu/LC_MESSAGES/${PN}.mo /usr/share/locale/hu/LC_MESSAGES/${PN}.mo
fi
doins readme.txt
if use linguas_it; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/it/LC_MESSAGES/${PN}.mo /usr/share/locale/it/LC_MESSAGES/${PN}.mo
fi
exeinto "${GAMES_DATADIR}"/${PN}
doexe run_fpdb.py
doins readme.txt
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
exeinto "${GAMES_DATADIR}"/${PN}
doexe run_fpdb.py
newicon gfx/fpdb-icon.png ${PN}.png
make_desktop_entry ${PN}
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
prepgamesdirs
newicon gfx/fpdb-icon.png ${PN}.png
make_desktop_entry ${PN}
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
prepgamesdirs
}
pkg_postinst() {
games_pkg_postinst
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
games_pkg_postinst
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
}

View File

@ -1,6 +1,7 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# created by Steffen Schaumburg, steffen@schaumburger.info and Erki Ferenc, erkiferenc@gmail.com
# $Header: $
EAPI="2"
inherit eutils
@ -18,53 +19,57 @@ SLOT="0"
KEYWORDS=""
#note: this should work on other architectures too, please send me your experiences
IUSE="graph mysql postgres sqlite linguas_hu"
IUSE="graph mysql postgres sqlite linguas_hu linguas_it"
RDEPEND="
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib
dev-python/pytz"
mysql? ( virtual/mysql
dev-python/mysql-python )
postgres? ( dev-db/postgresql-server
dev-python/psycopg )
sqlite? ( dev-lang/python[sqlite]
dev-python/numpy )
>=x11-libs/gtk+-2.10
dev-python/pygtk
graph? ( dev-python/numpy
dev-python/matplotlib[gtk] )
dev-python/python-xlib
dev-python/pytz"
DEPEND="${RDEPEND}"
src_unpack() {
git_src_unpack
git_src_unpack
}
src_install() {
insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx
doins -r pyfpdb
insinto "${GAMES_DATADIR}"/${PN}
doins -r gfx
doins -r pyfpdb
if use linguas_hu; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/hu/LC_MESSAGES/${PN}.mo /usr/share/locale/hu/LC_MESSAGES/${PN}.mo
fi
if use linguas_hu; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/hu/LC_MESSAGES/${PN}.mo /usr/share/locale/hu/LC_MESSAGES/${PN}.mo
fi
doins readme.txt
if use linguas_it; then
dosym "${GAMES_DATADIR}"/${PN}/pyfpdb/locale/it/LC_MESSAGES/${PN}.mo /usr/share/locale/it/LC_MESSAGES/${PN}.mo
fi
exeinto "${GAMES_DATADIR}"/${PN}
doexe run_fpdb.py
doins readme.txt
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
exeinto "${GAMES_DATADIR}"/${PN}
doexe run_fpdb.py
newicon gfx/fpdb-icon.png ${PN}.png
make_desktop_entry ${PN}
dodir "${GAMES_BINDIR}"
dosym "${GAMES_DATADIR}"/${PN}/run_fpdb.py "${GAMES_BINDIR}"/${PN}
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
prepgamesdirs
newicon gfx/fpdb-icon.png ${PN}.png
make_desktop_entry ${PN}
chmod +x "${D}/${GAMES_DATADIR}"/${PN}/pyfpdb/*.pyw
prepgamesdirs
}
pkg_postinst() {
games_pkg_postinst
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
games_pkg_postinst
elog "Note that if you really want to use mysql or postgresql you will have to create"
elog "the database and user yourself and enter it into the fpdb config."
elog "You can find the instructions on the project's website."
}

View File

@ -749,6 +749,7 @@ class Config:
raise ValueError("Database names must be unique")
if self.db_selected is None or db.db_selected:
self.db_selected = db.db_name
db_node.setAttribute("default", "True")
self.supported_databases[db.db_name] = db
#TODO: if the user may passes '' (empty string) as database name via command line, his choice is ignored
# ..when we parse the xml we allow for ''. there has to be a decission if to allow '' or not
@ -1039,7 +1040,11 @@ class Config:
if db_user is not None: db_node.setAttribute("db_user", db_user)
if db_pass is not None: db_node.setAttribute("db_pass", db_pass)
if db_server is not None: db_node.setAttribute("db_server", db_server)
if defaultb: db_node.setAttribute("default", default)
if defaultb or self.db_selected == db_name:
db_node.setAttribute("default", "True")
for dbn in self.doc.getElementsByTagName("database"):
if dbn.getAttribute('db_name') != db_name and dbn.hasAttribute("default"):
dbn.removeAttribute("default")
elif db_node.hasAttribute("default"):
db_node.removeAttribute("default")
if self.supported_databases.has_key(db_name):
@ -1052,6 +1057,64 @@ class Config:
if defaultb:
self.db_selected = db_name
return
def add_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None,
db_pass = None, db_desc = None, db_server = None,
default = "False"):
default = default.lower()
defaultb = string_to_bool(default, False)
if db_name in self.supported_databases:
raise ValueError("Database names must be unique")
db_node = self.get_db_node(db_name)
if db_node is None:
for db_node in self.doc.getElementsByTagName("supported_databases"):
# should only be one supported_databases element, use last one if there are several
suppdb_node = db_node
t_node = self.doc.createTextNode(" ")
suppdb_node.appendChild(t_node)
db_node = self.doc.createElement("database")
suppdb_node.appendChild(db_node)
t_node = self.doc.createTextNode("\r\n ")
suppdb_node.appendChild(t_node)
db_node.setAttribute("db_name", db_name)
if db_desc is not None: db_node.setAttribute("db_desc", db_desc)
if db_ip is not None: db_node.setAttribute("db_ip", db_ip)
if db_user is not None: db_node.setAttribute("db_user", db_user)
if db_pass is not None: db_node.setAttribute("db_pass", db_pass)
if db_server is not None: db_node.setAttribute("db_server", db_server)
if defaultb:
db_node.setAttribute("default", "True")
for dbn in self.doc.getElementsByTagName("database"):
if dbn.getAttribute('db_name') != db_name and dbn.hasAttribute("default"):
dbn.removeAttribute("default")
elif db_node.hasAttribute("default"):
db_node.removeAttribute("default")
else:
if db_desc is not None: db_node.setAttribute("db_desc", db_desc)
if db_ip is not None: db_node.setAttribute("db_ip", db_ip)
if db_user is not None: db_node.setAttribute("db_user", db_user)
if db_pass is not None: db_node.setAttribute("db_pass", db_pass)
if db_server is not None: db_node.setAttribute("db_server", db_server)
if defaultb or self.db_selected == db_name:
db_node.setAttribute("default", "True")
elif db_node.hasAttribute("default"):
db_node.removeAttribute("default")
if self.supported_databases.has_key(db_name):
if db_desc is not None: self.supported_databases[db_name].dp_desc = db_desc
if db_ip is not None: self.supported_databases[db_name].dp_ip = db_ip
if db_user is not None: self.supported_databases[db_name].dp_user = db_user
if db_pass is not None: self.supported_databases[db_name].dp_pass = db_pass
if db_server is not None: self.supported_databases[db_name].dp_server = db_server
self.supported_databases[db_name].db_selected = defaultb
else:
db = Database(node=db_node)
self.supported_databases[db.db_name] = db
if defaultb:
self.db_selected = db_name
return
def get_backend(self, name):
"""Returns the number of the currently used backend"""

View File

@ -19,6 +19,7 @@ import os
import sys
import traceback
import Queue
import re
import pygtk
pygtk.require('2.0')
@ -32,6 +33,7 @@ log = logging.getLogger("maintdbs")
import Exceptions
import Configuration
import Database
import SQL
@ -79,8 +81,17 @@ class GuiDatabase:
try:
#self.dia.set_modal(True)
self.vbox = self.dia.vbox
self.action_area = self.dia.action_area
#gtk.Widget.set_size_request(self.vbox, 700, 400);
h = gtk.HBox(False, spacing=3)
h.show()
self.vbox.pack_start(h, padding=3)
vbtn = gtk.VBox(True, spacing=3)
vbtn.show()
h.pack_start(vbtn, expand=False, fill=False, padding=2)
# list of databases in self.config.supported_databases:
self.liststore = gtk.ListStore(str, str, str, str, str
,str, str, str, str, str)
@ -101,12 +112,15 @@ class GuiDatabase:
self.scrolledwindow = gtk.ScrolledWindow()
self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.scrolledwindow.add(self.listview)
self.vbox.pack_start(self.scrolledwindow, expand=True, fill=True, padding=0)
h.pack_start(self.scrolledwindow, expand=True, fill=True, padding=0)
refreshbutton = gtk.Button(_("Refresh"))
refreshbutton.connect("clicked", self.refresh, None)
self.vbox.pack_start(refreshbutton, False, False, 3)
refreshbutton.show()
add_button = SideButton(_("_Add"), gtk.STOCK_ADD)
add_button.connect("clicked", self.addDB, None)
vbtn.pack_start(add_button, False, False, 3)
refresh_button = SideButton(_("_Refresh"), gtk.STOCK_REFRESH)
refresh_button.connect("clicked", self.refresh, None)
vbtn.pack_start(refresh_button, False, False, 3)
col = self.addTextColumn(_("Type"), 0, False)
col = self.addTextColumn(_("Name"), 1, False)
@ -114,7 +128,7 @@ class GuiDatabase:
col = self.addTextColumn(_("Username"), 3, True)
col = self.addTextColumn(_("Password"), 4, True)
col = self.addTextColumn(_("Host"), 5, True)
col = self.addTextObjColumn(_("Default"), 6, 6)
col = self.addTextObjColumn(_("Open"), 6, 6)
col = self.addTextObjColumn(_("Status"), 7, 8)
#self.listview.get_selection().set_mode(gtk.SELECTION_SINGLE)
@ -122,6 +136,7 @@ class GuiDatabase:
self.listview.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.listview.connect('button_press_event', self.selectTest)
self.dia.show_all()
self.loadDbs()
#self.dia.connect('response', self.dialog_response_cb)
@ -248,9 +263,9 @@ class GuiDatabase:
self.liststore.clear()
#self.listcols = []
dia = self.info_box2(None, _('Testing database connections ... '), "", False, False)
dia = InfoBox( parent=self.dia, str1=_('Testing database connections ... ') )
while gtk.events_pending():
gtk.mainiteration()
gtk.main_iteration()
try:
# want to fill: dbms, name, comment, user, passwd, host, default, status, icon
@ -268,57 +283,14 @@ class GuiDatabase:
default = (name == self.config.db_selected)
default_icon = None
if default: default_icon = gtk.STOCK_APPLY
status = ""
icon = None
err_msg = ""
sql = SQL.Sql(db_server=dbms)
db = Database.Database(self.config, sql = sql, autoconnect = False)
# try to connect to db, set status and err_msg if it fails
try:
# is creating empty db for sqlite ... mod db.py further?
# add noDbTables flag to db.py?
log.debug(_("loaddbs: trying to connect to: %s/%s, %s, %s/%s") % (str(dbms_num),dbms,name,user,passwd))
db.connect(backend=dbms_num, host=host, database=name, user=user, password=passwd, create=False)
if db.connected:
log.debug(_(" connected ok"))
status = 'ok'
icon = gtk.STOCK_APPLY
if db.wrongDbVersion:
status = 'old'
icon = gtk.STOCK_INFO
else:
log.debug(_(" not connected but no exception"))
except Exceptions.FpdbMySQLAccessDenied:
err_msg = _("MySQL Server reports: Access denied. Are your permissions set correctly?")
status = "failed"
icon = gtk.STOCK_CANCEL
except Exceptions.FpdbMySQLNoDatabase:
err_msg = _("MySQL client reports: 2002 or 2003 error. Unable to connect - Please check that the MySQL service has been started")
status = "failed"
icon = gtk.STOCK_CANCEL
except Exceptions.FpdbPostgresqlAccessDenied:
err_msg = _("Postgres Server reports: Access denied. Are your permissions set correctly?")
status = "failed"
except Exceptions.FpdbPostgresqlNoDatabase:
err_msg = _("Postgres client reports: Unable to connect - Please check that the Postgres service has been started")
status = "failed"
icon = gtk.STOCK_CANCEL
except:
err = traceback.extract_tb(sys.exc_info()[2])[-1]
log.info( 'db connection to '+str(dbms_num)+','+host+','+name+','+user+','+passwd+' failed: '
+ err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) )#TODO Gettextify
status = "failed"
icon = gtk.STOCK_CANCEL
if err_msg:
log.info( 'db connection to '+str(dbms_num)+','+host+','+name+','+user+','+passwd+' failed: '
+ err_msg )#TODO Gettextify
status, err_msg, icon = GuiDatabase.testDB(self.config, dbms, dbms_num, name, user, passwd, host)
b = gtk.Button(name)
b.show()
iter = self.liststore.append( (dbms, name, comment, user, passwd, host, "", default_icon, status, icon) )
self.info_box2(dia[0], _("finished."), "", False, True)
dia.add_msg( _("finished."), False, True )
self.listview.show()
self.scrolledwindow.show()
self.vbox.show()
@ -356,64 +328,368 @@ class GuiDatabase:
def refresh(self, widget, data):
self.loadDbs()
def info_box(self, dia, str1, str2, run, destroy):
if dia is None:
#if run:
btns = gtk.BUTTONS_NONE
btns = gtk.BUTTONS_OK
dia = gtk.MessageDialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, type=gtk.MESSAGE_INFO, buttons=(btns), message_format=str1 )
# try to remove buttons!
# (main message is in inverse video if no buttons, so try removing them after
# creating dialog)
# NO! message just goes back to inverse video :-( use info_box2 instead
for c in dia.vbox.get_children():
if isinstance(c, gtk.HButtonBox):
for d in c.get_children():
log.info('child: '+str(d)+' is a '+str(d.__class__))
if isinstance(d, gtk.Button):
log.info(_('removing button %s'% str(d)))
c.remove(d)
if str2:
dia.format_secondary_text(str2)
else:
dia.set_markup(str1)
if str2:
dia.format_secondary_text(str2)
dia.show()
response = None
if run: response = dia.run()
if destroy: dia.destroy()
return (dia, response)
def addDB(self, widget, data):
adb = AddDB(self.config, self.dia)
(status, err_msg, icon, dbms, dbms_num, name, comment, user, passwd, host) = adb.run()
adb.destroy()
def info_box2(self, dia, str1, str2, run, destroy):
if dia is None:
# create dialog and add icon and label
btns = (gtk.BUTTONS_OK)
btns = None
# messagedialog puts text in inverse colors if no buttons are displayed??
#dia = gtk.MessageDialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
# , type=gtk.MESSAGE_INFO, buttons=(btns), message_format=str1 )
dia = gtk.Dialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, title="" ) # , buttons=btns
vbox = dia.vbox
# save in liststore
if status == 'ok':
iter = self.liststore.append( (dbms, name, comment, user, passwd, host, "", None, status, icon) )
# keep config save code in line with edited_cb()? call common routine?
valid = True
# Validate new value (only for dbms so far, but dbms now not updateable so no validation at all!)
#if col == self.COL_DBMS:
# if new_text not in Configuration.DATABASE_TYPES:
# valid = False
if valid:
self.config.add_db_parameters( db_server = dbms
, db_name = name
, db_desc = comment
, db_ip = host
, db_user = user
, db_pass = passwd )
self.config.save()
self.changes = False
@staticmethod
def testDB(config, dbms, dbms_num, name, user, passwd, host):
status = ""
icon = None
err_msg = ""
sql = SQL.Sql(db_server=dbms)
db = Database.Database(config, sql = sql, autoconnect = False)
# try to connect to db, set status and err_msg if it fails
try:
# is creating empty db for sqlite ... mod db.py further?
# add noDbTables flag to db.py?
log.debug(_("loaddbs: trying to connect to: %s/%s, %s, %s/%s") % (str(dbms_num),dbms,name,user,passwd))
db.connect(backend=dbms_num, host=host, database=name, user=user, password=passwd, create=False)
if db.connected:
log.debug(_(" connected ok"))
status = 'ok'
icon = gtk.STOCK_APPLY
if db.wrongDbVersion:
status = 'old'
icon = gtk.STOCK_INFO
else:
log.debug(_(" not connected but no exception"))
except Exceptions.FpdbMySQLAccessDenied:
err_msg = _("MySQL Server reports: Access denied. Are your permissions set correctly?")
status = "failed"
icon = gtk.STOCK_CANCEL
except Exceptions.FpdbMySQLNoDatabase:
err_msg = _("MySQL client reports: 2002 or 2003 error. Unable to connect - Please check that the MySQL service has been started")
status = "failed"
icon = gtk.STOCK_CANCEL
except Exceptions.FpdbPostgresqlAccessDenied:
err_msg = _("Postgres Server reports: Access denied. Are your permissions set correctly?")
status = "failed"
except Exceptions.FpdbPostgresqlNoDatabase:
err_msg = _("Postgres client reports: Unable to connect - Please check that the Postgres service has been started")
status = "failed"
icon = gtk.STOCK_CANCEL
except:
# add more specific exceptions here if found (e.g. for sqlite?)
err = traceback.extract_tb(sys.exc_info()[2])[-1]
err_msg = err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
status = "failed"
icon = gtk.STOCK_CANCEL
if err_msg:
log.info( _('db connection to ') + str(dbms_num)+','+host+','+name+','+user+','+passwd+' failed: '
+ err_msg )
return( status, err_msg, icon )
class AddDB(gtk.Dialog):
def __init__(self, config, parent):
log.debug("AddDB starting")
self.dbnames = { 'Sqlite' : Configuration.DATABASE_TYPE_SQLITE
, 'MySQL' : Configuration.DATABASE_TYPE_MYSQL
, 'PostgreSQL' : Configuration.DATABASE_TYPE_POSTGRESQL
}
self.config = config
# create dialog and add icon and label
super(AddDB,self).__init__( parent=parent
, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
, title="Add New Database"
, buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT
,gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)
) # , buttons=btns
self.set_default_size(450, 280)
#self.connect('response', self.response_cb)
t = gtk.Table(5, 3, True)
self.vbox.pack_start(t, expand=False, fill=False, padding=3)
l = gtk.Label( _("DB Type") )
l.set_alignment(1.0, 0.5)
t.attach(l, 0, 1, 0, 1, xpadding=3)
self.cb_dbms = gtk.combo_box_new_text()
for s in ('Sqlite',): # keys(self.dbnames):
self.cb_dbms.append_text(s)
self.cb_dbms.set_active(0)
t.attach(self.cb_dbms, 1, 3, 0, 1, xpadding=3)
self.cb_dbms.connect("changed", self.db_type_changed, None)
l = gtk.Label( _("DB Name") )
l.set_alignment(1.0, 0.5)
t.attach(l, 0, 1, 1, 2, xpadding=3)
self.e_db_name = gtk.Entry()
self.e_db_name.set_width_chars(15)
t.attach(self.e_db_name, 1, 3, 1, 2, xpadding=3)
self.e_db_name.connect("focus-out-event", self.db_name_changed, None)
l = gtk.Label( _("DB Description") )
l.set_alignment(1.0, 0.5)
t.attach(l, 0, 1, 2, 3, xpadding=3)
self.e_db_desc = gtk.Entry()
self.e_db_desc.set_width_chars(15)
t.attach(self.e_db_desc, 1, 3, 2, 3, xpadding=3)
self.l_username = gtk.Label( _("Username") )
self.l_username.set_alignment(1.0, 0.5)
t.attach(self.l_username, 0, 1, 3, 4, xpadding=3)
self.e_username = gtk.Entry()
self.e_username.set_width_chars(15)
t.attach(self.e_username, 1, 3, 3, 4, xpadding=3)
self.l_password = gtk.Label( _("Password") )
self.l_password.set_alignment(1.0, 0.5)
t.attach(self.l_password, 0, 1, 4, 5, xpadding=3)
self.e_password = gtk.Entry()
self.e_password.set_width_chars(15)
t.attach(self.e_password, 1, 3, 4, 5, xpadding=3)
self.l_host = gtk.Label( _("Host Computer") )
self.l_host.set_alignment(1.0, 0.5)
t.attach(self.l_host, 0, 1, 5, 6, xpadding=3)
self.e_host = gtk.Entry()
self.e_host.set_width_chars(15)
self.e_host.set_text("localhost")
t.attach(self.e_host, 1, 3, 5, 6, xpadding=3)
parent.show_all()
self.show_all()
# hide username/password fields as not used by sqlite
self.l_username.hide()
self.e_username.hide()
self.l_password.hide()
self.e_password.hide()
def run(self):
response = super(AddDB,self).run()
log.debug("adddb.run: response is "+str(response)+" accept is "+str(int(gtk.RESPONSE_ACCEPT)))
ok,retry = False,True
while response == gtk.RESPONSE_ACCEPT:
ok,retry = self.check_fields()
if retry:
response = super(AddDB,self).run()
else:
response = gtk.RESPONSE_REJECT
(status, err_msg, icon, dbms, dbms_num
,name, db_desc, user, passwd, host) = ("error", "error", None, None, None
,None, None, None, None, None)
if ok:
log.debug("start creating new db")
# add a new db
master_password = None
dbms = self.dbnames[ self.cb_dbms.get_active_text() ]
dbms_num = self.config.get_backend(dbms)
name = self.e_db_name.get_text()
db_desc = self.e_db_desc.get_text()
user = self.e_username.get_text()
passwd = self.e_password.get_text()
host = self.e_host.get_text()
h = gtk.HBox(False, 2)
i = gtk.Image()
i.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG)
l = gtk.Label(str1)
h.pack_start(i, padding=5)
h.pack_start(l, padding=5)
vbox.pack_start(h)
# TODO:
# if self.cb_dbms.get_active_text() == 'Postgres':
# <ask for postgres master password>
# create_db() in Database.py or here? ... TODO
# test db after creating?
status, err_msg, icon = GuiDatabase.testDB(self.config, dbms, dbms_num, name, user, passwd, host)
log.debug('tested new db, result='+str((status,err_msg)))
if status == 'ok':
#dia = InfoBox( parent=self, str1=_('Database created') )
str1 = _('Database created')
else:
#dia = InfoBox( parent=self, str1=_('Database creation failed') )
str1 = _('Database creation failed')
#dia.add_msg("", True, True)
btns = (gtk.BUTTONS_OK)
dia = gtk.MessageDialog( parent=self, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, type=gtk.MESSAGE_INFO, buttons=(btns), message_format=str1 )
dia.run()
return( (status, err_msg, icon, dbms, dbms_num, name, db_desc, user, passwd, host) )
def check_fields(self):
"""check fields and return true/false according to whether user wants to try again
return False if fields are ok
"""
log.debug("check_fields: starting")
try_again = False
ok = True
# checks for all db's
if self.e_db_name.get_text() == "":
msg = _("No Database Name given")
ok = False
elif self.e_db_desc.get_text() is None or self.e_db_desc.get_text() == "":
msg = _("No Database Description given")
ok = False
elif self.cb_dbms.get_active_text() != 'Sqlite' and self.e_username.get_text() == "":
msg = _("No Username given")
ok = False
elif self.cb_dbms.get_active_text() != 'Sqlite' and self.e_password.get_text() == "":
msg = _("No Password given")
ok = False
elif self.e_host.get_text() == "":
msg = _("No Host given")
ok = False
if ok:
if self.cb_dbms.get_active_text() == 'Sqlite':
# checks for sqlite
pass
elif self.cb_dbms.get_active_text() == 'MySQL':
# checks for mysql
pass
elif self.cb_dbms.get_active_text() == 'Postgres':
# checks for postgres
pass
else:
msg = "Unknown Database Type selected"
ok = False
if not ok:
log.debug("check_fields: open dialog")
dia = gtk.MessageDialog( parent=self
, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, type=gtk.MESSAGE_ERROR
, message_format=msg
, buttons = gtk.BUTTONS_YES_NO
)
#l = gtk.Label(msg)
#dia.vbox.add(l)
l = gtk.Label( _("Do you want to try again?") )
dia.vbox.add(l)
dia.show_all()
ret = dia.run()
log.debug("check_fields: ret is "+str(ret)+" cancel is "+str(int(gtk.RESPONSE_CANCEL)))
if ret == gtk.RESPONSE_YES:
try_again = True
log.debug("check_fields: destroy dialog")
dia.hide()
dia.destroy()
log.debug("check_fields: returning ok as "+str(ok)+", try_again as "+str(try_again))
return(ok,try_again)
def db_type_changed(self, widget, data):
if self.cb_dbms.get_active_text() == 'Sqlite':
self.l_username.hide()
self.e_username.hide()
self.e_username.set_text("")
self.l_password.hide()
self.e_password.hide()
self.e_password.set_text("")
else:
# add extra label
vbox = dia.vbox
vbox.pack_start( gtk.Label(str1) )
dia.show_all()
self.l_username.show()
self.e_username.show()
self.l_password.show()
self.e_password.show()
return(response)
def db_name_changed(self, widget, event, data):
log.debug('db_name_changed: text='+widget.get_text())
if not re.match('\....$', widget.get_text()):
widget.set_text(widget.get_text()+'.db3')
widget.show()
#def response_cb(self, dialog, data):
# dialog.destroy()
# return(data)
class InfoBox(gtk.Dialog):
def __init__(self, parent, str1):
# create dialog and add icon and label
btns = (gtk.BUTTONS_OK)
btns = None
# messagedialog puts text in inverse colors if no buttons are displayed??
#dia = gtk.MessageDialog( parent=self.main_window, flags=gtk.DIALOG_DESTROY_WITH_PARENT
# , type=gtk.MESSAGE_INFO, buttons=(btns), message_format=str1 )
# so just use Dialog instead
super(InfoBox,self).__init__( parent=parent
, flags=gtk.DIALOG_DESTROY_WITH_PARENT
, title="" ) # , buttons=btns
h = gtk.HBox(False, 2)
i = gtk.Image()
i.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG)
l = gtk.Label(str1)
h.pack_start(i, padding=5)
h.pack_start(l, padding=5)
self.vbox.pack_start(h)
parent.show_all()
self.show_all()
def add_msg(self, str1, run, destroy):
# add extra label
self.vbox.pack_start( gtk.Label(str1) )
self.show_all()
response = None
if run: response = dia.run()
if destroy: dia.destroy()
return (dia, response)
if run: response = self.run()
if destroy: self.destroy()
return (response)
class SideButton(gtk.Button):
"""Create a button with the label below the icon"""
# to change label on buttons:
# ( see http://faq.pygtk.org/index.py?req=show&file=faq09.005.htp )
# gtk.stock_add([(gtk.STOCK_ADD, _("Add"), 0, 0, "")])
# alternatively:
# button = gtk.Button(stock=gtk.STOCK_CANCEL)
# button.show()
# alignment = button.get_children()[0]
# hbox = alignment.get_children()[0]
# image, label = hbox.get_children()
# label.set_text('Hide')
def __init__(self, label=None, stock=None, use_underline=True):
gtk.stock_add([(stock, label, 0, 0, "")])
super(SideButton, self).__init__(label=label, stock=stock, use_underline=True)
alignment = self.get_children()[0]
hbox = alignment.get_children()[0]
image, label = hbox.get_children()
#label.set_text('Hide')
hbox.remove(image)
hbox.remove(label)
v = gtk.VBox(False, spacing=3)
v.pack_start(image, 3)
v.pack_start(label, 3)
alignment.remove(hbox)
alignment.add(v)
self.show_all()
if __name__=="__main__":

View File

@ -62,6 +62,7 @@ class Hand(object):
def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"):
#log.debug( _("Hand.init(): handText is ") + str(handText) )
self.config = config
#log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log)
self.sitename = sitename
@ -314,7 +315,7 @@ If a player has None chips he won't be added."""
log.debug("markStreets:\n"+ str(self.streets))
else:
tmp = self.handText[0:100]
log.error(_("markstreets didn't match - Assuming hand cancelled"))
log.error(_("markstreets didn't match - Assuming hand %s was cancelled") % self.handid)
self.cancelled = True
raise FpdbParseError(_("FpdbParseError: markStreets appeared to fail: First 100 chars: '%s'") % tmp)

View File

@ -19,6 +19,13 @@
########################################################################
import sys
import exceptions
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("parser")
import Configuration
from HandHistoryConverter import *
from decimal import Decimal
@ -65,7 +72,6 @@ class OnGame(HandHistoryConverter):
# '5 Card Draw' : ('draw','fivedraw')
}
#self.rexx.setGameInfoRegex('.*Blinds \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)')
# Static regexes
# ***** End of hand R5-75443872-57 *****
re_SplitHands = re.compile(u'\*\*\*\*\*\sEnd\sof\shand\s[-A-Z\d]+.*\n(?=\*)')
@ -73,6 +79,18 @@ class OnGame(HandHistoryConverter):
# ***** History for hand R5-75443872-57 *****
# Start hand: Wed Aug 18 19:29:10 GMT+0100 2010
# Table: someplace [75443872] (LIMIT TEXAS_HOLDEM 0.50/1, Real money)
#***** History for hand R5-78042004-262 *****
#Start hand: Fri Aug 27 21:40:46 GMT+0100 2010
#Table: Bamako [78042004] (LIMIT TEXAS_HOLDEM $0.25/$0.50, Real money)
#User: sagi34
#{ u'BB': None
#, u'DATETIME': u'Fri Aug 27 22:38:26 GMT+0100 2010\\n'
#, u'GAME': None
#, u'HID': u'R5-78042004-346'
#, u'TABLE': u'Bamako'
#, u'LIMIT': None
#, u'SB': None
#}
re_HandInfo = re.compile(u"""
\*\*\*\*\*\sHistory\sfor\shand\s(?P<HID>[-A-Z\d]+).*
Start\shand:\s(?P<DATETIME>.*)
@ -80,8 +98,8 @@ class OnGame(HandHistoryConverter):
(
(?P<LIMIT>NO_LIMIT|Limit|LIMIT|Pot\sLimit)\s
(?P<GAME>TEXAS_HOLDEM|RAZZ)\s
(?P<SB>[.0-9]+)/
(?P<BB>[.0-9]+)
(%(LS)s)?(?P<SB>[.0-9]+)/
(%(LS)s)?(?P<BB>[.0-9]+)
)?
""" % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE)
@ -102,7 +120,9 @@ class OnGame(HandHistoryConverter):
# self.rexx.button_re = re.compile('#SUMMARY\nDealer: (?P<BUTTONPNAME>.*)\n')
#Seat 1: .Lucchess ($4.17 in chips)
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \((?P<CASH>[.0-9]+)\)')
#Seat 1: phantomaas ($27.11)
#Seat 5: mleo17 ($9.37)
re_PlayerInfo = re.compile(u'Seat (?P<SEAT>[0-9]+):\s(?P<PNAME>.*)\s\((%(LS)s)?(?P<CASH>[.0-9]+)\)' % substitutions)
def compilePlayerRegexs(self, hand):
players = set([player[1] for player in hand.players])
@ -117,23 +137,28 @@ class OnGame(HandHistoryConverter):
#helander2222 posts blind ($0.25), lopllopl posts blind ($0.50).
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]}
self.re_PostSB = re.compile('(?P<PNAME>.*) posts small blind \(\$?(?P<SB>[.0-9]+)\)')
self.re_PostBB = re.compile('\), (?P<PNAME>.*) posts big blind \(\$?(?P<BB>[.0-9]+)\)')
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P<ANTE>[.0-9]+)" % subst, re.MULTILINE)
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for %(CUR)s(?P<BRINGIN>[.0-9]+)" % subst, re.MULTILINE)
self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \(\$? (?P<SBBB>[.0-9]+)\)')
self.re_PostSB = re.compile('(?P<PNAME>.*) posts small blind \((%(CUR)s)?(?P<SB>[\.0-9]+)\)' % subst, re.MULTILINE)
self.re_PostBB = re.compile('\), (?P<PNAME>.*) posts big blind \((%(CUR)s)?(?P<BB>[\.0-9]+)\)' % subst, re.MULTILINE)
self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P<ANTE>[\.0-9]+)" % subst, re.MULTILINE)
self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P<BRINGIN>[\.0-9]+)" % subst, re.MULTILINE)
self.re_PostBoth = re.compile('.*\n(?P<PNAME>.*): posts small \& big blinds \( (%(CUR)s)?(?P<SBBB>[\.0-9]+)\)' % subst)
self.re_HeroCards = re.compile('Dealing\sto\s%(PLYR)s:\s\[(?P<CARDS>.*)\]' % subst)
#lopllopl checks, Eurolll checks, .Lucchess checks.
self.re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( (?P<BET>\d*\.?\d*))?( and is all-in)?')
#chumley. calls $0.25
self.re_Action = re.compile('(, )?(?P<PNAME>.*?)(?P<ATYPE> bets| checks| raises| calls| folds)( (%(CUR)s)?(?P<BET>[\d\.]+))?( and is all-in)?' % subst)
#self.re_Board = re.compile(r"\[board cards (?P<CARDS>.+) \]")
#Uchilka shows [ KC,JD ]
self.re_ShowdownAction = re.compile('(?P<PNAME>.*) shows \[ (?P<CARDS>.+) \]')
# TODO: read SUMMARY correctly for collected pot stuff.
# Main pot: 6.75 won by player3 (6.45)
self.re_CollectPot = re.compile('Main pot: (?P<POT>\d*\.?\d*) won by %(PLYR)s' % subst)
#Main pot: $3.57 won by mleo17 ($3.40)
#Side pot 1: $3.26 won by maac_5 ($3.10)
#Main pot: $2.87 won by maac_5 ($1.37), sagi34 ($1.36)
self.re_Pot = re.compile('(Main|Side)\spot(\s\d+)?:\s.*won\sby\s(?P<POT>.*$)', re.MULTILINE)
self.re_CollectPot = re.compile('\s*(?P<PNAME>.*)\s\((%(CUR)s)?(?P<POT>[\.\d]+)\)' % subst)
#Seat 5: mleo17 ($3.40), net: +$2.57, [Jd, Qd] (TWO_PAIR QUEEN, JACK)
self.re_ShownCards = re.compile("^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(.*\), net:.* \[(?P<CARDS>.*)\].*" % subst, re.MULTILINE)
self.re_sitsOut = re.compile('(?P<PNAME>.*) sits out')
def readSupportedGames(self):
@ -160,7 +185,13 @@ class OnGame(HandHistoryConverter):
info['currency'] = 'USD'
if 'LIMIT' in mg:
info['limitType'] = self.limits[mg['LIMIT']]
if mg['LIMIT'] in self.limits:
info['limitType'] = self.limits[mg['LIMIT']]
else:
tmp = handText[0:100]
log.error(_("determineGameType: limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
log.error(_("determineGameType: Raising FpdbParseError"))
raise FpdbParseError(_("limit not found in self.limits(%s). hand: '%s'") % (str(mg),tmp))
if 'GAME' in mg:
(info['base'], info['category']) = self.games[mg['GAME']]
if 'SB' in mg:
@ -168,6 +199,7 @@ class OnGame(HandHistoryConverter):
if 'BB' in mg:
info['bb'] = mg['BB']
#log.debug("determinegametype: returning "+str(info))
return info
def readHandInfo(self, hand):
@ -177,7 +209,7 @@ class OnGame(HandHistoryConverter):
if m:
info.update(m.groupdict())
log.debug("readHandInfo: %s" % info)
#log.debug("readHandInfo: %s" % info)
for key in info:
if key == 'DATETIME':
#'Wed Aug 18 19:45:30 GMT+0100 2010
@ -203,6 +235,7 @@ class OnGame(HandHistoryConverter):
hand.mixed = None
def readPlayerStacks(self, hand):
#log.debug("readplayerstacks: re is '%s'" % self.re_PlayerInfo)
m = self.re_PlayerInfo.finditer(hand.handText)
for a in m:
hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), a.group('CASH'))
@ -247,15 +280,13 @@ class OnGame(HandHistoryConverter):
hand.setCommunityCards(street, m.group('CARDS').split(', '))
def readBlinds(self, hand):
log.debug( _("readBlinds starting") )
#log.debug( _("readBlinds starting, hand=") + "\n["+hand.handText+"]" )
try:
m = self.re_PostSB.search(hand.handText)
if m is None:
log.debug( _("re_postSB failed, hand=") + hand.handText )
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except: # no small blind
log.debug( _("readBlinds in noSB exception")+str(sys.exc_info()) )
hand.addBlind(None, None, None)
except exceptions.AttributeError: # no small blind
log.debug( _("readBlinds in noSB exception - no SB created")+str(sys.exc_info()) )
#hand.addBlind(None, None, None)
for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.handText):
@ -289,7 +320,7 @@ class OnGame(HandHistoryConverter):
m = self.re_Action.finditer(hand.streets[street])
for action in m:
acts = action.groupdict()
#print "DEBUG: acts: %s" %acts
#log.debug("readaction: acts: %s" %acts)
if action.group('ATYPE') == ' raises':
hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') )
elif action.group('ATYPE') == ' calls':
@ -314,18 +345,22 @@ class OnGame(HandHistoryConverter):
hand.addShownCards(cards, shows.group('PNAME'))
def readCollectPot(self,hand):
for m in self.re_CollectPot.finditer(hand.handText):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
for m in self.re_Pot.finditer(hand.handText):
for splitpot in m.group('POT').split(','):
for m in self.re_CollectPot.finditer(splitpot):
hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT'))
def readShownCards(self,hand):
return
#for m in self.rexx.collect_pot_re.finditer(hand.string):
#if m.group('CARDS') is not None:
#cards = m.group('CARDS')
#cards = set(cards.split(','))
#hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards)
for m in self.re_ShownCards.finditer(hand.handText):
cards = m.group('CARDS')
cards = cards.split(', ') # needs to be a list, not a set--stud needs the order
(shown, mucked) = (False, False)
if m.group('CARDS') is not None:
shown = True
hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked)
if __name__ == "__main__":

View File

@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.20.905 plus git\n"
"POT-Creation-Date: 2010-08-26 18:52+CEST\n"
"PO-Revision-Date: 2010-08-26 01:40+0200\n"
"PO-Revision-Date: 2010-08-28 12:32+0200\n"
"Last-Translator: Ferenc Erki <erkiferenc@gmail.com>\n"
"Language-Team: Hungarian <erkiferenc@gmail.com>\n"
"Language: hu\n"
@ -156,7 +156,7 @@ msgstr "A %s konfigurációs fájl nem található. Alapértelmezések használa
#: Configuration.py:690
msgid "Reading configuration file %s"
msgstr "%s konfigurációs fájl használata"
msgstr "%s konfigurációs fájl olvasása"
#: Configuration.py:691
msgid ""
@ -164,11 +164,11 @@ msgid ""
"Reading configuration file %s\n"
msgstr ""
"\n"
"%s konfigurációs fájl használata\n"
"%s konfigurációs fájl olvasása\n"
#: Configuration.py:696
msgid "Error parsing %s. See error log file."
msgstr "Hiba a(z) %s olvasása közben. Nézz bele a naplófájlba."
msgstr "Hiba a(z) %s értelmezése közben. Nézz bele a hibanaplóba."
#: Database.py:74
msgid "Not using sqlalchemy connection pool."
@ -232,11 +232,11 @@ msgstr "ERROR: a(z) %s lekérdezés eredményének nem a player_id az első oszl
#: Database.py:907
msgid "getLastInsertId(): problem fetching insert_id? ret=%d"
msgstr "getLastInsertId(): probléma insert_id lekérdezése közben? ret=%d"
msgstr "getLastInsertId(): probléma az insert_id lekérdezése közben? ret=%d"
#: Database.py:919
msgid "getLastInsertId(%s): problem fetching lastval? row=%d"
msgstr "getLastInsertId(%s): probléma lastval lekérdezése közben? sor=%d"
msgstr "getLastInsertId(%s): probléma a lastval lekérdezése közben? sor=%d"
#: Database.py:926
msgid "getLastInsertId(): unknown backend: %d"
@ -398,7 +398,7 @@ msgstr "Hiba analyze közben:"
#: Database.py:1563
msgid "Analyze took %.1f seconds"
msgstr "Analyze %1.f másodpercig tartott"
msgstr "Analyze %.1f másodpercig tartott"
#: Database.py:1573 Database.py:1579
msgid "Error during vacuum:"
@ -854,8 +854,8 @@ msgid ""
"GuiBulkImport done: Stored: %d \tDuplicates: %d \tPartial: %d \tErrors: %d "
"in %s seconds - %.0f/sec"
msgstr ""
"GuiBulkImport kész: Tárolt: %d \tDuplikáció: %d \tRészleges: %d \tHibák: %d "
"%s másodperc alatt - %.0f/mp"
"GuiBulkImport kész: Tárolt: %d \tDuplikáció: %d \tRészleges: %d \tHibák: %d %"
"s másodperc alatt - %.0f/mp"
#: GuiDatabase.py:106 GuiLogView.py:96
msgid "Refresh"
@ -1242,7 +1242,7 @@ msgstr "A naplófájl "
#: HUD_main.pyw:90
msgid "HUD_main starting: using db name = %s"
msgstr "HUD_main indítás: "
msgstr "HUD_main indítás: %s adatbázis használata"
#: HUD_main.pyw:95
msgid "Note: error output is being diverted to:\n"
@ -1306,15 +1306,15 @@ msgstr "\"%s\" nevű asztal már nem létezik\n"
#: HUD_main.pyw:321
msgid ""
"HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,"
"%4.3f,%4.3f)"
"HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%"
"4.3f,%4.3f)"
msgstr ""
"HUD_main.read_stdin: leosztás beolvasva %4.3f mp alatt (%4.3f,%4.3f,%4.3f,"
"%4.3f,%4.3f,%4.3f)"
"HUD_main.read_stdin: leosztás beolvasva %4.3f mp alatt (%4.3f,%4.3f,%4.3f,%"
"4.3f,%4.3f,%4.3f)"
#: HUD_run_me.py:45
msgid "HUD_main starting\n"
msgstr "HUD_main indítása\n"
msgstr "HUD_main indítás\n"
#: HUD_run_me.py:51 TournamentTracker.py:317
msgid "Using db name = %s\n"
@ -1772,7 +1772,7 @@ msgstr "utcTime:"
#: HandHistoryConverter.py:685
msgid "Unable to create output directory %s for HHC!"
msgstr "A %s kimeneti könyvtár nem hozható létre a feldolgozó számára'"
msgstr "A %s kimeneti könyvtár nem hozható létre a feldolgozó számára!"
#: HandHistoryConverter.py:686
msgid "*** ERROR: UNABLE TO CREATE OUTPUT DIRECTORY"
@ -3136,8 +3136,8 @@ msgstr ""
"GPL2 vagy újabb licensszel.\n"
"A Windows telepítő csomag tartalmaz MIT licensz hatálya alá eső részeket "
"is.\n"
"A licenszek szövegét megtalálod az fpdb főkönyvtárában az agpl-3.0.txt, "
"gpl-2.0.txt, gpl-3.0.txt és mit.txt fájlokban."
"A licenszek szövegét megtalálod az fpdb főkönyvtárában az agpl-3.0.txt, gpl-"
"2.0.txt, gpl-3.0.txt és mit.txt fájlokban."
#: fpdb.pyw:1078
msgid "Help"
@ -3265,7 +3265,7 @@ msgid ""
"Error No.%s please send the hand causing this to fpdb-main@lists.sourceforge."
"net so we can fix the problem."
msgstr ""
"%s számú hiba. Kérlek küldd el az ezt okozo leosztást az fpdb-main@lists."
"%s számú hiba. Kérlek küldd el az ezt okozó leosztást az fpdb-main@lists."
"sourceforge.net címre, hogy ki tudjuk javítani a hibát."
#: fpdb_import.py:520