import latest

This commit is contained in:
Gerko de Roo 2009-12-23 20:40:29 +01:00
commit bb650e81a9
5 changed files with 810 additions and 926 deletions

164
pyfpdb/fpdb.py Executable file → Normal file
View File

@ -18,7 +18,6 @@
import os import os
import sys import sys
import re import re
import Queue
# if path is set to use an old version of python look for a new one: # if path is set to use an old version of python look for a new one:
# (does this work in linux?) # (does this work in linux?)
@ -67,14 +66,12 @@ if not options.errorsToConsole:
errorFile = open('fpdb-error-log.txt', 'w', 0) errorFile = open('fpdb-error-log.txt', 'w', 0)
sys.stderr = errorFile sys.stderr = errorFile
#import logging import logging
import logging, logging.config
try: try:
import pygtk import pygtk
pygtk.require('2.0') pygtk.require('2.0')
import gtk import gtk
import pango
except: except:
print "Unable to load PYGTK modules required for GUI. Please install PyCairo, PyGObject, and PyGTK from www.pygtk.org." print "Unable to load PYGTK modules required for GUI. Please install PyCairo, PyGObject, and PyGTK from www.pygtk.org."
raw_input("Press ENTER to continue.") raw_input("Press ENTER to continue.")
@ -82,27 +79,8 @@ except:
import interlocks import interlocks
# these imports not required in this module, imported here to report version in About dialog
try:
import matplotlib
matplotlib_version = matplotlib.__version__
except:
matplotlib_version = 'not found'
try:
import numpy
numpy_version = numpy.__version__
except:
numpy_version = 'not found'
try:
import sqlite3
sqlite3_version = sqlite3.version
sqlite_version = sqlite3.sqlite_version
except:
sqlite3_version = 'not found'
sqlite_version = 'not found'
import GuiPrefs import GuiPrefs
import GuiLogView
import GuiBulkImport import GuiBulkImport
import GuiPlayerStats import GuiPlayerStats
import GuiPositionalStats import GuiPositionalStats
@ -118,8 +96,6 @@ import Exceptions
VERSION = "0.12" VERSION = "0.12"
log = Configuration.get_logger("logging.conf", "fpdb")
class fpdb: class fpdb:
def tab_clicked(self, widget, tab_name): def tab_clicked(self, widget, tab_name):
"""called when a tab button is clicked to activate that tab""" """called when a tab button is clicked to activate that tab"""
@ -132,12 +108,12 @@ class fpdb:
def add_tab(self, new_page, new_tab_name): def add_tab(self, new_page, new_tab_name):
"""adds a tab, namely creates the button and displays it and appends all the relevant arrays""" """adds a tab, namely creates the button and displays it and appends all the relevant arrays"""
for name in self.nb_tab_names: #todo: check this is valid for name in self.nb_tabs: #todo: check this is valid
if name == new_tab_name: if name == new_tab_name:
return # if tab already exists, just go to it return # if tab already exists, just go to it
used_before = False used_before = False
for i, name in enumerate(self.tab_names): for i, name in enumerate(self.tab_names): #todo: check this is valid
if name == new_tab_name: if name == new_tab_name:
used_before = True used_before = True
event_box = self.tabs[i] event_box = self.tabs[i]
@ -153,13 +129,13 @@ class fpdb:
#self.nb.append_page(new_page, gtk.Label(new_tab_name)) #self.nb.append_page(new_page, gtk.Label(new_tab_name))
self.nb.append_page(page, event_box) self.nb.append_page(page, event_box)
self.nb_tab_names.append(new_tab_name) self.nb_tabs.append(new_tab_name)
page.show() page.show()
def display_tab(self, new_tab_name): def display_tab(self, new_tab_name):
"""displays the indicated tab""" """displays the indicated tab"""
tab_no = -1 tab_no = -1
for i, name in enumerate(self.nb_tab_names): for i, name in enumerate(self.nb_tabs):
if new_tab_name == name: if new_tab_name == name:
tab_no = i tab_no = i
break break
@ -210,13 +186,13 @@ class fpdb:
(nb, text) = data (nb, text) = data
page = -1 page = -1
#print "\n remove_tab: start", text #print "\n remove_tab: start", text
for i, tab in enumerate(self.nb_tab_names): for i, tab in enumerate(self.nb_tabs):
if text == tab: if text == tab:
page = i page = i
#print " page =", page #print " page =", page
if page >= 0 and page < self.nb.get_n_pages(): if page >= 0 and page < self.nb.get_n_pages():
#print " removing page", page #print " removing page", page
del self.nb_tab_names[page] del self.nb_tabs[page]
nb.remove_page(page) nb.remove_page(page)
# Need to refresh the widget -- # Need to refresh the widget --
# This forces the widget to redraw itself. # This forces the widget to redraw itself.
@ -237,42 +213,10 @@ class fpdb:
dia.set_comments("GTK AboutDialog comments here") dia.set_comments("GTK AboutDialog comments here")
dia.set_license("GPL v3") dia.set_license("GPL v3")
dia.set_website("http://fpdb.sourceforge.net/") dia.set_website("http://fpdb.sourceforge.net/")
dia.set_authors(['Steffen', 'Eratosthenes', 's0rrow', dia.set_authors("Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, Bostik, and others")
'EricBlade', '_mt', 'sqlcoder', 'Bostik', 'and others'])
dia.set_program_name("Free Poker Database (FPDB)") dia.set_program_name("Free Poker Database (FPDB)")
db_version = ""
#if self.db is not None:
# db_version = self.db.get_version()
nums = [ ('Operating System', os.name)
, ('Python', sys.version[0:3])
, ('GTK+', '.'.join([str(x) for x in gtk.gtk_version]))
, ('PyGTK', '.'.join([str(x) for x in gtk.pygtk_version]))
, ('matplotlib', matplotlib_version)
, ('numpy', numpy_version)
, ('sqlite3', sqlite3_version)
, ('sqlite', sqlite_version)
, ('database', self.settings['db-server'] + db_version)
]
versions = gtk.TextBuffer()
w = 20 # width used for module names and version numbers
versions.set_text( '\n'.join( [x[0].rjust(w)+' '+ x[1].ljust(w) for x in nums] ) )
view = gtk.TextView(versions)
view.set_editable(False)
view.set_justification(gtk.JUSTIFY_CENTER)
view.modify_font(pango.FontDescription('monospace 10'))
view.show()
dia.vbox.pack_end(view, True, True, 2)
l = gtk.Label('Version Information:')
l.set_alignment(0.5, 0.5)
l.show()
dia.vbox.pack_end(l, True, True, 2)
dia.run() dia.run()
dia.destroy() dia.destroy()
log.debug("Threads: ")
for t in self.threads:
log.debug("........." + str(t.__class__))
def dia_preferences(self, widget, data=None): def dia_preferences(self, widget, data=None):
dia = gtk.Dialog("Preferences", dia = gtk.Dialog("Preferences",
@ -488,53 +432,6 @@ class fpdb:
self.release_global_lock() self.release_global_lock()
def dia_logs(self, widget, data=None):
"""opens the log viewer window"""
#lock_set = False
#if self.obtain_global_lock():
# lock_set = True
# remove members from self.threads if close messages received
self.process_close_messages()
viewer = None
for i, t in enumerate(self.threads):
if str(t.__class__) == 'GuiLogView.GuiLogView':
viewer = t
break
if viewer is None:
#print "creating new log viewer"
new_thread = GuiLogView.GuiLogView(self.config, self.window, self.closeq)
self.threads.append(new_thread)
else:
#print "showing existing log viewer"
viewer.get_dialog().present()
#if lock_set:
# self.release_global_lock()
def addLogText(self, text):
end_iter = self.logbuffer.get_end_iter()
self.logbuffer.insert(end_iter, text)
self.logview.scroll_to_mark(self.logbuffer.get_insert(), 0)
def process_close_messages(self):
# check for close messages
try:
while True:
name = self.closeq.get(False)
for i, t in enumerate(self.threads):
if str(t.__class__) == str(name):
# thread has ended so remove from list:
del self.threads[i]
break
except Queue.Empty:
# no close messages on queue, do nothing
pass
def __calendar_dialog(self, widget, entry): def __calendar_dialog(self, widget, entry):
self.dia_confirm.set_modal(False) self.dia_confirm.set_modal(False)
d = gtk.Window(gtk.WINDOW_TOPLEVEL) d = gtk.Window(gtk.WINDOW_TOPLEVEL)
@ -637,7 +534,6 @@ class fpdb:
</menu> </menu>
<menu action="help"> <menu action="help">
<menuitem action="Abbrev"/> <menuitem action="Abbrev"/>
<menuitem action="Logs"/>
<separator/> <separator/>
<menuitem action="About"/> <menuitem action="About"/>
<menuitem action="License"/> <menuitem action="License"/>
@ -679,7 +575,6 @@ class fpdb:
('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats), ('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats),
('help', None, '_Help'), ('help', None, '_Help'),
('Abbrev', None, '_Abbrevations (todo)', None, 'List of Abbrevations', self.tab_abbreviations), ('Abbrev', None, '_Abbrevations (todo)', None, 'List of Abbrevations', self.tab_abbreviations),
('Logs', None, '_Log Messages', None, 'Log and Debug Messages', self.dia_logs),
('About', None, 'A_bout', None, 'About the program', self.dia_about), ('About', None, 'A_bout', None, 'About the program', self.dia_about),
('License', None, '_License and Copying (todo)', None, 'License and Copying', self.dia_licensing), ('License', None, '_License and Copying (todo)', None, 'License and Copying', self.dia_licensing),
]) ])
@ -709,26 +604,19 @@ class fpdb:
self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_import_parameters())
self.settings.update(self.config.get_default_paths()) self.settings.update(self.config.get_default_paths())
if self.db is not None and self.db.connected: if self.db is not None and self.db.fdb is not None:
self.db.disconnect() self.db.disconnect()
self.sql = SQL.Sql(db_server = self.settings['db-server']) self.sql = SQL.Sql(db_server = self.settings['db-server'])
err_msg = None
try: try:
self.db = Database.Database(self.config, sql = self.sql) self.db = Database.Database(self.config, sql = self.sql)
except Exceptions.FpdbMySQLAccessDenied: except Exceptions.FpdbMySQLAccessDenied:
err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?" self.warning_box("MySQL Server reports: Access denied. Are your permissions set correctly?")
exit()
except Exceptions.FpdbMySQLNoDatabase: except Exceptions.FpdbMySQLNoDatabase:
err_msg = "MySQL client reports: 2002 or 2003 error. Unable to connect - " \ msg = "MySQL client reports: 2002 error. Unable to connect - Please check that the MySQL service has been started"
+ "Please check that the MySQL service has been started" self.warning_box(msg)
except Exceptions.FpdbPostgresqlAccessDenied: exit
err_msg = "Postgres Server reports: Access denied. Are your permissions set correctly?"
except Exceptions.FpdbPostgresqlNoDatabase:
err_msg = "Postgres client reports: Unable to connect - " \
+ "Please check that the Postgres service has been started"
if err_msg is not None:
self.db = None
self.warning_box(err_msg)
# except FpdbMySQLFailedError: # except FpdbMySQLFailedError:
# self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR") # self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR")
@ -746,7 +634,7 @@ class fpdb:
# print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) # print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])
# sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])) # sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user']))
if self.db is not None and self.db.wrongDbVersion: if self.db.wrongDbVersion:
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))
label = gtk.Label("An invalid DB version or missing tables have been detected.") label = gtk.Label("An invalid DB version or missing tables have been detected.")
@ -765,14 +653,13 @@ class fpdb:
diaDbVersionWarning.destroy() diaDbVersionWarning.destroy()
if self.status_bar is None: if self.status_bar is None:
self.status_bar = gtk.Label("") self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host))
self.main_vbox.pack_end(self.status_bar, False, True, 0) self.main_vbox.pack_end(self.status_bar, False, True, 0)
self.status_bar.show() self.status_bar.show()
else:
self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.database, self.db.host))
if self.db is not None and self.db.connected: # Database connected to successfully, load queries to pass on to other classes
self.status_bar.set_text("Status: Connected to %s database named %s on host %s"
% (self.db.get_backend_name(),self.db.database, self.db.host))
# rollback to make sure any locks are cleared:
self.db.rollback() self.db.rollback()
self.validate_config() self.validate_config()
@ -794,7 +681,6 @@ class fpdb:
# TODO: can we get some / all of the stuff done in this function to execute on any kind of abort? # TODO: can we get some / all of the stuff done in this function to execute on any kind of abort?
print "Quitting normally" print "Quitting normally"
# TODO: check if current settings differ from profile, if so offer to save or abort # TODO: check if current settings differ from profile, if so offer to save or abort
if self.db is not None and self.db.connected:
self.db.disconnect() self.db.disconnect()
self.statusIcon.set_visible(False) self.statusIcon.set_visible(False)
gtk.main_quit() gtk.main_quit()
@ -862,6 +748,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
self.add_and_display_tab(gv_tab, "Graphs") self.add_and_display_tab(gv_tab, "Graphs")
def __init__(self): def __init__(self):
self.threads = []
# no more than 1 process can this lock at a time: # no more than 1 process can this lock at a time:
self.lock = interlocks.InterProcessLock(name="fpdb_global_lock") self.lock = interlocks.InterProcessLock(name="fpdb_global_lock")
self.db = None self.db = None
@ -885,17 +772,14 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
menubar.show() menubar.show()
#done menubar #done menubar
self.threads = [] # objects used by tabs - no need for threads, gtk handles it
self.closeq = Queue.Queue(20) # used to signal ending of a thread (only logviewer for now)
self.nb = gtk.Notebook() self.nb = gtk.Notebook()
self.nb.set_show_tabs(True) self.nb.set_show_tabs(True)
self.nb.show() self.nb.show()
self.main_vbox.pack_start(self.nb, True, True, 0) self.main_vbox.pack_start(self.nb, True, True, 0)
self.tabs=[] # the event_boxes forming the actual tabs self.pages=[]
self.tab_names=[] # names of tabs used since program started, not removed if tab is closed self.tabs=[]
self.pages=[] # the contents of the page, not removed if tab is closed self.tab_names=[]
self.nb_tab_names=[] # list of tab names currently displayed in notebook self.nb_tabs=[]
self.tab_main_help(None, None) self.tab_main_help(None, None)