again, many many changes + still ugly code

Signed-off-by: fpdb-mme <jUrner@arcor.de>
This commit is contained in:
fpdb-mme 2009-10-30 14:23:27 +01:00
parent 2a878d0a83
commit a3a72712ac

View File

@ -12,7 +12,7 @@ class DatabaseManager(object):
def from_fpdb(klass, data, defaultDatabaseType=None): def from_fpdb(klass, data, defaultDatabaseType=None):
#TODO: parse whatever data is #TODO: parse whatever data is
databases = ( databases = (
DatabaseTypePostgres(name='myDb'), DatabaseTypeSqLite(name='myDb'),
DatabaseTypeSqLite(name='myDb2'), DatabaseTypeSqLite(name='myDb2'),
) )
@ -34,11 +34,10 @@ class DatabaseManager(object):
return database return database
def database_id(self, database): def database_id(self, database):
return id(database) return id(database)
def create_database(self, databaseType, **kws): def add_database(self, database):
databaseKlass = self.DatabaseTypes[databaseType] if database in self._databases:
database = databaseType(**kws) raise ValueError('database already registered')
self._databases.append(database) self._databases.append(database)
return database
def remove_database(self, database): def remove_database(self, database):
self._databases.remove(database) self._databases.remove(database)
@ -54,9 +53,13 @@ class DatabaseTypeMeta(type):
class DatabaseTypeBase(object): class DatabaseTypeBase(object):
__metaclass__ = DatabaseTypeMeta __metaclass__ = DatabaseTypeMeta
Type = None Type = None
Params = ()
class DatabaseTypePostgres(DatabaseTypeBase): class DatabaseTypePostgres(DatabaseTypeBase):
Type = 'postgres' Type = 'postgres'
@classmethod
def display_name(klass):
return 'Postgres'
def __init__(self, name='', host='localhost', port=5432, user='postgres', password='', database='fpdb'): def __init__(self, name='', host='localhost', port=5432, user='postgres', password='', database='fpdb'):
self.name = name self.name = name
self.host = host self.host = host
@ -64,9 +67,12 @@ class DatabaseTypePostgres(DatabaseTypeBase):
self.user = user self.user = user
self.password = password self.password = password
self.database = database self.database = database
class DatabaseTypeMysql(DatabaseTypeBase): class DatabaseTypeMysql(DatabaseTypeBase):
Type = 'mysql' Type = 'mysql'
@classmethod
def display_name(klass):
return 'MySql'
def __init__(self, name='', host='localhost', port=3306, user='root', password='', database='fpdb'): def __init__(self, name='', host='localhost', port=3306, user='root', password='', database='fpdb'):
self.name = name self.name = name
self.host = host self.host = host
@ -74,13 +80,25 @@ class DatabaseTypeMysql(DatabaseTypeBase):
self.user = user self.user = user
self.password = password self.password = password
self.database = database self.database = database
class DatabaseTypeSqLite(DatabaseTypeBase): class DatabaseTypeSqLite(DatabaseTypeBase):
Type = 'sqlite' Type = 'sqlite'
@classmethod
def display_name(klass):
return 'SqLite'
def __init__(self, name='', host='', file=''): def __init__(self, name='', host='', file=''):
self.name = name self.name = name
self.file = file self.file = file
#TODO: how do we want to handle unsupported database types?
# ..uncomment to remove unsupported database types
#try: import psycopg2
#except ImportError: del DatabaseManager.DatabaseTypes['postgres']
#try: import MySQLdb
#except ImportError: del DatabaseManager.DatabaseTypes['mysql']
#try: import sqlite3
#except ImportError: del DatabaseManager.DatabaseTypes['sqlite']
#*************************************************************************************************************************** #***************************************************************************************************************************
class MyFileChooserButton(gtk.HBox): 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 #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
@ -124,8 +142,9 @@ class MyFileChooserButton(gtk.HBox):
# 1. user types in a new filename. easy one, create the file # 1. user types in a new filename. easy one, create the file
# 2. user selectes a file with the intention to overwrite it # 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 # 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? # if we create a new one, choice is create_new or overwrite
# if we add a database we may have to sanity check user picked one
def on_dialog_confirm_overwrite(self, dlg): def on_dialog_confirm_overwrite(self, dlg):
print dlg.get_filename() print dlg.get_filename()
@ -138,12 +157,14 @@ class MyFileChooserButton(gtk.HBox):
gtk.FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN gtk.FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN
# #
#TODO: rewrite to use idDatabase + create and remove databases through DatabaseManager
#TODO: derrive from gtk.VBox?
class WidgetDatabaseProperties(gtk.VBox): class WidgetDatabaseProperties(gtk.VBox):
ModeEdit = 0x1
ModeAdd = 0x2
ModeNew = 0x4
ModeNew = 0
ModeEdit = 1
ModeAdd = 2
class FieldWidget(object): class FieldWidget(object):
def __init__(self, text='', attrDatabase='', widget=None, attrGet=None, attrSet=None, defaultValue=None, canEdit=False, tooltip=''): def __init__(self, text='', attrDatabase='', widget=None, attrGet=None, attrSet=None, defaultValue=None, canEdit=False, tooltip=''):
""" """
@ -179,10 +200,13 @@ class WidgetDatabaseProperties(gtk.VBox):
def reset_value(self): def reset_value(self):
getattr(self._widget, self._attrSet)(self._defaultValue) getattr(self._widget, self._attrSet)(self._defaultValue)
def __init__(self, databaseManager, database=None, flags=ModeEdit): def __init__(self, databaseManager, database, mode=ModeEdit):
gtk.VBox.__init__(self) gtk.VBox.__init__(self)
self.flags = flags self.databaseManager = databaseManager
self.database = database
self.mode = mode
self.fieldWidgets = ( self.fieldWidgets = (
self.FieldWidget( self.FieldWidget(
text='Name:', text='Name:',
@ -263,10 +287,18 @@ class WidgetDatabaseProperties(gtk.VBox):
cell = gtk.CellRendererText() cell = gtk.CellRendererText()
self.comboType.pack_start(cell, True) self.comboType.pack_start(cell, True)
self.comboType.add_attribute(cell, 'text', 0) 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) self.comboType.connect('changed', self.on_combo_type_changed)
# fill database type combo with available database klasses. we store (databaseDisplayName, databaseType) in our model for later lookup
iCurrentDatabase = 0
databaseTypes = [(klass.display_name(), klass.Type) for klass in databaseManager.DatabaseTypes.values()]
databaseTypes.sort()
for i, (databaseDisplayName, databaseType) in enumerate(databaseTypes):
listStore.append( (databaseDisplayName, databaseType) )
if databaseType == self.database.Type:
iCurrentDatabase = i
if self.mode == self.ModeEdit or len(databaseTypes) < 2:
self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF)
# init and layout field widgets # init and layout field widgets
self.pack_start(self.comboType, False, False, 2) self.pack_start(self.comboType, False, False, 2)
@ -277,60 +309,37 @@ class WidgetDatabaseProperties(gtk.VBox):
table.attach(fieldWidget.widget(), 1, 2, i, i+1) table.attach(fieldWidget.widget(), 1, 2, i, i+1)
# init widget # init widget
self.comboType.set_active(iCurrentDatabase)
# if a database has been passed user is not allowed to change database type self._adjust_widgets(self.database)
if database is None:
self.comboType.set_button_sensitivity(gtk.SENSITIVITY_ON) def _adjust_widgets(self, database):
for fieldWidget in self.fieldWidgets:
isSensitive = fieldWidget.is_sensitive(database)
if isSensitive:
fieldWidget.value_from_database(database)
else: else:
self.comboType.set_button_sensitivity(gtk.SENSITIVITY_OFF) fieldWidget.reset_value()
if self.mode == self.ModeEdit:
# set current database isSensitive = isSensitive and fieldWidget.can_edit()
self.databaseManager = databaseManager fieldWidget.set_sensitive(isSensitive)
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): def on_combo_type_changed(self, combo):
i = self.comboType.get_active() i = self.comboType.get_active()
if i > -1: if i < 0:
# change database if necessary return
currentDatabaseType = self.comboType.get_model()[i][1]
if currentDatabaseType != self.database.Type: # check if we need to init a new database
newDatabase = self.databaseManager.DatabaseTypes[currentDatabaseType]() currentDatabaseType = self.comboType.get_model()[i][1]
self.set_database(newDatabase) if currentDatabaseType == self.database.Type:
return
def set_database(self, database):
self.database = database # create new empty database
#NOTE: we dont register it in DatabaseManager
# adjust database type combo if necessary self.database = self.databaseManager.DatabaseTypes[currentDatabaseType]()
i = self.comboType.get_active() self._adjust_widgets(self.database)
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): def get_database(self):
for fieldWidget in self.fieldWidgets: for fieldWidget in self.fieldWidgets:
if fieldWidget.is_sensitive(self.database): if fieldWidget.is_sensitive(self.database):
@ -339,16 +348,7 @@ class WidgetDatabaseProperties(gtk.VBox):
class DialogDatabaseProperties(gtk.Dialog): class DialogDatabaseProperties(gtk.Dialog):
def __init__(self, databaseManager, database=None,parent=None, flags=WidgetDatabaseProperties.ModeEdit): def __init__(self, databaseManager, database, parent=None, mode=WidgetDatabaseProperties.ModeEdit, title=''):
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, gtk.Dialog.__init__(self,
title=title, title=title,
parent=parent, parent=parent,
@ -361,13 +361,12 @@ class DialogDatabaseProperties(gtk.Dialog):
self.connect('response', self.on_dialog_response) self.connect('response', self.on_dialog_response)
# setup widget # setup widget
self.flags = flags self.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database, mode=mode)
self.widgetDatabaseProperties = WidgetDatabaseProperties(databaseManager,database=database, flags=self.flags)
self.vbox.pack_start(self.widgetDatabaseProperties, True, True) self.vbox.pack_start(self.widgetDatabaseProperties, True, True)
self.widgetDatabaseProperties.show_all() self.show_all()
def get_database(self): def get_widget_database_properties(self):
return self.widgetDatabaseProperties.get_database() return self.widgetDatabaseProperties
def on_dialog_response(self, dlg, responseId): def on_dialog_response(self, dlg, responseId):
if responseId == gtk.RESPONSE_REJECT: if responseId == gtk.RESPONSE_REJECT:
@ -375,21 +374,15 @@ class DialogDatabaseProperties(gtk.Dialog):
elif responseId == gtk.RESPONSE_ACCEPT: elif responseId == gtk.RESPONSE_ACCEPT:
pass pass
#TODO: just boilerplate code #TODO: derrive from gtk.VBox?
class DialogDatabase(gtk.Dialog): # ..is there a way to derrive from gtk.Widget or similar? this would make parentWidget kw obsolete
def __init__(self, databaseManager, parent=None): class WidgetDatabaseManager(gtk.VBox):
gtk.Dialog.__init__(self, def __init__(self, databaseManager, parentWidget=None):
title="My dialog", gtk.VBox.__init__(self)
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 self.databaseManager = databaseManager
self.parentWidget = parentWidget
#TODO: dono how to make word wrap work as expected #TODO: dono how to make word wrap work as expected
self.labelInfo = gtk.Label('database management') self.labelInfo = gtk.Label('database management')
@ -440,16 +433,14 @@ class DialogDatabase(gtk.Dialog):
col.set_visible(False) col.set_visible(False)
self.treeDatabaseColumns = dict([(name, i) for (i, name) in enumerate(self.treeDatabaseColumns)]) self.treeDatabaseColumns = dict([(name, i) for (i, name) in enumerate(self.treeDatabaseColumns)])
self.treeDatabases.get_selection().connect('changed', self.on_tree_databases_selection_changed) self.treeDatabases.get_selection().connect('changed', self.on_tree_databases_selection_changed)
# layout widgets # layout widgets
self.vbox.pack_start(self.labelInfo, False, False, 2) vbox = gtk.VBox(self)
self.vbox.pack_start(gtk.HSeparator(), False, False, 2) vbox.pack_start(self.labelInfo, False, False, 2)
vbox.pack_start(gtk.HSeparator(), False, False, 2)
hbox = gtk.HBox() hbox = gtk.HBox()
self.vbox.add(hbox) self.add(hbox)
hbox.set_homogeneous(False) hbox.set_homogeneous(False)
vbox = gtk.VBox() vbox = gtk.VBox()
hbox.pack_start(vbox, False, False, 2) hbox.pack_start(vbox, False, False, 2)
@ -470,25 +461,45 @@ class DialogDatabase(gtk.Dialog):
for database in self.databaseManager: for database in self.databaseManager:
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) ) self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
#TODO: for some reason i have to click OK/Cancel twice to close the dialog #TODO: for some reason i have to click OK/Cancel twice to close the dialog
def on_button_database_new_clicked(self, button): def on_button_database_new_clicked(self, button):
dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeNew) databaseType = self.databaseManager.get_default_database_type()
if databaseType is None:
raise ValueError('no defult database type set')
dlg = DialogDatabaseProperties(
self.databaseManager,
databaseType(),
parent=self.parentWidget,
mode=WidgetDatabaseProperties.ModeNew,
title='[New database] - database properties'
)
if dlg.run() == gtk.RESPONSE_REJECT: if dlg.run() == gtk.RESPONSE_REJECT:
pass pass
if dlg.run() == gtk.RESPONSE_ACCEPT: if dlg.run() == gtk.RESPONSE_ACCEPT:
database = dlg.get_database() database = dlg.get_widget_database_properties().get_database()
#TODO: sanity checks + init databse if necessary
self.databaseManager.add_database(database)
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) ) self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
dlg.destroy() dlg.destroy()
def on_button_database_add_clicked(self, button): def on_button_database_add_clicked(self, button):
dlg = DialogDatabaseProperties(self.databaseManager, parent=self, flags=WidgetDatabaseProperties.ModeAdd) databaseType = self.databaseManager.get_default_database_type()
if databaseType is None:
raise ValueError('no defult database type set')
dlg = DialogDatabaseProperties(
self.databaseManager,
databaseType(),
parent=self.parentWidget,
mode=WidgetDatabaseProperties.ModeAdd,
title='[Add database] - database properties'
)
if dlg.run() == gtk.RESPONSE_REJECT: if dlg.run() == gtk.RESPONSE_REJECT:
pass pass
if dlg.run() == gtk.RESPONSE_ACCEPT: if dlg.run() == gtk.RESPONSE_ACCEPT:
database = dlg.get_database() database = dlg.get_widget_database_properties().get_database()
print self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) ) #TODO: sanity checks
self.databaseManager.add_database(database)
self.treeDatabases.get_model().append( (database.name, 'foo', database.Type, self.databaseManager.database_id(database)) )
dlg.destroy() dlg.destroy()
def on_button_database_edit_clicked(self, button): def on_button_database_edit_clicked(self, button):
@ -499,8 +510,13 @@ class DialogDatabase(gtk.Dialog):
model, iter = selection.get_selected() model, iter = selection.get_selected()
idDatabase = model.get_value(iter, self.treeDatabaseColumns['_id']) idDatabase = model.get_value(iter, self.treeDatabaseColumns['_id'])
database = self.databaseManager.database_from_id(idDatabase) database = self.databaseManager.database_from_id(idDatabase)
dlg = DialogDatabaseProperties(
dlg = DialogDatabaseProperties(self.databaseManager, database=database, parent=self, flags=WidgetDatabaseProperties.ModeEdit) self.databaseManager,
database=database,
parent=self.parentWidget,
mode=WidgetDatabaseProperties.ModeEdit,
title='[Edit database] - database properties'
)
if dlg.run() == gtk.RESPONSE_REJECT: if dlg.run() == gtk.RESPONSE_REJECT:
pass pass
if dlg.run() == gtk.RESPONSE_ACCEPT: if dlg.run() == gtk.RESPONSE_ACCEPT:
@ -519,9 +535,22 @@ class DialogDatabase(gtk.Dialog):
self.buttonDatabaseRemove.set_sensitive(hasSelection) self.buttonDatabaseRemove.set_sensitive(hasSelection)
self.buttonDatabaseDelete.set_sensitive(hasSelection) self.buttonDatabaseDelete.set_sensitive(hasSelection)
class DialogDatabaseManager(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.widgetDatabaseManager = WidgetDatabaseManager(databaseManager, parentWidget=self)
self.vbox.pack_start(self.widgetDatabaseManager, True, True)
self.show_all()
#************************************************************************************************** #**************************************************************************************************
if __name__ == '__main__': if __name__ == '__main__':
databaseManager = DatabaseManager.from_fpdb('', defaultDatabaseType=DatabaseTypeSqLite) databaseManager = DatabaseManager.from_fpdb('', defaultDatabaseType=DatabaseTypeSqLite)
@ -531,7 +560,7 @@ if __name__ == '__main__':
#database=DatabaseTypePostgres(), #database=DatabaseTypePostgres(),
# database=None, # database=None,
# ) # )
d = DialogDatabase(databaseManager) d = DialogDatabaseManager(databaseManager)
d.connect("destroy", gtk.main_quit) d.connect("destroy", gtk.main_quit)
d.run() d.run()
#gtk.main() #gtk.main()