daboide Commit
Revision 216
Date: 2005-10-30 13:34:50 -0800 (Sun, 30 Oct 2005)
Author: paul

Changed:
A   trunk/wizards/AppWizardX/
A   trunk/wizards/AppWizardX/AppWizard.py
A   trunk/wizards/AppWizardX/spec-App.py
A   trunk/wizards/AppWizardX/spec-Biz.py
A   trunk/wizards/AppWizardX/spec-BizBase.py
A   trunk/wizards/AppWizardX/spec-Frm.py
A   trunk/wizards/AppWizardX/spec-FrmBase.py
A   trunk/wizards/AppWizardX/spec-MenFileOpen.py
A   trunk/wizards/AppWizardX/spec-PagBase.py
A   trunk/wizards/AppWizardX/spec-biz__init__.py
A   trunk/wizards/AppWizardX/spec-db__init__.py
A   trunk/wizards/AppWizardX/spec-main.py
A   trunk/wizards/AppWizardX/spec-ui__init__.py
D   trunk/wizards/AppWizardX.py

Log:
Moved AppWizardX into its own subdir and split out the templates into their
own files, which will make it easier to maintain.


Diff:

Property changes on: trunk/wizards/AppWizardX
___________________________________________________________________
Name: svn:ignore
   + *.pyc


Copied: trunk/wizards/AppWizardX/AppWizard.py (from rev 215, 
trunk/wizards/AppWizardX.py)
===================================================================
--- trunk/wizards/AppWizardX.py 2005-10-30 18:18:43 UTC (rev 215)
+++ trunk/wizards/AppWizardX/AppWizard.py       2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,950 @@
+#!/usr/bin/env python
+import os, time
+import dabo
+from dabo.dLocalize import _
+import dabo.dEvents as dEvents
+import dabo.dConstants as k
+dabo.ui.loadUI("wx")
+from dabo.ui.dialogs.WizardPage import WizardPage
+from dabo.ui.dialogs.Wizard import Wizard
+from dabo.ui import dLabel
+from dabo.lib.connParser import createXML
+
+
+class HSizer(dabo.ui.dSizer):
+       def __init__(self, *args, **kwargs):
+               super(HSizer, self).__init__("h", *args, **kwargs)
+
+
+class VSizer(dabo.ui.dSizer):
+       def __init__(self, *args, **kwargs):
+               super(VSizer, self).__init__("v", *args, **kwargs)
+               
+
+class PageIntro(WizardPage):
+       def __init__(self, parent, title="Introduction"):
+               super(PageIntro, self).__init__(parent=parent, Title=title)
+       
+       def createBody(self):
+               txt = """Use this wizard to quickly create an application 
+for your database. Point the wizard at a database;
+specify a target directory; the wizard will create
+a full-fledged Dabo application with forms for each 
+table in the database that allow you to run queries 
+and edit the results.
+
+You can then edit the resulting application to fit 
+your exact requirements. There is a tool included 
+called 'FieldSpecEditor.py' that allows you to edit 
+your application settings visually.
+
+Right now Dabo supports the MySQL, Firebird, 
+PostgreSQL and SQLite databases. In time the 
+number of supported databases will grow.
+
+Press 'Next' to enter database parameters."""
+               lbl = dLabel(self, Caption=txt)
+               self.Sizer.append(lbl)
+               
+
+class PageDatabase(WizardPage):
+       def __init__(self, parent, title="Database Parameters"):
+               super(PageDatabase, self).__init__(parent=parent, Title=title)
+       
+       
+       def createBody(self):
+               sz = self.Sizer
+               lbl = dLabel(self, Caption="Enter the parameters here, and then 
click 'Next'.")
+               sz.append(lbl)
+
+               lbl = dLabel(self, Caption="Profile:")
+               
+               self.dbDefaults = {}
+               self.dbDefaults["MySQL"] = {
+                               "DbType" : "MySQL",
+                               "Host" : "dabodev.com", 
+                               "Database" : "webtest",
+                               "User" : "webuser",
+                               "Password" : "foxrocks",
+                               "Port" : "3306" }
+               self.dbDefaults["Firebird"] = {
+                               "DbType" : "Firebird",
+                               "Host" : "dabodev.com", 
+                               "Database" : "webtest",
+                               "User" : "webuser",
+                               "Password" : "foxrox",
+                               "Port" : "3050" }
+               self.dbDefaults["PostgreSQL"] = {
+                               "DbType" : "PostgreSQL",
+                               "Host" : "dabodev.com", 
+                               "Database" : "webtest",
+                               "User" : "webuser",
+                               "Password" : "foxrox",
+                               "Port" : "5432" }
+               
+               self.dbDefaults["SQLite"] = {
+                               "DbType" : "SQLite",
+                               "Database" : "webtest.sqlite"}
+               
+               # List of all fields to create for the user to select
+               self.fieldNames = ("DbType", "Host", "Database", "User", 
"Password", "Port")
+               
+               # Now go through the profiles that the user may have saved in 
the 
+               # user settings file:
+               app = self.Application
+               userProfiles = app.getUserSettingKeys("appWizard.dbDefaults.")
+               dbDefaultKeys = self.dbDefaults.keys()
+               dbDefaultMap = {}
+               for key in dbDefaultKeys:
+                       dbDefaultMap[key.lower()] = key
+
+               ## Default to MySQL first:
+               defaultProfileName = "MySQL"
+               defaultUserProfileName = None
+
+               for profile in userProfiles:
+                       userDict = {}
+                       for field in (self.fieldNames):
+                               name = "appWizard.dbDefaults.%s.%s" % (profile, 
field)
+                               val = app.getUserSetting(name)
+                               if val is None: 
+                                       val = ""
+                               userDict[field] = val
+                       if profile in dbDefaultMap.keys():
+                               profile = dbDefaultMap[profile]
+                       self.dbDefaults[profile] = userDict
+                       
+                       # Override the default with the last user profile:
+                       defaultUserProfileName=profile
+               
+               # Set up the dropdown list based on the keys in the dbDefaults 
dict.
+               choiceParms = {"Choices": self.dbDefaults.keys(), 
+                       "Name": "dbChoice", 
+                       "ValueMode": "string"}
+               self.dbChoice = dabo.ui.dDropdownList(self, Name="dbChoice")
+               self.dbChoice.ValueMode = "string"
+               self.dbChoice.Choices = self.dbDefaults.keys()
+               if defaultUserProfileName is not None:
+                       self.dbChoice.Value = defaultUserProfileName
+               else:
+                       self.dbChoice.Value = defaultProfileName
+               self.dbChoice.bindEvent(dabo.dEvents.ValueChanged, 
self.onDbChoice)
+               
+               cmd = self.addObject(dabo.ui.dButton, 
+                       Caption="New Profile...", Name="cmdNewProfile")
+               cmd.bindEvent(dabo.dEvents.Hit, self.onNewProfile)
+               
+               gs = dabo.ui.dGridSizer()
+               gs.MaxCols = 2
+               gs.setColExpand(True, 1)
+               gs.append(lbl)
+               hs = HSizer()
+               hs.append(self.dbChoice, 1)
+               hs.appendSpacer(8)
+               hs.append(cmd, 0)
+               gs.append(hs, "x")
+               
+               for field in ("DbType", "Host", "Database", "User", "Password", 
"Port"):
+                       lbl = dLabel(self, Name=("lbl%s" % field), Width=75, 
Caption=("%s:" % field) )
+                       pw = (field.lower() == "password")
+                       obj = dabo.ui.dTextBox(self, PasswordEntry=pw, 
Name=("txt%s" % field) )
+                       obj.bindEvent(dabo.dEvents.ValueChanged, 
self.onParmValueChanged)
+                       
+                       gs.append(lbl)
+                       # Add a file search button. It will be hidden for all 
+                       # non-file-based backends.
+                       if field == "Database":
+                               self.btnSrch = dabo.ui.dButton(self, 
Caption="...")
+                               self.btnSrch.Width = (self.btnSrch.Height * 2)
+                               self.btnSrch.bindEvent(dabo.dEvents.Hit, 
self.onDbSearch)
+                               hs = self.szDB = dabo.ui.dSizer("H")
+                               hs.append1x(obj)
+                               hs.append(self.btnSrch, border=10, 
borderFlags="left")
+                               gs.append(hs, "x")
+                       else:   
+                               gs.append(obj, "x")
+               sz.append(gs, 1, "x")
+               self.onDbChoice()
+       
+       
+       def onDbSearch(self, evt):
+               """Select a file for the database"""
+               pth = dabo.ui.getFile(message="Select the database")
+               if pth:
+                       self.txtDatabase.Value = pth
+                       self.refresh()
+                       
+               
+       def onParmValueChanged(self, evt):
+               # write the new value back to the user settings table.
+               object = evt.EventObject
+               app = object.Application
+               field = object.Name[3:]
+               name = "appWizard.dbDefaults.%s.%s" % (self.dbChoice.Value, 
field)
+               app.setUserSetting(name, object.Value)
+               self.dbDefaults[self.dbChoice.Value][field] = object.Value
+               
+               
+       def onNewProfile(self, evt):
+               base = "New Profile"
+               i = 1
+               while True:
+                       default = "%s %s" % (base, i)
+                       if default in self.dbChoice.Choices:
+                               i += 1
+                       else:
+                               break
+                               
+               name = dabo.ui.getString("Please enter a name for the profile", 
defaultValue=default)
+               if name is not None:
+                       self.dbDefaults[name] = {
+                                       "DbType" : "",
+                                       "Host" : "", 
+                                       "Database" : "",
+                                       "User" : "",
+                                       "Password" : "",
+                                       "Port" : "" }
+                       dbChoice = self.dbChoice
+                       dbChoice.Choices = self.dbDefaults.keys()
+                       dbChoice.Value = name
+                       self.txtDbType.Value = "MySQL"
+                       self.txtPort.Value = "3306"
+                       self.txtDbType.SetFocus()
+                       
+                       
+       def onDbChoice(self, evt=None):
+               self.Form.dbType = self.dbChoice.Value
+               dbType = self.Form.dbType
+               dbdefs = self.dbDefaults[dbType]
+               for fld in self.fieldNames:
+                       if dbdefs.has_key(fld):
+                               val = dbdefs[fld]
+                               exec("self.txt%s.Value = '%s' " % (fld, val) )
+                               exec("self.txt%s.Visible = True " % fld )
+                       else:
+                               # Not a field used for this db type
+                               exec("self.txt%s.Value = '' " % fld )
+                               exec("self.txt%s.Visible = False " % fld )
+               # Enable the file search button if this is a file-based backend
+               if dbType in ("SQLite",):
+                       self.szDB.showItem(self.btnSrch)
+               else:
+                       self.szDB.hideItem(self.btnSrch)
+               
+       
+       def onLeavePage(self, direction):
+               if direction == "forward":
+                       if len(self.Form.tableDict) > 0:
+                               if not dabo.ui.areYouSure("Overwrite the 
current table information?"):
+                                       return True
+                                       
+                       # Set the wizard's connect info based on the user input:
+                       ci = self.Form.connectInfo
+                       be = self.txtDbType.Value
+                       try:
+                               ci.DbType = be
+                       except ValueError:
+                               dabo.ui.stop("The database type '%s' is 
invalid. "
+                                               "Please reenter and try again." 
% be)
+                               self.txtDbType.SetFocus()
+                               return False
+                       ci.Host = self.txtHost.Value
+                       ci.Database = self.txtDatabase.Value
+                       ci.User = self.txtUser.Value
+                       ci.Password = ci.encrypt(self.txtPassword.Value)
+                       try:
+                               ci.Port = int(self.txtPort.Value)
+                       except ValueError:
+                               ci.Port = None
+                       # Try to get a connection::
+                       try:
+                               conn = dabo.db.dConnection(ci)
+                               cursor = 
conn.getDaboCursor(ci.getDictCursorClass())
+                               cursor.BackendObject = ci.getBackendObject()
+                               tables = cursor.getTables()
+                       except Exception, e:
+                               dabo.ui.stop("Could not connect to the database 
server. "
+                                               "Please check your parameters 
and try again.")
+                               return False
+                       self.Form.tableDict = {}
+                       tableOrder = 0
+                       for table in tables:
+                               # Firebird databases have system tables with 
'$' in the name
+                               if table.find("$") > -1:
+                                       continue
+                               tableDict = {}
+                               count = cursor.getTableRecordCount(table)
+                               tableDict["name"] = table
+                               tableDict["recordCount"] = count
+                               tableDict["order"] = tableOrder
+                               fields = cursor.getFields(table)
+                               tableDict["fields"] = {}
+                               fieldOrder = 0
+                               for field in fields:
+                                       fieldName = field[0]
+                                       tableDict["fields"][fieldName] = {}
+                                       tableDict["fields"][fieldName]["name"] 
= fieldName
+                                       tableDict["fields"][fieldName]["type"] 
= field[1]
+                                       tableDict["fields"][fieldName]["order"] 
= fieldOrder
+                                       tableDict["fields"][fieldName]["pk"] = 
field[2]
+                                       fieldOrder += 1
+                                       
+                               self.Form.tableDict[table] = tableDict
+                               tableOrder += 1
+               return True
+
+
+class PageRelations(WizardPage):
+       def __init__(self, parent, title="Table Relationships"):
+               super(PageRelations, self).__init__(parent=parent, Title=title)
+
+
+       def createBody(self):           
+               txt = """If there are any relationships among your 
+selected tables, specify them here."""
+               lbl = dLabel(self, Caption=txt)
+               self.Sizer.append(lbl)
+               
+               self.selTabs = self.Form.selectedTables
+               hsz = HSizer()
+               szp = self.szrParent = VSizer()
+               szc = self.szrChild = VSizer()
+               szp.Border = szc.Border = 5
+               szp.BorderTop = szc.BorderTop = True            
+
+               tx = dLabel(self, Caption="Parent", FontBold=True)
+               szp.append(tx, "expand", halign="centre")
+               tx2 = dLabel(self, Caption="Child", FontBold=True)
+               szc.append(tx2, "expand", halign="centre")
+               
+               self.ddParent = dabo.ui.dDropdownList(self, Name="ddParent")
+               self.ddChild = dabo.ui.dDropdownList(self, Name="ddChild")
+               self.ddParent.bindEvent(dabo.dEvents.Hit, 
self.onParentSelection)
+               self.ddChild.bindEvent(dabo.dEvents.Hit, self.onChildSelection)
+               szp.append(self.ddParent, "expand")
+               szc.append(self.ddChild, "expand")
+               self.ddPrFields = dabo.ui.dDropdownList(self, Name="ddPrFields")
+               self.ddChFields = dabo.ui.dDropdownList(self, Name="ddChFields")
+               szp.append(self.ddPrFields, "expand")
+               szc.append(self.ddChFields, "expand")
+               
+               hsz.append(szp, 1, "expand")
+               hsz.append(szc, 1, "expand")
+               self.Sizer.append(hsz, 0, "expand", borderFlags="All", 
border=10)
+               
+               btnSet = dabo.ui.dButton(self, Caption="Set Relation")
+               btnSet.bindEvent(dabo.dEvents.Hit, self.onSetRelation)
+               self.Sizer.append(btnSet, 0, alignment="centre", border=5)
+               
+               # Add the list of current relationships
+               self.lstRelations = dabo.ui.dListBox(self)
+               self.displayRelations()
+               self.Sizer.append(self.lstRelations, 1, "expand", 
borderFlags="top", border=5)
+               btnRemove = dabo.ui.dButton(self, Caption="Remove Relation")
+               btnRemove.bindEvent(dabo.dEvents.Hit, self.onRemoveRelation)
+               self.Sizer.append(btnRemove, 0, alignment="centre", 
borderFlags="top", border=5)
+               
+
+       def onEnterPage(self, direction):
+               currSel = self.Form.selectedTables
+               if self.selTabs != currSel:
+                       self.selTabs = currSel
+                       # Table selection has changed. Update the child 
dropdowns
+                       self.populateDropDowns()
+       
+
+       def onRelTypeChange(self, evt):
+               pass
+#              if ( self.radRelType.Value == "Many-To-Many" ):
+#                      self.pgfType.SetSelection(1)
+#              else:
+#                      self.pgfType.SetSelection(0)
+               
+               
+       def onT1Selection(self, evt): pass
+       def onT2Selection(self, evt): pass
+       def onAllocSelection(self, evt): pass
+       
+       
+       def populateDropDowns(self):
+               currPar = self.ddParent.Value
+               currChld = self.ddChild.Value
+               
+               self.ddParent.removeAll()
+               self.ddChild.removeAll()
+               for tb in self.Form.selectedTables:
+                       self.ddParent.appendItem(tb)
+               try:
+                       self.ddParent.Value = currPar
+               except: pass
+               self.ddParent.PositionValue = max(0, 
self.ddParent.PositionValue)
+               currPar = self.ddParent.Value
+
+               for tb in self.Form.selectedTables:
+                       if tb != currPar:
+                               self.ddChild.appendItem(tb)
+               try:
+                       self.ddChild.Value = currChld
+               except: pass
+               self.ddChild.PositionValue = max(0, self.ddChild.PositionValue)
+
+# # # # # Not used without the M:M relations page
+#              self.ddT1.Choices = self.Form.selectedTables
+#              currT1 = self.ddT1.Value
+#              currT2 = self.ddT2.Value
+#              self.ddT2.Choices = self.Form.selectedTables
+#              self.ddAlloc.Choices = [tb for tb in self.Form.selectedTables
+#                      if tb not in (currT1, currT2)]
+               # Now populate the field selectors
+               self.populateFields()
+       
+       
+       def populateFields(self):
+               currPar = self.ddParent.Value
+               currChld = self.ddChild.Value
+               td = self.Form.tableDict
+
+               parentFields = td[currPar]["fields"]
+               childFields = td[currChld]["fields"]
+
+               # decorate, sort, undecorate to get the fields in the same order
+               # as they are in the database:
+               spkeys, sckeys = [], []
+               for k,v in parentFields.items():
+                       spkeys.append((v["order"], k))
+               for k,v in childFields.items():
+                       sckeys.append((v["order"], k))
+
+               spkeys.sort()
+               sckeys.sort()
+               
+               pkeys = [k[1] for k in spkeys]
+               ckeys = [k[1] for k in sckeys]
+
+               self.ddPrFields.Choices = pkeys
+               self.ddChFields.Choices = ckeys
+
+
+       def displayRelations(self):
+               trk = self.Form.tableRelationKeys
+               rels = []
+               rels = ["%s - %s.%s : %s.%s" % (tb[0], tb[1], trk[tb][0], 
tb[2], trk[tb][1]) 
+                               for tb in trk.keys() ]
+               self.lstRelations.Choices = rels
+               
+       
+       def onParentSelection(self, evt):
+               """ Parent selected; disable the matching entry in the child 
dropdown"""
+               self.populateDropDowns()
+       
+       def onChildSelection(self, evt):
+               self.populateFields()
+               
+       def onSetRelation(self, evt):
+#              if self.pgfType.GetSelection() == 0:
+                       # One-To-Many
+                       parent = self.ddParent.Value
+                       chld = self.ddChild.Value
+                       pFld = self.ddPrFields.Value
+                       cFld = self.ddChFields.Value
+                       pExp = "%s.%s" % (parent, pFld)
+                       cExp = "%s.%s" % (chld, cFld)
+               
+                       relaTuple = ("1M", parent, chld)
+                       keyTuple = (pFld, cFld)
+                       if relaTuple in self.Form.tableRelations:
+                               dabo.ui.info("The relationship between '%s' and 
'%s' is already defined" 
+                                               % relaTuple[1:])
+                       else:
+                               self.Form.tableRelations.append(relaTuple)
+                               self.Form.tableRelationKeys[relaTuple] = 
keyTuple
+                               self.displayRelations()
+#              else:
+#                      dabo.ui.stop("Sorry, not implemented yet", "Under 
Construction")
+                       
+                       
+       def onRemoveRelation(self, evt):
+               selct = self.lstRelations.Value
+               if not selct:
+                       return
+               typ,defs = selct.split(" - ")
+               sel = defs.strip().split(":")
+               tblTuple = ( typ.strip(), sel[0].strip().split(".")[0], 
sel[1].strip().split(".")[0] )
+               self.Form.tableRelations.remove( tblTuple )
+               del self.Form.tableRelationKeys[tblTuple]
+               self.displayRelations()
+               
+
+                       
+class PageTableSelection(WizardPage):
+       def __init__(self, parent, title="Table Selection"):
+               super(PageTableSelection, self).__init__(parent=parent, 
Title=title)
+       
+       
+       def createBody(self):
+               self.chks = []
+               txt = """The connection to the database was successful. 
+The following tables were found for that database.
+Please check all tables you want included in 
+your application."""
+               lbl = dLabel(self, Caption=txt)
+               self.Sizer.append(lbl)
+
+               
+       def onEnterPage(self, direction):
+               if direction == "forward":
+                       tbls = [t for t in self.Form.getTables()]
+                       tbls.sort()
+                       if self.chks:
+                               for i in range(len(self.chks)-1, -1, -1):
+                                       self.chks[i].release()
+                               self.chks = []
+                       try:
+                               pn = self.chkPanel
+                       except:
+                               # Not created yet
+                               self.chkPanel = dabo.ui.dScrollPanel(self)
+                               self.chkPanel.SetSizer(VSizer())
+                               self.Sizer.append(self.chkPanel, 1, "expand", 
+                                               border=10, borderFlags=("top", 
"left", "right"))
+                       self.chkPanel.Sizer.Spacing = 4
+                       for tb in tbls:
+                               chk = dabo.ui.dCheckBox(self.chkPanel)
+                               chk.Caption = tb
+                               chk.Value = False
+                               self.chkPanel.Sizer.append(chk)
+                               self.chks.append(chk)
+                       self.Sizer.Layout()
+
+       def getSelection(self):
+               return [chk.Caption for chk in self.chks if chk.Value]
+       
+       def onLeavePage(self, direction):
+               if direction == "forward":
+                       self.Form.selectedTables = self.getSelection()
+                       if not self.Form.selectedTables:
+                               dabo.ui.stop("No tables were selected. " + 
+                                               "Please select the tables you 
want to include in your application", 
+                                               title="No Tables Selected")
+                               return False            
+               return True
+
+       def nextPage(self):
+               """ If they have selected only one table, skip the relations 
page """
+               ## pkm: I'm not thinking about relations yet, so skip relations 
page 
+               ##      unconditionally for now.
+               if True or len(self.getSelection()) == 1:
+                       return 2
+               else:
+                       return 1
+
+                       
+class PageTargetDirectory(WizardPage):
+       def __init__(self, parent, title="Output Directory"):
+               super(PageTargetDirectory, self).__init__(parent=parent, 
Title=title)
+               
+       
+       def createBody(self):
+               txt = """Enter the directory where you wish to place your 
+new application. 
+
+You can always move the directory later."""
+               lbl = dLabel(self, Caption=txt)
+               self.Sizer.append(lbl)
+
+               hs = HSizer()
+               
+               self.txtDir = dabo.ui.dTextBox(self)
+               self.txtDir.FontSize=10
+               self.txtDir.Value = ""
+               hs.Add(self.txtDir, 1)
+               
+               self.cmdPick = dabo.ui.dButton(self)
+               self.cmdPick.Caption = "..."
+               self.cmdPick.Width = 30
+               self.cmdPick.Height = self.txtDir.Height
+               self.cmdPick.bindEvent(dEvents.Hit, self.onPick)
+               hs.Add(self.cmdPick, 0)
+               self.Sizer.append(hs, 1, "x")
+       
+       
+       def prevPage(self):
+               """ If they have selected only one table, skip the relations 
page """
+               ## pkm: I'm not thinking about relations yet, so skip relations 
page 
+               ##      unconditionally for now.
+               if True or len(self.Form.selectedTables) == 1:
+                       return -2
+               else:
+                       return -1
+
+
+       def onPick(self, evt):
+               dlg = dabo.ui.dFolderDialog(self, defaultPath = 
self.txtDir.Value)
+               if dlg.show() == k.DLG_OK:
+                       self.txtDir.Value = dlg.Path
+               dlg.release()
+       
+       
+       def onEnterPage(self, direction):
+               if direction == "forward":
+                       if self.txtDir.Value == "":
+                               self.txtDir.Value = os.path.abspath( 
os.path.join( os.getcwd(), 
+                                               
self.Form.connectInfo.Database.split(os.path.sep)[-1]) )
+
+               
+       def onLeavePage(self, direction):
+               if direction == "forward":
+                       directory = self.txtDir.Value
+                       if not os.path.exists(directory):
+                               msg = "The target directory %s does not exist. 
Do you want to create it now?" % directory
+                               if dabo.ui.areYouSure(msg):
+                                       os.mkdir(directory)
+                               else:
+                                       return False
+                       self.Form.outputDirectory = directory
+               return True
+
+               
+class PageGo(WizardPage):
+       def __init__(self, parent, title="Create Application"):
+               super(PageGo, self).__init__(parent=parent, Title=title)
+               txt = """Press 'Finish' to create your application, or
+'Back' to edit any information."""
+               lbl = dLabel(self, Caption=txt)
+               self.Sizer.append(lbl)
+
+               
+       def onLeavePage(self, direction):
+               if direction == "forward":
+                       if not self.Form.createApp():
+                               return False
+                       else:
+                               dabo.ui.info("""
+Your application has been created. Please remember that the
+intent of this is to give you, the database developer, the 
+ability to browse and edit all records in all tables of your
+database. 
+
+As it stands now, there are no limits to what you can do with 
+the data: add records, delete records, modify records. In other 
+words, the application you just created IS DANGEROUS. Treat it 
+as a demo, and if you do use it, use it with care and consider 
+adding business rules and organizing your screens into 
+master/childview parent/child relationships.
+
+We take no responsibility if your database gets hopelessly 
+mangled, but at the same time I hope you find this wizard useful.
+
+To see your app in action, navigate to the target directory and
+type 'python main.py' at the commandline.
+
+pkm
+""")
+               return True
+
+
+class AppWizard(Wizard):
+       def __init__(self, parent=None, *args, **kwargs):
+               super(AppWizard, self).__init__(parent=parent, *args, **kwargs)
+               
+               self.Caption = "Dabo Application Wizard"
+               self.Image = "daboIcon128"
+               self.Size = (520, 560)
+
+               self.tableDict = {}
+               self.selectedTables = []
+               self.tableRelations = []
+               self.tableRelationKeys = {}
+               self.outputDirectory = ""
+               self.connectInfo = dabo.db.dConnectInfo()
+               self.dbType = "MySQL"           # default to MySQL
+               
+               pgs = [PageIntro, PageDatabase, PageTableSelection, 
PageRelations, 
+                               PageTargetDirectory, PageGo]
+               self.append(pgs)
+               self.start()
+               
+
+       def getTables(self):
+               return self.tableDict.keys()
+       
+       def getTableInfo(self):
+               ti = ""
+               td = self.tableDict
+               tables = td.keys()
+               tables.sort()
+               for table in tables:
+                       count = td[table]["recordCount"]
+                       ti = "".join((ti, "\n%s  - %s record%s.\n" % (table, 
count, count==1 and "" or "s")))
+                       
+                       fields = td[table]["fields"].keys()
+                       fields.sort()
+                       for field in fields:
+                               ti = "".join((ti, "      %s (%s)  %s\n" % 
(td[table]["fields"][field]["name"], 
+                                               
td[table]["fields"][field]["type"],
+                                               
td[table]["fields"][field]["pk"] == True and "PK" or "")))
+               return ti.strip()
+               
+       
+       def createApp(self):
+               directory = self.outputDirectory
+               
+               if os.path.exists(directory):
+                       td = self.tableDict
+                       rd = self.tableRelationKeys
+                       selTb = self.selectedTables
+                       ci = self.connectInfo
+                       oldDir = os.getcwd()
+                       os.chdir(directory)
+                       appName = os.path.split(self.outputDirectory)[-1]
+                       
+                       ## Create the directory structure:
+                       for d in ("biz", "db", "ui", "resources", "reports"):
+                               if not os.path.exists(d):
+                                       os.mkdir(d)
+
+                       ## Create the main script:
+                       f = open("./%s.py" % appName, "w")
+                       f.write(self.getMain("[EMAIL PROTECTED]" % (ci.User, 
ci.Host), selTb[0]))
+                       f.close()
+
+                       ## Create App.py:
+                       f = open("./App.py", "w")
+                       f.write(self.getApp(appName))
+                       f.close()
+                       
+                       # Db module:
+                       os.chdir("./db")
+                       open("./__init__.py", 
"w").write(self.getModuleInit_db())
+                       open("./default.cnxml", 
"w").write(self.getDbConnXML(ci))
+
+
+                       # Biz module:
+                       os.chdir("../biz")
+                       open("./__init__.py", 
"w").write(self.getModuleInit_biz())
+
+                       # Write the base bizobj:
+                       open("./Base.py", "w").write(self.getBaseBizobj())
+
+                       # Write each bizobj:
+                       for table in selTb:
+                               f = open("./%s.py" % table.title(), "w")
+                               f.write(self.getBizobj(td, table))
+                               f.close()
+
+                       # UI module:
+                       os.chdir("../ui")
+                       open("./__init__.py", 
"w").write(self.getModuleInit_ui())
+
+                       ## fieldSpecs, relationSpecs:                   
+                       f = open("./fieldSpecs.fsxml", "w")
+                       f.write(fieldSpecs(td, selTb))
+                       f.close()
+                       
+                       f = open("./relationSpecs.rsxml", "w")
+                       f.write(relationSpecs(rd))
+                       f.close()
+                       
+                       ## file|open menu:
+                       f = open("./MenFileOpen.py", "w")
+                       f.write(self.getFileOpenMenu(selTb))
+                       f.close()
+                       
+
+                       ## base page:
+                       open("./PagBase.py", "w").write(self.getPagBase())
+
+                       ## base form:
+                       open("./FrmBase.py", "w").write(self.getFrmBase())
+
+                       # Write each form:
+                       for table in selTb:
+                               f = open("./Frm%s.py" % table.title(), "w")
+                               f.write(self.getForm(table))
+                               f.close()
+               
+                       return True
+
+               else:
+                       dabo.ui.stop("The target directory does not exist. 
Cannot continue.")           
+                       return False
+
+
+       def getFileOpenMenu(self, tables):
+               tables.sort()
+               forms = ""
+               for table in tables:
+                       forms = "".join((forms, """("%s", 
app.ui.Frm%s),\n\t\t\t\t""" % 
+                               (table.title(), table.title())))
+               forms = "".join((forms, """("-", None),\n\t\t\t\t"""))
+       
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-MenFileOpen.py")).read() % locals()
+
+       
+       def getForm(self, table):
+               tableName = table.title()
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-Frm.py")).read() % locals()
+
+                                               
+       def getMain(self, dbConnectionDef, table):
+               tableName = table.title()
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-main.py")).read() % locals()
+
+
+       def getModuleInit_db(self):
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-db__init__.py")).read() % locals()
+
+
+       def getModuleInit_biz(self):
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-biz__init__.py")).read() % locals()
+
+
+       def getModuleInit_ui(self):
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-ui__init__.py")).read() % locals()
+
+
+       def getApp(self, appName):
+               appName = appName.title()
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-App.py")).read() % locals()
+
+
+       def getDbConnXML(self, ci):
+               cxnDict = {"dbtype" : ci.DbType, "host" : ci.Host, "database" : 
ci.Database, 
+                       "user" : ci.User, "password" : ci.Password, "port" : 
ci.Port}
+               return createXML(cxnDict)
+
+
+       def getBaseBizobj(self):
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-BizBase.py")).read() % locals()
+
+
+       def getBizobj(self, tableDict, table):
+               tableName = table.title()
+               tbInfo = tableDict[table]
+
+               # find the pk field, if any:
+               pkField = None
+               for field in tableDict[table]["fields"].keys():
+                       if tableDict[table]["fields"][field]["pk"] == True:
+                               pkField = "\"" + field + "\""
+                               break
+                               
+               flds = tbInfo["fields"]
+               
+               sortedFieldNames = []
+               for fld in flds.keys():
+                       order = flds[fld]["order"]
+                       sortedFieldNames.append((order, fld))
+               sortedFieldNames.sort()
+               
+               fields = ""
+
+               for field in sortedFieldNames:
+                       fields += """self.addField("%s.%s as %s")\n\t\t""" % 
(table, field[1], field[1])
+                                               
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-Biz.py")).read() % locals()
+
+
+       def getFrmBase(self):
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-FrmBase.py")).read() % locals()
+
+
+       def getPagBase(self):
+               return open(os.path.join(self.Application.HomeDirectory, 
+                               "spec-PagBase.py")).read() % locals()
+
+
+def relationSpecs(relaDict):
+       ret = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<daboRelationSpecs>
+       <relations>
+%s     </relations>
+</daboRelationSpecs>
+"""
+       relaTemplate1M = """            <relation name="%s:%s" 
relationType="1M" 
+                       source="%s" target="%s" sourceField="%s" 
targetField="%s"  />
+"""
+       relaTemplateMM = """            <relation name="%s:%s" 
relationType="MM" 
+                       source="%s" sourceField="%s" 
+                       alloc="%s" allocSourceField="%s" allocTargetField="%s"
+                       target="%s" targetField="%s"  />
+"""
+       relaXML = ""
+       for key in relaDict.keys():
+               if key[0] == "1M":
+                       typ, relaParent, relaChild = key
+                       parentFld, childFld = relaDict[key]
+                       relaData = (relaParent, relaChild, relaParent, 
relaChild, parentFld, childFld)
+                       relaXML += relaTemplate1M % relaData
+       return ret % relaXML
+
+
+
+def fieldSpecs(tbDict, tbls):
+       ret = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<daboAppSpecs>
+%s
+</daboAppSpecs>
+"""
+
+       tblTemplate = """       <table name="%s">
+               <fields>
+%s             </fields>
+       </table>
+"""
+
+       fldTemplate = """                       <field name="%s"        
type="%s"       caption="%s" 
+                               searchInclude="%s"      searchOrder="%s"        
wordSearch="%s" 
+                               listInclude="%s"        listColWidth="%s"       
listOrder="%s"
+                               editInclude="%s"        editReadOnly="%s"       
editOrder="%s"  />
+                               
+"""
+
+       typeConversion = {"I" : "int", "C" : "char", "M" : "memo", "D" : 
"date", 
+                       "N" : "float", "F" : "float", "?" : "char", "L" : 
"bool", "B" : "bool", "T" : "datetime"}
+       tableXML = ""
+       tables = tbDict.keys()
+       tables.sort()
+       for tb in tables:
+               if tb in tbls:
+                       tbInfo = tbDict[tb]
+                       flds = tbInfo["fields"]
+                       fieldXML = ""
+                       fldOrd = 0
+                       
+                       sortedFieldNames = []
+                       for fld in flds.keys():
+                               order = flds[fld]["order"]
+                               sortedFieldNames.append((order, fld))
+                       sortedFieldNames.sort()
+                       
+                       for tup in sortedFieldNames:
+                               fld = tup[1]
+                               fldInfo = flds[fld]
+                               fldType = typeConversion[fldInfo["type"]]
+                               fldData = (fld, fldType, fld, 1, fldOrd, 0, 1, 
-1, fldOrd, 1, 0, fldOrd)
+                               fieldXML += fldTemplate % fldData
+                               fldOrd += 10
+                       
+                       tableXML += tblTemplate % (tb, fieldXML)
+       return ret % tableXML
+       
+
+
+if __name__ == "__main__":
+       app = dabo.dApp()
+       app.setAppInfo("appName", "Dabo Application Wizard")
+       app.setAppInfo("appName", "AppWizard")
+       app.MainFormClass = AppWizard
+       app.setup()
+       app.start()

Added: trunk/wizards/AppWizardX/spec-App.py
===================================================================
--- trunk/wizards/AppWizardX/spec-App.py        2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-App.py        2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,17 @@
+import dabo
+
+
+class App(dabo.dApp):
+
+       def initProperties(self):
+               self.MainFormClass = None
+
+               ## The following information can be used in various places in 
your app:
+               self.setAppInfo("appName", "%(appName)s")
+               self.setAppInfo("companyName", "Your company name")
+               self.setAppInfo("companyAddress1", "Your company address")
+               self.setAppInfo("companyAddress2", "Your company CSZ")
+               self.setAppInfo("companyPhone", "Your company phone")
+               self.setAppInfo("companyEmail", "Your company email")
+               self.setAppInfo("companyUrl", "Your company url")
+


Property changes on: trunk/wizards/AppWizardX/spec-App.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-Biz.py
===================================================================
--- trunk/wizards/AppWizardX/spec-Biz.py        2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-Biz.py        2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,26 @@
+from Base import Base
+
+
+class %(tableName)s(Base):
+       
+       def initProperties(self):
+               %(tableName)s.doDefault()
+               self.Caption = "%(tableName)s"
+               self.DataSource = "%(table)s"
+               self.KeyField = %(pkField)s
+               # Set the default values for new records added:
+               self.DefaultValues = {}
+       
+
+       def afterInit(self):
+               %(tableName)s.doDefault()
+               
+
+       def setBaseSQL(self):
+               # Set up the base SQL (the fields clause, the from clause, 
etc.) The
+               # UI refresh() will probably modify the where clause and maybe 
the
+               # limit clause, depending on what the runtime user chooses in 
the
+               # select page.
+               self.addFrom("%(table)s")
+               self.setLimitClause("500")
+               %(fields)s              


Property changes on: trunk/wizards/AppWizardX/spec-Biz.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-BizBase.py
===================================================================
--- trunk/wizards/AppWizardX/spec-BizBase.py    2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-BizBase.py    2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,8 @@
+import dabo.lib.datanav as datanav
+
+class Base(datanav.Bizobj):
+
+       def afterInit(self):
+               Base.doDefault()
+               self.setBaseSQL()
+


Property changes on: trunk/wizards/AppWizardX/spec-BizBase.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-Frm.py
===================================================================
--- trunk/wizards/AppWizardX/spec-Frm.py        2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-Frm.py        2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,37 @@
+import os
+from FrmBase import FrmBase
+
+
+class Frm%(tableName)s(FrmBase):
+
+       def initProperties(self):
+               Frm%(tableName)s.doDefault()
+               self.NameBase = "frm%(tableName)s"
+               self.Caption = "%(tableName)s"
+
+
+       def addEditPage(self, dataSource, title, pageClass=None):
+               # If you have an overridden edit page, stick it in here. eg:
+               #pageClass = self.Application.ui.PagEditClient
+               Frm%(tableName)s.doDefault(dataSource, title, pageClass)
+               
+
+       def afterInit(self):
+               Frm%(tableName)s.doDefault()
+
+               # Instantiate the bizobj:
+               app = self.Application
+               primaryBizobj = app.biz.%(tableName)s(app.dbConnection)
+               
+               # Register it with dForm:
+               self.addBizobj(primaryBizobj)
+               
+               # Set up the field information for the form
+               fsXML = os.path.join(app.HomeDirectory, "ui", 
"fieldSpecs.fsxml")
+               rsXML = os.path.join(app.HomeDirectory, "ui", 
"relationSpecs.rsxml")
+               self.setFieldSpecs(fsXML, "%(table)s")
+               self.setRelationSpecs(rsXML, app.biz)
+
+               # The form now knows what it needs to create itself. Do it!
+               self.creation()
+


Property changes on: trunk/wizards/AppWizardX/spec-Frm.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-FrmBase.py
===================================================================
--- trunk/wizards/AppWizardX/spec-FrmBase.py    2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-FrmBase.py    2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,19 @@
+import dabo.ui
+import dabo.lib.datanav as datanav
+
+
+class FrmBase(datanav.Form):
+
+       def initProperties(self):
+               self.RequeryOnLoad = False
+
+
+       def afterSetMenuBar(self):
+               self.fillFileOpenMenu()
+
+
+       def fillFileOpenMenu(self):
+               app = self.Application
+               fileMenu = self.MenuBar.getMenu("File")
+               fileMenu.prependMenu(app.ui.MenFileOpen(fileMenu))
+


Property changes on: trunk/wizards/AppWizardX/spec-FrmBase.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-MenFileOpen.py
===================================================================
--- trunk/wizards/AppWizardX/spec-MenFileOpen.py        2005-10-30 18:18:43 UTC 
(rev 215)
+++ trunk/wizards/AppWizardX/spec-MenFileOpen.py        2005-10-30 21:34:50 UTC 
(rev 216)
@@ -0,0 +1,40 @@
+import dabo
+import dabo.dEvents as dEvents
+
+
+class MenFileOpen(dabo.ui.dMenu):
+
+       def afterInit(self):
+               self.Caption = "&Open\tCtrl+O"
+               self.HelpText = "Open a module"
+
+               # Define the forms you want in your open menu here. Insert a 
("-", None) 
+               # tuple and the code below will insert a separator in its 
place. Explicitly
+               # set up which character has the hotkey by adding a & in front 
of it and
+               # by turning off the autoHotKeys flag.
+               autoHotKeys = True
+               app = self.Application
+
+               forms = (%(forms)s)
+
+               for form in forms:
+                       caption = form[0]
+                       if caption == "-":
+                               # insert separator instead:
+                               self.appendSeparator()
+                       else:
+                               if autoHotKeys and "&" not in caption:
+                                       caption = "&%%s" %% caption
+                               plainCaption = caption.replace("&", "")
+                               itm = dabo.ui.dMenuItem(self, Caption=caption,
+                                               HelpText="Open the %%s module" 
%% plainCaption,
+                                               Tag=form[1])
+                               itm.bindEvent(dEvents.Hit, self.openForm)
+                               self.appendItem(itm)
+
+
+       def openForm(self, evt):
+               app = self.Application
+               mainForm = app.MainForm
+               frm = evt.EventObject.Tag(mainForm)
+               frm.Show()


Property changes on: trunk/wizards/AppWizardX/spec-MenFileOpen.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-PagBase.py
===================================================================
--- trunk/wizards/AppWizardX/spec-PagBase.py    2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-PagBase.py    2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,5 @@
+import dabo.lib.datanav as datanav
+
+
+class PagBase(datanav.Page):
+       pass


Property changes on: trunk/wizards/AppWizardX/spec-PagBase.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-biz__init__.py
===================================================================
--- trunk/wizards/AppWizardX/spec-biz__init__.py        2005-10-30 18:18:43 UTC 
(rev 215)
+++ trunk/wizards/AppWizardX/spec-biz__init__.py        2005-10-30 21:34:50 UTC 
(rev 216)
@@ -0,0 +1,44 @@
+import os
+
+# Automatically import all classes from all .py files in this directory,
+# instead of having to explicitly import each of them like "from X import X":
+classes = []
+for f in os.listdir(__path__[0]):
+       if f[-3:] == ".py" and f != "__init__.py":
+               m = __import__(f[:-3], globals())
+               for i in dir(m):
+                       c = m.__dict__[i]
+                       if type(c) == type and c not in classes:
+                               classes.append(c)
+
+# Put the classes in the module namespace, replacing the submodules:
+for c in classes:
+       globals()[c.__name__] = c
+
+# Clean up things that don't need to be exposed in the biz namespace:
+del(os)
+del(classes)
+try:
+       del(f)
+except NameError:
+       pass
+try:
+       del(m)
+except NameError:
+       pass
+try:
+       del(i)
+except NameError:
+       pass
+try:
+       del(c)
+except NameError:
+       pass
+
+
+
+## Place any explicit imports below this point.
+
+# example:
+# from myModule import MyClass
+


Property changes on: trunk/wizards/AppWizardX/spec-biz__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-db__init__.py
===================================================================
--- trunk/wizards/AppWizardX/spec-db__init__.py 2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-db__init__.py 2005-10-30 21:34:50 UTC (rev 
216)
@@ -0,0 +1,40 @@
+import os
+
+# Automatically import all names from all .py files in this directory,
+# instead of having to explicitly import each of them like "from X import X":
+names = []
+for f in os.listdir(__path__[0]):
+       if f[-3:] == ".py" and f != "__init__.py":
+               m = __import__(f[:-3], globals())
+               if m.__dict__.has_key(f[:-3]):
+                       c = m.__dict__[f[:-3]]
+                       if c not in names:
+                               names.append(c)
+
+# Put the names in the module namespace, replacing the submodules:
+for c in names:
+       globals()[c.__name__] = c
+
+
+# Clean up things that don't need to be exposed in the ui namespace:
+del(os)
+del(names)
+try:
+       del(f)
+except NameError:
+       pass
+try:
+       del(m)
+except NameError:
+       pass
+try:
+       del(c)
+except NameError:
+       pass
+
+
+## Place any explicit imports below this point.
+
+# example:
+# from myModule import MyClass
+


Property changes on: trunk/wizards/AppWizardX/spec-db__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/wizards/AppWizardX/spec-main.py
===================================================================
--- trunk/wizards/AppWizardX/spec-main.py       2005-10-30 18:18:43 UTC (rev 
215)
+++ trunk/wizards/AppWizardX/spec-main.py       2005-10-30 21:34:50 UTC (rev 
216)
@@ -0

 (2238 bytes were truncated as it was too long for the email (max 40000 bytes.)


_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev

Reply via email to