Merge branch 'master' of git://git.assembla.com/fpdb-sql.git
This commit is contained in:
commit
e221c9c0f6
|
@ -17,7 +17,8 @@
|
|||
#agpl-3.0.txt in the docs folder of the package.
|
||||
|
||||
|
||||
import mmap
|
||||
import os
|
||||
import Queue
|
||||
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
|
@ -29,18 +30,27 @@ import Configuration
|
|||
|
||||
log = Configuration.get_logger("logging.conf", "logview")
|
||||
|
||||
MAX_LINES = 100000
|
||||
MAX_LINES = 100000 # max lines to display in window
|
||||
EST_CHARS_PER_LINE = 150 # used to guesstimate number of lines in log file
|
||||
logfile = 'logging.out' # name of logfile
|
||||
|
||||
class GuiLogView:
|
||||
|
||||
def __init__(self, config, mainwin, vbox):
|
||||
def __init__(self, config, mainwin, closeq):
|
||||
self.config = config
|
||||
self.main_window = mainwin
|
||||
self.vbox = vbox
|
||||
self.closeq = closeq
|
||||
|
||||
self.dia = gtk.Dialog(title="Log Messages"
|
||||
,parent=None
|
||||
,flags=gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
,buttons=(gtk.STOCK_CLOSE,gtk.RESPONSE_OK))
|
||||
self.dia.set_modal(False)
|
||||
|
||||
self.vbox = self.dia.vbox
|
||||
gtk.Widget.set_size_request(self.vbox, 700, 400);
|
||||
|
||||
self.liststore = gtk.ListStore(str, str, str, str, gobject.TYPE_BOOLEAN) # date, module, level, text
|
||||
|
||||
# this is how to add a filter:
|
||||
#
|
||||
# # Creation of the filter, from the model
|
||||
|
@ -49,7 +59,6 @@ class GuiLogView:
|
|||
#
|
||||
# # The TreeView gets the filter as model
|
||||
# self.listview = gtk.TreeView(filter)
|
||||
|
||||
self.listview = gtk.TreeView(model=self.liststore)
|
||||
self.listview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_NONE)
|
||||
self.listcols = []
|
||||
|
@ -67,6 +76,7 @@ class GuiLogView:
|
|||
self.listview.show()
|
||||
scrolledwindow.show()
|
||||
self.vbox.show()
|
||||
self.dia.set_focus(self.listview)
|
||||
|
||||
col = self.addColumn("Date/Time", 0)
|
||||
col = self.addColumn("Module", 1)
|
||||
|
@ -75,6 +85,17 @@ class GuiLogView:
|
|||
|
||||
self.loadLog()
|
||||
self.vbox.show_all()
|
||||
self.dia.show()
|
||||
|
||||
self.dia.connect('response', self.dialog_response_cb)
|
||||
|
||||
def dialog_response_cb(self, dialog, response_id):
|
||||
# this is called whether close button is pressed or window is closed
|
||||
self.closeq.put(self.__class__)
|
||||
dialog.destroy()
|
||||
|
||||
def get_dialog(self):
|
||||
return self.dia
|
||||
|
||||
def addColumn(self, title, n):
|
||||
col = gtk.TreeViewColumn(title)
|
||||
|
@ -92,39 +113,28 @@ class GuiLogView:
|
|||
|
||||
def loadLog(self):
|
||||
|
||||
#self.configStore = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
#self.configView = gtk.TreeView(self.configStore)
|
||||
#self.configView.set_enable_tree_lines(True)
|
||||
self.liststore.clear()
|
||||
self.listcols = []
|
||||
|
||||
# count number of lines in file
|
||||
f = open('logging.out', "r+")
|
||||
buf = mmap.mmap(f.fileno(), 0)
|
||||
readline = buf.readline
|
||||
lines = 0
|
||||
while readline():
|
||||
lines += 1
|
||||
f.close()
|
||||
# guesstimate number of lines in file
|
||||
if os.path.exists(logfile):
|
||||
stat_info = os.stat(logfile)
|
||||
lines = stat_info.st_size / EST_CHARS_PER_LINE
|
||||
print "logview: size =", stat_info.st_size, "lines =", lines
|
||||
|
||||
# set startline to line number to start display from
|
||||
startline = 0
|
||||
if lines > MAX_LINES:
|
||||
# only display from startline if log file is large
|
||||
startline = lines - MAX_LINES
|
||||
|
||||
f = open('logging.out', "r+")
|
||||
buf = mmap.mmap(f.fileno(), 0)
|
||||
readline = buf.readline
|
||||
l = 0
|
||||
line = readline()
|
||||
while line:
|
||||
for line in open(logfile):
|
||||
# eg line:
|
||||
# 2009-12-02 15:23:21,716 - config DEBUG config logger initialised
|
||||
l = l + 1
|
||||
if l > startline and len(line) > 49:
|
||||
iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) )
|
||||
line = readline()
|
||||
f.close()
|
||||
|
||||
def sortCols(self, col, n):
|
||||
try:
|
||||
|
|
129
pyfpdb/fpdb.py
129
pyfpdb/fpdb.py
|
@ -18,6 +18,7 @@
|
|||
import os
|
||||
import sys
|
||||
import re
|
||||
import Queue
|
||||
|
||||
# if path is set to use an old version of python look for a new one:
|
||||
# (does this work in linux?)
|
||||
|
@ -73,6 +74,7 @@ try:
|
|||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import pango
|
||||
except:
|
||||
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.")
|
||||
|
@ -80,6 +82,24 @@ except:
|
|||
|
||||
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 GuiLogView
|
||||
|
@ -112,12 +132,12 @@ class fpdb:
|
|||
|
||||
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"""
|
||||
for name in self.nb_tabs: #todo: check this is valid
|
||||
for name in self.nb_tab_names: #todo: check this is valid
|
||||
if name == new_tab_name:
|
||||
return # if tab already exists, just go to it
|
||||
|
||||
used_before = False
|
||||
for i, name in enumerate(self.tab_names): #todo: check this is valid
|
||||
for i, name in enumerate(self.tab_names):
|
||||
if name == new_tab_name:
|
||||
used_before = True
|
||||
event_box = self.tabs[i]
|
||||
|
@ -133,13 +153,13 @@ class fpdb:
|
|||
|
||||
#self.nb.append_page(new_page, gtk.Label(new_tab_name))
|
||||
self.nb.append_page(page, event_box)
|
||||
self.nb_tabs.append(new_tab_name)
|
||||
self.nb_tab_names.append(new_tab_name)
|
||||
page.show()
|
||||
|
||||
def display_tab(self, new_tab_name):
|
||||
"""displays the indicated tab"""
|
||||
tab_no = -1
|
||||
for i, name in enumerate(self.nb_tabs):
|
||||
for i, name in enumerate(self.nb_tab_names):
|
||||
if new_tab_name == name:
|
||||
tab_no = i
|
||||
break
|
||||
|
@ -190,13 +210,13 @@ class fpdb:
|
|||
(nb, text) = data
|
||||
page = -1
|
||||
#print "\n remove_tab: start", text
|
||||
for i, tab in enumerate(self.nb_tabs):
|
||||
for i, tab in enumerate(self.nb_tab_names):
|
||||
if text == tab:
|
||||
page = i
|
||||
#print " page =", page
|
||||
if page >= 0 and page < self.nb.get_n_pages():
|
||||
#print " removing page", page
|
||||
del self.nb_tabs[page]
|
||||
del self.nb_tab_names[page]
|
||||
nb.remove_page(page)
|
||||
# Need to refresh the widget --
|
||||
# This forces the widget to redraw itself.
|
||||
|
@ -219,8 +239,39 @@ class fpdb:
|
|||
dia.set_website("http://fpdb.sourceforge.net/")
|
||||
dia.set_authors("Steffen, Eratosthenes, s0rrow, EricBlade, _mt, sqlcoder, Bostik, and others")
|
||||
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.destroy()
|
||||
log.debug("Threads: ")
|
||||
for t in self.threads:
|
||||
log.debug("........." + str(t.__class__))
|
||||
|
||||
def dia_preferences(self, widget, data=None):
|
||||
dia = gtk.Dialog("Preferences",
|
||||
|
@ -429,28 +480,52 @@ class fpdb:
|
|||
self.release_global_lock()
|
||||
|
||||
def dia_logs(self, widget, data=None):
|
||||
lock_set = False
|
||||
if self.obtain_global_lock():
|
||||
lock_set = True
|
||||
"""opens the log viewer window"""
|
||||
|
||||
dia = gtk.Dialog(title="Log Messages"
|
||||
,parent=None
|
||||
,flags=0
|
||||
,buttons=(gtk.STOCK_CLOSE,gtk.RESPONSE_OK))
|
||||
logviewer = GuiLogView.GuiLogView(self.config, self.window, dia.vbox)
|
||||
response = dia.run()
|
||||
if response == gtk.RESPONSE_ACCEPT:
|
||||
pass
|
||||
dia.destroy()
|
||||
#lock_set = False
|
||||
#if self.obtain_global_lock():
|
||||
# lock_set = True
|
||||
|
||||
if lock_set:
|
||||
self.release_global_lock()
|
||||
# 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):
|
||||
self.dia_confirm.set_modal(False)
|
||||
d = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
|
@ -632,9 +707,11 @@ class fpdb:
|
|||
try:
|
||||
self.db = Database.Database(self.config, sql = self.sql)
|
||||
except Exceptions.FpdbMySQLAccessDenied:
|
||||
#self.db = None
|
||||
self.warning_box("MySQL Server reports: Access denied. Are your permissions set correctly?")
|
||||
exit()
|
||||
except Exceptions.FpdbMySQLNoDatabase:
|
||||
#self.db = None
|
||||
msg = "MySQL client reports: 2002 or 2003 error. Unable to connect - Please check that the MySQL service has been started"
|
||||
self.warning_box(msg)
|
||||
exit
|
||||
|
@ -769,7 +846,6 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
self.add_and_display_tab(gv_tab, "Graphs")
|
||||
|
||||
def __init__(self):
|
||||
self.threads = []
|
||||
# no more than 1 process can this lock at a time:
|
||||
self.lock = interlocks.InterProcessLock(name="fpdb_global_lock")
|
||||
self.db = None
|
||||
|
@ -793,14 +869,17 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
|
|||
menubar.show()
|
||||
#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.set_show_tabs(True)
|
||||
self.nb.show()
|
||||
self.main_vbox.pack_start(self.nb, True, True, 0)
|
||||
self.pages=[]
|
||||
self.tabs=[]
|
||||
self.tab_names=[]
|
||||
self.nb_tabs=[]
|
||||
self.tabs=[] # the event_boxes forming the actual tabs
|
||||
self.tab_names=[] # names of tabs used since program started, not removed if tab is closed
|
||||
self.pages=[] # the contents of the page, not removed if tab is closed
|
||||
self.nb_tab_names=[] # list of tab names currently displayed in notebook
|
||||
|
||||
self.tab_main_help(None, None)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user