Merge branch 'master' of git://git.assembla.com/fpdb-eric
This commit is contained in:
		
						commit
						1e051e47ec
					
				|  | @ -41,7 +41,8 @@ class GuiPlayerStats (threading.Thread): | |||
|         self.main_window = mainwin | ||||
|         self.sql = querylist | ||||
| 
 | ||||
|         self.liststore = None | ||||
|         self.liststore = []   # gtk.ListStore[]         stores the contents of the grids | ||||
|         self.listcols = []    # gtk.TreeViewColumn[][]  stores the columns in the grids | ||||
| 
 | ||||
|         self.MYSQL_INNODB   = 2 | ||||
|         self.PGSQL          = 3 | ||||
|  | @ -162,6 +163,8 @@ class GuiPlayerStats (threading.Thread): | |||
|     def refreshStats(self, widget, data): | ||||
|         try: self.stats_vbox.destroy() | ||||
|         except AttributeError: pass | ||||
|         self.liststore = [] | ||||
|         self.listcols = [] | ||||
|         #self.stats_vbox = gtk.VBox(False, 0) | ||||
|         self.stats_vbox = gtk.VPaned() | ||||
|         self.stats_vbox.show() | ||||
|  | @ -217,8 +220,10 @@ class GuiPlayerStats (threading.Thread): | |||
|         # 3rd parameter passes extra flags, currently includes: | ||||
|         #   holecards - whether to display card breakdown (True/False) | ||||
|         #   numhands  - min number hands required when displaying all players | ||||
|         flags = [False, self.filters.getNumHands()] | ||||
|         self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) | ||||
|         #   gridnum   - index for grid data structures | ||||
|         flags = [False, self.filters.getNumHands(), 0] | ||||
|         self.addGrid(swin, 'playerDetailedStats', flags, playerids | ||||
|                     ,sitenos, limits, type, seats, groups, dates) | ||||
| 
 | ||||
|         # Separator | ||||
|         vbox2 = gtk.VBox(False, 0) | ||||
|  | @ -236,7 +241,9 @@ class GuiPlayerStats (threading.Thread): | |||
| 
 | ||||
|         # Detailed table | ||||
|         flags[0] = True | ||||
|         self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) | ||||
|         flags[2] = 1 | ||||
|         self.addGrid(swin, 'playerDetailedStats', flags, playerids | ||||
|                     ,sitenos, limits, type, seats, groups, dates) | ||||
| 
 | ||||
|         self.db.rollback() | ||||
|         print "Stats page displayed in %4.2f seconds" % (time() - starttime) | ||||
|  | @ -257,11 +264,12 @@ class GuiPlayerStats (threading.Thread): | |||
| 
 | ||||
|         return | ||||
| 
 | ||||
|     def sortnums(self, model, iter1, iter2, n): | ||||
|     def sortnums(self, model, iter1, iter2, nums): | ||||
|         try: | ||||
|             ret = 0 | ||||
|             a = self.liststore.get_value(iter1, n) | ||||
|             b = self.liststore.get_value(iter2, n) | ||||
|             (n, grid) = nums | ||||
|             a = self.liststore[grid].get_value(iter1, n) | ||||
|             b = self.liststore[grid].get_value(iter2, n) | ||||
|             if 'f' in self.cols_to_show[n][4]: | ||||
|                 try:     a = float(a) | ||||
|                 except:  a = 0.0 | ||||
|  | @ -281,7 +289,7 @@ class GuiPlayerStats (threading.Thread): | |||
|                     ret = 0 | ||||
|                 else: | ||||
|                     ret = 1 | ||||
|             #print "n =", n, "iter1[n] =", self.liststore.get_value(iter1,n), "iter2[n] =", self.liststore.get_value(iter2,n), "ret =", ret | ||||
|             #print "n =", n, "iter1[n] =", self.liststore[grid].get_value(iter1,n), "iter2[n] =", self.liststore[grid].get_value(iter2,n), "ret =", ret | ||||
|         except: | ||||
|             err = traceback.extract_tb(sys.exc_info()[2]) | ||||
|             print "***sortnums error: " + str(sys.exc_info()[1]) | ||||
|  | @ -289,18 +297,19 @@ class GuiPlayerStats (threading.Thread): | |||
| 
 | ||||
|         return(ret) | ||||
| 
 | ||||
|     def sortcols(self, col, n): | ||||
|     def sortcols(self, col, nums): | ||||
|         try: | ||||
|             #This doesn't actually work yet - clicking heading in top section sorts bottom section :-( | ||||
|             if col.get_sort_order() == gtk.SORT_ASCENDING: | ||||
|             (n, grid) = nums | ||||
|             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) | ||||
|             for i in xrange(len(self.listcols)): | ||||
|                 self.listcols[i].set_sort_indicator(False) | ||||
|             self.listcols[n].set_sort_indicator(True) | ||||
|             self.liststore[grid].set_sort_column_id(n, col.get_sort_order()) | ||||
|             self.liststore[grid].set_sort_func(n, self.sortnums, (n,grid)) | ||||
|             for i in xrange(len(self.listcols[grid])): | ||||
|                 self.listcols[grid][i].set_sort_indicator(False) | ||||
|             self.listcols[grid][n].set_sort_indicator(True) | ||||
|             # use this   listcols[col].set_sort_indicator(True) | ||||
|             # to turn indicator off for other cols | ||||
|         except: | ||||
|  | @ -308,12 +317,12 @@ class GuiPlayerStats (threading.Thread): | |||
|             print "***sortcols error: " + str(sys.exc_info()[1]) | ||||
|             print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) | ||||
| 
 | ||||
|     def addTable(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates): | ||||
|     def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates): | ||||
|         counter = 0 | ||||
|         row = 0 | ||||
|         sqlrow = 0 | ||||
|         if not flags:  holecards = False | ||||
|         else:          holecards = flags[0] | ||||
|         if not flags:  holecards,grid = False,0 | ||||
|         else:          holecards,grid = flags[0],flags[2] | ||||
| 
 | ||||
|         tmp = self.sql.query[query] | ||||
|         tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates) | ||||
|  | @ -325,8 +334,9 @@ class GuiPlayerStats (threading.Thread): | |||
|         self.cols_to_show = [x for x in self.columns if x[colshow]] | ||||
|         hgametypeid_idx = colnames.index('hgametypeid') | ||||
| 
 | ||||
|         self.liststore = gtk.ListStore(*([str] * len(self.cols_to_show))) | ||||
|         view = gtk.TreeView(model=self.liststore) | ||||
|         assert len(self.liststore) == grid, "len(self.liststore)="+str(len(self.liststore))+" grid-1="+str(grid) | ||||
|         self.liststore.append( gtk.ListStore(*([str] * len(self.cols_to_show))) ) | ||||
|         view = gtk.TreeView(model=self.liststore[grid]) | ||||
|         view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) | ||||
|         #vbox.pack_start(view, expand=False, padding=3) | ||||
|         vbox.add(view) | ||||
|  | @ -335,7 +345,8 @@ class GuiPlayerStats (threading.Thread): | |||
|         textcell50.set_property('xalign', 0.5) | ||||
|         numcell = gtk.CellRendererText() | ||||
|         numcell.set_property('xalign', 1.0) | ||||
|         self.listcols = [] | ||||
|         assert len(self.listcols) == grid | ||||
|         self.listcols.append( [] ) | ||||
| 
 | ||||
|         # Create header row   eg column: ("game",     True, "Game",     0.0, "%s") | ||||
|         for col, column in enumerate(self.cols_to_show): | ||||
|  | @ -343,31 +354,33 @@ class GuiPlayerStats (threading.Thread): | |||
|                 s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] | ||||
|             else: | ||||
|                 s = column[colheading] | ||||
|             self.listcols.append(gtk.TreeViewColumn(s)) | ||||
|             view.append_column(self.listcols[col]) | ||||
|             self.listcols[grid].append(gtk.TreeViewColumn(s)) | ||||
|             view.append_column(self.listcols[grid][col]) | ||||
|             if column[colformat] == '%s': | ||||
|                 if column[colxalign] == 0.0: | ||||
|                     self.listcols[col].pack_start(textcell, expand=True) | ||||
|                     self.listcols[col].add_attribute(textcell, 'text', col) | ||||
|                     self.listcols[grid][col].pack_start(textcell, expand=True) | ||||
|                     self.listcols[grid][col].add_attribute(textcell, 'text', col) | ||||
|                     cellrend = textcell | ||||
|                 else: | ||||
|                     self.listcols[col].pack_start(textcell50, expand=True) | ||||
|                     self.listcols[col].add_attribute(textcell50, 'text', col) | ||||
|                 self.listcols[col].set_expand(True) | ||||
|                     self.listcols[grid][col].pack_start(textcell50, expand=True) | ||||
|                     self.listcols[grid][col].add_attribute(textcell50, 'text', col) | ||||
|                     cellrend = textcell50 | ||||
|                 self.listcols[grid][col].set_expand(True) | ||||
|             else: | ||||
|                 self.listcols[col].pack_start(numcell, expand=True) | ||||
|                 self.listcols[col].add_attribute(numcell, 'text', col) | ||||
|                 self.listcols[col].set_expand(True) | ||||
|                 #self.listcols[col].set_alignment(column[colxalign]) # no effect? | ||||
|             if holecards: | ||||
|                 self.listcols[col].set_clickable(True) | ||||
|                 self.listcols[col].connect("clicked", self.sortcols, col) | ||||
|                 self.listcols[grid][col].pack_start(numcell, expand=True) | ||||
|                 self.listcols[grid][col].add_attribute(numcell, 'text', col) | ||||
|                 self.listcols[grid][col].set_expand(True) | ||||
|                 cellrend = numcell | ||||
|                 #self.listcols[grid][col].set_alignment(column[colxalign]) # no effect? | ||||
|             self.listcols[grid][col].set_clickable(True) | ||||
|             self.listcols[grid][col].connect("clicked", self.sortcols, (col,grid)) | ||||
|             if col == 0: | ||||
|                     self.listcols[col].set_sort_order(gtk.SORT_DESCENDING) | ||||
|                     self.listcols[col].set_sort_indicator(True) | ||||
|                 self.listcols[grid][col].set_sort_order(gtk.SORT_DESCENDING) | ||||
|                 self.listcols[grid][col].set_sort_indicator(True) | ||||
|             if column[coltype] == 'cash': | ||||
|                 self.listcols[col].set_cell_data_func(numcell, self.ledger_style_render_func) | ||||
|                 self.listcols[grid][col].set_cell_data_func(numcell, self.ledger_style_render_func) | ||||
|             else: | ||||
|                 self.listcols[col].set_cell_data_func(numcell, self.reset_style_render_func) | ||||
|                 self.listcols[grid][col].set_cell_data_func(cellrend, self.reset_style_render_func) | ||||
| 
 | ||||
|         rows = len(result) # +1 for title row | ||||
| 
 | ||||
|  | @ -408,12 +421,12 @@ class GuiPlayerStats (threading.Thread): | |||
|                     treerow.append(column[colformat] % value) | ||||
|                 else: | ||||
|                     treerow.append(' ') | ||||
|             iter = self.liststore.append(treerow) | ||||
|             iter = self.liststore[grid].append(treerow) | ||||
|             sqlrow += 1 | ||||
|             row += 1 | ||||
|         vbox.show_all() | ||||
|          | ||||
|     #end def addTable(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates): | ||||
|     #end def addGrid(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates): | ||||
| 
 | ||||
|     def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates): | ||||
|         having = '' | ||||
|  |  | |||
|  | @ -24,18 +24,22 @@ import os | |||
| import traceback | ||||
| from time import time, strftime, localtime | ||||
| try: | ||||
|     calluse = not 'matplotlib' in sys.modules | ||||
|     import matplotlib | ||||
|     if calluse: | ||||
|         matplotlib.use('GTK') | ||||
|     from matplotlib.figure import Figure | ||||
|     from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas | ||||
|     from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar | ||||
|     from matplotlib.finance import candlestick2 | ||||
| 
 | ||||
|     from numpy import diff, nonzero, sum, cumsum, max, mina | ||||
|     from numpy import diff, nonzero, sum, cumsum, max, min | ||||
| #    from matplotlib.dates import  DateFormatter, WeekdayLocator, HourLocator, \ | ||||
| #     DayLocator, MONDAY, timezone | ||||
| 
 | ||||
| except: | ||||
|     err = traceback.extract_tb(sys.exc_info()[2])[-1] | ||||
|     print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) | ||||
|     print """Failed to load numpy in Session Viewer""" | ||||
|     print """This is of no consequence as the module currently doesn't do anything.""" | ||||
| 
 | ||||
|  |  | |||
|  | @ -189,7 +189,6 @@ class HUD_main(object): | |||
| #    be passed to HUDs for use in the gui thread. HUD objects should not | ||||
| #    need their own access to the database, but should open their own | ||||
| #    if it is required. | ||||
|         try: | ||||
|         self.db_connection = Database.Database(self.config) | ||||
|         tourny_finder = re.compile('(\d+) (\d+)') | ||||
|          | ||||
|  | @ -279,9 +278,6 @@ class HUD_main(object): | |||
|                 else: | ||||
|                     self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards) | ||||
|             self.db_connection.connection.rollback() | ||||
|         except: | ||||
|             err = traceback.extract_tb(sys.exc_info()[2])[-1] | ||||
|             print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) | ||||
| 
 | ||||
| if __name__== "__main__": | ||||
| 
 | ||||
|  |  | |||
|  | @ -238,7 +238,8 @@ def discover_nt_by_name(c, tablename): | |||
|         try: | ||||
|             # maybe it's better to make global titles[hwnd] decoding? | ||||
|             # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html | ||||
|             if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower(): continue | ||||
|             if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower(): | ||||
|                 continue | ||||
|         except: | ||||
|             continue | ||||
|         if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window | ||||
|  | @ -246,8 +247,8 @@ def discover_nt_by_name(c, tablename): | |||
|         if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows | ||||
|         if ' - Table ' in titles[hwnd]: continue # Absolute table Chat window.. sigh. TODO: Can we tell what site we're trying to discover for somehow in here, so i can limit this check just to AP searches? | ||||
|         temp = decode_windows(c, titles[hwnd], hwnd) | ||||
|         #print "attach to window", temp | ||||
|         return decode_windows(c, titles[hwnd], hwnd) | ||||
|         print "attach to window", temp | ||||
|         return temp | ||||
|     return None | ||||
| 
 | ||||
| def discover_nt_tournament(c, tour_number, tab_number): | ||||
|  | @ -257,9 +258,12 @@ def discover_nt_tournament(c, tour_number, tab_number): | |||
|     titles ={} | ||||
|     win32gui.EnumWindows(win_enum_handler, titles) | ||||
|     for hwnd in titles: | ||||
|         if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows | ||||
|         if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window | ||||
|         if 'HUD:' in titles[hwnd]: continue # FPDB HUD window | ||||
|         # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows | ||||
|         if 'Chat:' in titles[hwnd]: continue | ||||
|         # Everleaf Network HH viewer window | ||||
|         if 'History for table:' in titles[hwnd]: continue | ||||
|         # FPDB HUD window | ||||
|         if 'HUD:' in titles[hwnd]: continue | ||||
| 
 | ||||
|         if re.search(search_string, titles[hwnd]): | ||||
|             return decode_windows(c, titles[hwnd], hwnd) | ||||
|  | @ -268,18 +272,30 @@ def discover_nt_tournament(c, tour_number, tab_number): | |||
| def get_nt_exe(hwnd): | ||||
|     """Finds the name of the executable that the given window handle belongs to.""" | ||||
|      | ||||
|     # Request privileges to enable "debug process", so we can later use PROCESS_VM_READ, retardedly required to GetModuleFileNameEx() | ||||
|     # Request privileges to enable "debug process", so we can later use | ||||
|     # PROCESS_VM_READ, retardedly required to GetModuleFileNameEx() | ||||
|     priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY | ||||
|     hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), priv_flags) | ||||
|     hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), | ||||
|                                              priv_flags) | ||||
|     # enable "debug process" | ||||
|     privilege_id = win32security.LookupPrivilegeValue (None, win32security.SE_DEBUG_NAME) | ||||
|     old_privs = win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)]) | ||||
|     privilege_id = win32security.LookupPrivilegeValue(None, | ||||
|                                                       win32security.SE_DEBUG_NAME) | ||||
|     old_privs = win32security.AdjustTokenPrivileges(hToken, 0, | ||||
|                                                     [(privilege_id, | ||||
|                                                       win32security.SE_PRIVILEGE_ENABLED)]) | ||||
|      | ||||
|     # Open the process, and query it's filename | ||||
|     processid = win32process.GetWindowThreadProcessId(hwnd) | ||||
|     pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1]) | ||||
|     pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | | ||||
|                                     win32con.PROCESS_VM_READ, False, | ||||
|                                     processid[1]) | ||||
|     try: | ||||
|         exename = win32process.GetModuleFileNameEx(pshandle, 0) | ||||
|      | ||||
|     except pywintypes.error: | ||||
|         # insert code to call GetProcessImageName if we can find it.. | ||||
|         # returning None from here will hopefully break all following code | ||||
|         exename = None  | ||||
|     finally: | ||||
|         # clean up | ||||
|         win32api.CloseHandle(pshandle) | ||||
|         win32api.CloseHandle(hToken) | ||||
|  | @ -305,6 +321,8 @@ def decode_windows(c, title, hwnd): | |||
|     info['width']  = int( width ) - 2*b_width | ||||
|     info['height'] = int( height ) - b_width - tb_height | ||||
|     info['exe']    = get_nt_exe(hwnd) | ||||
|     print "get_nt_exe returned ", info['exe'] | ||||
|     # TODO: 'width' here is all sorts of screwed up. | ||||
| 
 | ||||
|     title_bits = re.split(' - ', info['title']) | ||||
|     info['name'] = title_bits[0] | ||||
|  |  | |||
|  | @ -516,6 +516,8 @@ class fpdb: | |||
|         print "Quitting normally" | ||||
|         #check if current settings differ from profile, if so offer to save or abort | ||||
|         self.db.disconnect() | ||||
|         # hide icon as it doesn't go away immediately in Windows - is this ok in Linux Eric? | ||||
|         self.statusIcon.set_visible(False) | ||||
|         gtk.main_quit() | ||||
| 
 | ||||
|     def release_global_lock(self): | ||||
|  |  | |||
|  | @ -77,10 +77,11 @@ class fpdb_db: | |||
|             import MySQLdb | ||||
|             if use_pool: | ||||
|                 MySQLdb = pool.manage(MySQLdb, pool_size=5) | ||||
|             try: | ||||
| #            try: | ||||
|             self.db = MySQLdb.connect(host=host, user=user, passwd=password, db=database, use_unicode=True) | ||||
|             except: | ||||
|                 raise FpdbMySQLFailedError("MySQL connection failed") | ||||
|             #TODO: Add port option | ||||
| #            except: | ||||
| #                raise FpdbMySQLFailedError("MySQL connection failed") | ||||
|         elif backend==fpdb_db.PGSQL: | ||||
|             import psycopg2 | ||||
|             import psycopg2.extensions | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user