From 3435cb106e5861a560de5f73c9f3636d4a3bd50b Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Mon, 26 Oct 2009 17:49:37 +0200 Subject: [PATCH 01/11] Bump version to 0.12 in packaging --- packaging/debian/changelog | 6 ++++++ setup.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packaging/debian/changelog b/packaging/debian/changelog index ce102bf5..ec66f4a7 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,9 @@ +free-poker-tools (0.12-1) unstable; urgency=low + + * New release + + -- Mika Bostrom Mon, 26 Oct 2009 17:49:07 +0200 + free-poker-tools (0.11.3+git20091023) unstable; urgency=low * Snapshot release diff --git a/setup.py b/setup.py index 0ba21bf0..689191bd 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from distutils.core import setup setup(name = 'fpdb', description = 'Free Poker Database', - version = '0.11.3', + version = '0.12', author = 'FPDB team', author_email = 'fpdb-main@lists.sourceforge.net', packages = ['fpdb'], From 2be3ab88975478fded91970bf7fe1682b857b664 Mon Sep 17 00:00:00 2001 From: Worros Date: Tue, 27 Oct 2009 13:18:51 +0800 Subject: [PATCH 02/11] Add Stars icon to folder --- gfx/img-PokerStars-Small.xpm | 92 ++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 gfx/img-PokerStars-Small.xpm diff --git a/gfx/img-PokerStars-Small.xpm b/gfx/img-PokerStars-Small.xpm new file mode 100644 index 00000000..f4fd457d --- /dev/null +++ b/gfx/img-PokerStars-Small.xpm @@ -0,0 +1,92 @@ +/* XPM */ +/* C:\Program Files\PokerStars\PokerStarsUpdate.exe */ +static char *icon[] = { +"48 48 40 2", +"01 c #800000", +"08 c #C0DCC0", +"4C c #7F1F00", +"6C c #AA0000", +"6D c #AA0055", +"70 c #AA1F00", +"90 c #D40000", +"91 c #D40055", +"94 c #D41F00", +"95 c #D41F55", +"99 c #D43F55", +"9D c #D45F55", +"9E c #D45FAA", +"A1 c #D47F55", +"A2 c #D47FAA", +"A5 c #D49F55", +"A6 c #D49FAA", +"AA c #D4BFAA", +"AE c #D4DFAA", +"AF c #D4DFFF", +"B4 c #FF0055", +"B6 c #FF1F00", +"B7 c #FF1F55", +"BA c #FF3F00", +"BB c #FF3F55", +"BE c #FF5F00", +"BF c #FF5F55", +"C3 c #FF7F55", +"C4 c #FF7FAA", +"C7 c #FF9F55", +"C8 c #FF9FAA", +"CC c #FFBFAA", +"CD c #FFBFFF", +"D0 c #FFDFAA", +"D1 c #FFDFFF", +"D5 c #FFCCFF", +"F6 c #FFFBF0", +"F9 c #FF0000", +"FF c #FFFFFF", +" c None", +"707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", +"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAD1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6949DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6BFBBF999F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A6A2C7B6F9F99DD1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A2C8CCBFB6B4F99099F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6C8CCC3BEB7F9F9F99099F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2C8D0C7BFBBB6F9B4F9F99099F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A6AAD0C8C3C3BBF9F9F9F9B4F99099D1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFA6C8D0CCC7C3BFBAB6B4F9F9F99090909DF6FFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFA2CCF6CCC8C3BFBEBBF9F9F9B4F9F9B4909099F6FFFFFFFFFFFFFFFFFFFFFFFFFF6C", +"70FFFFFFFFFFFFFFFFFFFFFFFFA6CCD1CCC7C3C3BFBAB6B7F9F9F9B490F990906C99FFFFFFD1FFFFFFD1FFFFFFD1FF70", +"6CFFFFFFFFFFFFFFFFFFFFFFAAC8F6CCC7C8C3BFBFBFB6C4B7F9F9F9F9F99190906C9DFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFD1FFFFFFD1FFFFFFAAC8F6CCCCC8C3C3C3BEBBB6F6BFF9B4F9B490F99091906CA2FFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFD1A6F6CCCCC7C7C3C3BFBBBABFFFC8F9F9F990F9909090906C90AAFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFF6A6D0D1CCC8C7C3C3BFBEBFB6CCFFF6F9F9F9B4F9B49090906C6C95F6FFFFFFFFFFFFFFFFFF6C", +"6CFFFFFFFFFFFFFFFFAACCF6CCCCC7C4C3BFBEBBBABBD1FFFFBFF9F9F990F9F99190956C6C99FFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFD1C8F6CCCCC8C7C7C8C7C8C7C3C8F6FFF6CDBFBBBFBBBFBF9090906C6C6CA6FFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFAAF6D0CCC8C7C3C4D0FFFFFFFFF6F6FFFFF6FFFFFFFFD199F9909090706C99F6FFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFD5CCD1CCCCC7C3C3C3BFC8F6FFFFFFFFFFFFFFFFFFFFC895F990B490916C016CA2FFFFFFFFFFFFFF6C", +"6CFFFFFFFFFFF6AAD1D0CCC7C8C3C3C3BFBEBFD1FFFFFFFFFFFFFFFFA1F9F990F9909090906C0170F6FFFFFFFFFFFF70", +"70FFFFFFFFFFD1CCD0CCC8C8C3C3BFBFBFBABBBACCFFFFFFFFFFD1BBF9F990B490B490906D6C6C6CA6FFFFFFFFFFFF70", +"70FFFFFFFFF6AACCD1CCC7C7C3C3BFBEBFBABABBD1FFFFFFFFFFF699F990B4F990F99090906C700199FFFFFFFFFFFF70", +"70FFFFFFFFFFA6D0CCC8C7C3C3BFBFBFBABBB6BFF6FFFFFFFFFFFFC8F9F990F99091F99190906C0194D1FFFFFFFFFF6C", +"6CFFFFFFFFF6C8CCCCC7C4C3BFBFBEBFBABBB6C8FFFFCCBBC4FFFFD091F9F991F9F990F9906C6D016CAAFFFFFFFFFF70", +"70FFFFFFF6D5A5CCC8C7C3C3BFBEBBBABBBAB6F6F6C4F9F9F9BBD1FFBBF990F9F991F99091906C016CA2FFFFFFFFFF70", +"70FFFFFFFFAEC4C7C7C3BFBFBEBFBABBB6B6BBD1BBF9F9F9F9F9B6CCC8F9B4F990F990909090706C6CA2F6FFFFFFFF70", +"70FFFFFFFFCCC3C8C3C3BFBEBBBABBBAB6B7BBB6F9F9F9B4F9F9F9B4BBB690F9B490B49090916C016CA1FFFFFFFFFF6C", +"6CFFFFFFFFD19DC3BFBFBFBBBABBB6B7B6F9F9F9F9B4F9F9F9B4F9F9F9B4F9F9F9F990B4906C6C016CC8FFFFFFFFFF70", +"70FFFFFFFFF69DBEBFBEBABABBB6B6B6F9F9F9B4F990F9B4F9F9F9F9F9F9F991F990F99090706C016CAAFFFFFFFFFF70", +"70FFFFFFFFFFA2B6BBBAB7B6B6B6B4F9B4F991909090F9F9F990B4F9B4F9F9F9F9B49090906D6C0199FFFFFFFFFFFF70", +"70FFFFFFFFF6F694F9B6B6B4F9F9F9F990F9909090C8A2F999CC95F9F9F9B4F9909090916C6C0190A6FFFFFFFFFFFF6C", +"6CFFFFFFFFFFFFCC91F990F9B4F991F991906C909DFFCCF9BFFFCCF9F9F990F9F991906C70016CA2FFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFC895909090909090906C909EFFFFA2F995FFFFA6B790F99190906C6C6C6CC4F6F6FFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFAEBF9590906C906C99C8FFF6FFBFB69008FFFFF69DB7906C6C6C9499D5F6F6FFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFD0A6A2C3A6CCFFFFFFFF08BBF990A2F6FFFFFFF6CCC8C8CCAFFFF6FFFFFFFFFFFFFFFFFF6C", +"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6BFF99095F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D1A1BFF9906CA6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2C3BBF9F96C95F6F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6A1C3B6F9B4906C99FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", +"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAC3C3BAB4F9F990906C9DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD19DBBBBB6F9F9F990F990909099AAFFFFFFFFFFFFFFFFFFF6FFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A2A1BF9D9EBFA2BFA2BFA29DA2BFA2CCFFFFFFFFF6FFFFFFFFFFFFFFFFFFFF70", +"70FFFFFFFFFFFFFFFFFFFFFFFFFFFFF6FFFFFFFFFFFFFFFFFFFFFFFFF6FFF6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C", +"6CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70", +"704C706C7001706C7001706C70706C7070707070707070706C7070707070704C707001707001706C704C6C7070017070"}; From 30103c5cb2a45a520afd8c03154ec71d930b1e53 Mon Sep 17 00:00:00 2001 From: fpdb-mme Date: Tue, 27 Oct 2009 09:01:06 +0100 Subject: [PATCH 03/11] second try... Signed-off-by: fpdb-mme --- pyfpdb/DatabaseManager.py | 419 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 pyfpdb/DatabaseManager.py diff --git a/pyfpdb/DatabaseManager.py b/pyfpdb/DatabaseManager.py new file mode 100644 index 00000000..130035cb --- /dev/null +++ b/pyfpdb/DatabaseManager.py @@ -0,0 +1,419 @@ + +import os +import pygtk +pygtk.require('2.0') +import gtk + +#******************************************************************************************************* +class DatabaseManager(object): + DatabaseTypes = {} + + def __init__(self, defaultDatabaseType=None): + self._defaultDatabaseType = defaultDatabaseType + def set_default_database_type(self, databaseType): + self._defaultDatabaseType = defaultDatabaseType + def get_default_database_type(self): + return self._defaultDatabaseType + +class DatabaseTypeMeta(type): + def __new__(klass, name, bases, kws): + newKlass = type.__new__(klass, name, bases, kws) + if newKlass.Type is not None: + if newKlass.Type in DatabaseManager.DatabaseTypes: + raise ValueError('data base type already registered for: %s' % newKlass.Type) + DatabaseManager.DatabaseTypes[newKlass.Type] = newKlass + return newKlass + +class DatabaseTypeBase(object): + __metaclass__ = DatabaseTypeMeta + Type = None + + DBHasHost = 0x1 + DBHasFile = 0x2 + DBHasPort = 0x4 + DBHasUser = 0x8 + DBHasPassword = 0x10 + DBHasDatabase = 0x20 + DBHasName = 0x40 + + DBFlagsFileSystem = DBHasFile|DBHasName + DBFlagsServer = DBHasHost|DBHasPort|DBHasUser|DBHasPassword|DBHasDatabase|DBHasName + + def __init__(self, host='', file='', port=0, user='', password='', database='', table='', name=''): + self.host = host + self.file = file + self.port = port + self.user = user + self.password = password + self.database = database + self.name = name + +class DatabaseTypePostgres(DatabaseTypeBase): + Type = 'postgres' + Flags = DatabaseTypeBase.DBFlagsServer + def __init__(self, host='localhost', file='', port=5432, user='postgres', password='', database='fpdb', name=''): + DatabaseTypeBase.__init__(self, host=host, file=file, port=port, user=user, password=password, database=database, name=name) + +class DatabaseTypeMysql(DatabaseTypeBase): + Type = 'mysql' + Flags = DatabaseTypeBase.DBFlagsServer + def __init__(self, host='localhost', file='root', port=3306, user='', password='', database='fpdb', name=''): + DatabaseTypeBase.__init__(self, host=host, file=file, port=port, user=user, password=password, database=database, name=name) + +class DatabaseTypeSqLite(DatabaseTypeBase): + Type = 'sqlite' + Flags = DatabaseTypeBase.DBFlagsFileSystem + def __init__(self, host='', file='', port=0, user='', password='',database='', name=''): + DatabaseTypeBase.__init__(self, host=host, file=file, port=port, user=user, password=password, database=database, name=name) + +#*************************************************************************************************************************** +class MyFileChooserButton(gtk.HBox): + #NOTE: for some weird reason it is impossible to let the user choose a non exiting filename with gtk.FileChooserButton, so impl our own on the fly + def __init__(self): + gtk.HBox.__init__(self) + self.set_homogeneous(False) + + self.entry = gtk.Entry() + self.button = gtk.Button('...') + self.button.connect('clicked', self.on_button_clicked) + + # layout widgets + self.pack_start(self.entry, True, True) + self.pack_start(self.button, False, False) + + def get_filename(self): + return self.entry.get_text() + + def set_filename(self, name): + self.entry.set_text(name) + + def on_button_clicked(self, button): + dlg = gtk.FileChooserDialog( + title='Choose an exiting database file or type in name of a new one', + parent=None, + action=gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=( + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_OK, + ), + backend=None + ) + dlg.connect('confirm-overwrite', self.on_dialog_confirm_overwrite) + dlg.set_default_response(gtk.RESPONSE_OK) + dlg.set_do_overwrite_confirmation(True) + if dlg.run() == gtk.RESPONSE_OK: + self.set_filename(dlg.get_filename()) + dlg.destroy() + + #TODO: when the user selects a sqLite database file we got three possible actions + # 1. user types in a new filename. easy one, create the file + # 2. user selectes a file with the intention to overwrite it + # 3. user selects a file with the intention to plug an existing database file in + #IDEA: impl open_existing as plug in, never overwrite, cos we can not guess + #PROBLEMS: how to validate an existing file is a database? + def on_dialog_confirm_overwrite(self, dlg): + print dlg.get_filename() + + gtk.FILE_CHOOSER_CONFIRMATION_CONFIRM + #The file chooser will present its stock dialog to confirm overwriting an existing file. + + gtk.FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME + #The file chooser will terminate and accept the user's choice of a file name. + + gtk.FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN + # + + + + + +class DialogDatabaseProperties(gtk.Dialog): + def __init__(self, databaseManager, database=None,parent=None): + gtk.Dialog.__init__(self, + title="My dialog", + parent=parent, + flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + buttons=( + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + ) + ) + self.connect('response', self.on_dialog_response) + + # setup widget + self.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database=database) + self.vbox.pack_start(self.widgetDatabaseProperties, True, True) + self.widgetDatabaseProperties.show_all() + + def get_database(self): + return self.widgetDatabaseProperties.get_database() + + def on_dialog_response(self, dlg, responseId): + if responseId == gtk.RESPONSE_REJECT: + pass + elif responseId == gtk.RESPONSE_ACCEPT: + pass + + + +class WidgetDatabaseProperties(gtk.VBox): + def __init__(self, databaseManager, database=None): + gtk.VBox.__init__(self) + + self.fieldWidgets = ( #fieldName--> fieldHandler + { + 'label': gtk.Label('Name:'), + 'widget': gtk.Entry(), + 'getter': lambda widget, database: setattr(database, 'name', widget.get_text() ), + 'setter': lambda widget, database: widget.set_text(database.name), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasName), + 'tooltip': '', + }, + { + 'label': gtk.Label('File:'), + 'widget': MyFileChooserButton(), + 'getter': lambda widget, database: lambda widget, database: setattr(database, 'file', widget.get_filename() ), + 'setter': lambda widget, database: widget.set_filename(database.file), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasFile), + 'tooltip': '', + }, + { + 'label': gtk.Label('Host:'), + 'widget': gtk.Entry(), + 'getter': lambda widget, database: setattr(database, 'host', widget.get_text() ), + 'setter': lambda widget, database: widget.set_text(database.host), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasHost), + 'tooltip': '', + }, + { + 'label': gtk.Label('Port:'), + 'widget': gtk.SpinButton(adjustment=gtk.Adjustment(value=0, lower=0, upper=999999, step_incr=1, page_incr=10) ), + 'getter': lambda widget, database: setattr(database, 'port', widget.get_value() ), + 'setter': lambda widget, database: widget.set_value(database.port), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasPort), + 'tooltip': '', + }, + { + 'label': gtk.Label('User:'), + 'widget': gtk.Entry(), + 'getter': lambda widget, database: setattr(database, 'user', widget.get_text() ), + 'setter': lambda widget, database: widget.set_text(database.user), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasUser), + 'tooltip': '', + }, + { + 'label': gtk.Label('Pwd:'), + 'widget': gtk.Entry(), + 'getter': lambda widget, database: setattr(database, 'password', widget.get_text() ), + 'setter': lambda widget, database: widget.set_text(database.password), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasPassword), + 'tooltip': '', + }, + { + 'label': gtk.Label('DB:'), + 'widget': gtk.Entry(), + 'getter': lambda widget, database: setattr(database, 'database', widget.get_text() ), + 'setter': lambda widget, database: widget.set_text(database.database), + 'isSensitive': lambda database: bool(database.Flags & database.DBHasDatabase), + 'tooltip': 'enter name of the database to create', + }, + ) + + # setup database type combo + self.comboType = gtk.ComboBox() + listStore= gtk.ListStore(str, str) + self.comboType.set_model(listStore) + cell = gtk.CellRendererText() + self.comboType.pack_start(cell, True) + self.comboType.add_attribute(cell, 'text', 0) + # fill out combo with database type. we store (displayName, databaseType) in our model for later lookup + for dbType, dbDisplayName in sorted([(klass.Type, klass.Type) for klass in databaseManager.DatabaseTypes.values()]): + listStore.append( (dbDisplayName, dbType) ) + self.comboType.connect('changed', self.on_combo_type_changed) + + # init and layout field widgets + self.pack_start(self.comboType, False, False, 2) + table = gtk.Table(rows=len(self.fieldWidgets) +1, columns=2, homogeneous=False) + self.pack_start(table, False, False, 2) + for i,fieldWidget in enumerate(self.fieldWidgets): + fieldWidget['widget'].set_tooltip_text(fieldWidget['tooltip']) + + table.attach(fieldWidget['label'], 0, 1, i, i+1, xoptions=gtk.FILL) + table.attach(fieldWidget['widget'], 1, 2, i, i+1) + + # init widget + + # if a database has been passed user is not allowed to change database type + if database is None: + self.comboType.set_button_sensitivity(gtk.SENSITIVITY_ON) + else: + self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF) + + # set current database + self.databaseManager = databaseManager + self.database= None + if database is None: + databaseType = self.databaseManager.get_default_database_type() + if databaseType is not None: + database = databaseType() + if database is not None: + self.set_database(database) + + def on_combo_type_changed(self, combo): + i = self.comboType.get_active() + if i > -1: + # change database if necessary + currentDatabaseType = self.comboType.get_model()[i][1] + if currentDatabaseType != self.database.Type: + newDatabase = self.databaseManager.DatabaseTypes[currentDatabaseType]() + self.set_database(newDatabase) + + def set_database(self, database): + self.database = database + + # adjust database type combo if necessary + i = self.comboType.get_active() + if i == -1: + currentDatabaseType = None + else: + currentDatabaseType = self.comboType.get_model()[i][1] + if currentDatabaseType != self.database.Type: + for i, row in enumerate(self.comboType.get_model()): + if row[1] == self.database.Type: + self.comboType.set_active(i) + break + else: + raise ValueError('unknown database type') + + # adjust field widgets to database + for fieldWidget in self.fieldWidgets: + isSensitive = fieldWidget['isSensitive'](self.database) + fieldWidget['widget'].set_sensitive(isSensitive) + fieldWidget['label'].set_sensitive(isSensitive) + fieldWidget['setter'](fieldWidget['widget'], self.database) + + def get_database(self): + for fieldWidget in self.fieldWidgets: + fieldWidget['getter'](fieldWidget['widget'], self.database) + return self.database + + +#TODO: just boilerplate code +class DialogDatabase(gtk.Dialog): + def __init__(self, databaseManager, parent=None): + gtk.Dialog.__init__(self, + title="My dialog", + parent=parent, + flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + buttons=( + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + )) + #self.set_size_request(260, 250) + + self.databaseManager = databaseManager + + #TODO: dono how to make word wrap work as expected + self.labelInfo = gtk.Label('database management') + self.labelInfo.set_line_wrap(True) + self.labelInfo.set_selectable(True) + self.labelInfo.set_single_line_mode(False) + self.labelInfo.set_alignment(0, 0) + + # database management buttons + + #TODO: bit messy the distinction New/Add/Edit. we'd have to pass three flags to DialogDatabaseProperties + # to handle this. maybe drop Edit (is just a Remove + Add), to keep things simple + self.buttonDatabaseNew = gtk.Button("New..") + self.buttonDatabaseNew.set_tooltip_text('creates a new database') + self.buttonDatabaseNew.connect('clicked', self.on_button_database_new_clicked) + self.buttonDatabaseAdd = gtk.Button("Add..") + self.buttonDatabaseAdd.set_tooltip_text('adds an existing database') + self.buttonDatabaseAdd.connect('clicked', self.on_button_database_add_clicked) + self.buttonDatabaseEdit = gtk.Button("Edit..") + self.buttonDatabaseEdit.set_tooltip_text('edit database settings') + #self.buttonDatabaseEdit.connect('clicked', self.on_button_database_edit_clicked) + self.buttonDatabaseRemove = gtk.Button("Remove") + self.buttonDatabaseRemove.set_tooltip_text('removes the database from the list') + + #TODO: i dont think we should do any real database management here. maybe drop it + self.buttonDatabaseDelete = gtk.Button("Delete") + self.buttonDatabaseDelete.set_tooltip_text('removes the database from the list and deletes it') + + # database tree + self.treeDatabases = gtk.TreeView() + store = gtk.ListStore(str, str, str) + self.treeDatabases.set_model(store) + columns = ('Name', 'Status', 'Type') + for i, column in enumerate(columns): + col = gtk.TreeViewColumn(column, gtk.CellRendererText(), text=i) + self.treeDatabases.append_column(col) + + # layout widgets + self.vbox.pack_start(self.labelInfo, False, False, 2) + self.vbox.pack_start(gtk.HSeparator(), False, False, 2) + + hbox = gtk.HBox() + self.vbox.add(hbox) + hbox.set_homogeneous(False) + vbox = gtk.VBox() + hbox.pack_start(vbox, False, False, 2) + vbox.pack_start(self.buttonDatabaseNew, False, False, 2) + vbox.pack_start(self.buttonDatabaseAdd, False, False, 2) + vbox.pack_start(self.buttonDatabaseEdit, False, False, 2) + vbox.pack_start(self.buttonDatabaseRemove, False, False, 2) + vbox.pack_start(self.buttonDatabaseDelete, False, False, 2) + box = gtk.VBox() + vbox.pack_start(box, True, True, 0) + + hbox.pack_start(gtk.VSeparator(), False, False, 2) + hbox.pack_end(self.treeDatabases, True, True, 2) + + self.show_all() + + + #TODO: for some reason i have to click OK/Cancel twice to close the dialog + def on_button_database_new_clicked(self, button): + dlg = DialogDatabaseProperties(self.databaseManager, parent=self) + if dlg.run() == gtk.RESPONSE_REJECT: + pass + if dlg.run() == gtk.RESPONSE_ACCEPT: + database = dlg.get_database() + self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) + + dlg.destroy() + + def on_button_database_add_clicked(self, button): + dlg = DialogDatabaseProperties(self.databaseManager, parent=self) + if dlg.run() == gtk.RESPONSE_REJECT: + pass + if dlg.run() == gtk.RESPONSE_ACCEPT: + database = dlg.get_database() + self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) + + dlg.destroy() + + #def on_button_database_edit_clicked(self, button): + # dlg = DialogDatabaseProperties(self.databaseManager, parent=self) + # if dlg.run() == gtk.RESPONSE_REJECT: + # pass + # if dlg.run() == gtk.RESPONSE_ACCEPT: + # database = dlg.get_database() + # self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) + # + # dlg.destroy() + + +#************************************************************************************************** +if __name__ == '__main__': + #d = DialogDatabaseProperties( + # DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite), + #database=DatabaseTypePostgres(), + # database=None, + # ) + d = DialogDatabase(DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite)) + d.connect("destroy", gtk.main_quit) + d.run() + #gtk.main() + + From e732b749561c97f8f52d1ab5c1a199ff721af202 Mon Sep 17 00:00:00 2001 From: fpdb-mme Date: Tue, 27 Oct 2009 11:04:24 +0100 Subject: [PATCH 04/11] too many changes to remember Signed-off-by: fpdb-mme --- pyfpdb/DatabaseManager.py | 839 ++++++++++++++++++++------------------ 1 file changed, 452 insertions(+), 387 deletions(-) diff --git a/pyfpdb/DatabaseManager.py b/pyfpdb/DatabaseManager.py index 130035cb..a9269654 100644 --- a/pyfpdb/DatabaseManager.py +++ b/pyfpdb/DatabaseManager.py @@ -6,414 +6,479 @@ import gtk #******************************************************************************************************* class DatabaseManager(object): - DatabaseTypes = {} - - def __init__(self, defaultDatabaseType=None): - self._defaultDatabaseType = defaultDatabaseType - def set_default_database_type(self, databaseType): - self._defaultDatabaseType = defaultDatabaseType - def get_default_database_type(self): - return self._defaultDatabaseType - + DatabaseTypes = {} + + def __init__(self, defaultDatabaseType=None): + self._defaultDatabaseType = defaultDatabaseType + def set_default_database_type(self, databaseType): + self._defaultDatabaseType = defaultDatabaseType + def get_default_database_type(self): + return self._defaultDatabaseType + class DatabaseTypeMeta(type): - def __new__(klass, name, bases, kws): - newKlass = type.__new__(klass, name, bases, kws) - if newKlass.Type is not None: - if newKlass.Type in DatabaseManager.DatabaseTypes: - raise ValueError('data base type already registered for: %s' % newKlass.Type) - DatabaseManager.DatabaseTypes[newKlass.Type] = newKlass - return newKlass + def __new__(klass, name, bases, kws): + newKlass = type.__new__(klass, name, bases, kws) + if newKlass.Type is not None: + if newKlass.Type in DatabaseManager.DatabaseTypes: + raise ValueError('data base type already registered for: %s' % newKlass.Type) + DatabaseManager.DatabaseTypes[newKlass.Type] = newKlass + return newKlass class DatabaseTypeBase(object): - __metaclass__ = DatabaseTypeMeta - Type = None - - DBHasHost = 0x1 - DBHasFile = 0x2 - DBHasPort = 0x4 - DBHasUser = 0x8 - DBHasPassword = 0x10 - DBHasDatabase = 0x20 - DBHasName = 0x40 - - DBFlagsFileSystem = DBHasFile|DBHasName - DBFlagsServer = DBHasHost|DBHasPort|DBHasUser|DBHasPassword|DBHasDatabase|DBHasName - - def __init__(self, host='', file='', port=0, user='', password='', database='', table='', name=''): - self.host = host - self.file = file - self.port = port - self.user = user - self.password = password - self.database = database - self.name = name + __metaclass__ = DatabaseTypeMeta + Type = None class DatabaseTypePostgres(DatabaseTypeBase): - Type = 'postgres' - Flags = DatabaseTypeBase.DBFlagsServer - def __init__(self, host='localhost', file='', port=5432, user='postgres', password='', database='fpdb', name=''): - DatabaseTypeBase.__init__(self, host=host, file=file, port=port, user=user, password=password, database=database, name=name) + Type = 'postgres' + def __init__(self, host='localhost', port=5432, user='postgres', password='', database='fpdb', name=''): + self.host = host + self.port = port + self.user = user + self.password = password + self.database = database + self.name = name class DatabaseTypeMysql(DatabaseTypeBase): - Type = 'mysql' - Flags = DatabaseTypeBase.DBFlagsServer - def __init__(self, host='localhost', file='root', port=3306, user='', password='', database='fpdb', name=''): - DatabaseTypeBase.__init__(self, host=host, file=file, port=port, user=user, password=password, database=database, name=name) - + Type = 'mysql' + def __init__(self, host='localhost', port=3306, user='root', password='', database='fpdb', name=''): + self.host = host + self.port = port + self.user = user + self.password = password + self.database = database + self.name = name + class DatabaseTypeSqLite(DatabaseTypeBase): - Type = 'sqlite' - Flags = DatabaseTypeBase.DBFlagsFileSystem - def __init__(self, host='', file='', port=0, user='', password='',database='', name=''): - DatabaseTypeBase.__init__(self, host=host, file=file, port=port, user=user, password=password, database=database, name=name) - + Type = 'sqlite' + def __init__(self, host='', file='', name=''): + self.file = file + self.name = name + #*************************************************************************************************************************** class MyFileChooserButton(gtk.HBox): - #NOTE: for some weird reason it is impossible to let the user choose a non exiting filename with gtk.FileChooserButton, so impl our own on the fly - def __init__(self): - gtk.HBox.__init__(self) - self.set_homogeneous(False) - - self.entry = gtk.Entry() - self.button = gtk.Button('...') - self.button.connect('clicked', self.on_button_clicked) - - # layout widgets - self.pack_start(self.entry, True, True) - self.pack_start(self.button, False, False) - - def get_filename(self): - return self.entry.get_text() - - def set_filename(self, name): - self.entry.set_text(name) - - def on_button_clicked(self, button): - dlg = gtk.FileChooserDialog( - title='Choose an exiting database file or type in name of a new one', - parent=None, - action=gtk.FILE_CHOOSER_ACTION_SAVE, - buttons=( - gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, - gtk.STOCK_OK, gtk.RESPONSE_OK, - ), - backend=None - ) - dlg.connect('confirm-overwrite', self.on_dialog_confirm_overwrite) - dlg.set_default_response(gtk.RESPONSE_OK) - dlg.set_do_overwrite_confirmation(True) - if dlg.run() == gtk.RESPONSE_OK: - self.set_filename(dlg.get_filename()) - dlg.destroy() - - #TODO: when the user selects a sqLite database file we got three possible actions - # 1. user types in a new filename. easy one, create the file - # 2. user selectes a file with the intention to overwrite it - # 3. user selects a file with the intention to plug an existing database file in - #IDEA: impl open_existing as plug in, never overwrite, cos we can not guess - #PROBLEMS: how to validate an existing file is a database? - def on_dialog_confirm_overwrite(self, dlg): - print dlg.get_filename() - - gtk.FILE_CHOOSER_CONFIRMATION_CONFIRM - #The file chooser will present its stock dialog to confirm overwriting an existing file. + #NOTE: for some weird reason it is impossible to let the user choose a non exiting filename with gtk.FileChooserButton, so impl our own on the fly + def __init__(self): + gtk.HBox.__init__(self) + self.set_homogeneous(False) + + self.entry = gtk.Entry() + self.button = gtk.Button('...') + self.button.connect('clicked', self.on_button_clicked) + + # layout widgets + self.pack_start(self.entry, True, True) + self.pack_start(self.button, False, False) + + def get_filename(self): + return self.entry.get_text() + + def set_filename(self, name): + self.entry.set_text(name) + + def on_button_clicked(self, button): + dlg = gtk.FileChooserDialog( + title='Choose an exiting database file or type in name of a new one', + parent=None, + action=gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=( + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_OK, + ), + backend=None + ) + dlg.connect('confirm-overwrite', self.on_dialog_confirm_overwrite) + dlg.set_default_response(gtk.RESPONSE_OK) + dlg.set_do_overwrite_confirmation(True) + if dlg.run() == gtk.RESPONSE_OK: + self.set_filename(dlg.get_filename()) + dlg.destroy() + + #TODO: when the user selects a sqLite database file we got three possible actions + # 1. user types in a new filename. easy one, create the file + # 2. user selectes a file with the intention to overwrite it + # 3. user selects a file with the intention to plug an existing database file in + #IDEA: impl open_existing as plug in, never overwrite, cos we can not guess + #PROBLEMS: how to validate an existing file is a database? + def on_dialog_confirm_overwrite(self, dlg): + print dlg.get_filename() + + gtk.FILE_CHOOSER_CONFIRMATION_CONFIRM + #The file chooser will present its stock dialog to confirm overwriting an existing file. - gtk.FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME - #The file chooser will terminate and accept the user's choice of a file name. + gtk.FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME + #The file chooser will terminate and accept the user's choice of a file name. - gtk.FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN - # - - - + gtk.FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN + # + + +class WidgetDatabaseProperties(gtk.VBox): + ModeEdit = 0x1 + ModeAdd = 0x2 + ModeNew = 0x4 + + class FieldWidget(object): + def __init__(self, text='', attrDatabase='', widget=None, attrGet=None, attrSet=None, defaultValue=None, canEdit=False, tooltip=''): + """ + @param canEdit: True if the user can edit the attr in edit mode, False otherwise + """ + self._label = gtk.Label(text) + self._attrDatabase = attrDatabase + self._widget = widget + self._defaultValue = defaultValue + self._attrGetter=None, + self._attrGet = attrGet + self._attrSet = attrSet + self._canEdit = canEdit + + self._label.set_tooltip_text(tooltip) + self._widget.set_tooltip_text(tooltip) + + def widget(self): + return self._widget + def label(self): + return self._label + def is_sensitive(self, database): + return hasattr(database, self._attrDatabase) + def can_edit(self): + return self._canEdit + def set_sensitive(self, flag): + self._label.set_sensitive(flag) + self._widget.set_sensitive(flag) + def value_from_database(self, database): + getattr(self._widget, self._attrSet)( getattr(database, self._attrDatabase) ) + def value_to_database(self, database): + setattr(database, self._attrDatabase, getattr(self._widget, self._attrGet)() ) + def reset_value(self): + getattr(self._widget, self._attrSet)(self._defaultValue) + + def __init__(self, databaseManager, database=None, flags=ModeEdit): + gtk.VBox.__init__(self) + + self.flags = flags + self.fieldWidgets = ( #fieldName--> fieldHandler + self.FieldWidget( + text='Name:', + attrDatabase='name', + widget=gtk.Entry(), + defaultValue='', + attrGet='get_text', + attrSet='set_text', + canEdit=True, + tooltip='' + ), + self.FieldWidget( + text='File:', + attrDatabase='file', + widget=MyFileChooserButton(), + defaultValue='', + attrGet='get_filename', + attrSet='set_filename', + canEdit=False, + tooltip='' + ), + self.FieldWidget( + text='Host:', + attrDatabase='host', + widget=gtk.Entry(), + defaultValue='', + attrGet='get_text', + attrSet='set_text', + canEdit=False, + tooltip='' + ), + self.FieldWidget( + text='Port:', + attrDatabase='port', + widget=gtk.SpinButton(adjustment=gtk.Adjustment(value=0, lower=0, upper=999999, step_incr=1, page_incr=10) ), + defaultValue=0, + attrGet='get_value', + attrSet='set_value', + canEdit=False, + tooltip='' + ), + self.FieldWidget( + text='User:', + attrDatabase='user', + widget=gtk.Entry(), + defaultValue='', + attrGet='get_text', + attrSet='set_text', + canEdit=False, + tooltip='' + ), + self.FieldWidget( + text='Pwd:', + attrDatabase='password', + widget=gtk.Entry(), + defaultValue='', + attrGet='get_text', + attrSet='set_text', + canEdit=False, + tooltip='' + ), + self.FieldWidget( + text='Db:', + attrDatabase='database', + widget=gtk.Entry(), + defaultValue='', + attrGet='get_text', + attrSet='set_text', + canEdit=False, + tooltip='' + ), + ) + + # setup database type combo + self.comboType = gtk.ComboBox() + listStore= gtk.ListStore(str, str) + self.comboType.set_model(listStore) + cell = gtk.CellRendererText() + self.comboType.pack_start(cell, True) + self.comboType.add_attribute(cell, 'text', 0) + # fill out combo with database type. we store (displayName, databaseType) in our model for later lookup + for dbType, dbDisplayName in sorted([(klass.Type, klass.Type) for klass in databaseManager.DatabaseTypes.values()]): + listStore.append( (dbDisplayName, dbType) ) + self.comboType.connect('changed', self.on_combo_type_changed) + + # init and layout field widgets + self.pack_start(self.comboType, False, False, 2) + table = gtk.Table(rows=len(self.fieldWidgets) +1, columns=2, homogeneous=False) + self.pack_start(table, False, False, 2) + for i,fieldWidget in enumerate(self.fieldWidgets): + table.attach(fieldWidget.label(), 0, 1, i, i+1, xoptions=gtk.FILL) + table.attach(fieldWidget.widget(), 1, 2, i, i+1) + + # init widget + + # if a database has been passed user is not allowed to change database type + if database is None: + self.comboType.set_button_sensitivity(gtk.SENSITIVITY_ON) + else: + self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF) + + # set current database + self.databaseManager = databaseManager + self.database= None + if database is None: + databaseType = self.databaseManager.get_default_database_type() + if databaseType is not None: + database = databaseType() + if database is not None: + self.set_database(database) + + def on_combo_type_changed(self, combo): + i = self.comboType.get_active() + if i > -1: + # change database if necessary + currentDatabaseType = self.comboType.get_model()[i][1] + if currentDatabaseType != self.database.Type: + newDatabase = self.databaseManager.DatabaseTypes[currentDatabaseType]() + self.set_database(newDatabase) + + def set_database(self, database): + self.database = database + + # adjust database type combo if necessary + i = self.comboType.get_active() + if i == -1: + currentDatabaseType = None + else: + currentDatabaseType = self.comboType.get_model()[i][1] + if currentDatabaseType != self.database.Type: + for i, row in enumerate(self.comboType.get_model()): + if row[1] == self.database.Type: + self.comboType.set_active(i) + break + else: + raise ValueError('unknown database type') + + # adjust field widgets to database + for fieldWidget in self.fieldWidgets: + isSensitive = fieldWidget.is_sensitive(self.database) + if isSensitive: + fieldWidget.value_from_database(self.database) + else: + fieldWidget.reset_value() + if self.flags & self.ModeEdit: + isSensitive = isSensitive and fieldWidget.can_edit() + fieldWidget.set_sensitive(isSensitive) + + def get_database(self): + for fieldWidget in self.fieldWidgets: + if fieldWidget.is_sensitive(self.database): + fieldWidget.value_to_database(self.database) + return self.database class DialogDatabaseProperties(gtk.Dialog): - def __init__(self, databaseManager, database=None,parent=None): - gtk.Dialog.__init__(self, - title="My dialog", - parent=parent, - flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - buttons=( - gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, - gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, - ) - ) - self.connect('response', self.on_dialog_response) - - # setup widget - self.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database=database) - self.vbox.pack_start(self.widgetDatabaseProperties, True, True) - self.widgetDatabaseProperties.show_all() + def __init__(self, databaseManager, database=None,parent=None, flags=WidgetDatabaseProperties.ModeEdit): + if flags & WidgetDatabaseProperties.ModeEdit: + title = '[Edit database] - database properties' + elif flags & WidgetDatabaseProperties.ModeAdd: + title = '[Add database] - database properties' + elif flags & WidgetDatabaseProperties.ModeNew: + title = '[New database] - database properties' + else: + title = 'database properties' + + gtk.Dialog.__init__(self, + title=title, + parent=parent, + flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + buttons=( + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + ) + ) + self.connect('response', self.on_dialog_response) + + # setup widget + self.flags = flags + self.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database=database, flags=self.flags) + self.vbox.pack_start(self.widgetDatabaseProperties, True, True) + self.widgetDatabaseProperties.show_all() - def get_database(self): - return self.widgetDatabaseProperties.get_database() - - def on_dialog_response(self, dlg, responseId): - if responseId == gtk.RESPONSE_REJECT: - pass - elif responseId == gtk.RESPONSE_ACCEPT: - pass - - - -class WidgetDatabaseProperties(gtk.VBox): - def __init__(self, databaseManager, database=None): - gtk.VBox.__init__(self) - - self.fieldWidgets = ( #fieldName--> fieldHandler - { - 'label': gtk.Label('Name:'), - 'widget': gtk.Entry(), - 'getter': lambda widget, database: setattr(database, 'name', widget.get_text() ), - 'setter': lambda widget, database: widget.set_text(database.name), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasName), - 'tooltip': '', - }, - { - 'label': gtk.Label('File:'), - 'widget': MyFileChooserButton(), - 'getter': lambda widget, database: lambda widget, database: setattr(database, 'file', widget.get_filename() ), - 'setter': lambda widget, database: widget.set_filename(database.file), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasFile), - 'tooltip': '', - }, - { - 'label': gtk.Label('Host:'), - 'widget': gtk.Entry(), - 'getter': lambda widget, database: setattr(database, 'host', widget.get_text() ), - 'setter': lambda widget, database: widget.set_text(database.host), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasHost), - 'tooltip': '', - }, - { - 'label': gtk.Label('Port:'), - 'widget': gtk.SpinButton(adjustment=gtk.Adjustment(value=0, lower=0, upper=999999, step_incr=1, page_incr=10) ), - 'getter': lambda widget, database: setattr(database, 'port', widget.get_value() ), - 'setter': lambda widget, database: widget.set_value(database.port), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasPort), - 'tooltip': '', - }, - { - 'label': gtk.Label('User:'), - 'widget': gtk.Entry(), - 'getter': lambda widget, database: setattr(database, 'user', widget.get_text() ), - 'setter': lambda widget, database: widget.set_text(database.user), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasUser), - 'tooltip': '', - }, - { - 'label': gtk.Label('Pwd:'), - 'widget': gtk.Entry(), - 'getter': lambda widget, database: setattr(database, 'password', widget.get_text() ), - 'setter': lambda widget, database: widget.set_text(database.password), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasPassword), - 'tooltip': '', - }, - { - 'label': gtk.Label('DB:'), - 'widget': gtk.Entry(), - 'getter': lambda widget, database: setattr(database, 'database', widget.get_text() ), - 'setter': lambda widget, database: widget.set_text(database.database), - 'isSensitive': lambda database: bool(database.Flags & database.DBHasDatabase), - 'tooltip': 'enter name of the database to create', - }, - ) - - # setup database type combo - self.comboType = gtk.ComboBox() - listStore= gtk.ListStore(str, str) - self.comboType.set_model(listStore) - cell = gtk.CellRendererText() - self.comboType.pack_start(cell, True) - self.comboType.add_attribute(cell, 'text', 0) - # fill out combo with database type. we store (displayName, databaseType) in our model for later lookup - for dbType, dbDisplayName in sorted([(klass.Type, klass.Type) for klass in databaseManager.DatabaseTypes.values()]): - listStore.append( (dbDisplayName, dbType) ) - self.comboType.connect('changed', self.on_combo_type_changed) - - # init and layout field widgets - self.pack_start(self.comboType, False, False, 2) - table = gtk.Table(rows=len(self.fieldWidgets) +1, columns=2, homogeneous=False) - self.pack_start(table, False, False, 2) - for i,fieldWidget in enumerate(self.fieldWidgets): - fieldWidget['widget'].set_tooltip_text(fieldWidget['tooltip']) - - table.attach(fieldWidget['label'], 0, 1, i, i+1, xoptions=gtk.FILL) - table.attach(fieldWidget['widget'], 1, 2, i, i+1) - - # init widget - - # if a database has been passed user is not allowed to change database type - if database is None: - self.comboType.set_button_sensitivity(gtk.SENSITIVITY_ON) - else: - self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF) - - # set current database - self.databaseManager = databaseManager - self.database= None - if database is None: - databaseType = self.databaseManager.get_default_database_type() - if databaseType is not None: - database = databaseType() - if database is not None: - self.set_database(database) - - def on_combo_type_changed(self, combo): - i = self.comboType.get_active() - if i > -1: - # change database if necessary - currentDatabaseType = self.comboType.get_model()[i][1] - if currentDatabaseType != self.database.Type: - newDatabase = self.databaseManager.DatabaseTypes[currentDatabaseType]() - self.set_database(newDatabase) - - def set_database(self, database): - self.database = database - - # adjust database type combo if necessary - i = self.comboType.get_active() - if i == -1: - currentDatabaseType = None - else: - currentDatabaseType = self.comboType.get_model()[i][1] - if currentDatabaseType != self.database.Type: - for i, row in enumerate(self.comboType.get_model()): - if row[1] == self.database.Type: - self.comboType.set_active(i) - break - else: - raise ValueError('unknown database type') - - # adjust field widgets to database - for fieldWidget in self.fieldWidgets: - isSensitive = fieldWidget['isSensitive'](self.database) - fieldWidget['widget'].set_sensitive(isSensitive) - fieldWidget['label'].set_sensitive(isSensitive) - fieldWidget['setter'](fieldWidget['widget'], self.database) - - def get_database(self): - for fieldWidget in self.fieldWidgets: - fieldWidget['getter'](fieldWidget['widget'], self.database) - return self.database - - + def get_database(self): + return self.widgetDatabaseProperties.get_database() + + def on_dialog_response(self, dlg, responseId): + if responseId == gtk.RESPONSE_REJECT: + pass + elif responseId == gtk.RESPONSE_ACCEPT: + pass + + #TODO: just boilerplate code class DialogDatabase(gtk.Dialog): - def __init__(self, databaseManager, parent=None): - gtk.Dialog.__init__(self, - title="My dialog", - parent=parent, - flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - buttons=( - gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, - gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, - )) - #self.set_size_request(260, 250) - - self.databaseManager = databaseManager - - #TODO: dono how to make word wrap work as expected - self.labelInfo = gtk.Label('database management') - self.labelInfo.set_line_wrap(True) - self.labelInfo.set_selectable(True) - self.labelInfo.set_single_line_mode(False) - self.labelInfo.set_alignment(0, 0) - - # database management buttons - - #TODO: bit messy the distinction New/Add/Edit. we'd have to pass three flags to DialogDatabaseProperties - # to handle this. maybe drop Edit (is just a Remove + Add), to keep things simple - self.buttonDatabaseNew = gtk.Button("New..") - self.buttonDatabaseNew.set_tooltip_text('creates a new database') - self.buttonDatabaseNew.connect('clicked', self.on_button_database_new_clicked) - self.buttonDatabaseAdd = gtk.Button("Add..") - self.buttonDatabaseAdd.set_tooltip_text('adds an existing database') - self.buttonDatabaseAdd.connect('clicked', self.on_button_database_add_clicked) - self.buttonDatabaseEdit = gtk.Button("Edit..") - self.buttonDatabaseEdit.set_tooltip_text('edit database settings') - #self.buttonDatabaseEdit.connect('clicked', self.on_button_database_edit_clicked) - self.buttonDatabaseRemove = gtk.Button("Remove") - self.buttonDatabaseRemove.set_tooltip_text('removes the database from the list') - - #TODO: i dont think we should do any real database management here. maybe drop it - self.buttonDatabaseDelete = gtk.Button("Delete") - self.buttonDatabaseDelete.set_tooltip_text('removes the database from the list and deletes it') - - # database tree - self.treeDatabases = gtk.TreeView() - store = gtk.ListStore(str, str, str) - self.treeDatabases.set_model(store) - columns = ('Name', 'Status', 'Type') - for i, column in enumerate(columns): - col = gtk.TreeViewColumn(column, gtk.CellRendererText(), text=i) - self.treeDatabases.append_column(col) - - # layout widgets - self.vbox.pack_start(self.labelInfo, False, False, 2) - self.vbox.pack_start(gtk.HSeparator(), False, False, 2) - - hbox = gtk.HBox() - self.vbox.add(hbox) - hbox.set_homogeneous(False) - vbox = gtk.VBox() - hbox.pack_start(vbox, False, False, 2) - vbox.pack_start(self.buttonDatabaseNew, False, False, 2) - vbox.pack_start(self.buttonDatabaseAdd, False, False, 2) - vbox.pack_start(self.buttonDatabaseEdit, False, False, 2) - vbox.pack_start(self.buttonDatabaseRemove, False, False, 2) - vbox.pack_start(self.buttonDatabaseDelete, False, False, 2) - box = gtk.VBox() - vbox.pack_start(box, True, True, 0) - - hbox.pack_start(gtk.VSeparator(), False, False, 2) - hbox.pack_end(self.treeDatabases, True, True, 2) - - self.show_all() - - - #TODO: for some reason i have to click OK/Cancel twice to close the dialog - def on_button_database_new_clicked(self, button): - dlg = DialogDatabaseProperties(self.databaseManager, parent=self) - if dlg.run() == gtk.RESPONSE_REJECT: - pass - if dlg.run() == gtk.RESPONSE_ACCEPT: - database = dlg.get_database() - self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) - - dlg.destroy() + def __init__(self, databaseManager, parent=None): + gtk.Dialog.__init__(self, + title="My dialog", + parent=parent, + flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + buttons=( + gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, + )) + #self.set_size_request(260, 250) + + self.databaseManager = databaseManager + + #TODO: dono how to make word wrap work as expected + self.labelInfo = gtk.Label('database management') + self.labelInfo.set_line_wrap(True) + self.labelInfo.set_selectable(True) + self.labelInfo.set_single_line_mode(False) + self.labelInfo.set_alignment(0, 0) + + # database management buttons + + #TODO: bit messy the distinction New/Add/Edit. we'd have to pass three flags to DialogDatabaseProperties + # to handle this. maybe drop Edit (is just a Remove + Add), to keep things simple + self.buttonDatabaseNew = gtk.Button("New..") + self.buttonDatabaseNew.set_tooltip_text('creates a new database') + self.buttonDatabaseNew.connect('clicked', self.on_button_database_new_clicked) + self.buttonDatabaseAdd = gtk.Button("Add..") + self.buttonDatabaseAdd.set_tooltip_text('adds an existing database') + self.buttonDatabaseAdd.connect('clicked', self.on_button_database_add_clicked) + self.buttonDatabaseEdit = gtk.Button("Edit..") + self.buttonDatabaseEdit.set_tooltip_text('edit database settings') + self.buttonDatabaseEdit.connect('clicked', self.on_button_database_edit_clicked) + self.buttonDatabaseEdit.set_sensitive(False) + self.buttonDatabaseRemove = gtk.Button("Remove") + self.buttonDatabaseRemove.set_tooltip_text('removes the database from the list') + self.buttonDatabaseRemove.set_sensitive(False) + + #TODO: i dont think we should do any real database management here. maybe drop it + self.buttonDatabaseDelete = gtk.Button("Delete") + self.buttonDatabaseDelete.set_tooltip_text('removes the database from the list and deletes it') + self.buttonDatabaseDelete.set_sensitive(False) + + # database tree + self.treeDatabases = gtk.TreeView() + store = gtk.ListStore(str, str, str) + self.treeDatabases.set_model(store) + columns = ('Name', 'Status', 'Type') + for i, column in enumerate(columns): + col = gtk.TreeViewColumn(column, gtk.CellRendererText(), text=i) + self.treeDatabases.append_column(col) + self.treeDatabases.get_selection().connect('changed', self.on_tree_databases_selection_changed) + + # layout widgets + self.vbox.pack_start(self.labelInfo, False, False, 2) + self.vbox.pack_start(gtk.HSeparator(), False, False, 2) + + hbox = gtk.HBox() + self.vbox.add(hbox) + hbox.set_homogeneous(False) + vbox = gtk.VBox() + hbox.pack_start(vbox, False, False, 2) + vbox.pack_start(self.buttonDatabaseNew, False, False, 2) + vbox.pack_start(self.buttonDatabaseAdd, False, False, 2) + vbox.pack_start(self.buttonDatabaseEdit, False, False, 2) + vbox.pack_start(self.buttonDatabaseRemove, False, False, 2) + vbox.pack_start(self.buttonDatabaseDelete, False, False, 2) + box = gtk.VBox() + vbox.pack_start(box, True, True, 0) + + hbox.pack_start(gtk.VSeparator(), False, False, 2) + hbox.pack_end(self.treeDatabases, True, True, 2) + + self.show_all() + + + #TODO: for some reason i have to click OK/Cancel twice to close the dialog + def on_button_database_new_clicked(self, button): + dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeNew) + if dlg.run() == gtk.RESPONSE_REJECT: + pass + if dlg.run() == gtk.RESPONSE_ACCEPT: + database = dlg.get_database() + self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) + dlg.destroy() - def on_button_database_add_clicked(self, button): - dlg = DialogDatabaseProperties(self.databaseManager, parent=self) - if dlg.run() == gtk.RESPONSE_REJECT: - pass - if dlg.run() == gtk.RESPONSE_ACCEPT: - database = dlg.get_database() - self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) - - dlg.destroy() - - #def on_button_database_edit_clicked(self, button): - # dlg = DialogDatabaseProperties(self.databaseManager, parent=self) - # if dlg.run() == gtk.RESPONSE_REJECT: - # pass - # if dlg.run() == gtk.RESPONSE_ACCEPT: - # database = dlg.get_database() - # self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) - # - # dlg.destroy() - + def on_button_database_add_clicked(self, button): + dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeAdd) + if dlg.run() == gtk.RESPONSE_REJECT: + pass + if dlg.run() == gtk.RESPONSE_ACCEPT: + database = dlg.get_database() + self.treeDatabases.get_model().append( (database.name, 'foo', database.Type) ) + dlg.destroy() + + def on_button_database_edit_clicked(self, button): + dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeEdit) + if dlg.run() == gtk.RESPONSE_REJECT: + pass + if dlg.run() == gtk.RESPONSE_ACCEPT: + database = dlg.get_database() + selection = self.treeDatabases.get_selection() + if selection is not None: + model, iter = selection.get_selected() + model.set_value(iter, 0, database.name) + dlg.destroy() + + def on_tree_databases_selection_changed(self, treeSelection): + hasSelection = bool(treeSelection.count_selected_rows()) + + # enable/disable selection dependend widgets + self.buttonDatabaseEdit.set_sensitive(hasSelection) + self.buttonDatabaseRemove.set_sensitive(hasSelection) + self.buttonDatabaseDelete.set_sensitive(hasSelection) + + + #************************************************************************************************** if __name__ == '__main__': - #d = DialogDatabaseProperties( - # DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite), - #database=DatabaseTypePostgres(), - # database=None, - # ) - d = DialogDatabase(DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite)) - d.connect("destroy", gtk.main_quit) - d.run() - #gtk.main() + #d = DialogDatabaseProperties( + # DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite), + #database=DatabaseTypePostgres(), + # database=None, + # ) + d = DialogDatabase(DatabaseManager(defaultDatabaseType=DatabaseTypeSqLite)) + d.connect("destroy", gtk.main_quit) + d.run() + #gtk.main() From e25e4cf9b3c92113396bfff39703b43f522140c3 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Tue, 27 Oct 2009 15:24:49 +0200 Subject: [PATCH 05/11] Use custom tray icon instead of GTK stock Use the "Anonymous Cards" image from openclipart.org (http://openclipart.org/media/files/Anonymous/12230) This same image is used in other new FPDB icons, but the combinations with looking-glass don't look good in systray. This icon is plain enough to work properly even when scaled really small. --- gfx/fpdb-cards.png | Bin 0 -> 3711 bytes pyfpdb/fpdb.py | 7 ++++++- setup.py | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 gfx/fpdb-cards.png diff --git a/gfx/fpdb-cards.png b/gfx/fpdb-cards.png new file mode 100644 index 0000000000000000000000000000000000000000..4d14be623637d200a58c0011f9076bc7c843a3df GIT binary patch literal 3711 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 Date: Tue, 27 Oct 2009 15:28:11 +0200 Subject: [PATCH 06/11] Typofix in status icon load --- pyfpdb/fpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index c3d7e399..5370bccb 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -628,7 +628,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.statusIcon = gtk.StatusIcon() if os.path.exists('../gfx/fpdb-cards.png'): self.statusIcon.set_from_file('../gfx/fpdb-cards.png') - elif os.path.exits('/usr/share/pixmaps/fpdb-cards.png'): + elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'): self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png') else: self.statusIcon.set_from_stock(gtk.STOCK_HOME) From 7bd7b5b053af4d4f31bf9121aa07ef39b2395f4d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Oct 2009 11:01:45 -0400 Subject: [PATCH 07/11] add todo to remind me --- pyfpdb/fpdb_db.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 986c747f..da0bbbe7 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -77,10 +77,11 @@ class fpdb_db: import MySQLdb if use_pool: MySQLdb = pool.manage(MySQLdb, pool_size=5) - try: - self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) - except: - raise FpdbMySQLFailedError("MySQL connection failed") +# try: + self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) + #TODO: Add port option +# except: +# raise FpdbMySQLFailedError("MySQL connection failed") elif backend==fpdb_db.PGSQL: import psycopg2 import psycopg2.extensions From 9886b618404429a387dfb5dbb355033464568cd9 Mon Sep 17 00:00:00 2001 From: Mika Bostrom Date: Tue, 27 Oct 2009 19:45:52 +0200 Subject: [PATCH 08/11] Tray icon click toggles window visibility Many of the tools that place an icon in systray allow to toggle the application visibility by left-clicking on the icon. Why not follow suit? --- pyfpdb/fpdb.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 5370bccb..0b3c4f4a 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -678,8 +678,14 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") pass def statusicon_activate(self, widget, data = None): - self.window.show() - self.window.present() + # Let's allow the tray icon to toggle window visibility, the way + # most other apps work + shown = self.window.get_property('visible') + if shown: + self.window.hide() + else: + self.window.show() + self.window.present() def warning_box(self, str, diatitle="FPDB WARNING"): diaWarning = gtk.Dialog(title=diatitle, parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) From 645be076676f60a2a5c1d17191690845b3d67ed0 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 28 Oct 2009 22:00:05 -0400 Subject: [PATCH 09/11] Make DS.py friendlier to stud and draw. --- pyfpdb/DerivedStats.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/pyfpdb/DerivedStats.py b/pyfpdb/DerivedStats.py index 106bd038..56b0d489 100644 --- a/pyfpdb/DerivedStats.py +++ b/pyfpdb/DerivedStats.py @@ -56,7 +56,10 @@ class DerivedStats(): # This (i think...) is correct for both stud and flop games, as hand.board['street'] disappears, and # those values remain default in stud. - boardcards = hand.board['FLOP'] + hand.board['TURN'] + hand.board['RIVER'] + [u'0x', u'0x', u'0x', u'0x', u'0x'] + boardcards = [] + for street in hand.communityStreets: + boardcards += hand.board[street] + boardcards += [u'0x', u'0x', u'0x', u'0x', u'0x'] cards = [Card.encodeCard(c) for c in boardcards[0:5]] self.hands['boardcard1'] = cards[0] self.hands['boardcard2'] = cards[1] @@ -809,24 +812,11 @@ class DerivedStats(): self.hands['playersAtStreet4'] = 0 self.hands['playersAtShowdown'] = 0 - for street in hand.actionStreets: + for (i, street) in enumerate(hand.actionStreets[2:]): actors = {} for act in hand.actions[street]: actors[act[0]] = 1 - #print "len(actors.keys(%s)): %s" % ( street, len(actors.keys())) - if hand.gametype['base'] in ("hold"): - if street in "FLOP": self.hands['playersAtStreet1'] = len(actors.keys()) - elif street in "TURN": self.hands['playersAtStreet2'] = len(actors.keys()) - elif street in "RIVER": self.hands['playersAtStreet3'] = len(actors.keys()) - elif hand.gametype['base'] in ("stud"): - if street in "FOURTH": self.hands['playersAtStreet1'] = len(actors.keys()) - elif street in "FIFTH": self.hands['playersAtStreet2'] = len(actors.keys()) - elif street in "SIXTH": self.hands['playersAtStreet3'] = len(actors.keys()) - elif street in "SEVENTH": self.hands['playersAtStreet4'] = len(actors.keys()) - elif hand.gametype['base'] in ("draw"): - if street in "DRAWONE": self.hands['playersAtStreet1'] = len(actors.keys()) - elif street in "DRAWTWO": self.hands['playersAtStreet2'] = len(actors.keys()) - elif street in "DRAWTHREE": self.hands['playersAtStreet3'] = len(actors.keys()) + self.hands['playersAtStreet%s' % str(i+1)] = len(actors.keys()) #Need playersAtShowdown From 626ff49eb41e5bb28d8db33277f3fe726d90aef5 Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 29 Oct 2009 13:17:17 +0800 Subject: [PATCH 10/11] Print out actual exception when import fails --- pyfpdb/GuiGraphViewer.py | 3 ++- pyfpdb/GuiSessionViewer.py | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index 4011ba00..739a8f18 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -32,11 +32,12 @@ try: from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from numpy import arange, cumsum from pylab import * -except ImportError: +except ImportError as inst: print """Failed to load libs for graphing, graphing will not function. Please in stall numpy and matplotlib if you want to use graphs.""" print """This is of no consequence for other parts of the program, e.g. import and HUD are NOT affected by this problem.""" + print "ImportError: %s" % inst.args import fpdb_import import Database diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index 7695cf73..5711cb89 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -37,11 +37,10 @@ try: # 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]) +except ImportError as inst: print """Failed to load numpy in Session Viewer""" - print """This is of no consequence as the module currently doesn't do anything.""" + print """This is of no consequence as the page is broken and only of interest to developers.""" + print "ImportError: %s" % inst.args import Card import fpdb_import From a872769b2b44b1a2c2079d8e8627858efe25647a Mon Sep 17 00:00:00 2001 From: Worros Date: Thu, 29 Oct 2009 16:37:33 +0800 Subject: [PATCH 11/11] Fix cli to Everleaf --- pyfpdb/EverleafToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/EverleafToFpdb.py b/pyfpdb/EverleafToFpdb.py index 2835b6ff..fcd76c25 100755 --- a/pyfpdb/EverleafToFpdb.py +++ b/pyfpdb/EverleafToFpdb.py @@ -304,5 +304,5 @@ if __name__ == "__main__": LOG_FILENAME = './logging.out' logging.basicConfig(filename=LOG_FILENAME,level=options.verbosity) - e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True, debugging=True) + e = Everleaf(in_path = options.ipath, out_path = options.opath, follow = options.follow, autostart=True)