commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gnue designer/src/LayoutEditor.py designer/src/...


From: James Thompson
Subject: gnue designer/src/LayoutEditor.py designer/src/...
Date: Tue, 17 Jul 2001 12:24:25 -0700

CVSROOT:        /cvs
Module name:    gnue
Branch:         gnuef-new-datasources
Changes by:     James Thompson <address@hidden> 01/07/17 12:24:25

Modified files:
        designer/src   : LayoutEditor.py MenuBar.py PropertyEditor.py 
                         TreeView.py 
        docbook/DevelopersIntroduction/shared: copyright.sgml 
        gnue-common    : setup.py 
        gnue-common/etc: sample.gnue.conf 
        gnue-common/src/dbdrivers/db2: DBdriver.py 
        gnue-common/src/dbdrivers/geas: DBdriver.py 
        gnue-common/src/dbdrivers/mysql: DBdriver.py 
        gnue-common/src/dbdrivers/odbc: DBdriver.py 
        gnue-common/src/dbdrivers/oracle: DBdriver.py 
        gnue-common/src/dbdrivers/postgresql: DBdriver.py 
        gnuef          : TODO 
        gnuef/doc      : techref.lyx 
        gnuef/samples/trigger: trigger.gfd 
        gnuef/src      : GFForm.py GFInstance.py GFParser.py 
                         GFTrigger.py UIwxpython.py 
        gnuef/src/GFObjects: GFBlock.py GFDataSource.py GFDatabase.py 
                             GFEntry.py GFLabel.py 
Added files:
        designer/src   : PopupMenu.py 
        gnue-common/doc: DataObjects.txt 
        gnue-common/src: GDateTime.py 
        gnue-common/src/FormatMasks: BaseMask.py DateMask.py 
                                     FormatExceptions.py __init__.py 
        gnuef/client   : gfclient 
        objectserver   : autogen.sh 

Log message:
        merged trunk, from gnuef-new-datasources to HEAD

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/designer/src/PopupMenu.py?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.2.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/designer/src/LayoutEditor.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.15&tr2=1.15.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/designer/src/MenuBar.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.9&tr2=1.9.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/designer/src/PropertyEditor.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.10&tr2=1.10.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/designer/src/TreeView.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.6&tr2=1.6.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/docbook/DevelopersIntroduction/shared/copyright.sgml.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/setup.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.13&tr2=1.13.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/doc/DataObjects.txt?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.3.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/etc/sample.gnue.conf.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.3&tr2=1.3.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GDateTime.py?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.3.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/FormatMasks/BaseMask.py?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.2.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/FormatMasks/DateMask.py?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.4.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/FormatMasks/FormatExceptions.py?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.2.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/FormatMasks/__init__.py?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/dbdrivers/db2/DBdriver.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/dbdrivers/geas/DBdriver.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.5&tr2=1.5.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/dbdrivers/mysql/DBdriver.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/dbdrivers/odbc/DBdriver.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/dbdrivers/oracle/DBdriver.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.4&tr2=1.4.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/dbdrivers/postgresql/DBdriver.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.8&tr2=1.8.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/TODO.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.55&tr2=1.55.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/client/gfclient?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.44.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/doc/techref.lyx.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.7&tr2=1.7.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/samples/trigger/trigger.gfd.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.7&tr2=1.7.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFForm.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.110&tr2=1.110.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFInstance.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.16&tr2=1.16.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFParser.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.46&tr2=1.46.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFTrigger.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.40&tr2=1.40.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/UIwxpython.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.104&tr2=1.104.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFBlock.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.4&tr2=1.4.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFDataSource.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.3&tr2=1.3.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFDatabase.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFEntry.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFLabel.py.diff?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/objectserver/autogen.sh?cvsroot=OldCVS&only_with_tag=gnuef-new-datasources&rev=1.5.2.1

Patches:
Index: gnue/designer/src/LayoutEditor.py
diff -u gnue/designer/src/LayoutEditor.py:1.15 
gnue/designer/src/LayoutEditor.py:1.16
--- gnue/designer/src/LayoutEditor.py:1.15      Tue Jul  3 18:43:11 2001
+++ gnue/designer/src/LayoutEditor.py   Thu Jul 12 15:51:08 2001
@@ -299,13 +299,14 @@
 
     for widget in self.mainWidget.widgets:
       widget.SetCursor (wxSTANDARD_CURSOR)
-      if isinstance(widget, wxControl):
+      if isinstance(widget, wxWindow):
         widget.Enable(0)
       self.setAllChildren(EVT_KEY_UP, widget, self.instance.keyTrap)
       self.setAllChildren(EVT_SET_FOCUS, widget, self.focusGainedTrap)
       self.setAllChildren(EVT_KILL_FOCUS, widget, self.focusLostTrap)
       self.setAllChildren(EVT_LEFT_UP, widget, self.OnLeftUp)
       self.setAllChildren(EVT_LEFT_DOWN, widget, self.OnLeftDown)
+      self.setAllChildren(EVT_RIGHT_DOWN, widget, self.OnRightDown)
       self.setAllChildren(EVT_RIGHT_UP, widget, self.OnRightUp)
       self.setAllChildren(EVT_MOTION, widget, self.instance.OnMotion)
 
@@ -353,10 +354,12 @@
       self.setAllChildren(event, child, trap)
 
   def focusGainedTrap(self, event): 
+    self.instance.panel.SetFocus()
     pass
+#    event.Skip()
 
   def focusLostTrap(self, event): 
-    pass
+    event.Skip()
 
   def OnLeftDown(self, event): 
 #    self.instance.panel.CaptureMouse() 
@@ -377,9 +380,12 @@
   def OnLeftUp(self, event): 
     pass
 #    self.instance.panel.ReleaseMouse() 
+
+  def OnRightDown(self, event): 
+    pass
  
   def OnRightUp(self, event): 
-    pt = event.GetPosition() 
+    pt = event.GetPositionTuple() 
     self.instance._instance.onSetCurrentObject(self.object, None)
     wxPyTypeCast(event.GetEventObject(),'wxWindow') \
        .PopupMenu(self.object._popupMenu, pt)
Index: gnue/designer/src/MenuBar.py
diff -u gnue/designer/src/MenuBar.py:1.10 gnue/designer/src/MenuBar.py:1.11
--- gnue/designer/src/MenuBar.py:1.10   Thu Jul 12 11:53:26 2001
+++ gnue/designer/src/MenuBar.py        Thu Jul 12 15:51:08 2001
@@ -98,185 +98,3 @@
   def lastToolAdded(self): 
    self._window.AppendSeparator()
 
-
-class ObjectMenu(wxMenu): 
-  def __init__(self, instance, object): 
-    wxMenu.__init__(self, "Object Tasks...")
-
-    self.object = object
-    self.instance = instance
-    self._newMap = {}
-
-    if object == None: 
-      id = wxNewId()
-      self.Append(id, "New Data Source") 
-      EVT_MENU(self, id, self.OnCreateDataSource)
-      id = wxNewId()
-      self.Append(id, "New Shared Trigger") 
-      EVT_MENU(self, id, self.OnCreateNamedTrigger)
-      id = wxNewId()
-      self.Append(id, "New Layout Page") 
-      EVT_MENU(self, id, self.OnCreatePage)
-    else: 
-
-      # New >
-
-      menu = wxMenu("New...")
-
-      id = wxNewId()
-      menu.Append(id, "Data Source") 
-      EVT_MENU(menu, id, self.OnCreateDataSource)
-      id = wxNewId()
-      menu.Append(id, "Shared Trigger") 
-      EVT_MENU(menu, id, self.OnCreateNamedTrigger)
-      id = wxNewId()
-      menu.Append(id, "Layout Page") 
-      EVT_MENU(menu, id, self.OnCreatePage)
-  
-      menu.AppendSeparator()
- 
-      tag = string.lower(object.getObjectType()[2:])
-      if Incubator.elementMapping.has_key(tag): 
-        Incubator.elementMapping[tag].sort()
-        for element in Incubator.elementMapping[tag]: 
-          tid = wxNewId()
-          self._newMap[tid] = element
-          menu.Append(tid, element) 
-          EVT_MENU(menu, tid, self.OnCreateObject)
-        self.AppendMenu(wxNewId(), "&New", menu)
-  
-      # Properties
-      id = wxNewId()
-      self.Append(id, "&Properties...")
-      EVT_MENU(self, id, self.OnEditProperties)
-
-      if not isinstance (object, GFForm.GFForm): 
-        # Delete
-        id = wxNewId()
-        self.Append(id, "&Delete %s" % object.getObjectType()[2:])
-        EVT_MENU(self, id, self.OnDeleteObject)
-
-      self.AppendSeparator()
-
-      # Events >
-      if isinstance (object, GFTrigger.GFTriggerAware): 
-        menu = wxMenu("Events...")
-        self._triggerMap = {}
-        keys = GFTrigger.VALIDTRIGGERS.keys()
-        keys.sort()
-        for trigger in (keys): 
-          tid = wxNewId()
-          self._triggerMap[tid] = trigger
-          menu.Append(tid, GFTrigger.VALIDTRIGGERS[trigger] + "...") 
-          EVT_MENU(menu, tid, self.OnEditEvent)
-        self.AppendMenu(wxNewId(), "&Events", menu)
-
-      self.AppendSeparator()
-
-      if isinstance(object, GFObjects.GFPage) or \
-         isinstance(object, GFObjects.GFBlock): 
-        # Reorder
-        id = wxNewId()
-        self.Append(id, "&Reorder by Location")
-        EVT_MENU(self, id, self.OnReorderLayout)
-     
-  def OnEditProperties(self, event): 
-    self.instance.propertyEditorWindow.Show(1)
-    self.instance.propertyEditorWindow.Raise()
-
-  def OnEditEvent(self, event): 
-    pass
-
-  def OnDeleteObject(self, event):
-    Incubator.deleteObject(self.instance, self.instance._form, self.object)
-
-  def OnReorderLayout(self, event):
-    unqId = 0 
-    hiddenObjects = []
-    boxObjects = {}
-    navObjects = {}
-    blockObjects = {}
-    self.object._upperX = 99999
-    self.object._upperY = 99999
-   
-    # Handle each child (note we are working from a copy 
-    # because self.oject._children will be morphing
-    for object in self.object._children[:]: 
-      if hasattr(object, 'hidden') and object.hidden: 
-        hiddenObjects.append(object)
-      elif object.getObjectType() == 'GFBlock': 
-        object._popupMenu.OnReorderLayout(event)
-        object.__savedChildren = object._children[:]
-        for o2 in object.__savedChildren:
-          self.instance.onDeleteObject(o2, __name__)
-        
-        oid = "%5d.%5d.%5d" % (object._upperY, object._upperX, unqId)
-        unqId = unqId + 1
-        blockObjects[oid] = object
-
-      else: 
-        if hasattr(object,'y') and object.y < self.object._upperY: 
-          self.object._upperY = object.y
-        if hasattr(object,'x') and object.x < self.object._upperX: 
-          self.object._upperX = object.x
-
-        oid = "%5d.%5d.%5d" % (object.y, object.x, unqId) 
-        unqId  = unqId + 1
-        if object.getObjectType() == 'GFBox': 
-          boxObjects[oid] = object
-        else: 
-          navObjects[oid] = object
-    
-      # Notify everyone that this object was deleted
-      self.instance.onDeleteObject(object, __name__)
-
-    self.object._children = []
-    # First, add back hidden objects all 
-    for object in hiddenObjects:
-      self.object._children.append(object)
-      self.instance.onCreateObject(object, __name__)
-
-    # Now, add hidden objects
-    boxes = boxObjects.keys()
-    boxes.sort()
-    for box in boxes: 
-      self.object._children.append(boxObjects[box])
-      self.instance.onCreateObject(boxObjects[box], __name__)
-    
-    # The rest of the objects (other than blocks) go here
-    nav = navObjects.keys()
-    nav.sort()
-    for n in nav: 
-      self.object._children.append(navObjects[n])
-      self.instance.onCreateObject(navObjects[n], __name__)
-
-    # And, finally, any child blocks 
-    blocks = blockObjects.keys()
-    blocks.sort()
-    for block in blocks: 
-      children = blockObjects[block].__savedChildren[:]
-      self.object._children.append(blockObjects[block])
-      self.instance.onCreateObject(blockObjects[block], __name__)
-      for child in children: 
-        blockObjects[block]._children.append(child)
-        self.instance.onCreateObject(child,__name__)
-
-      
-  def OnCreateObject(self, event):
-    GDebug.printMesg(3, "Creating Object")
-    tag = self._newMap[event.GetId()]
-    Incubator.createObject(self.instance, self.instance._form, tag, 
-      parentHint=self.object)
-
-  def OnCreateDataSource(self, event):
-    Incubator.createObject(self.instance, self.instance._form, 'datasource')
-
-  def OnCreateNamedTrigger(self, event):
-    Incubator.createObject(self.instance, self.instance._form, 'trigger')
-
-  def OnCreatePage(self, event):
-    Incubator.createObject(self.instance, self.instance._form, 'page')
-
-
-
-
Index: gnue/designer/src/PopupMenu.py
diff -u gnue/designer/src/PopupMenu.py:1.1 gnue/designer/src/PopupMenu.py:1.2
--- gnue/designer/src/PopupMenu.py:1.1  Thu Jul 12 15:51:08 2001
+++ gnue/designer/src/PopupMenu.py      Thu Jul 12 19:54:20 2001
@@ -125,6 +125,7 @@
 
   def OnReorderLayout(self, event):
     unqId = 0 
+    triggerObjects = []
     hiddenObjects = []
     boxObjects = {}
     navObjects = {}
@@ -137,6 +138,8 @@
     for object in self.object._children[:]: 
       if hasattr(object, 'hidden') and object.hidden: 
         hiddenObjects.append(object)
+      elif object.getObjectType() == 'GFTrigger': 
+        triggerObjects.append(object)
       elif object.getObjectType() == 'GFBlock': 
         object._popupMenu.OnReorderLayout(event)
         object.__savedChildren = object._children[:]
@@ -164,7 +167,14 @@
       self.instance.onDeleteObject(object, __name__)
 
     self.object._children = []
-    # First, add back hidden objects all 
+
+    # First, add back triggers 
+    for object in triggerObjects:
+      self.object._children.append(object)
+      self.instance.onCreateObject(object, __name__)
+
+
+    # Next, add back hidden objects 
     for object in hiddenObjects:
       self.object._children.append(object)
       self.instance.onCreateObject(object, __name__)
Index: gnue/designer/src/PropertyEditor.py
diff -u gnue/designer/src/PropertyEditor.py:1.11 
gnue/designer/src/PropertyEditor.py:1.12
--- gnue/designer/src/PropertyEditor.py:1.11    Thu Jul 12 11:53:26 2001
+++ gnue/designer/src/PropertyEditor.py Thu Jul 12 12:01:14 2001
@@ -68,42 +68,52 @@
         self.grid.Destroy()
       self.grid = wxGrid(self.panel, -1, pos=wxPoint(0,0))
 
-      self.grid.CreateGrid(len(self.attributes.keys()),1)
-      self.grid.SetColLabelSize(0)
       self.rowList = self.attributes.keys()
       self.rowList.sort()
+
+
+      # Only show properties for nondeprecated values (unless set)
       i = 0
-      for key in self.rowList: 
+      while i < len(self.rowList):   
+        key = self.rowList[i]
+        if self.attributes[key].has_key ('Deprecated') and \
+           self.attributes[key]['Deprecated'] and \
+           (not hasattr(object, key) or \
+              (self.attributes[key].has_key('Default') and \
+               object.__dict__[key] == self.attributes[key]['Default'] ) ): 
+          self.rowList.pop(i)
+        else: 
+          i = i + 1
 
-        # Only show properties for nondeprecated values (unless set)
-        if not (self.attributes[key].has_key ('Deprecated') and \
-                self.attributes[key]['Deprecated'] and \
-                (not hasattr(object, key) or \
-                   (self.attributes[key].has_key('Default') and \
-                    object.__dict__[key] == self.attributes[key]['Default'] )
-                ) ): 
-
-          self.grid.SetRowLabelValue(i, string.upper(key[0]) + 
string.lower(key[1:]))
-
-          if self.attributes[key].has_key('ValueSet'): 
-            self.grid.SetCellEditor(i, 0, 
RestrictedCellEditor(self.attributes[key]))
-          elif self.attributes[key]['Typecast'] == GTypecast.boolean: 
-            self.grid.SetCellEditor(i, 0, BoolCellEditor(self.attributes[key]))
-          elif self.attributes[key]['Typecast'] in (GTypecast.integer, 
-                  GTypecast.number, GTypecast.whole):
-            self.grid.SetCellEditor(i, 0, IntCellEditor(self.attributes[key]))
-          else: 
-            self.grid.SetCellEditor(i, 0, CharCellEditor(self.attributes[key]))
-  
-          if hasattr(object, key): 
-            if self.attributes[key]['Typecast'] == GTypecast.boolean:
-              if object.__dict__[key]:    
-                self.grid.SetCellValue(i,0,"TRUE")
-              else: 
-                self.grid.SetCellValue(i,0,"FALSE")
+
+      self.grid.CreateGrid(len(self.rowList),1)
+      self.grid.SetColLabelSize(0)
+
+      i = 0
+
+      for key in self.rowList:
+
+        self.grid.SetRowLabelValue(i, string.upper(key[0]) + 
string.lower(key[1:]))
+
+        if self.attributes[key].has_key('ValueSet'): 
+          self.grid.SetCellEditor(i, 0, 
RestrictedCellEditor(self.attributes[key]))
+        elif self.attributes[key]['Typecast'] == GTypecast.boolean: 
+          self.grid.SetCellEditor(i, 0, BoolCellEditor(self.attributes[key]))
+        elif self.attributes[key]['Typecast'] in (GTypecast.integer, 
+                GTypecast.number, GTypecast.whole):
+          self.grid.SetCellEditor(i, 0, IntCellEditor(self.attributes[key]))
+        else: 
+          self.grid.SetCellEditor(i, 0, CharCellEditor(self.attributes[key]))
+
+        if hasattr(object, key): 
+          if self.attributes[key]['Typecast'] == GTypecast.boolean:
+            if object.__dict__[key]:    
+              self.grid.SetCellValue(i,0,"TRUE")
             else: 
-              self.grid.SetCellValue(i,0, "%s" % object.__dict__[key])
-          i = i + 1
+              self.grid.SetCellValue(i,0,"FALSE")
+          else: 
+            self.grid.SetCellValue(i,0, "%s" % object.__dict__[key])
+        i = i + 1
       self.onSize(None)
       EVT_GRID_CELL_CHANGE(self.grid, self.OnCellChange)
 
Index: gnue/designer/src/TreeView.py
diff -u gnue/designer/src/TreeView.py:1.6 gnue/designer/src/TreeView.py:1.7
--- gnue/designer/src/TreeView.py:1.6   Fri Jun 22 06:16:35 2001
+++ gnue/designer/src/TreeView.py       Thu Jul 12 15:51:08 2001
@@ -31,7 +31,7 @@
 from gnue.common import GDebug, GConfig
 from gnue.forms import GFForm, GFInstance, GFParser, GFObjects, GFTrigger, 
GFLibrary, UIwxpython
 from GFDesigner import *
-from MenuBar import ObjectMenu
+from PopupMenu import ObjectMenu
 
 class TreeView (wxTreeCtrl):
   def __init__(self, instance, form, parent): 
Index: gnue/docbook/DevelopersIntroduction/shared/copyright.sgml
diff -u gnue/docbook/DevelopersIntroduction/shared/copyright.sgml:1.4 
gnue/docbook/DevelopersIntroduction/shared/copyright.sgml:1.5
--- gnue/docbook/DevelopersIntroduction/shared/copyright.sgml:1.4       Sun Jul 
15 20:20:24 2001
+++ gnue/docbook/DevelopersIntroduction/shared/copyright.sgml   Sun Jul 15 
20:32:56 2001
@@ -1,7 +1,7 @@
 
 <legalnotice>
   <para>
-    Copyright (c) 2001 The Scrappy Team 
+    Copyright (c) 2000 Free Software Foundation 
   </para>
   <para>
     Permission is granted to copy, distribute and/or modify this document
Index: gnue/gnue-common/doc/DataObjects.txt
diff -u gnue/gnue-common/doc/DataObjects.txt:1.2 
gnue/gnue-common/doc/DataObjects.txt:1.3
--- gnue/gnue-common/doc/DataObjects.txt:1.2    Tue Jul 17 12:06:19 2001
+++ gnue/gnue-common/doc/DataObjects.txt        Tue Jul 17 12:10:54 2001
@@ -3,6 +3,8 @@
 GRD for forms and reports, respectively). The DataSource object acts as
 a implementation buffer between vendor-specific DataObjects and vendor-
 neutral datasource tags (explained further in the DataObject discussion).
+In other words, a vendor-specific DataObject will be bound to the 
+DataSource after the DataSource is initialized.
 
 A DataObject is the highest level object in the Database Driver hierarchy. 
 It basically maintains state information such as the database connection,
@@ -39,24 +41,28 @@
 
 ***********
 DataSource: 
-  getDataSet(): 
-  
-  addDetailDataSource() : Adds a DataSource in a master/detail relationship
-  masterRecordChanged() : Called when master in master/detail is updated
+  initialize()
+    Called to initialize the datasource. Binds the 
+    DataSource to a DataObject.
+
+  getDataObject()
+    Returns the bound DataObject
+
+  referenceField(field)
+    Used by the client app to notify that a certain field is being 
+    referenced.  This will ensure that the DataObject includes this
+    field in its query.
 
-  commit()      : 
-  rollback()    : 
 
-
 ***********
 DataObject:
-  createResultSet(self, conditions={}, readOnly=0): 
+  createResultSet(conditions={}, readOnly=0): 
     Creates and returns a resultset satisfying "conditions". conditions
     can either be a dictionary/hash of fieldname:value AND pairs, or, for
     more complex conditions, a GConditions object.
 
 
-  addDetailDataObject(self, dataObject, handler=None): 
+  addDetailDataObject(dataObject, handler=None): 
     Add a detail data object.  This dataobject will create a new resultset 
     everything this dataobject changes (new record, etc).  The optional 
     handler will be called after the detail dataobject is notified.  The 
Index: gnue/gnue-common/etc/sample.gnue.conf
diff -u gnue/gnue-common/etc/sample.gnue.conf:1.3 
gnue/gnue-common/etc/sample.gnue.conf:1.4
--- gnue/gnue-common/etc/sample.gnue.conf:1.3   Wed Jun 27 18:58:51 2001
+++ gnue/gnue-common/etc/sample.gnue.conf       Mon Jul 16 20:10:44 2001
@@ -57,6 +57,7 @@
 msg_query_prep=Switch to input query mask mode.
 msg_query=Execute query using current mask.
 msg_help=Display info about GNUe Forms. 
+msg_jump=Prompts for a record number to which the system should jump.
 
 #
 GEASDIR=/usr/local/
Index: gnue/gnue-common/setup.py
diff -u gnue/gnue-common/setup.py:1.13 gnue/gnue-common/setup.py:1.14
--- gnue/gnue-common/setup.py:1.13      Sat Jun 30 15:58:26 2001
+++ gnue/gnue-common/setup.py   Mon Jul 16 14:31:22 2001
@@ -86,6 +86,7 @@
        data_files = dfiles,
        packages = ["gnue", 
                    "gnue.common",
+                   "gnue.common.FormatMasks",
                    "gnue.common.dbdrivers",
                    "gnue.common.dbdrivers.geas",
                    "gnue.common.dbdrivers.mysql",
Index: gnue/gnue-common/src/FormatMasks/BaseMask.py
diff -u gnue/gnue-common/src/FormatMasks/BaseMask.py:1.1 
gnue/gnue-common/src/FormatMasks/BaseMask.py:1.2
--- gnue/gnue-common/src/FormatMasks/BaseMask.py:1.1    Sun Jul 15 21:17:24 2001
+++ gnue/gnue-common/src/FormatMasks/BaseMask.py        Mon Jul 16 13:03:07 2001
@@ -38,12 +38,14 @@
   def getFormattedValue(self, value): 
     return self.literal
 
+  def isValidEntry(self, value): 
+    return value == self.literal
 
 class BaseMask: 
   value = ""
   maskMappings = {}
-  inputMaskHandlers = []
-  outputMaskHandlers = []
+  inputHandlers = []
+  outputHandlers = []
   predefinedLiterals = ""
   basetype = "base"
   defaultmask = ""
@@ -54,6 +56,7 @@
     if inputMask != None: 
       self.inputHandlers = self.parseMask(inputMask)
 
+
   # Take a mask string and break it into its elements and map it to handlers
   def parseMask(self, mask): 
     maskHandler = []
@@ -78,7 +81,7 @@
         isLiteral = 1
       elif isLiteral or ch in self.predefinedLiterals: 
         isLiteral = 0
-        maskHandler.append(Literal(ch))
+        maskHandler.append(self.literalClass(ch))
       elif self.maskMappings.has_key(ch): 
         maskHandler.append(self.maskMappings[ch]())
       else:
@@ -110,5 +113,7 @@
   def getFormattedValue(self): 
     return self.value
 
+  def isValidEntry(self, value): 
+    return 0
 
 
Index: gnue/gnue-common/src/FormatMasks/DateMask.py
diff -u gnue/gnue-common/src/FormatMasks/DateMask.py:1.3 
gnue/gnue-common/src/FormatMasks/DateMask.py:1.4
--- gnue/gnue-common/src/FormatMasks/DateMask.py:1.3    Mon Jul 16 13:24:54 2001
+++ gnue/gnue-common/src/FormatMasks/DateMask.py        Mon Jul 16 20:00:08 2001
@@ -53,7 +53,7 @@
 
 from BaseMask import BaseMask, MaskSection, Literal
 from gnue.common import GDebug
-from gnue.common.GDateTime import GDateTime
+from gnue.common.GDateTime import GDateTime, InvalidDate
 from FormatExceptions import *
 
 # TODO: This is obviously not Internationalized!
@@ -72,11 +72,6 @@
 predefinedDateLiterals = "-./: ,"
 
 
-def isLeapYear(year): 
-  return divmod(year,400)[1] == 0 or \
-      (divmod(year,4)[1] == 0 and divmod(year,100)[1] != 0)
-
-
 class DateLiteral (Literal): 
   def addSelfToDate(self, value, date):
     pass
@@ -169,18 +164,21 @@
   def getFormattedOutput(self): 
     rv = ""
     value = self._buildDate(self.entry, 1)
-
-    for m in self.outputHandlers: 
-      rv = rv + m.getFormattedValue(value)
 
-    return rv
+    try: 
+      for m in self.outputHandlers: 
+        rv = rv + m.getFormattedValue(value)
+
+      return rv
+    except InvalidDate, msg:
+      raise InvalidEntry, msg
 
 
   def getFormattedInput(self, padding=""): 
     rv = ""
     value = self._buildDate(self.entry, 0)
 
-#    self.lastInputPos
+    self.lastInputPos = 
 
     print self.inputMaskLen
 
Index: gnue/gnue-common/src/FormatMasks/FormatExceptions.py
diff -u gnue/gnue-common/src/FormatMasks/FormatExceptions.py:1.1 
gnue/gnue-common/src/FormatMasks/FormatExceptions.py:1.2
--- gnue/gnue-common/src/FormatMasks/FormatExceptions.py:1.1    Sun Jul 15 
21:17:24 2001
+++ gnue/gnue-common/src/FormatMasks/FormatExceptions.py        Mon Jul 16 
13:03:07 2001
@@ -26,10 +26,26 @@
 # NOTES:
 #
 
-class PredefinedMaskNotFound (StandardError): 
+# Base Exception for markup problems with mask
+class MaskMarkupError (StandardError): 
   pass
 
-class InvalidCharInMask (StandardError): 
+# Developer specified a predefined mask (using "&name" notation)
+# that does not exist
+class PredefinedMaskNotFound (MaskMarkupError): 
+  pass
+
+# The supplied mask includes a token that is not recognized
+class InvalidCharInMask (MaskMarkupError): 
+  pass
+
+
+# Base exception for user/data input problems
+class MaskInputError (StandardError): 
+  pass
+
+# The supplied input from user is invalid
+class InvalidEntry(MaskInputError): 
   pass
 
 
Index: gnue/gnue-common/src/GDateTime.py
diff -u gnue/gnue-common/src/GDateTime.py:1.2 
gnue/gnue-common/src/GDateTime.py:1.3
--- gnue/gnue-common/src/GDateTime.py:1.2       Mon Jul 16 13:24:54 2001
+++ gnue/gnue-common/src/GDateTime.py   Mon Jul 16 20:00:08 2001
@@ -26,6 +26,14 @@
 # NOTES:
 #
 
+
+def isLeapYear(year): 
+  return divmod(year,400)[1] == 0 or \
+      (divmod(year,4)[1] == 0 and divmod(year,100)[1] != 0)
+
+class InvalidDate(StandardError): 
+  pass
+
 class GDateTime: 
   def __init__(self): 
     self.month = 1
@@ -42,4 +50,19 @@
     y = self.year - a
     m = self.month + 12*a - 2
     return divmod(self.day + y + int(y/4) - int(y/100) + int(y/400) + 
(31*m)/12,7)[1]
+
+
+  def validate(self): 
+    if not (\
+        self.month >= 1 and self.month <= 12 and \
+        self.year >= 0 and \
+        self.day >= 1 and self.day <= ( \
+             (self.month in (1,3,5,7,8,10,12) and 31) or \
+             (self.month == 2 and (28 + isLeapYear(self.year))) \
+             or 30) and \
+        self.hour >= 0 and self.hour <= 23 and \
+        self.minute >= 0 and self.minute <= 59 and \
+        self.second >= 0 and self.second <= 59 ):
+      raise InvalidDate, "Not a valid date"
+
 
Index: gnue/gnue-common/src/dbdrivers/db2/DBdriver.py
diff -u gnue/gnue-common/src/dbdrivers/db2/DBdriver.py:1.2 
gnue/gnue-common/src/dbdrivers/db2/DBdriver.py:1.3
--- gnue/gnue-common/src/dbdrivers/db2/DBdriver.py:1.2  Mon Jun 25 21:32:46 2001
+++ gnue/gnue-common/src/dbdrivers/db2/DBdriver.py      Thu Jul 12 20:56:31 2001
@@ -1,366 +1,394 @@
-#
-# This file is part of GNU Enterprise. 
-#
-# GNU Enterprise is free software; you can redistribute it 
-# and/or modify it under the terms of the GNU General Public 
-# License as published by the Free Software Foundation; either 
-# version 2, or (at your option) any later version.
-#
-# GNU Enterprise is distributed in the hope that it will be 
-# useful, but WITHOUT ANY WARRANTY; without even the implied 
-# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
-# PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 
-# License along with program; see the file COPYING. If not, 
-# write to the Free Software Foundation, Inc., 59 Temple Place 
-# - Suite 330, Boston, MA 02111-1307, USA.
-#
-# Copyright 2000 Free Software Foundation
-#
-# FILE:
-# DSgedi.py
-#
-# DESCRIPTION:
-# Driver to provide access to data stored in a DB2 database
-#
-# NOTES:
-#
-
-import DB2
-import string
-import sys
-
-from string import lower       
-# from gnue.forms import GFOptions
-from gnue.forms.GFError import DBError
-from gnue.common import GDebug, GDataObjects
-from gnue.common.dbdrivers._dbsig.DBdriver \
-   import DBSIG_RecordSet, DBSIG_ResultSet, DBSIG_DataObject, \
-          DBSIG_DataObject_SQL, DBSIG_DataObject_Object
-
-
-class PG_RecordSet(DBSIG_RecordSet): 
-  def _postChanges(self): 
-    values = []
-    fields = []
-    fieldString = ""
-    for field in (self._modifiedFields.keys()): 
-      fields.append(field + " = %s")
-      values.append(self._fields[field])
-    
-    statement = 'UPDATE %s SET %s WHERE %s = %s'
-    
-
-class PG_ResultSet(DBSIG_ResultSet): 
-  def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None): 
-    DBSIG_ResultSet.__init__(self, dataObject, \
-            cursor, defaultValues, masterRecordSet)
-    self._recordSetClass = PG_RecordSet
-
-
-  #### NOTE:  Once PyGreSQL's .fetchone() bug is fixed, this method 
-  ####   should be deleted!  Also note the line in PG_DataObject.__init__.
-  ####   Right now, we are having to preload *ALL* rows from a datasource.
-  def _loadNextRecord(self): 
-    if self._cursor: 
-      try: 
-        rsall = self._cursor.fetchall()
-      except self._DatabaseError, err:
-        raise GDataObjects.ConnectionError, err
-
-      if len(rsall): 
-        for rs in(rsall):
-          GDebug.printMesg(5, "New row retrieved: %s" % rs)
-          if not self._fieldNames: 
-            self._fieldNames = []
-            for t in(self._cursor.description): 
-              self._fieldNames.append(t[0])
-              self._boundFields[lower(t[0])] = ""
-            GDebug.printMesg(5, "Field names set to %s" % self._fieldNames)
-          if rs: 
-            i = 0
-            dict = {}
-            for f in(rs): 
-              dict[self._fieldNames[i]] = f
-              i = i + 1
-            
self._cachedRecords.append(self._recordSetClass(parent=self,initialData=dict))
-          else:
-            return 0
-        return 1
-      else: 
-        return 0
-    else: 
-      return 0
-####
-
-
-class PG_DataObject(DBSIG_DataObject): 
-  def __init__(self): 
-    DBSIG_DataObject.__init__(self)
-    self._DatabaseError = "Database Error"
-    #### When the PyGreSQL's .fetchone() bug is fixed, delete following line
-    self._resultSetClass = PG_ResultSet
-
-
-  def connect(self, connectData={}): 
-    GDebug.printMesg(1,"DB2 database driver initializing")
-    try: 
-      self._dataConnection = DB2.connect(uid=connectData['_username'], 
-                   pwd=connectData['_password'], 
-                   dsn=connectData['dbname'])
-    except self._DatabaseError, value:
-      raise GDataObjects.ConnectionError, value
-
-
-class PG_DataObject_Object(PG_DataObject, \
-      DBSIG_DataObject_Object): 
-
-  def __init__(self): 
-    # Call DBSIG init first because PG_DataObject needs to overwrite 
-    # some of its values
-    DBSIG_DataObject_Object.__init__(self) 
-    PG_DataObject.__init__(self)
-
-  def _buildQuery(self, conditions={}): 
-    return DBSIG_DataObject_Object._buildQuery(self, conditions)
-
-
-class PG_DataObject_SQL(PG_DataObject, \
-      DBSIG_DataObject_SQL): 
-  def __init__(self): 
-    # Call DBSIG init first because PG_DataObject needs to overwrite 
-    # some of its values
-    DBSIG_DataObject_SQL.__init__(self) 
-    PG_DataObject.__init__(self)
-
-  def _buildQuery(self, conditions={}): 
-    return DBSIG_DataObject_SQL._buildQuery(self, conditions)
-
-
-
-supportedDataObjects = { 
-  'object': PG_DataObject_Object,
-  'sql':    PG_DataObject_SQL
-}
-
-
-
-##########################################################################
-##########################################################################
-##
-## The following is the old-style (pre-GDataObject/GDataSource) driver 
-## code. It will soon be deleted after GForms is converted to new style.
-##
-##########################################################################
-##########################################################################
-
-
-class DBdriver:
-  def __init__(self):
-    GDebug.printMesg(1,"DB2 database driver initializing")
-    self.connection = None
-    self.cursor = None
-    self.uniqueKey = None
-    self.oldMaskData = {}
-    self.maskCount = 1
-
-  def connect(self, dbhost, dbname, dbuser, dbpasswd):
-    GDebug.printMesg(1,"connecting")
-    try:
-      self.connection = DB2.connect(dsn=dbname, uid=dbuser, pwd=dbpasswd)
-#      self.connection.cursorclass = DB2.DictCursor
-      self.cursor = self.connection.cursor()
-    except:
-      raise DBError, "Connection Error: %s" % (sys.exc_info()[1])
-    
-  def disconnect(self):
-    try:
-      self.connection.close()
-    except:
-      raise DBError, "Disconnect Error: %s" % (sys.exc_info()[1])
-
-
-  def beginTransaction(self):
-    try:
-      pass
-    except:
-      raise DBError, "Begin Transaction Error: %s" % (sys.exc_info()[1])
-
-  def commit(self):
-    try:
-      self.connection.commit()
-    except:
-      raise DBError, "Commit Error: %s" % (sys.exc_info()[1])
-
-  def rollback(self):
-    try:
-      self.connection.rollback()
-    except:
-      raise DBError, "Rollback Error: %s " % (sys.exc_info()[1])
-
-
-  def insert(self, table, mask):
-    for fieldname in mask.keys():
-      if mask[fieldname] == None or len(mask[fieldname]) == 0:
-        del mask[fieldname]
-
-    command = self.constructSQL('insert', table, mask)
-    try:
-      self.cursor.execute(command)
-    except:
-      raise DBError, "Insert Error: %s" % (sys.exc_info()[1])
-
-    mask[self.uniqueKey] = self.getMaskCount()
-    return mask
-  
-  def delete(self, table, mask):
-    command = self.constructSQL('delete', table, mask)
-    try:
-      self.cursor.execute(command)
-    except:
-      raise DBError, "Deletion Error: %s" % (sys.exc_info()[1])
-
-
-  def update(self, table, mask):
-    command = self.constructSQL('update', table, mask)
-    try:
-      self.cursor.execute(command)
-    except:
-      raise DBError, "Update Error: %s " % (sys.exc_info()[1])
-
-
-  def getFieldList(self, table):
-    l = {}
-    try:
-      cr = self.connection.cursor()
-      cr.execute("select * from %s where 1=2" % table)
-      rs = cr.description
-    except:
-      raise DBError, "Field retrieval error"
-    self.getUniqueKey(table)
-    for r in rs:
-      l[lower(r[0])] = "text"
-    return l
-
-    # Primary key fetching code, will possibly be used in later implementation
-    #  if r["Key"] == "PRI":
-    #    print "PK = %s" % (r["Field"])
-    #    self.primaryKey[r["Field"]] = ''
-    #for d in cr.description:
-    #  l[d[0]] = 'text'
-
-
-  def query(self, table, mask, order_by = None):
-    command = self.constructSQL('query',table, mask)
-    try:
-      self.cursor.execute(command)
-      rs = self.cursor.fetchallDict()
-    except:
-      raise DBError, "Query Error: %s" % (sys.exc_info()[1])
-                                          
-    self.oldMaskData = {}
-    self.maskCount = 1
-    for r in rs:
-      r[self.uniqueKey] = self.getMaskCount()
-      self.oldMaskData[int(r[self.uniqueKey])] = self.copyDict(r)
-    return rs
-
-  def constructSQL(self, style, table, mask = None):
-    sql = None
-    fields = None
-    qualifier = None
-
-    if style == 'query':
-      action = "SELECT "
-      location = "FROM %s " % (table)
-      fields = " * "
-      
-      if type(mask) == type({}):
-        fields = "%s" % (string.join(mask.keys(), ','))
-        fields = string.replace(fields, "%s," % (self.uniqueKey), '')
-        fields = "%s " % (fields)
-        for fieldname in mask.keys():
-          if fieldname != self.uniqueKey:
-            if mask[fieldname] != None and len(mask[fieldname]):
-              if qualifier == None:
-                qualifier = "WHERE %s LIKE '%s'" % (fieldname,mask[fieldname])
-              else:
-                qualifier = "%s AND %s LIKE  '%s'" % (qualifier, 
fieldname,mask[fieldname])
-
-      sql = action + fields + location + (qualifier and qualifier or "")
-
-    elif style == 'insert':
-      action = "INSERT "
-      location = "INTO %s " % (table)
-      values = None
-
-      if type(mask) == type({}):
-        fields = "(%s) " % (string.join(mask.keys(), ','))
-        for fieldname in mask.keys():  
-          if fieldname != self.uniqueKey:
-            if mask[fieldname] != None and len(mask[fieldname]):
-              if values == None:
-                values = "VALUES ('%s'" % (mask[fieldname])
-              else:
-                values = "%s, '%s'" % (values, mask[fieldname])
-        values = "%s)" % (values)
-        
-      sql = action + location + fields + values + (qualifier and qualifier or 
"")
-
-    elif style == 'update':
-      action = "UPDATE "
-      location = "%s " % (table)
-      values = " SET "
-      qualifier = " WHERE "
-
-      if type(mask) == type({}):
-        for fieldname in mask.keys():
-          if fieldname != self.uniqueKey:
-            if mask[fieldname] != None and len(mask[fieldname]):
-              values = "%s %s='%s'," % (values, fieldname, mask[fieldname])
-              qualifier = "%s %s='%s' AND" % (qualifier, fieldname, 
self.oldMaskData[int(mask[self.uniqueKey])][fieldname])
-        values = values[:-1]
-        qualifier = qualifier[:-3]
-        
-      sql = action + location + values + (qualifier and qualifier or "")
-
-    elif style == 'delete':
-      action = "DELETE FROM "
-      location = "%s " % (table)
-      values = ""
-      qualifier = " WHERE "
-
-      if type(mask) == type({}):
-        for fieldname in mask.keys():
-          if fieldname != self.uniqueKey:
-            if mask[fieldname] != None and len(mask[fieldname]):
-              qualifier = "%s %s='%s' AND" % (qualifier, fieldname, 
self.oldMaskData[int(mask[self.uniqueKey])][fieldname])
-        qualifier = qualifier[:-3]
-        
-      sql = action + location + values + (qualifier and qualifier or "")
-
-    else:
-      print "constructSQL: unsupport SQL statement type"
-
-    return sql
-
-  def getUniqueKey(self, table):
-    self.uniqueKey = "uniqueKey_%s" % (table)
-    return self.uniqueKey
-
-  def getMaskCount(self):
-    self.maskCount = self.maskCount + 1
-    return self.maskCount - 1
-
-  def copyDict(self, dict):
-    nd = {}
-    for key in dict.keys():
-      nd[key] = dict[key]
-
-    return nd
-
-  supportedDataObjects = { 
-  'object': PG_DataObject_Object,
-  'sql':    PG_DataObject_SQL
-  }
+#
+# This file is part of GNU Enterprise. 
+#
+# GNU Enterprise is free software; you can redistribute it 
+# and/or modify it under the terms of the GNU General Public 
+# License as published by the Free Software Foundation; either 
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be 
+# useful, but WITHOUT ANY WARRANTY; without even the implied 
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 
+# License along with program; see the file COPYING. If not, 
+# write to the Free Software Foundation, Inc., 59 Temple Place 
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright 2000 Free Software Foundation
+#
+# FILE:
+# DSgedi.py
+#
+# DESCRIPTION:
+# Driver to provide access to data stored in a DB2 database
+#
+# NOTES:
+#
+
+import DB2
+import string
+import sys
+
+from string import lower       
+# from gnue.forms import GFOptions
+from gnue.forms.GFError import DBError
+from gnue.common import GDebug, GDataObjects
+from gnue.common.dbdrivers._dbsig.DBdriver \
+   import DBSIG_RecordSet, DBSIG_ResultSet, DBSIG_DataObject, \
+          DBSIG_DataObject_SQL, DBSIG_DataObject_Object
+
+
+class PG_RecordSet(DBSIG_RecordSet): 
+  def _postChanges(self): 
+    values = []
+    fields = []
+    fieldString = ""
+    for field in (self._modifiedFields.keys()): 
+      fields.append(field + " = %s")
+      values.append(self._fields[field])
+    
+    statement = 'UPDATE %s SET %s WHERE %s = %s'
+    
+
+class PG_ResultSet(DBSIG_ResultSet): 
+  def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None): 
+    DBSIG_ResultSet.__init__(self, dataObject, \
+            cursor, defaultValues, masterRecordSet)
+    self._recordSetClass = PG_RecordSet
+
+
+  #### NOTE:  Once PyGreSQL's .fetchone() bug is fixed, this method 
+  ####   should be deleted!  Also note the line in PG_DataObject.__init__.
+  ####   Right now, we are having to preload *ALL* rows from a datasource.
+  def _loadNextRecord(self): 
+    if self._cursor: 
+      try: 
+        rsall = self._cursor.fetchall()
+      except self._DatabaseError, err:
+        raise GDataObjects.ConnectionError, err
+
+      if len(rsall): 
+        for rs in(rsall):
+          GDebug.printMesg(5, "New row retrieved: %s" % rs)
+          if not self._fieldNames: 
+            self._fieldNames = []
+            for t in(self._cursor.description): 
+              self._fieldNames.append(t[0])
+              self._boundFields[lower(t[0])] = ""
+            GDebug.printMesg(5, "Field names set to %s" % self._fieldNames)
+          if rs: 
+            i = 0
+            dict = {}
+            for f in(rs): 
+              dict[self._fieldNames[i]] = f
+              i = i + 1
+            
self._cachedRecords.append(self._recordSetClass(parent=self,initialData=dict))
+          else:
+            return 0
+        return 1
+      else: 
+        return 0
+    else: 
+      return 0
+####
+
+
+class PG_DataObject(DBSIG_DataObject): 
+  def __init__(self): 
+    DBSIG_DataObject.__init__(self)
+    self._DatabaseError = "Database Error"
+    #### When the PyGreSQL's .fetchone() bug is fixed, delete following line
+    self._resultSetClass = PG_ResultSet
+
+
+  def connect(self, connectData={}): 
+    GDebug.printMesg(1,"DB2 database driver initializing")
+    try: 
+      self._dataConnection = DB2.connect(uid=connectData['_username'], 
+                   pwd=connectData['_password'], 
+                   dsn=connectData['dbname'])
+      self.triggerExtensions = TriggerExtensions(self._dataConnection)
+    except self._DatabaseError, value:
+      raise GDataObjects.ConnectionError, value
+
+
+class PG_DataObject_Object(PG_DataObject, \
+      DBSIG_DataObject_Object): 
+
+  def __init__(self): 
+    # Call DBSIG init first because PG_DataObject needs to overwrite 
+    # some of its values
+    DBSIG_DataObject_Object.__init__(self) 
+    PG_DataObject.__init__(self)
+
+  def _buildQuery(self, conditions={}): 
+    return DBSIG_DataObject_Object._buildQuery(self, conditions)
+
+
+class PG_DataObject_SQL(PG_DataObject, \
+      DBSIG_DataObject_SQL): 
+  def __init__(self): 
+    # Call DBSIG init first because PG_DataObject needs to overwrite 
+    # some of its values
+    DBSIG_DataObject_SQL.__init__(self) 
+    PG_DataObject.__init__(self)
+
+  def _buildQuery(self, conditions={}): 
+    return DBSIG_DataObject_SQL._buildQuery(self, conditions)
+
+
+
+supportedDataObjects = { 
+  'object': PG_DataObject_Object,
+  'sql':    PG_DataObject_SQL
+}
+
+
+
+##########################################################################
+##########################################################################
+##
+## The following is the old-style (pre-GDataObject/GDataSource) driver 
+## code. It will soon be deleted after GForms is converted to new style.
+##
+##########################################################################
+##########################################################################
+
+
+class DBdriver:
+  def __init__(self):
+    GDebug.printMesg(1,"DB2 database driver initializing")
+    self.connection = None
+    self.cursor = None
+    self.uniqueKey = None
+    self.oldMaskData = {}
+    self.maskCount = 1
+
+  def connect(self, dbhost, dbname, dbuser, dbpasswd):
+    GDebug.printMesg(1,"connecting")
+    try:
+      self.connection = DB2.connect(dsn=dbname, uid=dbuser, pwd=dbpasswd)
+#      self.connection.cursorclass = DB2.DictCursor
+      self.cursor = self.connection.cursor()
+      self.triggerExtensions = TriggerExtensions(self.connection)
+    except:
+      raise DBError, "Connection Error: %s" % (sys.exc_info()[1])
+    
+  def disconnect(self):
+    try:
+      self.connection.close()
+    except:
+      raise DBError, "Disconnect Error: %s" % (sys.exc_info()[1])
+
+
+  def beginTransaction(self):
+    try:
+      pass
+    except:
+      raise DBError, "Begin Transaction Error: %s" % (sys.exc_info()[1])
+
+  def commit(self):
+    try:
+      self.connection.commit()
+    except:
+      raise DBError, "Commit Error: %s" % (sys.exc_info()[1])
+
+  def rollback(self):
+    try:
+      self.connection.rollback()
+    except:
+      raise DBError, "Rollback Error: %s " % (sys.exc_info()[1])
+
+
+  def insert(self, table, mask):
+    for fieldname in mask.keys():
+      if mask[fieldname] == None or len(mask[fieldname]) == 0:
+        del mask[fieldname]
+
+    command = self.constructSQL('insert', table, mask)
+    try:
+      self.cursor.execute(command)
+    except:
+      raise DBError, "Insert Error: %s" % (sys.exc_info()[1])
+
+    mask[self.uniqueKey] = self.getMaskCount()
+    return mask
+  
+  def delete(self, table, mask):
+    command = self.constructSQL('delete', table, mask)
+    try:
+      self.cursor.execute(command)
+    except:
+      raise DBError, "Deletion Error: %s" % (sys.exc_info()[1])
+
+
+  def update(self, table, mask):
+    command = self.constructSQL('update', table, mask)
+    try:
+      self.cursor.execute(command)
+    except:
+      raise DBError, "Update Error: %s " % (sys.exc_info()[1])
+
+
+  def getFieldList(self, table):
+    l = {}
+    try:
+      cr = self.connection.cursor()
+      cr.execute("select * from %s where 1=2" % table)
+      rs = cr.description
+    except:
+      raise DBError, "Field retrieval error"
+    self.getUniqueKey(table)
+    for r in rs:
+      l[lower(r[0])] = "text"
+    return l
+
+    # Primary key fetching code, will possibly be used in later implementation
+    #  if r["Key"] == "PRI":
+    #    print "PK = %s" % (r["Field"])
+    #    self.primaryKey[r["Field"]] = ''
+    #for d in cr.description:
+    #  l[d[0]] = 'text'
+
+
+  def query(self, table, mask, order_by = None):
+    command = self.constructSQL('query',table, mask)
+    try:
+      self.cursor.execute(command)
+      rs = self.cursor.fetchallDict()
+    except:
+      raise DBError, "Query Error: %s" % (sys.exc_info()[1])
+                                          
+    self.oldMaskData = {}
+    self.maskCount = 1
+    for r in rs:
+      r[self.uniqueKey] = self.getMaskCount()
+      self.oldMaskData[int(r[self.uniqueKey])] = self.copyDict(r)
+    return rs
+
+  def constructSQL(self, style, table, mask = None):
+    sql = None
+    fields = None
+    qualifier = None
+
+    if style == 'query':
+      action = "SELECT "
+      location = "FROM %s " % (table)
+      fields = " * "
+      
+      if type(mask) == type({}):
+        fields = "%s" % (string.join(mask.keys(), ','))
+        fields = string.replace(fields, "%s," % (self.uniqueKey), '')
+        fields = "%s " % (fields)
+        for fieldname in mask.keys():
+          if fieldname != self.uniqueKey:
+            if mask[fieldname] != None and len(mask[fieldname]):
+              if qualifier == None:
+                qualifier = "WHERE %s LIKE '%s'" % (fieldname,mask[fieldname])
+              else:
+                qualifier = "%s AND %s LIKE  '%s'" % (qualifier, 
fieldname,mask[fieldname])
+
+      sql = action + fields + location + (qualifier and qualifier or "")
+
+    elif style == 'insert':
+      action = "INSERT "
+      location = "INTO %s " % (table)
+      values = None
+
+      if type(mask) == type({}):
+        fields = "(%s) " % (string.join(mask.keys(), ','))
+        for fieldname in mask.keys():  
+          if fieldname != self.uniqueKey:
+            if mask[fieldname] != None and len(mask[fieldname]):
+              if values == None:
+                values = "VALUES ('%s'" % (mask[fieldname])
+              else:
+                values = "%s, '%s'" % (values, mask[fieldname])
+        values = "%s)" % (values)
+        
+      sql = action + location + fields + values + (qualifier and qualifier or 
"")
+
+    elif style == 'update':
+      action = "UPDATE "
+      location = "%s " % (table)
+      values = " SET "
+      qualifier = " WHERE "
+
+      if type(mask) == type({}):
+        for fieldname in mask.keys():
+          if fieldname != self.uniqueKey:
+            if mask[fieldname] != None and len(mask[fieldname]):
+              values = "%s %s='%s'," % (values, fieldname, mask[fieldname])
+              qualifier = "%s %s='%s' AND" % (qualifier, fieldname, 
self.oldMaskData[int(mask[self.uniqueKey])][fieldname])
+        values = values[:-1]
+        qualifier = qualifier[:-3]
+        
+      sql = action + location + values + (qualifier and qualifier or "")
+
+    elif style == 'delete':
+      action = "DELETE FROM "
+      location = "%s " % (table)
+      values = ""
+      qualifier = " WHERE "
+
+      if type(mask) == type({}):
+        for fieldname in mask.keys():
+          if fieldname != self.uniqueKey:
+            if mask[fieldname] != None and len(mask[fieldname]):
+              qualifier = "%s %s='%s' AND" % (qualifier, fieldname, 
self.oldMaskData[int(mask[self.uniqueKey])][fieldname])
+        qualifier = qualifier[:-3]
+        
+      sql = action + location + values + (qualifier and qualifier or "")
+
+    else:
+      print "constructSQL: unsupport SQL statement type"
+
+    return sql
+
+  def getUniqueKey(self, table):
+    self.uniqueKey = "uniqueKey_%s" % (table)
+    return self.uniqueKey
+
+  def getMaskCount(self):
+    self.maskCount = self.maskCount + 1
+    return self.maskCount - 1
+
+  def copyDict(self, dict):
+    nd = {}
+    for key in dict.keys():
+      nd[key] = dict[key]
+
+    return nd
+
+  supportedDataObjects = { 
+  'object': PG_DataObject_Object,
+  'sql':    PG_DataObject_SQL
+  }
+
+
+
+#
+#  Extensions to Trigger Namespaces
+#  
+class TriggerExtensions: 
+
+  def __init__(self, connection): 
+    self.__connection = connection
+
+  # Return the current date, according to database
+#  def getDate(self): 
+#    pass
+
+  # Return a sequence number from sequence 'name' 
+#  def getSequence(self, name): 
+#    pass
+
+  # Run the SQL statement 'statement'
+#  def sql(self, statement): 
+#    pass
+
+
+
+
Index: gnue/gnue-common/src/dbdrivers/geas/DBdriver.py
diff -u gnue/gnue-common/src/dbdrivers/geas/DBdriver.py:1.5 
gnue/gnue-common/src/dbdrivers/geas/DBdriver.py:1.6
--- gnue/gnue-common/src/dbdrivers/geas/DBdriver.py:1.5 Wed Jun 27 18:58:51 2001
+++ gnue/gnue-common/src/dbdrivers/geas/DBdriver.py     Thu Jul 12 20:56:31 2001
@@ -21,7 +21,7 @@
 #
 # GEAS database driver
 #
-# $Id: DBdriver.py,v 1.5 2001/06/28 01:58:51 jamest Exp $
+# $Id: DBdriver.py,v 1.6 2001/07/13 03:56:31 jcater Exp $
 #
 
 import sys
@@ -82,6 +82,7 @@
 
             ## Now make connection
             #self.database.connect()
+          self.triggerExtensions = TriggerExtensions(self.database)
         except (GEAS.ServerError,
                GEAS.AuthenticationError),ex:
             print "Failed to connect to database. Exiting."
@@ -253,3 +254,29 @@
             i = ord(c)
             r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
         return r
+
+
+
+#
+#  Extensions to Trigger Namespaces
+#  
+class TriggerExtensions: 
+
+  def __init__(self, connection): 
+    self.__connection = connection
+
+  # Return the current date, according to database
+#  def getDate(self): 
+#    pass
+
+  # Return a sequence number from sequence 'name' 
+#  def getSequence(self, name): 
+#    pass
+
+  # Run the SQL statement 'statement'
+#  def sql(self, statement): 
+#    pass
+
+
+
+
Index: gnue/gnue-common/src/dbdrivers/mysql/DBdriver.py
diff -u gnue/gnue-common/src/dbdrivers/mysql/DBdriver.py:1.2 
gnue/gnue-common/src/dbdrivers/mysql/DBdriver.py:1.3
--- gnue/gnue-common/src/dbdrivers/mysql/DBdriver.py:1.2        Mon Jun 25 
21:32:46 2001
+++ gnue/gnue-common/src/dbdrivers/mysql/DBdriver.py    Thu Jul 12 20:56:31 2001
@@ -50,6 +50,7 @@
       self.connection = MySQLdb.connect(db=dbname, host=dbhost, user=dbuser, 
passwd=dbpasswd)
       self.connection.cursorclass = MySQLdb.DictCursor
       self.cursor = self.connection.cursor()
+      self.triggerExtensions = TriggerExtensions(self.connection)
     except:
       raise DBError, "Connection Error: %s" % (sys.exc_info()[1])
     
@@ -238,3 +239,29 @@
       nd[key] = dict[key]
 
     return nd
+
+
+
+#
+#  Extensions to Trigger Namespaces
+#  
+class TriggerExtensions: 
+
+  def __init__(self, connection): 
+    self.__connection = connection
+
+  # Return the current date, according to database
+#  def getDate(self): 
+#    pass
+
+  # Return a sequence number from sequence 'name' 
+#  def getSequence(self, name): 
+#    pass
+
+  # Run the SQL statement 'statement'
+#  def sql(self, statement): 
+#    pass
+
+
+
+
Index: gnue/gnue-common/src/dbdrivers/odbc/DBdriver.py
diff -u gnue/gnue-common/src/dbdrivers/odbc/DBdriver.py:1.2 
gnue/gnue-common/src/dbdrivers/odbc/DBdriver.py:1.3
--- gnue/gnue-common/src/dbdrivers/odbc/DBdriver.py:1.2 Mon Jun 25 21:32:46 2001
+++ gnue/gnue-common/src/dbdrivers/odbc/DBdriver.py     Thu Jul 12 20:56:31 2001
@@ -46,6 +46,7 @@
     try:
       self.connection = self.driver.DriverConnect(self.dsn)
       self.cursor = self.connection.cursor()
+      self.triggerExtensions = TriggerExtensions(self.connection)
     except:
       raise DBError, "Database Error: %s" % (sys.exc_info()[1])
 
@@ -245,3 +246,28 @@
     self.driver = __import__("ODBC/%s" % (driver[1]))
     if len(driver) > 2:
       self.dsn = driver[2]
+
+
+#
+#  Extensions to Trigger Namespaces
+#  
+class TriggerExtensions: 
+
+  def __init__(self, connection): 
+    self.__connection = connection
+
+  # Return the current date, according to database
+#  def getDate(self): 
+#    pass
+
+  # Return a sequence number from sequence 'name' 
+#  def getSequence(self, name): 
+#    pass
+
+  # Run the SQL statement 'statement'
+#  def sql(self, statement): 
+#    pass
+
+
+
+
Index: gnue/gnue-common/src/dbdrivers/oracle/DBdriver.py
diff -u gnue/gnue-common/src/dbdrivers/oracle/DBdriver.py:1.4 
gnue/gnue-common/src/dbdrivers/oracle/DBdriver.py:1.5
--- gnue/gnue-common/src/dbdrivers/oracle/DBdriver.py:1.4       Tue Jul 10 
14:30:10 2001
+++ gnue/gnue-common/src/dbdrivers/oracle/DBdriver.py   Thu Jul 12 20:56:31 2001
@@ -47,7 +47,8 @@
     GFDebug.printMesg(10,"Oracle DBdriver: Connect String: " 
         + dbuser + "/" + dbpasswd + "@" + dbname) 
     self.connectWithString (dbuser + "/" + dbpasswd + "@" + dbname)
-  
+    self.triggerExtensions = TriggerExtensions(self.connection)
+
   def connectWithString(self, dbConnectString):
     try:
       self.connection = DCOracle.Connect(dbConnectString)
@@ -263,3 +264,36 @@
   def getMaskCount(self):
     self.maskCount = self.maskCount + 1
     return self.maskCount - 1
+
+  
+
+#
+#  Extensions to Trigger Namespaces
+#  
+class TriggerExtensions: 
+
+  def __init__(self, connection): 
+    self.__connection = connection
+
+  # Return the current date, according to database
+  def getDate(self): 
+    cursor = self.__connection.cursor()
+    command = "select sysdate from dual"
+    cursor.execute(command)
+    return cursor.fetchone()[0]
+
+  # Return a sequence number from sequence 'name' 
+  def getSequence(self, name): 
+    cursor = self.__connection.cursor()
+    command = "select %s.nextval from dual" % name
+    cursor.execute(command)
+    return cursor.fetchone()[0]
+
+  # Run the SQL statement 'statement'
+  def sql(self, statement): 
+    self.__connection.cursor().execute(statement)
+
+
+
+
+
Index: gnue/gnue-common/src/dbdrivers/postgresql/DBdriver.py
diff -u gnue/gnue-common/src/dbdrivers/postgresql/DBdriver.py:1.8 
gnue/gnue-common/src/dbdrivers/postgresql/DBdriver.py:1.9
--- gnue/gnue-common/src/dbdrivers/postgresql/DBdriver.py:1.8   Wed Jul  4 
17:24:11 2001
+++ gnue/gnue-common/src/dbdrivers/postgresql/DBdriver.py       Thu Jul 12 
20:56:31 2001
@@ -109,6 +109,7 @@
                    password=connectData['_password'], 
                    host=connectData['host'], 
                    database=connectData['dbname'])
+      self.triggerExtensions = TriggerExtensions(self._dataConnection)
     except self._DatabaseError, value:
       raise GDataObjects.ConnectionError, value
 
@@ -138,16 +139,44 @@
     return DBSIG_DataObject_SQL._buildQuery(self, conditions)
 
 
+#
+#  Extensions to Trigger Namespaces
+#  
+class TriggerExtensions: 
+
+  def __init__(self, connection): 
+    self.__connection = connection
+
+  # Return the current date, according to database
+#  def getDate(self): 
+#    pass
+
+  # Return a sequence number from sequence 'name' 
+#  def getSequence(self, name): 
+#    pass
+
+  # Run the SQL statement 'statement'
+#  def sql(self, statement): 
+#    pass
 
+
+
+######################################
+#
+#  The following hashes describe 
+#  this driver's characteristings.
+#
+######################################
+
+#
+#  All datasouce "types" and corresponding DataObject class
+# 
 supportedDataObjects = { 
   'object': PG_DataObject_Object,
   'sql':    PG_DataObject_SQL
 }
 
 
-
-
-
 ##########################################################################
 ##########################################################################
 ##
@@ -175,7 +204,8 @@
       self.connection = pg.DB(dbname, host, -1, None, None, user, passwd)
       if GConfig.get('Encoding') != 'DEFAULT':
         self.connection.query("set encoding to '%s'" % GConfig.get('Encoding'))
-       
+
+      self.triggerExtensions = TriggerExtensions(self.connection)
     except pg.error, value:
       raise GDataObjects.ConnectionError, value
 
Index: gnue/gnuef/TODO
diff -u gnue/gnuef/TODO:1.56 gnue/gnuef/TODO:1.57
--- gnue/gnuef/TODO:1.56        Thu Jul 12 08:52:48 2001
+++ gnue/gnuef/TODO     Mon Jul 16 20:09:41 2001
@@ -84,7 +84,6 @@
 
 
 Features
-  Goto record shortcut
   Input masks 
   Mirrored Fields 
 
Index: gnue/gnuef/doc/techref.lyx
diff -u gnue/gnuef/doc/techref.lyx:1.8 gnue/gnuef/doc/techref.lyx:1.9
--- gnue/gnuef/doc/techref.lyx:1.8      Wed Jul 11 21:58:49 2001
+++ gnue/gnuef/doc/techref.lyx  Mon Jul 16 20:09:41 2001
@@ -2068,7 +2068,7 @@
 
 
 \begin_inset  Tabular
-<lyxtabular version="2" rows="6" columns="4">
+<lyxtabular version="2" rows="8" columns="4">
 <features rotate="false" islongtable="false" endhead="0" endfirsthead="0" 
endfoot="0" endlastfoot="0">
 <column alignment="center" valignment="top" leftline="true" rightline="false" 
width="" special="">
 <column alignment="center" valignment="top" leftline="true" rightline="false" 
width="" special="">
@@ -2289,7 +2289,7 @@
 \end_inset 
 </cell>
 </row>
-<row topline="true" bottomline="true" newpage="false">
+<row topline="true" bottomline="false" newpage="false">
 <cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
 \begin_inset Text
 
@@ -2333,6 +2333,75 @@
 \end_inset 
 </cell>
 </row>
+<row topline="true" bottomline="false" newpage="false">
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+rows
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+int
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="true" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+Overrides the rows setting defined at the block level.
+ The replacement for the old visibleCount attribute.
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="true" newpage="false">
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+rowSpacer
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+int
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="true" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+Overriders the rowSpace setting defined at the block level.
+\end_inset 
+</cell>
+</row>
 </lyxtabular>
 
 \end_inset 
@@ -2354,7 +2423,7 @@
 
 
 \begin_inset  Tabular
-<lyxtabular version="2" rows="19" columns="4">
+<lyxtabular version="2" rows="21" columns="4">
 <features rotate="false" islongtable="false" endhead="0" endfirsthead="0" 
endfoot="0" endlastfoot="0">
 <column alignment="center" valignment="top" leftline="true" rightline="false" 
width="" special="">
 <column alignment="center" valignment="top" leftline="true" rightline="false" 
width="" special="">
@@ -2906,9 +2975,81 @@
 \layout Standard
 
 
+\series bold 
 \lang english
-The number of entry widgets displayed at one time in a verticle column.
+Deprecated
+\series default 
+ - The number of entry widgets displayed at one time in a verticle column.
  Simulates a very crude grid entry system.
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="false" newpage="false">
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+rows
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+int
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="true" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+Overrides the rows setting defined at the block level.
+ The replacement for the old visibleCount attribute.
+\end_inset 
+</cell>
+</row>
+<row topline="true" bottomline="false" newpage="false">
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+rowSpacer
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+int
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="false" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+1
+\end_inset 
+</cell>
+<cell multicolumn="0" alignment="center" valignment="top" topline="true" 
bottomline="false" leftline="true" rightline="true" rotate="false" 
usebox="none" width="" special="">
+\begin_inset Text
+
+\layout Standard
+
+Overriders the rowSpace setting defined at the block level.
 \end_inset 
 </cell>
 </row>
Index: gnue/gnuef/samples/trigger/trigger.gfd
diff -u gnue/gnuef/samples/trigger/trigger.gfd:1.7 
gnue/gnuef/samples/trigger/trigger.gfd:1.8
--- gnue/gnuef/samples/trigger/trigger.gfd:1.7  Tue Mar 20 12:23:12 2001
+++ gnue/gnuef/samples/trigger/trigger.gfd      Thu Jul 12 20:59:01 2001
@@ -29,7 +29,7 @@
            <tip>Type Field One's Replacement</tip>
          </options>
          <trigger type ="Pre-FOCUSOUT">
-block1.fields.one = self.value
+block1.fields.one = self.getValue()
 #
 #User name trigger
 #
Index: gnue/gnuef/src/GFForm.py
diff -u gnue/gnuef/src/GFForm.py:1.112 gnue/gnuef/src/GFForm.py:1.113
--- gnue/gnuef/src/GFForm.py:1.112      Thu Jul 12 20:56:13 2001
+++ gnue/gnuef/src/GFForm.py    Mon Jul 16 20:09:41 2001
@@ -783,6 +783,16 @@
             return message
     self._currentBlock.nextRecord()
 
+  def jumpRecord(self,count):
+    for block in self._blockList:
+      if hasattr(block,'master'):
+        masterBlock,masterField = string.split(block.master,'.')
+        if masterBlock == self._currentBlock.name:
+          if not block.isSaved():
+            message = GConfig.get('_msgNOTSAVED')
+            return message
+    self._currentBlock.jumpRecord(count)
+
 
   def toggleInsertMode(self):
     self._insertMode = not self._insertMode
Index: gnue/gnuef/src/GFInstance.py
diff -u gnue/gnuef/src/GFInstance.py:1.17 gnue/gnuef/src/GFInstance.py:1.18
--- gnue/gnuef/src/GFInstance.py:1.17   Thu Jul 12 20:56:13 2001
+++ gnue/gnuef/src/GFInstance.py        Mon Jul 16 20:09:41 2001
@@ -34,7 +34,7 @@
 #
 # Copyright (c) 2000 Free Software Foundation
 #
-# $Id: GFInstance.py,v 1.17 2001/07/13 03:56:13 jcater Exp $
+# $Id: GFInstance.py,v 1.18 2001/07/17 03:09:41 jamest Exp $
 #
 
 import pstats
@@ -72,7 +72,7 @@
                            'requestPREVBLOCK'    : self.previousBlock,
                            'requestPREVRECORD'   : self.prevRecord,
                            'requestNEXTRECORD'   : self.nextRecord,
-                           'requestJUMPRECORD'   : self.jumpRecords,
+                           'requestRECORDNUMBER' : self.jumpRecords,
                            'requestPAGE'         : self.gotoPage,
                            
                            'requestKEYPRESS'     : self.keyPress,
@@ -225,12 +225,18 @@
   # form move an arbitrary number of records
   #
   def jumpRecords(self,event):
-    count = event.data
-    for jumps in range(abs(count)):
-      if count > 0:
-        self._form.nextRecord()
-      if count < 0:
-        self._form.prevRecord()
+    try:
+      count = abs(int(event.data))-1
+    except ValueError:
+      message = "Invalid numeric value entered."
+    else:
+      message = self._form.jumpRecord(count)
+
+    if message:
+      messageBox = GFMsgBox(self,message)
+      messageBox.show()
+      return                    
+
     
self.dispatchEvent(GFEvent('gotoENTRY',{'object':self._form._currentEntry}))
     self.updateRecordCounter()
     self.updateRecordStatus()
Index: gnue/gnuef/src/GFObjects/GFBlock.py
diff -u gnue/gnuef/src/GFObjects/GFBlock.py:1.4 
gnue/gnuef/src/GFObjects/GFBlock.py:1.5
--- gnue/gnuef/src/GFObjects/GFBlock.py:1.4     Wed Jul 11 16:06:46 2001
+++ gnue/gnuef/src/GFObjects/GFBlock.py Mon Jul 16 20:09:41 2001
@@ -158,6 +158,13 @@
         self._currentRecord = self._recordCount    
     self.switchRecord(-1)
 
+  def jumpRecord(self, recordNumber):
+    if recordNumber > self._recordCount:
+      recordNumber = self._recordCount
+    jump = recordNumber - self._currentRecord
+    self._currentRecord = recordNumber
+    self.switchRecord(jump)
+    
       
   #
   # processCommit
Index: gnue/gnuef/src/GFObjects/GFDataSource.py
diff -u gnue/gnuef/src/GFObjects/GFDataSource.py:1.3 
gnue/gnuef/src/GFObjects/GFDataSource.py:1.4
--- gnue/gnuef/src/GFObjects/GFDataSource.py:1.3        Wed Jul 11 16:06:46 2001
+++ gnue/gnuef/src/GFObjects/GFDataSource.py    Tue Jul 17 06:43:09 2001
@@ -188,31 +188,23 @@
   def commit(self):
     if hasattr(self,'database'):
       for count in range(len(self.resultSet)):
-        GDebug.printMesg(2, "record %s is %s \n %s" % (count, 
self.resultSetStatus[count],self.resultSet[count]))
-        mask = {}
-        for key in self.resultSet[count].keys():
-          if key in self.dataConnection.getFieldList(self.table).keys() or \
-             key == self.uniqueKey:
-            mask[key]=self.resultSet[count][key]
+        if self.resultSetStatus[count] in ('modified', 'deleted'):
+          GDebug.printMesg(2, "record %s is %s \n %s" % (count, 
self.resultSetStatus[count],self.resultSet[count]))
+          mask = {}
+          for key in self.resultSet[count].keys():
+            if key in self.dataConnection.getFieldList(self.table).keys() or \
+               key == self.uniqueKey:
+              mask[key]=self.resultSet[count][key]
 
-        GDebug.printMesg(10, "will be passing\n%s"% mask)
+          GDebug.printMesg(10, "will be passing\n%s"% mask)
                                                   
-        if self.resultSetStatus[count] in ('modified', 'deleted'):
           if self.resultSet[count].has_key(self.uniqueKey):
             if self.resultSetStatus[count]  == 'modified':
-              # record never in database so just mark for cleanup
-              # self.resultSet[count][self.uniqueKey] = -1
-              
-              # elif self.resultSet[count][self.uniqueKey] > 0:
               GDebug.printMesg(1, "updating the record")
               self.dataConnection.update(self.table,mask)
             else:
               GDebug.printMesg(1,"deleting the record")
-              #mask[self.uniqueKey] = \
-              #  mask[self.uniqueKey] * -1
               self.dataConnection.delete(self.table,mask)
-              # flip negative again so upcomming list purge see's the negatives
-              #mask[self.uniqueKey] = -1
               
           else:
             GDebug.printMesg(1, "Inserting the record")
Index: gnue/gnuef/src/GFObjects/GFDatabase.py
diff -u gnue/gnuef/src/GFObjects/GFDatabase.py:1.1 
gnue/gnuef/src/GFObjects/GFDatabase.py:1.2
--- gnue/gnuef/src/GFObjects/GFDatabase.py:1.1  Fri Jun 29 15:55:58 2001
+++ gnue/gnuef/src/GFObjects/GFDatabase.py      Thu Jul 12 20:56:13 2001
@@ -54,14 +54,22 @@
 class GFDatabase(GFObj):
   def __init__(self, parent=None):
     GFObj.__init__(self, parent)
-    self.factory = factory()
     self._type = "GFDatabase"
     self.uniqueKey = None
     self.comment = ""
+    self.triggerNamespace = None
 
   def initialize(self,user,passwd):
+    self.factory = factory()
     self.link = self.factory.create(self.provider)
     self.link.connect(self.host,self.dbname,user,passwd)
+
+    # Add the database connection's trigger extensions to 
+    # the trigger namespace under the name of the connection. 
+    # (e.g., if database name="gnue", then add "gnue" to 
+    # namespace as a reference to the trigger extensions
+    if hasattr(self.link, 'triggerExtensions'):  
+      self.triggerNamespace = self.link.triggerExtensions
 
   def query(self, table, mask, order_by):
     results = self.link.query(table,mask,order_by)
Index: gnue/gnuef/src/GFObjects/GFEntry.py
diff -u gnue/gnuef/src/GFObjects/GFEntry.py:1.4 
gnue/gnuef/src/GFObjects/GFEntry.py:1.5
--- gnue/gnuef/src/GFObjects/GFEntry.py:1.4     Thu Jul 12 11:38:19 2001
+++ gnue/gnuef/src/GFObjects/GFEntry.py Mon Jul 16 20:09:41 2001
@@ -100,11 +100,18 @@
       self.datasource = self._block._form._datasourceDictionary[datasourceName]
 
     #if not hasattr(self,'visibleCount'):
-    if hasattr(self._block,'rows'):
-      self.visibleCount = self._block.rows
-    if hasattr(self._block,'rowSpacer'):
-      self.gap = self._block.rowSpacer
-
+    if not hasattr(self,'rows'):
+      if hasattr(self._block,'rows'):
+        self.visibleCount = self._block.rows
+    else:
+      self.visibleCount = self.rows
+      
+    if not hasattr(self,'rowSpacer'):
+      if hasattr(self._block,'rowSpacer'):
+        self.gap = self._block.rowSpacer
+    else:
+      self.gap = self.rowSpacer
+      
     #following check does not work if move it to GFEntry.__init__ (ra3vat) 
     if hasattr(self, 'style'):
       if self.style=='checkbox':
Index: gnue/gnuef/src/GFObjects/GFLabel.py
diff -u gnue/gnuef/src/GFObjects/GFLabel.py:1.1 
gnue/gnuef/src/GFObjects/GFLabel.py:1.2
--- gnue/gnuef/src/GFObjects/GFLabel.py:1.1     Fri Jun 29 15:55:58 2001
+++ gnue/gnuef/src/GFObjects/GFLabel.py Mon Jul 16 20:09:41 2001
@@ -64,11 +64,17 @@
   def initialize(self):
     self._block = self.findParentOfType('GFBlock')
     if not hasattr(self,'visibleCount'):
-      if hasattr(self._block,'rows'):
-        self.visibleCount = self._block.rows
-      if hasattr(self._block,'rowSpacer'):
-        self.gap = self._block.rowSpacer
+      if not hasattr(self,'rows'):
+        if hasattr(self._block,'rows'):
+          self.visibleCount = self._block.rows
+        else:
+          self.visibleCount = self.rows
 
+        if not hasattr(self,'rowSpacer'):
+          if hasattr(self._block,'rowSpacer'):
+            self.gap = self._block.rowSpacer
+          else:
+            self.gap = self.rowSpacer
 
 
 
Index: gnue/gnuef/src/GFParser.py
diff -u gnue/gnuef/src/GFParser.py:1.47 gnue/gnuef/src/GFParser.py:1.48
--- gnue/gnuef/src/GFParser.py:1.47     Thu Jul 12 11:38:19 2001
+++ gnue/gnuef/src/GFParser.py  Mon Jul 16 20:09:41 2001
@@ -205,7 +205,12 @@
                   'center': {} }, 
                'Default': "left"}, 
             'width': {
-               'Typecast': GTypecast.whole }, 
+               'Typecast': GTypecast.whole },
+            'rows': {
+               'Typecast': GTypecast.whole,
+               'Default': 1},
+            'rowSpacer': {
+               'Typecast': GTypecast.whole },
             'x': {
                'Required': 1, 
                'Typecast': GTypecast.whole }, 
@@ -234,8 +239,12 @@
                'Typecast': GTypecast.whole }, 
             'visibleCount':{
                'Typecast': GTypecast.whole, 
-               'Deprecated': 'Use the block "row" attribute instead.', 
+               'Deprecated': 'Use the block "rows" attribute instead.', 
                'Default': 1 }, 
+            'rows': {
+               'Typecast': GTypecast.whole},
+            'rowSpacer': {
+               'Typecast': GTypecast.whole },
             'readonly': {
                'Typecast': GTypecast.boolean, 
                'Default': 0   }, 
Index: gnue/gnuef/src/GFTrigger.py
diff -u gnue/gnuef/src/GFTrigger.py:1.40 gnue/gnuef/src/GFTrigger.py:1.41
--- gnue/gnuef/src/GFTrigger.py:1.40    Thu Jul  5 10:57:21 2001
+++ gnue/gnuef/src/GFTrigger.py Thu Jul 12 20:56:13 2001
@@ -180,6 +180,7 @@
         # May be better to deal with this in GFTriggerAware
         import sys
         print "%s in trigger code, value: %s" % (sys.exc_type, sys.exc_value)
+
     self.__call__ = thisTrigger
       
   def dummyFunction(self, myself):
@@ -302,7 +303,6 @@
   def __init__(self, object):
     GFTriggerHelperBase.__init__(self, object)
   
-        
 
 class GFTriggerFields( GFTriggerHelperBase ):
   def getattribute( self, name ):
Index: gnue/gnuef/src/UIwxpython.py
diff -u gnue/gnuef/src/UIwxpython.py:1.104 gnue/gnuef/src/UIwxpython.py:1.105
--- gnue/gnuef/src/UIwxpython.py:1.104  Tue Jul  3 18:42:45 2001
+++ gnue/gnuef/src/UIwxpython.py        Mon Jul 16 20:09:41 2001
@@ -42,8 +42,6 @@
 _NOTEBOOK = None
 _LOOPTRAP = 0
 
-
-
 #
 # Little global helper routine to set font according to options
 #
@@ -226,6 +224,8 @@
     EVT_MENU(self, 201, lambda event, l=self: 
l.dispatchEvent(GFEvent('requestNEXTRECORD')))
     dataMenu.Append( 202, "Previous Record   
(Down)",GConfig.get('msg_previous'))
     EVT_MENU(self, 202, lambda event, l=self: 
l.dispatchEvent(GFEvent('requestPREVRECORD')))
+    dataMenu.Append( 209, "Jump to Record...     (F2)",GConfig.get('msg_jump'))
+    EVT_MENU(self, 209, self.promptForRecordNumber)
     dataMenu.Append( 203, "New Record           
(F12)",GConfig.get('msg_insert'))
     EVT_MENU(self, 203, lambda event, l=self: 
l.dispatchEvent(GFEvent('requestNEWRECORD')))
     dataMenu.Append( 204, "Delete Record          
(F5)",GConfig.get('msg_delete'))
@@ -438,6 +438,19 @@
     self.mainWindow.Close()
 
   #
+  # promptForRecordNumber
+  #
+  # Presents a dialog to user asking for the record number to jump to
+  #
+  def promptForRecordNumber(self, event= None):
+    dlg = wxTextEntryDialog(self.mainWindow, 'Enter record number to jump to',
+                                                        'Which record?')
+    if dlg.ShowModal() == wxID_OK:
+      self.dispatchEvent(GFEvent('requestRECORDNUMBER', dlg.GetValue()))
+      dlg.Destroy()
+                      
+
+  #
   # closeTrap
   #
   # intercepts the applications closure and generates an event to the form 
requesting
@@ -480,6 +493,9 @@
           elif (1728 <= event.KeyCode() <= 1791):
             offset = 1536
             action = GFEvent('requestKEYPRESS',chr(event.KeyCode()-offset))
+          elif event.KeyCode() == WXK_F2:
+            self.promptForRecordNumber()
+
             
     #
     # Mouse Events
@@ -1007,6 +1023,7 @@
 class UIMessageBox(wxMessageDialog, UIHelper):
   def __init__(self, interface, message, caption):
     wxMessageDialog.__init__(self, interface, message, caption, 
style=wxOK|wxICON_EXCLAMATION)
+
 
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]