From f7ed06d071a86bd2e8a9e205ea5cb949bc5843d5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 30 Nov 2009 21:43:29 +0000 Subject: [PATCH 01/11] improve rebuild hudcache and indexes dialogs --- pyfpdb/Database.py | 17 ++++++++----- pyfpdb/fpdb.py | 63 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index cd6ad298..1c44bb61 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -58,7 +58,8 @@ class Database: PGSQL = 3 SQLITE = 4 - hero_hudstart_def = '1999-12-31' # default for length of Hero's stats in HUD + hero_hudstart_def = '1999-12-31' # default for length of Hero's stats in HUD + villain_hudstart_def = '1999-12-31' # default for length of Villain's stats in HUD # Data Structures for index and foreign key creation # drop_code is an int with possible values: 0 - don't drop for bulk import @@ -1324,7 +1325,7 @@ class Database: self.dropAllForeignKeys() self.createAllForeignKeys() - def rebuild_hudcache(self, start=None): + def rebuild_hudcache(self, h_start=None, v_start=None): """clears hudcache and rebuilds from the individual handsplayers records""" try: @@ -1344,13 +1345,17 @@ class Database: if p_id: self.hero_ids[site_id] = int(p_id) - if start is None: - start = self.hero_hudstart_def + if h_start is None: + h_start = self.hero_hudstart_def + if v_start is None: + v_start = self.villain_hudstart_def if self.hero_ids == {}: where = "" else: - where = "where hp.playerId not in " + str(tuple(self.hero_ids.values())) \ - + " or h.handStart > '" + start + "'" + where = "where ( hp.playerId not in " + str(tuple(self.hero_ids.values())) \ + + " and h.handStart > '" + v_start + "')" \ + + " or ( hp.playerId in " + str(tuple(self.hero_ids.values())) \ + + " and h.handStart > '" + h_start + "')" rebuild_sql = self.sql.query['rebuildHudCache'].replace('', where) self.get_cursor().execute(self.sql.query['clearHudCache']) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index d5f4faec..faaf4fdc 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -334,27 +334,48 @@ class fpdb: diastring = "Please confirm that you want to re-create the HUD cache." self.dia_confirm.format_secondary_text(diastring) - hb = gtk.HBox(True, 1) + hb1 = gtk.HBox(True, 1) + self.h_start_date = gtk.Entry(max=12) + self.h_start_date.set_text( self.db.get_hero_hudcache_start() ) + lbl = gtk.Label(" Hero's cache starts: ") + btn = gtk.Button() + btn.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) + btn.connect('clicked', self.__calendar_dialog, self.h_start_date) + + hb1.pack_start(lbl, expand=True, padding=3) + hb1.pack_start(self.h_start_date, expand=True, padding=2) + hb1.pack_start(btn, expand=False, padding=3) + self.dia_confirm.vbox.add(hb1) + hb1.show_all() + + hb2 = gtk.HBox(True, 1) self.start_date = gtk.Entry(max=12) self.start_date.set_text( self.db.get_hero_hudcache_start() ) - lbl = gtk.Label(" Hero's cache starts: ") + lbl = gtk.Label(" Villains' cache starts: ") btn = gtk.Button() btn.set_image(gtk.image_new_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)) btn.connect('clicked', self.__calendar_dialog, self.start_date) - hb.pack_start(lbl, expand=True, padding=3) - hb.pack_start(self.start_date, expand=True, padding=2) - hb.pack_start(btn, expand=False, padding=3) - self.dia_confirm.vbox.add(hb) - hb.show_all() + hb2.pack_start(lbl, expand=True, padding=3) + hb2.pack_start(self.start_date, expand=True, padding=2) + hb2.pack_start(btn, expand=False, padding=3) + self.dia_confirm.vbox.add(hb2) + hb2.show_all() response = self.dia_confirm.run() - self.dia_confirm.destroy() if response == gtk.RESPONSE_YES: - self.db.rebuild_hudcache( self.start_date.get_text() ) + lbl = gtk.Label(" Rebuilding HUD Cache ... ") + self.dia_confirm.vbox.add(lbl) + lbl.show() + while gtk.events_pending(): + gtk.main_iteration_do(False) + + self.db.rebuild_hudcache( self.h_start_date.get_text(), self.start_date.get_text() ) elif response == gtk.RESPONSE_NO: print 'User cancelled rebuilding hud cache' + self.dia_confirm.destroy() + self.release_global_lock() def dia_rebuild_indexes(self, widget, data=None): @@ -368,14 +389,28 @@ class fpdb: self.dia_confirm.format_secondary_text(diastring) response = self.dia_confirm.run() - self.dia_confirm.destroy() if response == gtk.RESPONSE_YES: + lbl = gtk.Label(" Rebuilding Indexes ... ") + self.dia_confirm.vbox.add(lbl) + lbl.show() + while gtk.events_pending(): + gtk.main_iteration_do(False) self.db.rebuild_indexes() + + lbl.set_text(" Cleaning Database ... ") + while gtk.events_pending(): + gtk.main_iteration_do(False) self.db.vacuumDB() + + lbl.set_text(" Analyzing Database ... ") + while gtk.events_pending(): + gtk.main_iteration_do(False) self.db.analyzeDB() elif response == gtk.RESPONSE_NO: print 'User cancelled rebuilding db indexes' + self.dia_confirm.destroy() + self.release_global_lock() def __calendar_dialog(self, widget, entry): @@ -397,10 +432,13 @@ class fpdb: d.show_all() def __get_dates(self): - t1 = self.start_date.get_text() + t1 = self.h_start_date.get_text() if t1 == '': t1 = '1970-01-01' - return (t1) + t2 = self.start_date.get_text() + if t2 == '': + t2 = '1970-01-01' + return (t1, t2) def __get_date(self, widget, calendar, entry, win): # year and day are correct, month is 0..11 @@ -835,6 +873,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") gtk.main() return 0 + if __name__ == "__main__": me = fpdb() me.main() From 5e3c920e1628519001210a54ba62bad81103551c Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 2 Dec 2009 15:17:31 +0000 Subject: [PATCH 02/11] add timing info to log --- pyfpdb/HUD_main.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index dfe1c5fa..2bb3a995 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -63,6 +63,9 @@ elif os.name == 'nt': import Hud +log = Configuration.get_logger("logging.conf") + + class HUD_main(object): """A main() object to own both the read_stdin thread and the gui.""" # This class mainly provides state for controlling the multiple HUDs. @@ -192,6 +195,7 @@ class HUD_main(object): while 1: # wait for a new hand number on stdin new_hand_id = sys.stdin.readline() + t0 = time() new_hand_id = string.rstrip(new_hand_id) if new_hand_id == "": # blank line means quit self.destroy() @@ -206,6 +210,7 @@ class HUD_main(object): print "db error: skipping %s" % new_hand_id sys.stderr.write("Database error: could not find hand %s.\n" % new_hand_id) continue + t1 = time() if type == "tour": # hand is from a tournament temp_key = tour_number @@ -217,8 +222,10 @@ class HUD_main(object): # get stats using hud's specific params and get cards self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] , self.hud_dict[temp_key].hud_params['h_hud_days']) + t2 = time() stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params ,self.hero_ids[site_id], num_seats) + t3 = time() try: self.hud_dict[temp_key].stat_dict = stat_dict except KeyError: # HUD instance has been killed off, key is stale @@ -239,8 +246,10 @@ class HUD_main(object): else: # get stats using default params--also get cards self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) + t4 = time() stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params ,self.hero_ids[site_id], num_seats) + t5 = time() cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) if comm_cards != {}: # stud! @@ -264,6 +273,9 @@ class HUD_main(object): else: sys.stderr.write('Table "%s" no longer exists\n', table_name) + t6 = time() + log.info("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)" + % (t6-t0,t1-t0,t2-t0,t3-t0,t4-t0,t5-t0,t6-t0)) self.db_connection.connection.rollback() if __name__== "__main__": From cd65aae3743ec91f2e67818364cb8db879deff74 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 3 Dec 2009 20:20:42 +0000 Subject: [PATCH 03/11] allow legend box to work in python 2.5 --- pyfpdb/GuiGraphViewer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 76c80f2e..9daa940f 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -196,7 +196,10 @@ class GuiGraphViewer (threading.Thread): self.ax.plot(green, color='green', label='Hands: %d\nProfit: $%.2f' %(len(green), green[-1])) self.ax.plot(blue, color='blue', label='Showdown: $%.2f' %(blue[-1])) self.ax.plot(red, color='red', label='Non-showdown: $%.2f' %(red[-1])) - self.ax.legend(loc='best', fancybox=True, shadow=True, prop=FontProperties(size='smaller')) + if sys.version[0:3] == '2.5': + self.ax.legend(loc='best', shadow=True, prop=FontProperties(size='smaller')) + else: + self.ax.legend(loc='best', fancybox=True, shadow=True, prop=FontProperties(size='smaller')) self.graphBox.add(self.canvas) From c9b99273156346a72901448c47582c72bdd47600 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 3 Dec 2009 21:02:05 +0000 Subject: [PATCH 04/11] fix new timing code so it actually works\! --- pyfpdb/HUD_main.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index c3c66d70..c3599a3b 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -195,7 +195,8 @@ class HUD_main(object): while 1: # wait for a new hand number on stdin new_hand_id = sys.stdin.readline() - t0 = time() + t0 = time.time() + t1 = t2 = t3 = t4 = t5 = t6 = t0 new_hand_id = string.rstrip(new_hand_id) if new_hand_id == "": # blank line means quit self.destroy() @@ -210,7 +211,7 @@ class HUD_main(object): print "db error: skipping %s" % new_hand_id sys.stderr.write("Database error: could not find hand %s.\n" % new_hand_id) continue - t1 = time() + t1 = time.time() if type == "tour": # hand is from a tournament temp_key = tour_number @@ -222,10 +223,10 @@ class HUD_main(object): # get stats using hud's specific params and get cards self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] , self.hud_dict[temp_key].hud_params['h_hud_days']) - t2 = time() + t2 = time.time() stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params ,self.hero_ids[site_id], num_seats) - t3 = time() + t3 = time.time() try: self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] , self.hud_dict[temp_key].hud_params['h_hud_days']) @@ -249,10 +250,10 @@ class HUD_main(object): else: # get stats using default params--also get cards self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) - t4 = time() + t4 = time.time() stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params ,self.hero_ids[site_id], num_seats) - t5 = time() + t5 = time.time() cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) if comm_cards != {}: # stud! @@ -276,8 +277,8 @@ class HUD_main(object): else: sys.stderr.write('Table "%s" no longer exists\n' % table_name) - t6 = time() - log.info("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)" + t6 = time.time() + log.info("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)" % (t6-t0,t1-t0,t2-t0,t3-t0,t4-t0,t5-t0,t6-t0)) self.db_connection.connection.rollback() From 6826d0157a82cf7811396aac6b90d4a0626378c5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 5 Dec 2009 15:54:49 +0000 Subject: [PATCH 05/11] create gui option to view the log --- pyfpdb/GuiLogView.py | 129 +++++++++++++++++++++++++++++++++++++++++++ pyfpdb/fpdb.py | 31 ++++++++++- pyfpdb/logging.conf | 14 ++++- 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100755 pyfpdb/GuiLogView.py diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py new file mode 100755 index 00000000..77f09b06 --- /dev/null +++ b/pyfpdb/GuiLogView.py @@ -0,0 +1,129 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +#Copyright 2008 Carl Gherardi +#This program is free software: you can redistribute it and/or modify +#it under the terms of the GNU Affero General Public License as published by +#the Free Software Foundation, version 3 of the License. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + + +import xml.dom.minidom +from xml.dom.minidom import Node + +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import pango + +import Configuration + +log = Configuration.get_logger("logging.conf", "logview") + +class GuiLogView: + + def __init__(self, config, mainwin, vbox): + self.config = config + self.main_window = mainwin + self.vbox = vbox + gtk.Widget.set_size_request(self.vbox, 700, 400); + + self.liststore = gtk.ListStore(str, str, str, str) # date, module, level, text + self.listview = gtk.TreeView(model=self.liststore) + self.listview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) + + scrolledwindow = gtk.ScrolledWindow() + scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.vbox.pack_start(scrolledwindow, expand=True, fill=True, padding=0) + scrolledwindow.add(self.listview) + + self.listview.show() + scrolledwindow.show() + self.vbox.show() + + self.loadLog() + self.vbox.show_all() + + 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() + + col = gtk.TreeViewColumn("Date/Time") + self.listview.append_column(col) + cRender = gtk.CellRendererText() + cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) + col.pack_start(cRender, True) + col.add_attribute(cRender, 'text', 0) + col.set_max_width(1000) + + col = gtk.TreeViewColumn("Module") + self.listview.append_column(col) + cRender = gtk.CellRendererText() + cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) + col.pack_start(cRender, True) + col.add_attribute(cRender, 'text', 1) + col.set_max_width(1000) + + col = gtk.TreeViewColumn("Level") + self.listview.append_column(col) + cRender = gtk.CellRendererText() + cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) + col.pack_start(cRender, True) + col.add_attribute(cRender, 'text', 2) + col.set_max_width(1000) + + col = gtk.TreeViewColumn("Text") + self.listview.append_column(col) + cRender = gtk.CellRendererText() + cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) + col.pack_start(cRender, True) + col.add_attribute(cRender, 'text', 3) + col.set_max_width(1000) + + l = 0 + for line in open('logging.out', 'r'): + #self.addLogText(line) + iter = self.liststore.append([line.strip(), "", "", ""]) + l = l + 1 + if l >= 100: + break + + + +if __name__=="__main__": + + config = Configuration.Config() + + win = gtk.Window(gtk.WINDOW_TOPLEVEL) + win.set_title("Test Log Viewer") + win.set_border_width(1) + win.set_default_size(600, 500) + win.set_resizable(True) + + dia = gtk.Dialog("Log Viewer", + win, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_CLOSE, gtk.RESPONSE_OK)) + dia.set_default_size(500, 500) + log = GuiLogView(config, win, dia.vbox) + response = dia.run() + if response == gtk.RESPONSE_ACCEPT: + pass + dia.destroy() + + + + diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index faaf4fdc..79567578 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -60,7 +60,8 @@ if not options.errorsToConsole: errorFile = open('fpdb-error-log.txt', 'w', 0) sys.stderr = errorFile -import logging +#import logging +import logging, logging.config import pygtk pygtk.require('2.0') @@ -70,6 +71,7 @@ import interlocks import GuiPrefs +import GuiLogView import GuiBulkImport import GuiPlayerStats import GuiPositionalStats @@ -85,6 +87,8 @@ import Exceptions VERSION = "0.12" +log = Configuration.get_logger("logging.conf", "fpdb") + class fpdb: def tab_clicked(self, widget, tab_name): """called when a tab button is clicked to activate that tab""" @@ -413,6 +417,29 @@ class fpdb: self.release_global_lock() + def dia_logs(self, widget, data=None): + lock_set = False + if self.obtain_global_lock(): + lock_set = True + + 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() + + 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 __calendar_dialog(self, widget, entry): self.dia_confirm.set_modal(False) d = gtk.Window(gtk.WINDOW_TOPLEVEL) @@ -515,6 +542,7 @@ class fpdb: + @@ -556,6 +584,7 @@ class fpdb: ('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats), ('help', None, '_Help'), ('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), ('License', None, '_License and Copying (todo)', None, 'License and Copying', self.dia_licensing), ]) diff --git a/pyfpdb/logging.conf b/pyfpdb/logging.conf index 124b509d..1b54b453 100644 --- a/pyfpdb/logging.conf +++ b/pyfpdb/logging.conf @@ -11,6 +11,18 @@ keys=fileFormatter,stderrFormatter level=INFO handlers=consoleHandler,fileHandler +[logger_fpdb] +level=INFO +handlers=consoleHandler,fileHandler +qualname=fpdb +propagate=0 + +[logger_logview] +level=INFO +handlers=consoleHandler,fileHandler +qualname=logview +propagate=0 + [logger_parser] level=INFO handlers=consoleHandler,fileHandler @@ -24,7 +36,7 @@ qualname=importer propagate=0 [logger_config] -level=DEBUG +level=INFO handlers=consoleHandler,fileHandler qualname=config propagate=0 From 2d8c44110c5a77bac5823e301b9bc74dac4d42f1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 5 Dec 2009 20:10:00 +0000 Subject: [PATCH 06/11] refine log viewer --- pyfpdb/GuiLogView.py | 90 +++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py index 77f09b06..646ccb0e 100755 --- a/pyfpdb/GuiLogView.py +++ b/pyfpdb/GuiLogView.py @@ -30,6 +30,8 @@ import Configuration log = Configuration.get_logger("logging.conf", "logview") +MAX_LINES = 1000 + class GuiLogView: def __init__(self, config, mainwin, vbox): @@ -38,9 +40,19 @@ class GuiLogView: self.vbox = vbox gtk.Widget.set_size_request(self.vbox, 700, 400); - self.liststore = gtk.ListStore(str, str, str, str) # date, module, level, text + 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 + # filter = self.liststore.filter_new() + # filter.set_visible_column(1) + # + # # 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_BOTH) + self.listview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_NONE) scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) @@ -60,47 +72,55 @@ class GuiLogView: #self.configView = gtk.TreeView(self.configStore) #self.configView.set_enable_tree_lines(True) self.liststore.clear() + self.listcols = [] - col = gtk.TreeViewColumn("Date/Time") - self.listview.append_column(col) - cRender = gtk.CellRendererText() - cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) - col.pack_start(cRender, True) - col.add_attribute(cRender, 'text', 0) - col.set_max_width(1000) + col = self.addColumn("Date/Time", 0) - col = gtk.TreeViewColumn("Module") - self.listview.append_column(col) - cRender = gtk.CellRendererText() - cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) - col.pack_start(cRender, True) - col.add_attribute(cRender, 'text', 1) - col.set_max_width(1000) - - col = gtk.TreeViewColumn("Level") - self.listview.append_column(col) - cRender = gtk.CellRendererText() - cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) - col.pack_start(cRender, True) - col.add_attribute(cRender, 'text', 2) - col.set_max_width(1000) - - col = gtk.TreeViewColumn("Text") - self.listview.append_column(col) - cRender = gtk.CellRendererText() - cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) - col.pack_start(cRender, True) - col.add_attribute(cRender, 'text', 3) - col.set_max_width(1000) + col = self.addColumn("Module", 1) + col = self.addColumn("Level", 2) + col = self.addColumn("Text", 3) l = 0 for line in open('logging.out', 'r'): - #self.addLogText(line) - iter = self.liststore.append([line.strip(), "", "", ""]) + # 2009-12-02 15:23:21,716 - config DEBUG config logger initialised + if len(line) > 49: + iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) ) l = l + 1 - if l >= 100: + if l >= MAX_LINES: break + def addColumn(self, title, n): + col = gtk.TreeViewColumn(title) + self.listview.append_column(col) + cRender = gtk.CellRendererText() + cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) + col.pack_start(cRender, True) + col.add_attribute(cRender, 'text', n) + col.set_max_width(1000) + col.set_spacing(0) # no effect + self.listcols.append(col) + col.set_clickable(True) + col.connect("clicked", self.sortCols, n) + return(col) + + def sortCols(self, col, n): + try: + if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING: + col.set_sort_order(gtk.SORT_DESCENDING) + else: + col.set_sort_order(gtk.SORT_ASCENDING) + self.liststore.set_sort_column_id(n, col.get_sort_order()) + #self.liststore.set_sort_func(n, self.sortnums, (n,grid)) + for i in xrange(len(self.listcols)): + self.listcols[i].set_sort_indicator(False) + self.listcols[n].set_sort_indicator(True) + # use this listcols[col].set_sort_indicator(True) + # to turn indicator off for other cols + except: + err = traceback.extract_tb(sys.exc_info()[2]) + print "***sortCols error: " + str(sys.exc_info()[1]) + print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) + if __name__=="__main__": From 2934c3213265813859bd097a818dfc4660b202d1 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 5 Dec 2009 20:31:37 +0000 Subject: [PATCH 07/11] limit number of lines displayed in log viewer --- pyfpdb/GuiLogView.py | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py index 646ccb0e..0f7f03c7 100755 --- a/pyfpdb/GuiLogView.py +++ b/pyfpdb/GuiLogView.py @@ -17,8 +17,7 @@ #agpl-3.0.txt in the docs folder of the package. -import xml.dom.minidom -from xml.dom.minidom import Node +import mmap import pygtk pygtk.require('2.0') @@ -30,7 +29,7 @@ import Configuration log = Configuration.get_logger("logging.conf", "logview") -MAX_LINES = 1000 +MAX_LINES = 100000 class GuiLogView: @@ -80,14 +79,33 @@ class GuiLogView: col = self.addColumn("Level", 2) col = self.addColumn("Text", 3) + # 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() + + 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 - for line in open('logging.out', 'r'): + line = readline() + while line: + # eg line: # 2009-12-02 15:23:21,716 - config DEBUG config logger initialised - if len(line) > 49: - iter = self.liststore.append( (line[0:23], line[26:32], line[39:46], line[48:].strip(), True) ) l = l + 1 - if l >= MAX_LINES: - break + 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 addColumn(self, title, n): col = gtk.TreeViewColumn(title) From 85242f13cb1a4d66d564d9368f1034d33c730bdf Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 5 Dec 2009 21:59:42 +0000 Subject: [PATCH 08/11] fix bug with hud stats, must use ORDER BY in the selects --- pyfpdb/SQL.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index eb9296ef..5a0d1965 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1317,6 +1317,7 @@ class Sql: 1.25 would be a config value so user could change it) */ GROUP BY hc.PlayerId, hp.seatNo, p.name + ORDER BY hc.PlayerId, hp.seatNo, p.name """ # same as above except stats are aggregated for all blind/limit levels @@ -1418,6 +1419,7 @@ class Sql: ) ) GROUP BY hc.PlayerId, p.name + ORDER BY hc.PlayerId, p.name """ # NOTES on above cursor: # - Do NOT include %s inside query in a comment - the db api thinks From 18b0a47555fd96246f4ad1db4134a9fd90b817e4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 5 Dec 2009 22:20:44 +0000 Subject: [PATCH 09/11] move print message to log --- pyfpdb/Database.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 1c44bb61..36fdd2d2 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -474,8 +474,9 @@ class Database: else: h_seats_min, h_seats_max = 0, 10 print "bad h_seats_style value:", h_seats_style - print "opp seats style", seats_style, "hero seats style", h_seats_style - print "opp seats:", seats_min, seats_max, " hero seats:", h_seats_min, h_seats_max + log.info("opp seats style %s %d %d hero seats style %s %d %d" + % (seats_style, seats_min, seats_max + ,h_seats_style, h_seats_min, h_seats_max) ) if hud_style == 'S' or h_hud_style == 'S': self.get_stats_from_hand_session(hand, stat_dict, hero_id From 66b4ed35e538967073456cc9a0c0d148dadbc146 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 5 Dec 2009 22:48:41 +0000 Subject: [PATCH 10/11] add refresh button to log viewer --- pyfpdb/GuiLogView.py | 50 +++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/pyfpdb/GuiLogView.py b/pyfpdb/GuiLogView.py index 0f7f03c7..3b7b8aa6 100755 --- a/pyfpdb/GuiLogView.py +++ b/pyfpdb/GuiLogView.py @@ -52,19 +52,44 @@ class GuiLogView: self.listview = gtk.TreeView(model=self.liststore) self.listview.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_NONE) + self.listcols = [] scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.vbox.pack_start(scrolledwindow, expand=True, fill=True, padding=0) scrolledwindow.add(self.listview) + self.vbox.pack_start(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() self.listview.show() scrolledwindow.show() self.vbox.show() + col = self.addColumn("Date/Time", 0) + col = self.addColumn("Module", 1) + col = self.addColumn("Level", 2) + col = self.addColumn("Text", 3) + self.loadLog() self.vbox.show_all() + def addColumn(self, title, n): + col = gtk.TreeViewColumn(title) + self.listview.append_column(col) + cRender = gtk.CellRendererText() + cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) + col.pack_start(cRender, True) + col.add_attribute(cRender, 'text', n) + col.set_max_width(1000) + col.set_spacing(0) # no effect + self.listcols.append(col) + col.set_clickable(True) + col.connect("clicked", self.sortCols, n) + return(col) + def loadLog(self): #self.configStore = gtk.TreeStore(gobject.TYPE_PYOBJECT, gobject.TYPE_STRING, gobject.TYPE_STRING) @@ -73,12 +98,6 @@ class GuiLogView: self.liststore.clear() self.listcols = [] - col = self.addColumn("Date/Time", 0) - - col = self.addColumn("Module", 1) - col = self.addColumn("Level", 2) - col = self.addColumn("Text", 3) - # count number of lines in file f = open('logging.out', "r+") buf = mmap.mmap(f.fileno(), 0) @@ -107,20 +126,6 @@ class GuiLogView: line = readline() f.close() - def addColumn(self, title, n): - col = gtk.TreeViewColumn(title) - self.listview.append_column(col) - cRender = gtk.CellRendererText() - cRender.set_property("wrap-mode", pango.WRAP_WORD_CHAR) - col.pack_start(cRender, True) - col.add_attribute(cRender, 'text', n) - col.set_max_width(1000) - col.set_spacing(0) # no effect - self.listcols.append(col) - col.set_clickable(True) - col.connect("clicked", self.sortCols, n) - return(col) - def sortCols(self, col, n): try: if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING: @@ -139,6 +144,9 @@ class GuiLogView: print "***sortCols error: " + str(sys.exc_info()[1]) print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) + def refresh(self, widget, data): + self.loadLog() + if __name__=="__main__": From 63f04908beab47949209fd5c57b54be4aa5cbeb0 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sun, 6 Dec 2009 14:17:22 +0000 Subject: [PATCH 11/11] add simple test scripts for python and gtk --- pyfpdb/test1.py | 29 +++++++++++++++++++++++++ pyfpdb/test2.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100755 pyfpdb/test1.py create mode 100755 pyfpdb/test2.py diff --git a/pyfpdb/test1.py b/pyfpdb/test1.py new file mode 100755 index 00000000..76bde20e --- /dev/null +++ b/pyfpdb/test1.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +"""test1.py + +Test if python is working. +""" +# Copyright 2008, Ray E. Barker +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +######################################################################## + +import sys + +print "\npython is working!" +print "\npress return to finish" + +sys.stdin.readline() diff --git a/pyfpdb/test2.py b/pyfpdb/test2.py new file mode 100755 index 00000000..c52d0a6c --- /dev/null +++ b/pyfpdb/test2.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +"""test2.py + +Test if gtk is working. +""" +# Copyright 2008, Ray E. Barker +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +######################################################################## + +import sys + +try: + import pygtk + pygtk.require('2.0') + import gtk + + + win = gtk.Window(gtk.WINDOW_TOPLEVEL) + win.set_title("Test GTK") + win.set_border_width(1) + win.set_default_size(600, 500) + win.set_resizable(True) + #win.show() + + dia = gtk.Dialog("Test GTK", + win, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_CLOSE, gtk.RESPONSE_OK)) + dia.set_default_size(500, 300) + + l = gtk.Label("GTK is working!") + dia.vbox.add(l) + l.show() + + response = dia.run() + if response == gtk.RESPONSE_ACCEPT: + pass + dia.destroy() + +except: + print "\nError:", sys.exc_info() + print "\npress return to finish" + sys.stdin.readline()