[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
gnue gnue-common/setup.py gnue-common/doc/DataO...
From: |
James Thompson |
Subject: |
gnue gnue-common/setup.py gnue-common/doc/DataO... |
Date: |
Sun, 12 Aug 2001 12:55:28 -0700 |
CVSROOT: /cvs
Module name: gnue
Changes by: James Thompson <address@hidden> 01/08/12 12:55:27
Modified files:
gnue-common : setup.py
gnue-common/doc: DataObjects.txt
gnue-common/etc: sample.gnue.conf
gnue-common/src: GClientApp.py GConditions.py GConnections.py
GDataObjects.py GDataSource.py GLoginHandler.py
GObjects.py GParser.py
gnuef : TODO
gnuef/client : gfclient
gnuef/samples/location/forms: zipcode_maint.gfd
gnuef/samples/trigger: trigger.gfd
gnuef/samples/zipcode: states.gfd zipcode.gfd
gnuef/src : GFClient.py GFForm.py GFInstance.py GFParser.py
GFTrigger.py UIbase.py UIwxpython.py
gnuef/src/GFObjects: GFBlock.py GFDataSource.py GFEntry.py
GFLabel.py GFObj.py
reports/src : GRDataMapper.py GRLayout.py GRParser.py
GRQueryBuilder.py
Added files:
gnue-common/doc: CustomizedLoginHandlers.txt
Removed files:
gnuef/src : GFController.py GFDebug.py GFGetOpt.py
GFOptions.py
Log message:
Merged new datasource branch w/ HEAD
*****THIS WILL BREAK THINGS*****
The previous cvs HEAD was tagged prior to doing this. Use that if you
need
features not yet present in this code.
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/setup.py.diff?cvsroot=OldCVS&tr1=1.15&tr2=1.16&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/doc/CustomizedLoginHandlers.txt.diff?cvsroot=OldCVS&tr1=1.1&tr2=1.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/doc/DataObjects.txt.diff?cvsroot=OldCVS&tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/etc/sample.gnue.conf.diff?cvsroot=OldCVS&tr1=1.5&tr2=1.6&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GClientApp.py.diff?cvsroot=OldCVS&tr1=1.9&tr2=1.10&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GConditions.py.diff?cvsroot=OldCVS&tr1=1.1&tr2=1.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GConnections.py.diff?cvsroot=OldCVS&tr1=1.9&tr2=1.10&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GDataObjects.py.diff?cvsroot=OldCVS&tr1=1.7&tr2=1.8&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GDataSource.py.diff?cvsroot=OldCVS&tr1=1.11&tr2=1.12&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GLoginHandler.py.diff?cvsroot=OldCVS&tr1=1.2&tr2=1.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GObjects.py.diff?cvsroot=OldCVS&tr1=1.16&tr2=1.17&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/GParser.py.diff?cvsroot=OldCVS&tr1=1.18&tr2=1.19&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/TODO.diff?cvsroot=OldCVS&tr1=1.57&tr2=1.58&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/client/gfclient.diff?cvsroot=OldCVS&tr1=1.44&tr2=1.45&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/samples/location/forms/zipcode_maint.gfd.diff?cvsroot=OldCVS&tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/samples/trigger/trigger.gfd.diff?cvsroot=OldCVS&tr1=1.8&tr2=1.9&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/samples/zipcode/states.gfd.diff?cvsroot=OldCVS&tr1=1.14&tr2=1.15&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/samples/zipcode/zipcode.gfd.diff?cvsroot=OldCVS&tr1=1.10&tr2=1.11&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFClient.py.diff?cvsroot=OldCVS&tr1=1.24&tr2=1.25&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFForm.py.diff?cvsroot=OldCVS&tr1=1.114&tr2=1.115&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFInstance.py.diff?cvsroot=OldCVS&tr1=1.20&tr2=1.21&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFParser.py.diff?cvsroot=OldCVS&tr1=1.51&tr2=1.52&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFTrigger.py.diff?cvsroot=OldCVS&tr1=1.44&tr2=1.45&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/UIbase.py.diff?cvsroot=OldCVS&tr1=1.42&tr2=1.43&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/UIwxpython.py.diff?cvsroot=OldCVS&tr1=1.106&tr2=1.107&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFBlock.py.diff?cvsroot=OldCVS&tr1=1.8&tr2=1.9&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFDataSource.py.diff?cvsroot=OldCVS&tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFEntry.py.diff?cvsroot=OldCVS&tr1=1.7&tr2=1.8&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFLabel.py.diff?cvsroot=OldCVS&tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnuef/src/GFObjects/GFObj.py.diff?cvsroot=OldCVS&tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/reports/src/GRDataMapper.py.diff?cvsroot=OldCVS&tr1=1.3&tr2=1.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/reports/src/GRLayout.py.diff?cvsroot=OldCVS&tr1=1.6&tr2=1.7&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/reports/src/GRParser.py.diff?cvsroot=OldCVS&tr1=1.10&tr2=1.11&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/reports/src/GRQueryBuilder.py.diff?cvsroot=OldCVS&tr1=1.2&tr2=1.3&r1=text&r2=text
Patches:
Index: gnue/gnue-common/doc/DataObjects.txt
diff -u gnue/gnue-common/doc/DataObjects.txt:1.3
gnue/gnue-common/doc/DataObjects.txt:1.4
--- gnue/gnue-common/doc/DataObjects.txt:1.3 Tue Jul 17 12:10:54 2001
+++ gnue/gnue-common/doc/DataObjects.txt Sun Aug 12 12:55:26 2001
@@ -74,9 +74,11 @@
***********
ResultSet:
- isFirstRecord() : Returns 1=At first record, 0=
- getRecord() : returns 0=No records in memory, #=Current record #
- setRecord() : move to record #, returns 1=New record loaded, 0=invalid #
+ isFirstRecord() : Returns 1=At first record, 0=not at first record or no
records loaded
+ getRecordNumber() : returns -1=No records in memory, #=Current record #
(0-based)
+ getRecord() : return a specified record w/o changing
+ current record (returns None if invalid #) (0-based)
+ setRecord() : move to record #, returns 1=New record loaded, 0=invalid #
(0-based)
nextRecord() : returns 1=New record loaded, 0=No more records
prevRecord() : returns 1=New record loaded, 0=At first record
firstRecord() : returns 1=at first record, 0=No records loaded
Index: gnue/gnue-common/etc/sample.gnue.conf
diff -u gnue/gnue-common/etc/sample.gnue.conf:1.5
gnue/gnue-common/etc/sample.gnue.conf:1.6
--- gnue/gnue-common/etc/sample.gnue.conf:1.5 Thu Aug 2 20:02:28 2001
+++ gnue/gnue-common/etc/sample.gnue.conf Sun Aug 12 12:55:26 2001
@@ -27,6 +27,10 @@
# Create new records in blocks automagically when you hit the bottom
autoCreate = 1
+# Remember last query entered. (if enabled, then the last values entered
+# for a query can be retrieved by doing an Enter-Query twice)
+RememberLastQuery = 1
+
# Hack for db encoding
Encoding=DEFAULT
Index: gnue/gnue-common/setup.py
diff -u gnue/gnue-common/setup.py:1.15 gnue/gnue-common/setup.py:1.16
--- gnue/gnue-common/setup.py:1.15 Wed Jul 18 21:02:29 2001
+++ gnue/gnue-common/setup.py Sun Aug 12 12:55:26 2001
@@ -92,6 +92,7 @@
"gnue.common.dbdrivers.geas",
"gnue.common.dbdrivers.mysql",
"gnue.common.dbdrivers._dbsig",
+ "gnue.common.dbdrivers.empty",
"gnue.common.dbdrivers.odbc",
"gnue.common.dbdrivers.oracle",
"gnue.common.dbdrivers.postgresql"
Index: gnue/gnue-common/src/GClientApp.py
diff -u gnue/gnue-common/src/GClientApp.py:1.9
gnue/gnue-common/src/GClientApp.py:1.10
--- gnue/gnue-common/src/GClientApp.py:1.9 Mon Jun 4 20:23:39 2001
+++ gnue/gnue-common/src/GClientApp.py Sun Aug 12 12:55:26 2001
@@ -149,7 +149,7 @@
# Get the connection definitions
if connections != None:
- self.connections = Connections
+ self.connections = connections
else:
if self.OPTIONS['connections']:
self.connections_file = self.OPTIONS['connections']
Index: gnue/gnue-common/src/GConditions.py
diff -u gnue/gnue-common/src/GConditions.py:1.1
gnue/gnue-common/src/GConditions.py:1.2
--- gnue/gnue-common/src/GConditions.py:1.1 Wed Jun 6 19:09:45 2001
+++ gnue/gnue-common/src/GConditions.py Sun Aug 12 12:55:26 2001
@@ -31,12 +31,15 @@
from GObjects import GObj
+class ConditionError (StandardError):
+ pass
+
#
# Build a condition tree using a dict
# as a source. Assumes keys are field
# names and values are constants.
#
-def buildConditionFromDict (dict):
+def buildConditionFromDict (dict, comparison=None):
cond = GCondition()
lastParent = cond
@@ -44,7 +47,7 @@
lastParent = GCand(lastParent)
for key in dict.keys():
- eq = GCeq(lastParent)
+ eq = (comparison or GCeq)(lastParent)
GCField(eq, key)
GCConst(eq, dict[key])
Index: gnue/gnue-common/src/GConnections.py
diff -u gnue/gnue-common/src/GConnections.py:1.9
gnue/gnue-common/src/GConnections.py:1.10
--- gnue/gnue-common/src/GConnections.py:1.9 Mon Jun 25 12:29:11 2001
+++ gnue/gnue-common/src/GConnections.py Sun Aug 12 12:55:26 2001
@@ -144,6 +144,7 @@
def setDataConnection(self, dataSource):
connection_name = dataSource.database
dataObject = dataSource.getDataObject()
+ print "*** GConnections.setDataConnection.dataObject=%s" % dataObject
if self._openConnections.has_key(string.lower(connection_name)):
# If a database connetion has already been established, use it
Index: gnue/gnue-common/src/GDataObjects.py
diff -u gnue/gnue-common/src/GDataObjects.py:1.7
gnue/gnue-common/src/GDataObjects.py:1.8
--- gnue/gnue-common/src/GDataObjects.py:1.7 Tue Jun 5 08:57:45 2001
+++ gnue/gnue-common/src/GDataObjects.py Sun Aug 12 12:55:26 2001
@@ -62,8 +62,14 @@
# Raised when connection raises an exception.
pass
+class MasterDetailFieldMismatch(Exception):
+ # Raised when a the number of master fields doesn't match the
+ # number of detail fields. (e.g., masterlink="id,subid"
+ # and detaillink="id" would be a problem; must be 1:1)
+ pass
+
###########################################################
#
#
@@ -78,24 +84,57 @@
self._masterfields = []
self._detailfields = []
+
+ self._masterObject = None
+
+ # TODO: This is SO not true.
+ # _detailObjects really isn't used anywhere and shoud be removed
+
self._detailObjects = []
self._dataConnection = None
self._resultSetClass = ResultSet
self._fieldReferences = {} # Set by GDataSource; lists all fields
# a client explicits references
+ self._unboundFieldReferences = {} # Contains names of all unbound
+ # field references
+
+ self.triggerExtensions = None
+
+
+ # Do we have a master datasource?
+ def hasMaster(self):
+ return self._masterObject != None
+
def createResultSet(self, conditions={}, readOnly=0):
pass
+ def createEmptyResultSet(self, readOnly=0):
+ return self.createResultSet(conditions={'1':2}, readOnly=readOnly)
+
# Add a detail data object. This dataobject will create a new resultset
- # everything this dataobject changes (new record, etc). The optional
+ # everytime this dataobject changes (new record, etc). The optional
# handler will be called after the detail dataobject is notified. The
- # client application may with to add a handler to know when the detail
+ # client application may wish to add a handler to know when the detail
# has been requeried. handler is a method that takes two arguments:
# the master ResultSet and the detail ResultSet
def addDetailDataObject(self, dataObject, handler=None):
GDebug.printMesg (1,"Adding a master/detail relationship to DataObject")
+ dataObject._masterObject = self
+ dataObject._masterfields = string.split(hasattr(dataObject,'masterlink')
and \
+ dataObject.masterlink or "", ',')
+ dataObject._detailfields = string.split(hasattr(dataObject,'detaillink')
and \
+ dataObject.detaillink or "", ',')
+
+ if len(dataObject._masterfields) != len(dataObject._detailfields):
+ raise MasterDetailFieldMismatch, "master=%s; detail=%s" % \
+ (dataObject._masterfields, dataObject._detailfields)
+
+ # Make sure "master" fields will be in our future query
+ for field in dataObject._masterfields:
+ self._fieldReferences[string.strip(string.lower(field))] = 1
+
self._detailObjects.append ([dataObject, handler])
@@ -104,15 +143,47 @@
def getLoginFields(self):
return []
+
+ #
+ # Connect to database. Design to be replaced by vendor-specific code.
+ #
+ # NOTE: This will only be called for the FIRST dataobject
+ # using a particular connection. Any subsequent dataobjects
+ # will only get setDataConnection() called. Therefore, any
+ # routines that must be run for EACH dataobject after a connection
+ # has been establisted should be placed in _postConnect(), not connect().
+ #
+ # As such, if the vendor-specific drivers replace this method, the last
+ # line of the new method should be self._postConnect()!
+ #
def connect(self, connectData={}):
+ self._postConnect()
+
+
+ #
+ # Post connection routines. Design to be replaced by vendor-specific code.
+ #
+ # NOTE: See note for connect()
+ #
+ def _postConnect(self):
pass
+
+ #
+ # Set the associated data connection. Used by GConnections.
+ # THERE IS NO NEED FOR VENDOR-CLASSES TO REPLACE THIS METHOD!
+ #
+ # NOTE: See note for connect()
+ #
def setDataConnection(self, connection):
self._dataConnection = connection
+ self._postConnect()
+
def getDataConnection(self):
return self._dataConnection
+
def commit(self):
pass
@@ -121,8 +192,8 @@
# Called when new record master in master/detail is queried
def _masterRecordChanged(self, master):
- self._masterfields = string.split(self.masterlink, ',')
- self._detailfields = string.split(self.detaillink, ',')
+# self._masterfields = string.split(self.masterlink, ',')
+# self._detailfields = string.split(self.detaillink, ',')
GDebug.printMesg (5, 'Master Record Changed')
criteria = {}
for i in range(0, len(self._masterfields)):
@@ -130,7 +201,7 @@
criteria[string.strip(self._detailfields[i])] = \
master.current.getField(string.strip(self._masterfields[i]))
GDebug.printMesg(10,master.current.getField(self._masterfields[i]))
- return self.createResultSet(criteria)
+ return self.createResultSet(conditions=criteria)
###########################################################
@@ -146,10 +217,14 @@
self._cursor = cursor
self._cachedRecords = []
self._currentRecord = -1
- self._defaultValues = defaultValues
self._masterRecordSet = masterRecordSet
self._readonly = 0
self._boundFields = {}
+ self._unboundFields = {}
+
+ self._defaultValues = {}
+ for key in defaultValues.keys():
+ self._defaultValues[key] = defaultValues[key]
self.current = None
@@ -164,21 +239,44 @@
# Returns 1=At first record, 0=Not first record
def isFirstRecord(self):
- return (_currentRecord == 1)
+ return (self._currentRecord == 1)
+
+
+ # returns -1=No records in memory, #=Current record #
+ def getRecordNumber(self):
+ return self._currentRecord
- # returns 0=No records in memory, #=Current record #
- def getRecord(self):
- return _currentRecord + 1
+ # returns # of records currently loaded
+ def getCacheCount(self):
+ return len(self._cachedRecords)
+ # Get a specific record (0=based)
+ def getRecord(self, record):
+ while (record + 1 > len(self._cachedRecords)) and self._loadNextRecord():
+ pass
+
+ if record + 1 > len(self._cachedRecords):
+ return None
+ else:
+ return self._cachedRecords[record]
+
+
# move to record #, returns 1=New record loaded, 0=invalid #
def setRecord(self, record):
- if record - 1 > len(self._cachedRecords):
- # load records
- pass
+ while (record - 1 > len(self._cachedRecords)) and self._loadNextRecord():
+ pass
+ if record - 1 > len(self._cachedRecords):
+ return 0
+ else:
+ self._currentRecord = record
+ self.current = self._cachedRecords[self._currentRecord]
+ self.notifyDetailObjects()
+ return 1
+
# returns 1=New record loaded, 0=No more records
def nextRecord(self):
if self._currentRecord + 1 == len(self._cachedRecords):
@@ -205,12 +303,14 @@
# returns 1=at first record, 0=No records loaded
def firstRecord(self):
if self._currentRecord < 0:
- return 0
- else:
- self._currentRecord = 0
- self.current = self._cachedRecords[0]
- self.notifyDetailObjects()
- return 1
+ if not self._loadNextRecord():
+ return 0
+
+ self._currentRecord = 0
+ self.current = self._cachedRecords[0]
+ self.notifyDetailObjects()
+ return 1
+
# returns 1=at last record, 0=No records loaded
@@ -218,10 +318,10 @@
if self._currentRecord == -1:
return 0
else:
- while self._loadNextRecord:
+ while self._loadNextRecord():
pass
- self._currentRecord = len(self._cachedRecords)
- self.current = self._cachedRecords(self._currentRecord)
+ self._currentRecord = len(self._cachedRecords) - 1
+ self.current = self._cachedRecords[self._currentRecord]
self.notifyDetailObjects()
return 1
@@ -232,9 +332,10 @@
# Provide better feedback??
raise ReadOnlyError, "Attempted to insert into a read only datasource"
else:
+ GDebug.printMesg(7,'Inserting a blank record')
self._currentRecord = self._currentRecord+1
- self._cachedRecords.insert(_currentRecord, self._createEmptyRecord())
- current = self._cachedRecords[self._currentRecord]
+ self._cachedRecords.insert(self._currentRecord,
self._createEmptyRecord())
+ self.current = self._cachedRecords[self._currentRecord]
self.notifyDetailObjects()
return 1
@@ -248,6 +349,9 @@
break
return isPending
+ # Returns 1=DataObject has uncommitted changes
+ def isRecordPending(self):
+ return self.current.isPending()
# Post changes to the database
def post(self):
@@ -255,10 +359,15 @@
for record in (self._cachedRecords):
record.post()
- #
+ # jst
def notifyDetailObjects(self):
GDebug.printMesg(5,'Master record changed; Notifying Detail Objects')
+ #if self.current:
+ # for detail in self.current._detailObjects:
+ # print "GDataObjects ",detail
+
for detail in self._dataObject._detailObjects:
+ print detail
rs = detail[0]._masterRecordChanged(self)
if detail[1]:
detail[1].masterResultSetChanged(self, rs)
@@ -276,12 +385,12 @@
# Load cacheCount number of new records
def _loadNextRecord(self):
- return 1
+ return 0
# Load cacheCount number of new records
def _createEmptyRecord(self):
- return self._recordSetClass()
+ return self._recordSetClass(self)
###########################################################
@@ -299,18 +408,30 @@
self._parent = parent
self._modifiedFlags = {} # If field name is present as a key,
# then field has been modified
+
+ self._initialData = initialData
+
+ self._unboundFields = {}
+
if len(initialData):
self._insertFlag = 0
self._emptyFlag = 0
- self._fields = initialData
+ self._fields = {}
+ for key in initialData.keys():
+ self._fields[key] = initialData[key]
else:
self._insertFlag = 1
self._emptyFlag = 1
- self._fields = defaultData
+ self._fields = {}
+ for key in defaultData.keys():
+ self._fields[key] = defaultData[key]
# Returns 1=Record has uncommitted changes
def isPending(self):
+
+ # The _insertFlag and _deleteFlag takes care of records that
+ # were inserted, but then deleted before a save (i.e., nothing to do)
if self._emptyFlag or self._insertFlag and self._deleteFlag:
return 0
else:
@@ -364,14 +485,14 @@
else:
self._emptyFlag = 0
fn = string.lower(field)
- self._fields[fn] = value
+ self._fields[fn] = "%s" % value
if self._parent.isFieldBound(field):
self._updateFlag = 1
- if self._modifiedFlags.has_key(fn):
- flag = self._modifiedFlags[fn] + 1
- else:
- flag = 1
- self._modifiedFlags[fn] = flag
+ if self._modifiedFlags.has_key(fn):
+ flag = self._modifiedFlags[fn] + 1
+ else:
+ flag = 1
+ self._modifiedFlags[fn] = flag
# Returns 1=Field has been modified
@@ -379,7 +500,7 @@
return self._modifiedFlags.has_key (string.lower(fieldName))
- # Posts changes to database
+ # Mark the current record as deleted
def delete(self):
if self._parent.isReadOnly():
# Provide better feedback??
@@ -414,5 +535,6 @@
# Post any changes to database
def _postChanges(self):
return 1
+
Index: gnue/gnue-common/src/GDataSource.py
diff -u gnue/gnue-common/src/GDataSource.py:1.11
gnue/gnue-common/src/GDataSource.py:1.12
--- gnue/gnue-common/src/GDataSource.py:1.11 Wed Jul 4 17:24:11 2001
+++ gnue/gnue-common/src/GDataSource.py Sun Aug 12 12:55:26 2001
@@ -55,6 +55,7 @@
self._dataObject = None
self._connectionComment = ""
self._fieldReferences = {}
+ self._unboundFieldReferences = {}
#
# This method should be called after the object is created
@@ -64,18 +65,28 @@
self._connectionManager = connectionManager
def initialize(self):
- if self.database and self._connectionManager:
+
+ if not self.database:
+ # We are a connectionless datasource (virtual?)
+ # We have to bind to something, so bind to empty driver
+ from gnue.common.dbdrivers.empty import DBdriver
+ GDebug.printMesg (7, 'Using empty data driver')
+ self._dataObject = DBdriver.supportedDataObjects['object']()
+
+ elif self._connectionManager:
# This will throw a GConnections.NotFoundError if an unknown
# connection name is specified. The calling method should
# catch this exception and handle it properly (exit w/message)
self._dataObject = \
self._connectionManager.getDataObject(self.database, self.type)
- self._dataObject._fieldReferences = self._fieldReferences
- # Copy all attributes from XML to the dataObject
- for attribute in tagAttributes.keys():
- if hasattr(self, attribute):
- self._dataObject.__dict__[attribute] = self.__dict__[attribute]
+ self._dataObject._fieldReferences = self._fieldReferences
+ self._dataObject._unboundFieldReferences = self._unboundFieldReferences
+
+ # Copy all attributes from XML to the dataObject
+ for attribute in tagAttributes.keys():
+ if hasattr(self, attribute):
+ self._dataObject.__dict__[attribute] = self.__dict__[attribute]
def connect(self):
@@ -91,7 +102,37 @@
if self._dataObject != None:
self._dataObject._fieldReferences[field] = 1
+ def referenceUnboundField(self, field):
+ GDebug.printMesg(7,'Field %s implicitly referenced' % field)
+ self._unboundFieldReferences[field] = 1
+ if self._dataObject != None:
+ self._dataObject._unboundFieldReferences[field] = 1
+
+ #
+ # The following are a simple wrapper arround the datasource's dataobject
+ # to hide the dataobject from the app programmer
+ #
+ def hasMaster(self):
+ return self._dataObject != None and self._dataObject.hasMaster()
+
+ def createResultSet(self, conditions={}, readOnly=0):
+# if self._dataObject:
+ return self._dataObject.createResultSet(conditions,readOnly)
+
+ def addDetailDataObject(self, dataObject, handler=None):
+# if self._dataObject:
+ self._dataObject.addDetailDataObject(dataObject, handler)
+
+ def createEmptyResultSet(self, readOnly=0):
+# if self._dataObject:
+ return self._dataObject.createEmptyResultSet(readOnly)
+
+######
+#
+#
+#
+######
class GSql(GObjects.GObj):
def __init__(self, parent=None):
GObjects.GObj(self, parent, type="GDSql")
Index: gnue/gnue-common/src/GLoginHandler.py
diff -u gnue/gnue-common/src/GLoginHandler.py:1.2
gnue/gnue-common/src/GLoginHandler.py:1.3
--- gnue/gnue-common/src/GLoginHandler.py:1.2 Tue May 15 08:16:38 2001
+++ gnue/gnue-common/src/GLoginHandler.py Sun Aug 12 12:55:26 2001
@@ -40,6 +40,10 @@
class LoginHandler:
+
+ # The client app can set any default values for the needed parameters.
+ defaults = {}
+
#
# getLogin is passed an list consisting of:
# Connection Name
Index: gnue/gnue-common/src/GObjects.py
diff -u gnue/gnue-common/src/GObjects.py:1.16
gnue/gnue-common/src/GObjects.py:1.17
--- gnue/gnue-common/src/GObjects.py:1.16 Sat Jul 28 20:21:41 2001
+++ gnue/gnue-common/src/GObjects.py Sun Aug 12 12:55:26 2001
@@ -57,6 +57,7 @@
self._parent = parent
self._children = []
self._attributes = {}
+ self._inits = []
if parent :
parent.addChild(self)
@@ -72,6 +73,27 @@
for child in self._children:
if isinstance(child, GObj):
child.initialize()
+
+ #
+ # phaseInit
+ #
+ # TODO: Phase init should really get the size of the largest _inits
+ # TODO: array and use it instead of hardcoding 5 iterations
+ def phaseInit(self):
+ for phase in range(5):
+ self._phaseInit(phase)
+ phase = phase + 1
+
+ def _phaseInit(self,phase):
+ if (len(self._inits) > phase) and (self._inits[phase] != None):
+ GDebug.printMesg(6,"%s: Init Phase %s" % (self.getObjectType(), phase+1))
+ self._inits[phase]()
+
+ if self._children:
+ for child in self._children:
+ if isinstance(child, GObj):
+ child._phaseInit(phase)
+
#
# getObjectType
Index: gnue/gnue-common/src/GParser.py
diff -u gnue/gnue-common/src/GParser.py:1.18
gnue/gnue-common/src/GParser.py:1.19
--- gnue/gnue-common/src/GParser.py:1.18 Wed Jul 4 17:24:11 2001
+++ gnue/gnue-common/src/GParser.py Sun Aug 12 12:55:27 2001
@@ -103,7 +103,14 @@
object.__dict__[att] = attributes[att]
if initialize:
- object.initializeTree()
+ GDebug.printMesg(10,"Initializing the object tree starting at %s"
%(object))
+
+ # TODO: initializeTree is depreciated but left in here for
+ # TODO: backwards compatibility.
+ if hasattr(object,'initializeTree'):
+ object.initializeTree()
+ else:
+ object.phaseInit()
return object
Index: gnue/gnuef/TODO
diff -u gnue/gnuef/TODO:1.57 gnue/gnuef/TODO:1.58
--- gnue/gnuef/TODO:1.57 Mon Jul 16 20:09:41 2001
+++ gnue/gnuef/TODO Sun Aug 12 12:55:27 2001
@@ -1,7 +1,6 @@
A name inside of [] means that person has taken that task
Bugs
- Fix symlink support
I've broken msgboxs in triggers
triggers should not fire during query entry
@@ -16,15 +15,6 @@
provide better seperation of Objects in the Data system
restore proper encapsulation in system
- Move things like database init in GFForm out of __init__ and
- into a initialize routine that is called via some type of
- uiINITIALIZED event so that a UI windows can prompt for things
- like name/password.
-
- move initialize function into the base object and have them
- call the initializes of their children so we can get rid of
- more of the self.walk nonsense
-
Rewrite the event system to allow greater efficency and flexibility
Data source related
Index: gnue/gnuef/samples/location/forms/zipcode_maint.gfd
diff -u gnue/gnuef/samples/location/forms/zipcode_maint.gfd:1.3
gnue/gnuef/samples/location/forms/zipcode_maint.gfd:1.4
--- gnue/gnuef/samples/location/forms/zipcode_maint.gfd:1.3 Sun Jul 29
12:36:32 2001
+++ gnue/gnuef/samples/location/forms/zipcode_maint.gfd Sun Aug 12 12:55:27 2001
@@ -14,15 +14,14 @@
<datasource name="validator" database="gnue" table="state" prequery="" />
<page>
+ <label text="City" x="1" y="1"/>
+ <label text="State" x="31" y="1"/>
+ <label text="Zip" x="39" y="1"/>
<block name="zip" datasource="zips" rows="10">
- <label text="City" x="1" y="1"/>
- <entry name="city" field="city" x="1" y="2" width="30" uppercase="">
- </entry>
+ <entry name="city" field="city" x="1" y="2" width="30" uppercase=""/>
- <label text="State" x="31" y="1"/>
<entry name="state" field="state" x="32" y="2" width="10"
style="dropdown" foreign_key="validator.state"
foreign_key_description="description"/>
- <label text="Zip" x="39" y="1"/>
<entry name="zip" field="zipcode" x="42" y="2" width="7" numeric=""
max_length="5"/>
</block>
</page>
Index: gnue/gnuef/samples/trigger/trigger.gfd
diff -u gnue/gnuef/samples/trigger/trigger.gfd:1.8
gnue/gnuef/samples/trigger/trigger.gfd:1.9
--- gnue/gnuef/samples/trigger/trigger.gfd:1.8 Thu Jul 12 20:59:01 2001
+++ gnue/gnuef/samples/trigger/trigger.gfd Sun Aug 12 12:55:27 2001
@@ -29,7 +29,7 @@
<tip>Type Field One's Replacement</tip>
</options>
<trigger type ="Pre-FOCUSOUT">
-block1.fields.one = self.getValue()
+block1.fields.one.setValue(self.getValue())
#
#User name trigger
#
Index: gnue/gnuef/samples/zipcode/states.gfd
diff -u gnue/gnuef/samples/zipcode/states.gfd:1.14
gnue/gnuef/samples/zipcode/states.gfd:1.15
--- gnue/gnuef/samples/zipcode/states.gfd:1.14 Sat Jul 21 16:33:49 2001
+++ gnue/gnuef/samples/zipcode/states.gfd Sun Aug 12 12:55:27 2001
@@ -8,29 +8,29 @@
<width>39</width>
</options>
- <database name="gnue" provider="postgresql" dbname="gnue" host="gnue"/>
- <datasource name="dsstate" database="gnue" table="state" cache="5"
order_by="state"/>
- <datasource name="dscities" database="gnue" table="zipcode" cache="5"
order_by="city"/>
+ <datasource name="dsstate" database="devel" table="state" cache="5"
order_by="state"/>
+ <datasource name="dscities" database="devel" table="zipcode" cache="5"
order_by="city"
+ master="dsstate" detaillink="state_code" masterlink="state"/>
<page>
- <block name="blkstate" datasource="dsstate">
+ <block name="blkstate" datasource="dsstate" rows="5">
<label text="Code" x="2" y="1"/>
- <entry name="entstate" field="state" x="2" y="2" width="4" height="1"
rows="5"/>
+ <entry name="entstate" field="state" x="2" y="2" width="4" height="1"/>
<label text="Description" x="7" y="1"/>
- <entry name="entdesc" field="description" x="7" y="2" width="30"
height="1" rows="5"/>
+ <entry name="entdesc" field="description" x="7" y="2" width="30"
height="1"/>
</block>
<!-- Block of cities -->
- <block name="cities" datasource="dscities" master="blkstate.state"
detail="state_code">
+ <block name="cities" datasource="dscities" rows="5">
<label text="City" x="2" y="9"/>
- <entry name="city" field="city" x="2" y="10" width="20" rows="5" />
+ <entry name="city" field="city" x="2" y="10" width="20" />
<label text="ST" x="23" y="9"/>
- <entry name="state" field="state_code" x="23" y="10" width="3" rows="5"
/>
+ <entry name="state" field="state_code" x="23" y="10" width="3" />
<label text="Zip" x="27" y="9"/>
- <entry name="zip" field="zip" x="27" y="10" width="10" rows="5" />
+ <entry name="zip" field="zip" x="27" y="10" width="10" />
<box x="1" y="8" width="37" height="8" label="State Cities"/>
Index: gnue/gnuef/samples/zipcode/zipcode.gfd
diff -u gnue/gnuef/samples/zipcode/zipcode.gfd:1.10
gnue/gnuef/samples/zipcode/zipcode.gfd:1.11
--- gnue/gnuef/samples/zipcode/zipcode.gfd:1.10 Tue Mar 20 15:25:50 2001
+++ gnue/gnuef/samples/zipcode/zipcode.gfd Sun Aug 12 12:55:27 2001
@@ -8,30 +8,27 @@
<width>42</width>
</options>
-<!-- <database name="gnue" provider="mysql" dbname="gnue" host="localhost"/>
-->
- <database name="gnue" provider="postgresql" dbname="gnue" host="gnue"/>
+ <datasource name="zips" database="devel" table="zipcode" cache="5"
order_by="state_code,city" prequery=""/>
+ <datasource name="validator" database="devel" table="state" prequery=""
order_by="description"/>
- <datasource name="zips" database="gnue" table="zipcode" cache="5"
order_by="state_code,city" prequery=""/>
- <datasource name="validator" database="gnue" table="state" prequery=""
order_by="description"/>
-
<page>
- <block name="zip" datasource="zips">
+ <block name="zip" datasource="zips" rows="15">
<label text="City" x="1" y="1"/>
- <entry name="city" field="city" x="1" y="2" width="15" visibleCount="15"
uppercase="">
+ <entry name="city" field="city" x="1" y="2" width="15" uppercase="">
<options>
<option name="tip">Full name of city</option>
</options>
</entry>
<label text="State" x="17" y="1"/>
- <entry name="state" field="state_code" x="17" y="2" width="15"
visibleCount="15" uppercase="" foreign_key="validator.state"
foreign_key_description="description" style="dropdown">
+ <entry name="state" field="state_code" x="17" y="2" width="15"
uppercase="" foreign_key="validator.state"
foreign_key_description="description" style="dropdown">
<options>
<tip>State</tip>
</options>
</entry>
<label text="Zip" x="33" y="1"/>
- <entry name="zip" field="zip" x="33" y="2" width="5" visibleCount="15"
numeric="" max_length="5" >
+ <entry name="zip" field="zip" x="33" y="2" width="5" numeric=""
max_length="5" >
<options>
<tip>US Postal Zip Code</tip>
</options>
Index: gnue/gnuef/src/GFClient.py
diff -u gnue/gnuef/src/GFClient.py:1.24 gnue/gnuef/src/GFClient.py:1.25
--- gnue/gnuef/src/GFClient.py:1.24 Mon Jul 2 10:54:19 2001
+++ gnue/gnuef/src/GFClient.py Sun Aug 12 12:55:27 2001
@@ -34,7 +34,7 @@
#
# Copyright (c) 2000 Free Software Foundation
#
-# $Id: GFClient.py,v 1.24 2001/07/02 17:54:19 jcater Exp $
+# $Id: GFClient.py,v 1.25 2001/08/12 19:55:27 jamest Exp $
#
import pstats
@@ -42,12 +42,9 @@
import os.path
import sys
import urllib
-import gnue.forms.GFOptions
-from gnue.forms.GFGetOpt import *
from gnue.forms.GFInstance import *
from gnue.forms.GFForm import *
-from gnue.forms.GFController import *
from gnue.forms.GFParser import loadForm
from gnue.common import GDebug
from gnue.common import GConfig
@@ -106,17 +103,17 @@
if self.ui_type == 'gui' :
if os.environ.has_key('DISPLAY') or os.name != 'posix':
from gnue.forms import UIwxpython
- self._ui=UIwxpython.GFUserInterface
+ self._ui=UIwxpython
else:
self.ui_type='text'
if self.ui_type == 'pytext':
from gnue.forms import UIpyncurses
- self._ui=UIpyncurses.GFUserInterface
+ self._ui=UIpyncurses
if self.ui_type == 'text' :
from gnue.forms import UIcurses
- self._ui=UIcurses.GFUserInterface
+ self._ui=UIcurses
self.runForm(formfile, self.disableSplash)
@@ -125,11 +122,19 @@
self.runForm(formFile, disableSplash=1)
def runForm(self, formFile, disableSplash=0):
-
+ #
+ # Create the instance
+ #
instance = GFInstance(self, self.getNextSerialNumber(),
connections=self.connections, ui=self._ui, disableSplash=disableSplash)
+ self._formInstances[instance.getSerialNumber()] = instance
#
+ # Assign the proper login handler based upon the user interface choice
+ #
+ self.getConnectionManager().setLoginHandler(self._ui.UILoginHandler())
+
+ #
# Build the form tree
#
drive = os.path.splitdrive(formFile)
@@ -142,13 +147,10 @@
fileHandle.close()
#
- # Create and start the instance
+ # Start the instance
#
- self._formInstances[instance.getSerialNumber()] = instance
-
instance.setForm(form)
instance.activate()
-
def getNextSerialNumber (self):
self._lastSerialNumber = self._lastSerialNumber + 1
Index: gnue/gnuef/src/GFForm.py
diff -u gnue/gnuef/src/GFForm.py:1.114 gnue/gnuef/src/GFForm.py:1.115
--- gnue/gnuef/src/GFForm.py:1.114 Tue Aug 7 20:17:00 2001
+++ gnue/gnuef/src/GFForm.py Sun Aug 12 12:55:27 2001
@@ -1,3 +1,4 @@
+#
# This file is part of GNU Enterprise.
#
# GNU Enterprise is free software; you can redistribute it
@@ -15,7 +16,7 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000 Free Software Foundation
+# Copyright 2000-2001 Free Software Foundation
#
# FILE:
# GFForm.py
@@ -28,14 +29,12 @@
#
import sys
-import os
import string
-from gnue.common import GDebug, openResource
-from gnue.common import GConfig
import traceback
+from gnue.common import GDebug, openResource
+from gnue.common import GConfig
from GFObjects import *
-#import GFObjects
from GFEvent import *
from GFError import DBError
from GFTriggerError import *
@@ -68,10 +67,15 @@
self._blockList = []
self._pageList = []
- #self.borderPercentage = 10
- #self._textPercentage = 7.5
self._app = app
+ self._triggerns={}
+ self._triggerns['TRUE'] = 1
+ self._triggerns['FALSE'] = 0
+ self._triggerns['GFMsgBox'] = GFMsgBox
+
+ self._inits = [self.primaryInit, self.secondaryInit]
+
def buildObject(self):
# Convert some deprecated options to new style
@@ -93,73 +97,76 @@
i = i + 1
else:
i = i + 1
-
-
-
- def initializeTree(self):
-
- # Import all needed objects
+ #
+ # primaryInit
+ #
+ # Called during phaseInit startup by GParser.
+ #
+ def primaryInit(self):
+ # TODO: Look at moving this into GParser
+ # Import all needed objects
self.walk(self.initImportedObjects)
- # set the initial focus
- self.walk(self.setInitialFocus)
+ # analyze the tree
+ self.walk(self.analyzeTree)
+
+ def secondaryInit(self):
+ # create the first records
+ for key in self._datasourceDictionary.keys():
+ if not self._datasourceDictionary[key].hasMaster():
+ self._datasourceDictionary[key].createEmptyResultSet()
- # Connect to the defined databases
- self.walk(self.initDatabaseObjects)
- self.walk(self.initDataSources)
-
- # build the block list
- self.walk(self.initBlocks)
- self.walk(self.initPages)
- self.walk(self.initEntries)
- self.walk(self.initLabels)
-
- GDebug.printMesg(3, "Database Dictionary")
- GDebug.printMesg(3, "%s"%self._databaseDictionary)
- GDebug.printMesg(3, "Datasource Dictionary")
- GDebug.printMesg(3, "%s"%self._datasourceDictionary)
-
- #Set trigger namespace, we'll need something more
- #detailed than this including widgets etc. Also attaches
- #named triggers to thier placeholders
- self._triggerns={}
- self._triggerns['TRUE'] = 1
- self._triggerns['FALSE'] = 0
+ #
+ # begin routines made for walking
+ #
+ # routines that are used by the walk() method
+ # suggesting a better way probably exists :)
+ #
- for block in self._blockList:
+ #
+ # analyzeTree
+ #
+ # Scans the tree form tree and performs the following
+ #
+ # builds the various entity lists
+ # it also sets the initial focus of the form
+ # constructs the trigger namespace
+ #
+ def analyzeTree(self,object):
+ if object.getObjectType() == 'GFBlock':
+ self._blockList.append(object)
+ if self._currentBlock == None:
+ self._currentBlock = object
+
try:
- self._triggerns[block.name] = GFTrigger.GFTriggerHelper( block )
+ self._triggerns[object.name] = GFTrigger.GFTriggerHelper( object )
except AttributeError: pass
-
- for key in self._datasourceDictionary.keys():
- self._triggerns[key] = self._datasourceDictionary[key]
-
-
- self._triggerns['GFMsgBox'] = GFMsgBox
+ elif object.getObjectType() == 'GFPage':
+ self._pageList.append(object)
+ if self._currentPage == None:
+ self._currentPage = object
- # Initialization steps that must occur after connected to database
- def postLoginInitialization(self):
+ elif object.getObjectType() == 'GFEntry' and self._currentEntry == None
and not object.hidden:
+ self._currentEntry = object
+
+ elif object.getObjectType() =='GFDataSource':
+ self._datasourceDictionary[object.name]=object
- for db in self._databaseDictionary.keys():
- self._triggerns[db] = self._databaseDictionary[db].triggerNamespace
- self._databaseDictionary[db].properties = self._databaseDictionary[db]
-
- for key in self._datasourceDictionary.keys():
- object = self._datasourceDictionary[key]
- object.initialize()
+ def setFocus(self,object):
+ if object.getObjectType() == 'GFBlock' and self._currentBlock == None:
+ self._currentBlock = object
- self.walk(self.initTriggers)
+ elif object.getObjectType() == 'GFPage' and self._currentPage == None:
+ self._currentPage = object
+ elif object.getObjectType() == 'GFEntry' and \
+ self._currentEntry == None and \
+ not object.readonly and \
+ not object.hidden:
+ self._currentEntry = object
-
- #
- # begin routines made for walking
- #
- # routines that are used by the walk() method
- # suggesting a better way probably exists :)
- #
def initImportedObjects(self, object):
if isinstance(object, GFLibrary.GFImport):
importAllDataSources = object.datasources == "*"
@@ -220,8 +227,7 @@
rv.__dict__[key] = object._loadedxmlattrs[key]
GDebug.printMesg (5, ">>> Moving %s" % key)
rv.buildObject()
-
-
+
def __findImportItem(self, find, object, id):
if isinstance(object, find._importclass) and \
hasattr(object, id) and \
@@ -236,70 +242,10 @@
return rv
else:
return None
-
-
- def setInitialFocus(self, object):
- if object.getObjectType() == 'GFBlock' and self._currentBlock == None:
- self._currentBlock = object
- if object.getObjectType() == 'GFPage' and self._currentPage == None:
- self._currentPage = object
- if object.getObjectType() == 'GFEntry' and self._currentEntry == None and
not object.hidden:
- self._currentEntry = object
-
- def initBlocks(self, object):
- if object.getObjectType() == 'GFBlock':
- self._blockList.append(object)
- object.initialize()
-
- def initPages(self,object):
- if object.getObjectType() == 'GFPage':
- self._pageList.append(object)
-
- def initEntries(self, object):
- if object.getObjectType() == 'GFEntry':
- object.initialize()
- value = object._block._dataSourceLink.getField(0,object.field)
- if value=='':
- if hasattr(object, 'style') and object.style=='checkbox':
- value = 0
- object._value = value
-
- def initLabels(self, object):
- if object.getObjectType() == 'GFLabel':
- object.initialize()
-
- def initDataSources(self, object):
- if object.getObjectType() =='GFDataSource':
- self._datasourceDictionary[object.name]=object
-
- # Should we load a connection definition?
- # This is a temporary hack :(
- if hasattr(object,'database') and not \
- self._databaseDictionary.has_key(object.database) and \
- self._connections.hasConnectionParameters(object.database):
- conn = self._connections.getConnectionParameters(object.database)
- self._databaseDictionary[object.database] = GFDatabase()
- self._databaseDictionary[object.database].name = object.database
- for attr in conn.keys():
- self._databaseDictionary[object.database].__dict__[attr] = conn[attr]
-
-
- def initDatabaseObjects(self, object):
- if object.getObjectType() =='GFDatabase':
- self._databaseDictionary[object.name]=object
-
- def initTriggers(self, object):
- if object.getObjectType() == "GFTrigger":
- object._triggerns.update( self._triggerns )
- object.initialize()
- if object.src != None:
- object.setFunctionFrom(self._triggerDictionary[object.src])
#
# end of routines made for walking
#
- def getDatabaseList(self):
- return self._databaseDictionary
def updateUIEntry(self,entry):
@@ -349,30 +295,41 @@
entry.setValue(entry.queryDefault)
self._currentBlock.initQuery()
return message
-
def executeQuery(self):
+ self._app.dispatchEvent(GFEvent('beginWAIT',None));
+
message = None
try:
self._currentBlock.processQuery()
-# self.processTrigger('Post-Query')
except DBError:
- for key in self._databaseDictionary.keys():
- self._databaseDictionary[key].rollback()
+ self.processRollback()
message = "Database query error:\n%s\n%s " % (sys.exc_info()[0],
sys.exc_info()[1])
+ self._app.dispatchEvent(GFEvent('endWAIT',None));
+
def commit(self):
+ self._app.dispatchEvent(GFEvent('beginWAIT',None));
+
message = None
- for key in self._databaseDictionary.keys():
- self._databaseDictionary[key].beginTransaction()
+ # TODO: Disabling transactions for now to remove need for
_databaseDictionary
+ #
+ # TODO: Addendum by jcater: the new database drivers are assumed to be in
a
+ # TODO: transactional state if the underlying database supports
transactions.
+ # TODO: Therefore, beginTransaction is no longer necessary.
+ #
+ #for key in self._databaseDictionary.keys():
+ # self._databaseDictionary[key].beginTransaction()
+
try:
if not self.readonly:
try:
self.processTrigger('Pre-Commit')
except TriggerError:
GDebug.printMesg(1, "Trigger form Pre-Commit threw a TriggerError!")
+ self._app.dispatchEvent(GFEvent('endWAIT',None));
return "Form trigger returned error"
for block in self._blockList:
@@ -382,6 +339,7 @@
block.processCommit()
except TriggerError:
GDebug.printMesg(1, "Trigger block Pre-Commit threw a
TriggerError!")
+ self._app.dispatchEvent(GFEvent('endWAIT',None));
return "Block trigger returned error"
block.processTrigger('Post-Commit')
@@ -390,15 +348,16 @@
else:
message = 'Form is readonly'
+ self._app.dispatchEvent(GFEvent('endWAIT',None));
return message
self.processTrigger('Post-Commit')
- for key in self._databaseDictionary.keys():
- self._databaseDictionary[key].commit()
+ # TODO: Disabling transactions for now to remove need for
_databaseDictionary
+ # for key in self._databaseDictionary.keys():
+ # self._databaseDictionary[key].commit()
except DBError:
- for key in self._databaseDictionary.keys():
- self._databaseDictionary[key].rollback()
+ self.processRollback()
message = "Database commit error:\n%s\n%s " % (sys.exc_info()[0],
sys.exc_info()[1])
except:
print "\n\nGFForm: Unexpected Exception:"
@@ -406,6 +365,8 @@
traceback.print_exc(file=sys.stdout)
print '-'*60
+ self._app.dispatchEvent(GFEvent('endWAIT',None));
+
return message
def executeAbout(self,event):
@@ -420,21 +381,8 @@
def rollback(self):
for block in self._blockList:
block.processRollback();
- self._currentBlock.nextRecord()
- self._currentBlock.prevRecord()
+ self._currentBlock.jumpRecord(self._currentBlock._currentRecord)
- #
- # updateDetailBlocks
- #
- # This should be redone so that master blocks have detailBlocks register w/
them
- # then the blocks updateDetail() could be simpler as only blocks that need
the
- # update get it
- def updateDetailBlocks(self, originatingBlock):
- if originatingBlock.mode == 'normal':
- for block in self._blockList:
- block.updateDetail(originatingBlock)
-
- # Need to force UI update here for other blocks
# i question if this fuction is needed as one could just use t.msg
# however i gave it a return and converted print to debugas some of the
@@ -510,7 +458,6 @@
if (self._currentEntry != None):
currentvalue = self._currentEntry.getValue()
-
if ord(value) == 13:
if self._currentEntry.height > 1: value = '\n';
else: return modified
@@ -548,9 +495,6 @@
self._currentEntry.processTrigger('pre-change')
self._currentEntry.setValue(currentvalue)
self._currentEntry.processTrigger('post-change')
- # Hack alert
- self.updateDetailBlocks(self._currentBlock)
- # end hack alert
modified = 1
@@ -578,9 +522,6 @@
self._currentEntry.setValue(currentvalue)
self._currentEntry.processTrigger('post-change')
modified = 1
- # hack alert
- self.updateDetailBlocks(self._currentBlock)
- # end hack alert
return modified
@@ -588,6 +529,7 @@
# fireTrigger
#
def fireTrigger(self, triggerName):
+ print self._triggerDictionary.keys()
self._triggerDictionary[triggerName](self)
#
@@ -603,7 +545,9 @@
def nextEntry(self):
nextEntry = None
keepNext = 0
- if not self._currentEntry.verifyValue(): return
+ if not self._currentEntry.verifyValue():
+ return "Invalid field value"
+
for object in self._currentEntry._parent._children:
# Put the first field as the next to rollover
if (object.getObjectType()=='GFEntry' and
@@ -707,7 +651,7 @@
# reset current entry
self._currentEntry = None
- self._currentBlock.walk(self.setInitialFocus)
+ self._currentBlock.walk(self.setFocus)
# set current page
pageWidget = self._currentBlock
@@ -740,7 +684,7 @@
# reset current entry
self._currentEntry = None
- self._currentBlock.walk(self.setInitialFocus)
+ self._currentBlock.walk(self.setFocus)
# set current page
pageWidget = self._currentBlock
@@ -748,7 +692,6 @@
pageWidget = pageWidget._parent
self._currentPage = pageWidget
-
def gotoPage(self, index):
for object in self._blockList:
pageWidget = object
@@ -762,46 +705,29 @@
# reset current entry
self._currentEntry = None
- self._currentBlock.walk(self.setInitialFocus)
+ self._currentBlock.walk(self.setFocus)
def prevRecord(self):
- 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
- #message = GFMsgBox(self, GConfig.get('_msgNOTSAVED'))
- #message.show()
- #return
+ if self._currentBlock.mode == 'query':
+ GDebug.printMesg(5,'Cannot go to previous record: in query mode!')
+ return
self._currentBlock.prevRecord()
def nextRecord(self):
- 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
+ if self._currentBlock.mode == 'query':
+ GDebug.printMesg(5,'Cannot go to next record: in query mode!')
+ return
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
+ if self._currentBlock.mode == 'query':
+ GDebug.printMesg(5,'Cannot jump to record: in query mode!')
+ return
self._currentBlock.jumpRecord(count)
-
def toggleInsertMode(self):
self._insertMode = not self._insertMode
-
def dumpXML(self, treeDump=None, gap=" "):
- return GObj.dumpXML(self, GFParser.xmlFormsHandler().xmlElements,
treeDump, gap)
+ return GObj.dumpXML(self, GFParser.getXMLelements(), treeDump, gap)
Index: gnue/gnuef/src/GFInstance.py
diff -u gnue/gnuef/src/GFInstance.py:1.20 gnue/gnuef/src/GFInstance.py:1.21
--- gnue/gnuef/src/GFInstance.py:1.20 Thu Aug 2 21:57:35 2001
+++ gnue/gnuef/src/GFInstance.py Sun Aug 12 12:55:27 2001
@@ -34,7 +34,7 @@
#
# Copyright (c) 2000 Free Software Foundation
#
-# $Id: GFInstance.py,v 1.20 2001/08/03 04:57:35 jamest Exp $
+# $Id: GFInstance.py,v 1.21 2001/08/12 19:55:27 jamest Exp $
#
import pstats
@@ -44,8 +44,6 @@
import urllib
import gnue.common.GConfig
from gnue.forms.GFForm import *
-from gnue.forms.GFGetOpt import *
-from gnue.forms.GFController import *
from gnue.forms.GFParser import loadForm
from gnue.forms import VERSION
from gnue.common import GDebug, GDataObjects
@@ -53,18 +51,19 @@
from gnue.common.GClientApp import *
-class GFInstance(GFController):
+class GFInstance(GFEventAware):
#
# Initialize the class
#
def __init__(self, manager, serial, connections, ui, disableSplash):
- GFController.__init__(self)
+ GFEventAware.__init__(self)
self.connections = connections
self.manager = manager
self._serial = serial
- self._uiclass = ui
+ self._uiclass = ui.GFUserInterface
self._disableSplash = disableSplash
+ self._uiinstance = self._uiclass(self._disableSplash)
# Incomming events
self.incommingEvent = {'requestNEXTENTRY' : self.nextEntry,
'requestPREVENTRY' : self.previousEntry,
@@ -101,10 +100,6 @@
'requestTOGGLECHKBOX' : self.toggleCheckBox,
}
- # Init database list
- self._databaseDictionary = {}
-
-
#
# Associate a form object with this instance
#
@@ -355,7 +350,7 @@
self.dispatchEvent(GFEvent('uiUPDATESTATUS',[None,None,self._form._insertMode,None,None,None,None]))
def updateRecordCounter(self):
-
self.dispatchEvent(GFEvent('uiUPDATESTATUS',[None,None,None,self._form._currentBlock._currentRecord+1,self._form._currentBlock._recordCount+1,None,None]))
+
self.dispatchEvent(GFEvent('uiUPDATESTATUS',[None,None,None,self._form._currentBlock._currentRecord+1,self._form._currentBlock._recordCount,None,None]))
def updatePageCounter(self):
maxPages = len(self._form._pageList)
@@ -378,8 +373,13 @@
def updateRecordStatus(self):
if self._form._currentBlock.mode == 'query':
status = 'query'
- else:
- status =
self._form._currentBlock._dataSourceLink.resultSetStatus[self._form._currentBlock._currentRecord]
+ elif self._form._currentBlock._resultSet.current.isDeleted():
+ status = 'deleted'
+ elif self._form._currentBlock._resultSet.current.isPending():
+ status = 'modified'
+ else:
+ status = 'saved'
+
self.dispatchEvent(GFEvent('uiUPDATESTATUS',[None,status,None,None,None,None,None]))
def updateStatus(self):
@@ -499,82 +499,21 @@
value = event.data[1]
object.setValue(value)
-
-#
-# old stuff still in use
-#
-
-
#
# Activate this puppy...
#
def activate(self):
- ui = self._uiclass(self._disableSplash)
+ ui = self._uiinstance
ui.registerEventListener(self.processEvent)
self.registerEventListener(ui.processEvent)
- #
- # extract DB info and init datasources
- #
- databaseList = self._form.getDatabaseList()
- for key in databaseList.keys():
- object = databaseList[key]
- attempts = 4
- while 1:
- try:
- #Login
- loginData = [key, object.comment,
- [["user", "Username", 0],
- ["passwd", "Password", 1]]]
-
- # Returned data is in format of [ Completed?, {dict of values} ]
- self.dispatchEvent( GFEvent('getLogin', loginData) )
- results = loginData[3] # Set by the login manager
- if not results[0]:
- print "\n\nUser cancelled login process. Exiting...\n"
- sys.exit()
-
- user = results[1]['user']
- passwd = results[1]['passwd']
-
- object.initialize(user,passwd)
-
- except GDataObjects.ConnectionError:
- attempts = attempts - 1
- if not attempts:
- print "\n\nToo many unsuccessful login attempts. Exiting...\n"
- sys.exit()
- message = GFMsgBox(self,"\nInvalid Login.\nPlease Try Again. ")
#\n\nActual Error: \n%s" % sys.exc_info()[1])
- message.show()
- except DBError:
- attempts = attempts - 1
- if not attempts:
- print "\n\nToo many unsuccessful login attempts. Exiting...\n"
- sys.exit()
- message = GFMsgBox(self,"Database initialization error:\n%s\n%s " %
(sys.exc_info()[0], sys.exc_info()[1]))
- message.show()
- except TypeError:
- # For some bizarre reason, the Oracle driver
- # returns a TypeError for an invalid login????
- attempts = attempts - 1
- if not attempts:
- print "\n\nToo many unsuccessful login attempts. Exiting...\n"
- sys.exit()
- print "Invalid Login"
- except:
- # All other errors: make tty sane and re-raise error
- if sys.platform != 'win32':
- os.system("stty sane")
- raise
- else:
- break
-
- self._form.postLoginInitialization()
-
- # pass control to UI
ui.buildForm(self._form)
ui.activateForm(self._form)
+
+
self.dispatchEvent(GFEvent('gotoENTRY',{'object':self._form._currentEntry}))
self.updateStatus()
self._ui = ui
+
+ # pass control to UI
ui.mainLoop()
Index: gnue/gnuef/src/GFObjects/GFBlock.py
diff -u gnue/gnuef/src/GFObjects/GFBlock.py:1.8
gnue/gnuef/src/GFObjects/GFBlock.py:1.9
--- gnue/gnuef/src/GFObjects/GFBlock.py:1.8 Tue Aug 7 20:17:00 2001
+++ gnue/gnuef/src/GFObjects/GFBlock.py Sun Aug 12 12:55:27 2001
@@ -16,7 +16,7 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000. 2001 Free Software Foundation
+# Copyright 2000, 2001 Free Software Foundation
#
#
# FILE:
@@ -28,15 +28,13 @@
# NOTES:
#
# HISTORY:
-# Copyright (c) 2000 Free Software Foundation
#
-#from gnue.common.GObjects import *
from gnue.forms.GFEvent import *
from gnue.forms.GFObjects.GFDataSource import GFDataSource
from gnue.common import GDebug
-from gnue.common import GConfig
+from gnue.common import GConfig, GConditions
from GFObj import GFObj
import string
@@ -55,25 +53,40 @@
GFObj.__init__(self, parent)
GFEventAware.__init__(self)
self._type = "GFBlock"
- self.buildObject()
-
+
+ # TODO: For some reason, self.initialize is already getting called.
+ # TODO: If we rename to something else and list here, something else
+ # TODO: breaks. If we list it here as self.initialize, then entryList
+ # TODO: is doubly populated, causing lots o' problems.
+ self._inits = []
+ #self._inits = [self.initialize]
+
+
+ self._datasource = None
+ self._resultSet = None
self._dataSourceLink = None
self.mode = 'normal'
self._entryList = []
self._currentRecord = 0
self._recordCount = 0
+ self._queryValues = {}
+ self._lastQueryValues = {}
def initialize(self):
self._form = self.findParentOfType('GFForm')
self.walk(self.buildEntryList)
- if hasattr(self,'datasource'):
- self._dataSourceLink = self._form._datasourceDictionary[self.datasource]
- else:
- self._dataSourceLink = GFDataSource(self)
- self._dataSourceLink.initialize()
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
+ if not hasattr(self,'datasource') or not self.datasource:
+ ds = GFDataSource(self)
+ self.datasource = ds.name = "dts_%s" % self
+ self._form._datasourceDictionary[ds.name] = ds
+ ds.buildObject()
+ ds.initialize()
+
+ self._dataSourceLink = self._form._datasourceDictionary[self.datasource]
+ self._dataSourceLink.registerResultSetListener(self._loadResultSet)
+
def buildEntryList(self, object):
if object.getObjectType() == 'GFEntry':
@@ -86,7 +99,7 @@
# with is saved
#
def isSaved(self):
- return self._dataSourceLink.isSaved()
+ return self._resultSet == None or not self._resultSet.isPending()
#
# deleteRecord
@@ -95,75 +108,74 @@
# deletion during next commit
#
def deleteRecord(self):
- self._dataSourceLink.markForRemoval(self._currentRecord)
+ self._resultSet.current.delete()
- #
- # newRecord
- #
- # Adds a record to the current records in memory
+ #
+ # Load and process a resultset
#
- def newRecord(self):
- self._dataSourceLink.new()
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
+ def _loadResultSet(self, resultSet):
+ self._resultSet = resultSet
+ self._currentRecord = -1
+ self._recordCount = 0
- if hasattr(self,"master"):
- masterBlock,masterField = string.split(self.master,'.')
- fieldValue = str(self._form.findValue(masterBlock, masterField))
- if len(fieldValue) > 0:
-
self._dataSourceLink.setField(self._recordCount,self.detail,fieldValue,TRUE)
-
- self._currentRecord = self._recordCount
- adjustment = self._recordCount - self._currentRecord
- self.switchRecord(adjustment)
- self.processTrigger('on-newrecord')
-
+ if self._resultSet.firstRecord():
+ self.switchRecord(0)
+ self._recordCount = self._resultSet.getCacheCount()
+ else:
+ # TODO: This means no results were returned from a query.
+ # TODO: It probably shouldn't create a new record :) Display a message?
+ print "WARNING: GFBlock.py self.newRecord - ", self.newRecord()
+
#
# Moves the proper record into editing position
#
def switchRecord(self, adjustment):
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
+ self._currentRecord = self._resultSet.getRecordNumber()
+ print "Current record is %s" % self._currentRecord
for entry in self._entryList:
- entry.switchRecord(self._currentRecord)
+ entry.switchRecord()
entry.recalculateVisible( adjustment, self._currentRecord,
self._recordCount)
self._form.updateUIEntry(entry)
-#qwik hack ask jamest how to handle long term for adj 0
+ # TODO: qwik hack ask jamest how to handle long term for adj 0
if adjustment <> 0:
self.processTrigger('on-switch')
- self._form.updateDetailBlocks(self)
+ #
+ # newRecord
+ #
+ # Adds a record to the current records in memory
+ #
+ def newRecord(self):
+ if self._resultSet.insertRecord():
+ self._recordCount = self._resultSet.getCacheCount()
+ self.switchRecord(1)
+ self.processTrigger('on-newrecord')
+
def nextRecord(self):
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
- self._currentRecord = self._currentRecord + 1
- if self._currentRecord > self._recordCount :
- if int(GConfig.get('autocreate')) and
(self._dataSourceLink.resultSetStatus[self._recordCount] != 'saved' or
- (hasattr(self._dataSourceLink,'uniqueKey') and
self._dataSourceLink.resultSet[self._recordCount].has_key(self._dataSourceLink.uniqueKey))
- ):
- self.newRecord()
- else:
- self._currentRecord = 0
- self.switchRecord(1)
+ if self._resultSet.nextRecord():
+ self._recordCount = self._resultSet.getCacheCount()
+ self.switchRecord(1)
+ #TODO: pending system is broken?
+ elif int(GConfig.get('autocreate')) and not
self._resultSet.current.isEmpty():
+ self.newRecord()
+
+# TODO: This statement only allowed new entries
+# if int(GConfig.get('autocreate')) and
(self._dataSourceLink.resultSetStatus[self._recordCount] != 'saved' or
+# (hasattr(self._dataSourceLink,'uniqueKey') and
self._dataSourceLink.resultSet[self._recordCount].has_key(self._dataSourceLink.uniqueKey))
):
+
def prevRecord(self):
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
- self._currentRecord = self._currentRecord - 1
- if self._currentRecord < 0 :
- if int(GConfig.get('autocreate')) and
(self._dataSourceLink.resultSetStatus[self._recordCount] != 'saved' or
- (hasattr(self._dataSourceLink,'uniqueKey') and
self._dataSourceLink.resultSet[self._recordCount].has_key(self._dataSourceLink.uniqueKey))
- ):
- self.newRecord()
- else:
- self._currentRecord = self._recordCount
- self.switchRecord(-1)
+ if self._resultSet.prevRecord():
+ self.switchRecord(-1)
def jumpRecord(self, recordNumber):
- if recordNumber > self._recordCount:
- recordNumber = self._recordCount
- jump = recordNumber - self._currentRecord
- self._currentRecord = recordNumber
+ if not self._resultSet.setRecord(recordNumber):
+ self._resultSet.lastRecord()
+ jump = self._resultSet.getRecordNumber() - self._currentRecord
+ self._currentRecord = self._resultSet.getRecordNumber()
self.switchRecord(jump)
-
-
+
#
# processCommit
#
@@ -171,21 +183,21 @@
GDebug.printMesg(1, "processing commit on block %s"%self.name)
self.mode='commit'
- # if this is a detail and the key isn't filled from master block then fill
it
- if hasattr(self,"master"):
- masterBlock,masterField = string.split(self.master,'.')
- fieldValue = self._form.findValue(masterBlock, masterField)
-
- GDebug.printMesg(2, "Master field value is :%s:"%fieldValue)
- if len(fieldValue) > 0:
- for count in range(self._recordCount+1):
- self._dataSourceLink.setField(count,self.detail,fieldValue, TRUE)
-
- #self._currentRecord = 0
- self._dataSourceLink.commit()
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
+ if not self._dataSourceLink.hasMaster():
+ self._resultSet.post()
+ self._dataSourceLink._dataObject.commit()
+
+ # TODO: What should happen after a commit?
+ # TODO: If we stay at the current record,
+ # TODO: how do we know the "current record"
+ # TODO: or one of the earlier records wasn't
+ # TODO: deleted. Or worse yet, what if our
+ # TODO: "current" record is higher than the
+ # TODO: actual number of records left in cache?
+ if self._currentRecord >= self._resultSet.getCacheCount():
+ self.switchRecord(-self._currentRecord)
+
self.mode='normal'
- #self.switchRecord(0)
#
# processRollback
@@ -193,17 +205,31 @@
def processRollback(self):
self._currentRecord = 0
self._recordCount = 0
- self._dataSourceLink.clear()
+ self._dataSourceLink.createEmptyResultSet()
self.switchRecord(0)
#
# initQuery and processQuery
#
def initQuery(self):
+
+ # If Enter-Query is hit once, enter query mode
+ # If Enter-Query is hit twice, bring back conditions from last query.
+ # If Enter-Query is hit thrice, cancel the query and go into normal mode.
+
if self.mode != 'query':
self.mode = 'query'
- else:
+ self._query2 = int(GConfig.get("RememberLastQuery","1"))
+ self._queryValues = {}
+ elif self._query2:
+ self._query2 = 0
+ self._queryValues = {}
+ for key in self._lastQueryValues.keys():
+ self._queryValues[key] = self._lastQueryValues[key]
+ self.switchRecord(0)
+ else:
self.mode = 'normal'
+ self.switchRecord(0)
# Removed to allow the GFForm object to deside when to clear the block
# self.processRollback()
@@ -222,36 +248,39 @@
self.mode = 'normal'
- self._dataSourceLink.query()
- self.processTrigger('Post-Query')
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
-
- self._currentRecord = 0
- self.switchRecord(0)
+ self._lastQueryValues = {}
+ for key in self._queryValues.keys():
+ self._lastQueryValues[key] = self._queryValues[key]
+
+ conditionLike = {}
+ conditionEq = {}
+
+ # Get all the user-supplied parameters from the entry widgets
+ for entry in self._queryValues.keys():
+ if entry._bound and entry.isQueryable():
+ if entry.typecast == 'text':
+ conditionLike[entry.field] = self._queryValues[entry]
+ else:
+ conditionEq[entry.field] = self._queryValues[entry]
+
+ if len(conditionLike.keys()) and len(conditionEq.keys()):
+ conditions = GConditions.combineConditions( \
+ GConditions.buildConditionFromDict(conditionLike,
GConditions.GClike), \
+ GConditions.buildConditionFromDict(conditionEq, GConditions.GCeq) )
+
+ elif len(conditionLike.keys()):
+ conditions = GConditions.buildConditionFromDict(conditionLike,
GConditions.GClike)
- #
- # updateDetail - makes block check to see if it needs to update itself
- # if so it forces the update automagically
- #
- def updateDetail(self,originatingBlock):
- # Block can't be master of itself
- if self != originatingBlock and hasattr(self,'master'):
- masterBlock,masterField = string.split(self.master,'.')
- if masterBlock == originatingBlock.name:
- fieldValue = str(self._form.findValue(masterBlock, masterField))
-
- ## clear the link
- self._dataSourceLink.clear()
- self._recordCount = 0
- self._currentRecord = 0
-
- if len(fieldValue) > 0:
- self._dataSourceLink.setField(0,self.detail,fieldValue,TRUE)
- self._dataSourceLink.query()
- self._recordCount = self._dataSourceLink.getLastRecordNumber()
-
- self.switchRecord(0)
+ elif len(conditionEq.keys()):
+ conditions = GConditions.buildConditionFromDict(conditionEq,
GConditions.GCeq)
+
+ else:
+ conditions = {}
+ self._dataSourceLink.createResultSet(conditions)
+ self._recordCount = self._resultSet.getCacheCount()
+
+ self.processTrigger('Post-Query')
Index: gnue/gnuef/src/GFObjects/GFDataSource.py
diff -u gnue/gnuef/src/GFObjects/GFDataSource.py:1.4
gnue/gnuef/src/GFObjects/GFDataSource.py:1.5
--- gnue/gnuef/src/GFObjects/GFDataSource.py:1.4 Tue Jul 17 06:43:09 2001
+++ gnue/gnuef/src/GFObjects/GFDataSource.py Sun Aug 12 12:55:27 2001
@@ -16,7 +16,7 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000. 2001 Free Software Foundation
+# Copyright 2000, 2001 Free Software Foundation
#
#
# FILE:
@@ -28,294 +28,73 @@
# NOTES:
#
# HISTORY:
-# Copyright (c) 2000 Free Software Foundation
#
from gnue.common.GObjects import *
from gnue.common.dbdrivers.factory import factory
from gnue.common import GDebug
-from gnue.common import GConfig
-from GFObj import GFObj
+from gnue.common.GDataSource import GDataSource
-import string
-import types
-
-
-# These should really go somewhere else
-TRUE = 1
-FALSE = 0
-
############################################################
# GFDataSource
#
-# In memory store of data manipulated by forms
-# sometimes attached to a database, sometimes not
-#
-class GFDataSource(GFObj):
- def __init__(self, parent=None):
- GFObj.__init__(self, parent)
- self._type = "GFDataSource"
-
- self._form = None
- self.dataConnection = None
- self.fieldList = []
-
- self.emptyRecord = {}
- self.resultSet = []
- self.resultSetStatus = []
- self.prequery = None
-
- self.sql = None
-
-
- def initialize(self):
- self._form = self.findParentOfType('GFForm')
-
- #self.emptyRecord = {}
-
- if hasattr(self,'database'):
- GDebug.printMesg(1, " linking to database %s" % (self.database))
-
- self.dataConnection = self._form._databaseDictionary[self.database]
- self.fieldList = self.dataConnection.getFieldList(self.table).keys()
- self.uniqueKey = self.dataConnection.getUniqueKey(self.table)
-
- # Build an empty record for new records and query mask seed
- for field in self.fieldList:
- self.emptyRecord[string.lower(field)] = ""
-
- self.clear()
-
- if self.prequery:
- self.query()
-
- #
- # new
- #
- # create a new, empty record
- #
- def new(self):
- newentry = {}
- for key in self.emptyRecord.keys():
- newentry[key] = self.emptyRecord[key]
- self.resultSet.append(newentry)
- self.resultSetStatus.append('saved')
-
- #
- # clear
- #
- # remove all records from memory except for an initial
- # empty record
- #
- def clear(self):
- self.resultSet = []
- self.resultSetStatus = []
-
- # Copy initial empty record into the resultSet
- newentry = {}
- for key in self.emptyRecord.keys():
- newentry[key] = self.emptyRecord[key]
-
- self.resultSet.append(newentry)
- self.resultSetStatus.append('saved')
-
- def getLastRecordNumber(self):
- return len(self.resultSet)-1
-
- #
- # isSaved
- #
- # returns a positive value if all records in the datasource are saved
- #
- def isSaved(self):
- value = 1
- for count in range(len(self.resultSetStatus)):
- if self.resultSetStatus[count] != 'saved':
- value = 0
- break
- return value
-
- #
- # query
- #
- # Takes the first record in the datasource and uses it as a query mask
- # against the database backend
- #
- def query(self):
- GDebug.printMesg(2, "Query with this in resultSet\n%s"%self.resultSet[0])
- if hasattr(self,'database'):
- if self.sql == None:
- mask = {}
- for key in self.fieldList:
- if key in self.dataConnection.getFieldList(self.table).keys():
- mask[key]=self.resultSet[0][key]
-
- self.clear()
- if not hasattr(self,'order_by'):
- self.order_by = None
-
- self.resultSet = self.dataConnection.query(self.table, len(mask) and
mask or None, self.order_by)
-
- if self.resultSet:
- # Set each record's status
- for count in range(len(self.resultSet)):
- self.resultSetStatus.append('saved')
-
- # Check first record to see if field present - if not then add one to
all records
- for fieldName in self.emptyRecord.keys():
- if not self.resultSet[0].has_key(string.lower(fieldName)):
- for result in self.resultSet:
- result [fieldName] = ""
-
-
- # Reset the internal type to string so things like len() work properly
- for count in range(len(self.resultSet)):
- for key in self.resultSet[count].keys():
- if self.resultSet[count][key] != None:
- self.resultSet[count][key] = str(self.resultSet[count][key])
+class GFDataSource (GDataSource):
+ def __init__(self, parent):
+ GDataSource.__init__(self, parent, 'GFDataSource')
+# self._form = None
+ self._inits =[self.primaryInit]
+ self._currentResultSet = None
+ self._resultSetListeners = []
+
+ # Called by dbdrivers whenever this datasource's master has changed
+ def masterResultSetChanged(self, masterResultSet, detailResultSet):
+ self._masterResultSet = masterResultSet
+ self.__setResultSet( detailResultSet )
+ def primaryInit(self):
+ self._form = self.findParentOfType('GFForm')
+ GDebug.printMesg(10,"Setting %s to connect mgr %s"
%(self.name,self._form._connections))
+ self.setConnectionManager(self._form._connections)
+ self.initialize()
+ self.connect()
+ self._form._triggerns[self.name] = self._dataObject.triggerExtensions
+
+ if hasattr(self, 'master') and self.master:
+ GDebug.printMesg(3,"Linking detail '%s' to master '%s'" \
+ % (self.name, self.master) )
+
+ if self._form._datasourceDictionary.has_key(self.master):
+ self._form._datasourceDictionary[self.master] \
+ .getDataObject().addDetailDataObject(self.getDataObject(),
+ self)
else:
- self.clear()
-
- #
- # commit
- #
- # goes thru all records in the datasource and if they are new, have been
altered, or marked
- # for delete then it calls the appropriate GFDatabase methods to accomplish
inserts,updates,or deletes
- #
- def commit(self):
- if hasattr(self,'database'):
- for count in range(len(self.resultSet)):
- 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)
-
- if self.resultSet[count].has_key(self.uniqueKey):
- if self.resultSetStatus[count] == 'modified':
- GDebug.printMesg(1, "updating the record")
- self.dataConnection.update(self.table,mask)
- else:
- GDebug.printMesg(1,"deleting the record")
- self.dataConnection.delete(self.table,mask)
-
- else:
- GDebug.printMesg(1, "Inserting the record")
- result = self.dataConnection.insert(self.table,mask)
-
- for newkey in result.keys():
- self.resultSet[count][newkey] = result[newkey]
-
- # Clean up record list
- count = 0
- #self.resultSetStatus = []
- while (count < len(self.resultSet)):
- if self.resultSet[count].has_key(self.uniqueKey) and
self.resultSetStatus[count]=='deleted':
- del self.resultSet[count]
- del self.resultSetStatus[count]
- else:
- self.resultSetStatus[count] = 'saved'
-
- count = count + 1
-# self.resultSetStatus.append('saved')
-
- if len(self.resultSet) == 0:
- self.clear()
-
- # Reset the internal type to string so things like len() work properly
- for count in range(len(self.resultSet)):
- for key in self.resultSet[count].keys():
- if self.resultSet[count][key] != None:
- self.resultSet[count][key] = str(self.resultSet[count][key])
-
- #
- # markForRemoval
- #
- # Flips a specifics record number's unique key value from back and forth
- # from positive to negative. A negative unique key means that the record
- # is marked for deletion on next commit
- #
- def markForRemoval(self,recordNumber):
- if self.resultSetStatus[recordNumber] == 'deleted':
- self.resultSetStatus[recordNumber] = 'modified'
- else:
- self.resultSetStatus[recordNumber] = 'deleted'
-
- #if not self.resultSet[recordNumber].has_key(self.uniqueKey):
- # self.resultSet[recordNumber][self.uniqueKey] = 'delete'
- #else:
- # if self.resultSet[recordNumber][self.uniqueKey] == 'delete':
- # del self.resultSet[recordNumber][self.uniqueKey]
- # else:
- # self.resultSet[recordNumber][self.uniqueKey] = \
- # int(self.resultSet[recordNumber][self.uniqueKey]) * -1
-
- #self.resultSetStatus[recordNumber] = 'deleted'
- #GDebug.printMesg(1, "removing object: %s" %
(self.resultSet[recordNumber][self.uniqueKey]))
-
- def getField(self,recordNumber,fieldName):
- try:
- return self.resultSet[recordNumber][string.lower(fieldName)] or ''
- except:
- return ''
-
- #
- # setField
- #
- # The internal call argument allows other objects to
- # adjust field values w/o altering the entries state.
- # mainly usefull to set default values or master/detail
- # values
- #
- def setField(self,recordNumber,fieldName,value,internalCall=FALSE):
- if len(self.resultSet) > recordNumber:
-
- #CheckBox does not work if uncomment these (ra3vat)
- #if len(value) == 0:
- # value = None
-
-
- # Believed fixed but leaving comment in for now just in case - jamest
- # Hack warning - the value != None is catching an error in the code
- # where none is being stored for some reason in widgets. Need to fix in
proper
- # place. Without this hack the rollback doesn't work properly and the
current
- # block is never in a state of Saved after a rollback
- #if self.resultSet[recordNumber][fieldName] != value and value != None:
-
- # Commenting out for now - not sure why we're doing this
- #if fieldName in self.dataConnection.getFieldList(self.table).keys() or \
- # fieldName == self.uniqueKey:
- if self.resultSet[recordNumber][string.lower(fieldName)] != value:
- self.resultSet[recordNumber][string.lower(fieldName)] = value
- if not internalCall:
- self.resultSetStatus[recordNumber] = 'modified'
- #
- # Eventually we need to lock that record in the datasource here
- #
-
- #
- # addField
- #
- # Adds a named field to a datasource
- #
- def addField(self,fieldName):
- if not fieldName in self.fieldList:
- for count in range(len(self.resultSet)):
- self.resultSet[count][string.lower(fieldName)] = ""
- self.emptyRecord[string.lower(fieldName)]=""
- self.fieldList.append(fieldName)
-
-
-
-
-
+ raise StandardError, \
+ "Detail source '%s' references non-existant master '%s'" \
+ % (self.name, self.master)
+
+
+ print "GFDataSource.py - dataobject name ",self.getDataObject().name
+
+ def createResultSet(self, conditions={}):
+ resultSet = GDataSource.createResultSet(self, conditions=conditions)
+ self.__setResultSet( resultSet )
+ return resultSet
+
+ def createEmptyResultSet(self):
+ resultSet = GDataSource.createEmptyResultSet(self)
+ self.__setResultSet( resultSet )
+ return resultSet
+
+ def __setResultSet(self, resultSet):
+ self._currentResultSet = resultSet
+ # Notify all the listeners (i.e., blocks) that the result set changed
+ for listener in self._resultSetListeners:
+ listener(resultSet)
+
+ def registerResultSetListener(self, listener):
+ self._resultSetListeners.append(listener)
Index: gnue/gnuef/src/GFObjects/GFEntry.py
diff -u gnue/gnuef/src/GFObjects/GFEntry.py:1.7
gnue/gnuef/src/GFObjects/GFEntry.py:1.8
--- gnue/gnuef/src/GFObjects/GFEntry.py:1.7 Tue Jul 31 16:22:30 2001
+++ gnue/gnuef/src/GFObjects/GFEntry.py Sun Aug 12 12:55:27 2001
@@ -16,7 +16,7 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000. 2001 Free Software Foundation
+# Copyright 2000, 2001 Free Software Foundation
#
#
# FILE:
@@ -49,17 +49,17 @@
self._type = "GFEntry"
self.height = float(GConfig.get('widgetHeight'))
self.width = float(GConfig.get('widgetWidth'))
- self._value=""
+ self._oldval=""
self._uppercase = 0
self._lowercase = 0
self._numeric = 0
- self._rows = 1
+ self._queryable = 1
self.typecast="text"
self.case="mixed"
+ self._inits = [self.initialize, self.loadStartingValues]
def buildObject(self):
-
# Convert deprecated attributes
if hasattr(self,'numeric') and self.numeric:
del self.numeric
@@ -72,14 +72,7 @@
del self.lowercase
self.case = 'lower'
- if not hasattr(self, 'rows') and hasattr(self,'visibleCount'):
- self.rows = self.visibleCount
- del self.visibleCount
-
-
-
def initialize(self):
-
if self.typecast == 'number':
self._numeric = 1
if self.case == 'upper':
@@ -87,60 +80,90 @@
elif self.case == 'lower':
self._lowercase = 1
- self._cursorPosition = len(self._value)
+ self._cursorPosition = len(self._oldval)
self._block = self.findParentOfType('GFBlock')
if not hasattr(self,'field'):
GDebug.printMesg(1,"%s" % self.getObjectType())
GDebug.printMesg(1,"%s" % self.__dict__)
- self.field = self.name
+ self.field = "__GNUe__%s" % self.name
+ self._block._dataSourceLink.referenceUnboundField(self.field)
+ self._bound = 0
+ else:
+ self._block._dataSourceLink.referenceField(self.field)
+ self._bound = 1
- self._block._dataSourceLink.addField(self.field)
if hasattr(self,'foreign_key'):
datasourceName,self.fieldName = string.split(self.foreign_key,'.')
self.datasource = self._block._form._datasourceDictionary[datasourceName]
- if not hasattr(self,'rows'):
- if hasattr(self._block,'rows'):
- self._rows = self._block.rows
+ if not hasattr(self,'rows') and hasattr(self._block,'rows'):
+ self.rows = self._block.rows
else:
- self._rows = self.rows
+ self.rows = 1
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':
- self._value = 0
+ def isQueryable(self):
+ if self._queryable and len(self._oldval):
+ return 1
+
+ #
+ # Once the phase 1 init is complete for the tree
+ # then attempt to load the proper values
+ #
+ def loadStartingValues(self):
+ pass
+# value = self.getValue()
+# if value=='' and hasattr(self, 'style') and self.style=='checkbox':
+# value = 0
+# self.setValue(value)
+
+
+ #
+ # Pulls the proper value from the resultSet
+ #
def getValue(self):
+ if self._block.mode == 'query':
+ if self._block._queryValues.has_key(self):
+ value = self._block._queryValues[self]
+ else:
+ value = None
+ else:
+ value = self._block._resultSet.current.getField(self.field)
+
+ if value == None: value = ''
+
#CheckBox does not work if comment following "if" block (ra3vat)
- if self._value=='':
- if hasattr(self, 'style') and self.style=='checkbox':
- self._value = 0
- GDebug.printMesg(10, "Value = %s"% self._value)
- return self._value
+ if value == '' and self.style == 'checkbox': value = 0
+
+ self._oldval = value
+ return value
def setValue(self, value):
- if value=='':
- if hasattr(self, 'style') and self.style=='checkbox':
- value = 0
- self._value = value
- self._block._dataSourceLink.setField(self._block._currentRecord,
- self.field,self._value)
+ if value =='' and hasattr(self, 'style') and self.style=='checkbox':
+ value = 0
+ self._oldval = value
+ if self._block.mode == 'query':
+ self._block._queryValues[self] = value
+ else:
+ self._block._resultSet.current.setField(self.field,value)
self._block._form.updateUIEntry(self)
#
# switchRecord
#
- def switchRecord(self, newRecord):
- GDebug.printMesg(2, "Switching to record %s" % (newRecord))
- self._value = self._block._dataSourceLink.getField(newRecord,self.field)
- self._cursorPosition = len(self._value)
+ def switchRecord(self):
+ value = self._block._resultSet.current.getField(self.field)
+ if value == None:
+ value = ''
+ else:
+ value = "%s" % value
+ self._cursorPosition = len(value)
#
# verifyValue
@@ -149,15 +172,15 @@
value = 1
# If empty skip test
- if len(self._value) != 0:
+ if len(self._oldval) != 0:
if hasattr(self,'foreign_key'):
value = 0
datasourceName,fieldName = string.split(self.foreign_key,'.')
datasource = self._block._form._datasourceDictionary[datasourceName]
- for count in range(datasource.getLastRecordNumber()+1):
- if datasource.getField(count,fieldName) == self._value:
+ for count in range(self._block._form._currentBlock._recordCount+1):
+ if datasource.getField(count,fieldName) == self._oldval:
value = 1
break
return value
@@ -168,28 +191,40 @@
def findClosestValue(self, value):
newvalue=None
if hasattr(self,'foreign_key'):
+
datasourceName,fieldName = string.split(self.foreign_key,'.')
- datasource = self._block._form._datasourceDictionary[datasourceName]
- for count in range(datasource.getLastRecordNumber()+1):
- if
string.lower(datasource.getField(count,self.foreign_key_description)[:len(value)])
== string.lower(value):
- newvalue = datasource.getField(count,fieldName)
- if newvalue == self._value: continue
+ rs =
self._block._form._datasourceDictionary[datasourceName]._currentResultSet
+
+ more = rs.firstRecord()
+ while more:
+ if
string.lower(rs.current.getField(self.foreign_key_description)[:len(value)]) ==
string.lower(value):
+ newvalue = rs.current.getField(fieldName)
+ if newvalue == self._oldval: continue
break
+ more = rs.nextRecord()
return newvalue
#
# allowedValues
#
def allowedValues(self):
- values = {}
- values[""]=""
- for count in range(self.datasource.getLastRecordNumber()+1):
- try:
- values[self.datasource.getField(count,self.fieldName)] = \
- self.datasource.getField(count,self.foreign_key_description)
- except AttributeError:
- values[self.datasource.getField(count,self.fieldName)] = None
- return values
+
+ if not hasattr(self.datasource,'_allowedValues'):
+ rs = self.datasource.createResultSet()
+ self.datasource._allowedValues = {"":""}
+
+ more = rs.firstRecord()
+
+ while more:
+ try:
+ self.datasource._allowedValues["%s" %
rs.current.getField(self.fieldName)] = "%s" % \
+ rs.current.getField(self.foreign_key_description)
+ except AttributeError:
+ self.datasource._allowedValues[rs.current.getField(self.fieldName)]
= None
+ more = rs.nextRecord()
+ GDebug.printMesg (5,'Created for DropDown: %s' %
self.datasource._allowedValues)
+
+ return self.datasource._allowedValues
Index: gnue/gnuef/src/GFObjects/GFLabel.py
diff -u gnue/gnuef/src/GFObjects/GFLabel.py:1.4
gnue/gnuef/src/GFObjects/GFLabel.py:1.5
--- gnue/gnuef/src/GFObjects/GFLabel.py:1.4 Tue Jul 31 16:22:30 2001
+++ gnue/gnuef/src/GFObjects/GFLabel.py Sun Aug 12 12:55:27 2001
@@ -41,6 +41,8 @@
def __init__(self, parent=None, value=None):
GFValue.__init__(self, parent, value)
self._type = "GFLabel"
+ self._inits = [self.initialize]
+
self.alignment = "left"
self.height = float(GConfig.get('widgetHeight'))
self._rows = 1
@@ -54,6 +56,9 @@
if not self._value:
GFValue.setValue(self,value)
+ #
+ # Routines called during a phaseInit
+ #
def initialize(self):
self._block = self.findParentOfType('GFBlock')
if not hasattr(self,'rows'):
Index: gnue/gnuef/src/GFObjects/GFObj.py
diff -u gnue/gnuef/src/GFObjects/GFObj.py:1.4
gnue/gnuef/src/GFObjects/GFObj.py:1.5
--- gnue/gnuef/src/GFObjects/GFObj.py:1.4 Tue Jul 31 16:22:30 2001
+++ gnue/gnuef/src/GFObjects/GFObj.py Sun Aug 12 12:55:27 2001
@@ -16,7 +16,7 @@
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
-# Copyright 2000. 2001 Free Software Foundation
+# Copyright 2000, 2001 Free Software Foundation
#
#
# FILE:
@@ -28,7 +28,6 @@
# NOTES:
#
# HISTORY:
-# Copyright (c) 2000 Free Software Foundation
#
from gnue.common.GObjects import GObj
@@ -48,6 +47,7 @@
self.readonly = 0
self._visibleIndex = 0
self.name = "__%s__" % self
+ self._inits = [self.initialize]
#
# get an Option
@@ -72,8 +72,8 @@
if index < 0 : index = 0
# Don't let index pass the number of widgets on screen
- if index >= int(self._rows):
- index = int(self._rows)-1
+ if index >= int(self.rows):
+ index = int(self.rows)-1
# Don't let the index past the number of records in the
# system
@@ -82,25 +82,25 @@
if lowestVisible + index > recordCount:
index = index -1
+
# If the current record has rolled around
# from the top to the bottom then reset
# the counter
if currentRecord == 0:
index = 0
+
# if the current record has rolled from
# bottom to top then flip to bottom keeping
# in mind the number of records in memory
if currentRecord == recordCount:
- if recordCount > int(self._rows)-1:
- index = int(self._rows)-1
+ if recordCount > int(self.rows)-1:
+ index = int(self.rows)-1
else:
index = recordCount
-
+
self._visibleIndex = index
self.lowestVisible = lowestVisible
-
-
Index: gnue/gnuef/src/GFParser.py
diff -u gnue/gnuef/src/GFParser.py:1.51 gnue/gnuef/src/GFParser.py:1.52
--- gnue/gnuef/src/GFParser.py:1.51 Thu Aug 2 20:02:28 2001
+++ gnue/gnuef/src/GFParser.py Sun Aug 12 12:55:27 2001
@@ -151,7 +151,6 @@
'BaseClass': GFObjects.GFDataSource,
'Attributes': GDataSource.tagAttributes,
'ParentTags': ('form',) },
-
'page': {
'BaseClass': GFObjects.GFPage,
'Required': 1,
Index: gnue/gnuef/src/GFTrigger.py
diff -u gnue/gnuef/src/GFTrigger.py:1.44 gnue/gnuef/src/GFTrigger.py:1.45
--- gnue/gnuef/src/GFTrigger.py:1.44 Thu Aug 2 20:02:28 2001
+++ gnue/gnuef/src/GFTrigger.py Sun Aug 12 12:55:27 2001
@@ -62,7 +62,6 @@
class GFTriggerAware:
def __init__(self):
self._trigger = {}
-
self._validTriggers = VALIDTRIGGERS.keys()
# addTrigger
@@ -103,6 +102,7 @@
self.src = src
self.type = type
self.name = name
+ self._inits = [None,self.initialize]
if text != None:
GContent(self, text)
if self.type != None:
@@ -117,10 +117,18 @@
self.name = self.id
del self.__dict__['id']
+ #
+ # Must be at least a phase 2 init
+ #
def initialize(self):
+ print "GFTrigger.py - initialize"
+ self._form = self.findParentOfType('GFForm')
+ self._triggerns.update( self._form._triggerns )
self.__call__ = self.dummyFunction
- if self.type!="NAMED":
+ print "GFTrigger.py ",self.type
+
+ if self.type != "NAMED":
if self._parent:
self._parent.addTrigger( self.type, self )
else:
@@ -128,6 +136,9 @@
if self.src == None:
self.setFunction( self.getChildrenAsContent(), self.language )
+ else:
+ self.setFunctionFrom(self._form._triggerDictionary[self.src])
+
def setFunctionFrom(self, object):
self.__call__=object.__call__
Index: gnue/gnuef/src/UIbase.py
diff -u gnue/gnuef/src/UIbase.py:1.42 gnue/gnuef/src/UIbase.py:1.43
--- gnue/gnuef/src/UIbase.py:1.42 Tue Jul 31 16:22:30 2001
+++ gnue/gnuef/src/UIbase.py Sun Aug 12 12:55:27 2001
@@ -50,14 +50,14 @@
'updateENTRY' : self.updateEntry,
'gotoPAGE' : self.gotoPage,
'formALERT' : self.formAlert,
- 'requireLOGIN' : self.getLogin,
+ 'beginWAIT' : self.beginWait,
+ 'endWAIT' : self.endWait,
'uiNEXTRECORD' : self.adjustMultiView,
'uiPREVRECORD' : self.adjustMultiView,
'uiUPDATESTATUS' : self.updateStatusBar,
'uiABOUT' : self.aboutBox,
'exitApplication' : self.exitApplication,
- 'msgBoxUI' : self.msgBox,
- 'getLogin' : self.getLogin
+ 'msgBoxUI' : self.msgBox
}
#
@@ -276,7 +276,7 @@
index = event.data._visibleIndex
block = event.data._block
- currentRecord = block._currentRecord
+ currentRecord = block._resultSet.getRecordNumber()
if hasattr(event.data, 'style'):
style = event.data.style
@@ -284,22 +284,24 @@
style = 'text'
# Fill the prior spots
- for count in range(index):
- value =
block._dataSourceLink.getField(currentRecord-(index-count),event.data.field)
- value = str(value) # Done to remove unicode types which wxpython doesn't
like
- if style == 'dropdown':
- value = event.data.allowedValues()[value]
- elif style == 'checkbox':
- if value in (1,'1','T','t','TRUE','true'):
- value = 1
- else:
- value = 0
+ if block.mode != 'query':
+ for count in range(index):
+ value =
block._resultSet.getRecord(currentRecord-(index-count)).getField(event.data.field)
+ if value == None: value = ""
+ value = str(value) # Done to remove unicode types which wxpython
doesn't like
+ if style == 'dropdown':
+ value = event.data.allowedValues()[value]
+ elif style == 'checkbox':
+ if value in (1,'1','T','t','TRUE','true'):
+ value = 1
+ else:
+ value = 0
- self._formToUIWidget[event.data].setValue(value,count)
+ self._formToUIWidget[event.data].setValue(value,count)
# fill currently indexed spot
if style == 'dropdown':
- value = event.data.allowedValues()[event.data.getValue()]
+ value = event.data.allowedValues()["%s" % event.data.getValue()]
else:
value = event.data.getValue()
value = str(value) # Done to remove unicode types which wxpython doesn't
like
@@ -321,26 +323,40 @@
# you do not want to just add 1 to count
# as the formulas would then be off
count = index
- while count < int(event.data._rows):
+ while count < int(event.data.rows):
if count != index:
- if currentRecord+(count-index) > block._recordCount:
+ rec = block._resultSet.getRecord(currentRecord+(count-index))
+ if rec == None:
if style == 'checkbox':
value = int(0)
else:
value = ""
else:
- value =
block._dataSourceLink.getField(currentRecord+(count-index),event.data.field)
+ value = rec.getField(event.data.field)
+ if value == None: value = ""
value = str(value) # Done to remove unicode types which wxpython
doesn't like
if style == 'dropdown':
value = event.data.allowedValues()[value]
elif style == 'checkbox':
- if value in (1,'1','T','t','TRUE','true'):
- value = 1
+ if value in (1,'1','T','t','TRUE','true'):
+ value = 1
else:
value = 0
self._formToUIWidget[event.data].setValue(value, count)
count = count +1
-
+
+
+ # Called whenever forms goes into a "wait" state in which user cannot
+ # interact with interface (e.g., while waiting for a query or a commit)
+ def beginWait (self, event):
+ pass
+
+
+ # Called whenever forms leaves a "wait" state
+ def endWait (self, event):
+ pass
+
+
#############################################################################
#
# UIWidget class
@@ -352,10 +368,10 @@
class UIWidget:
def __init__(self, object, container, textWidth, textHeight, widgetWidth,
widgetHeight, interface, initialize=1):
self.widgets = []
- if not hasattr(object,'_rows'):
- object._rows = 1
+ if not hasattr(object,'rows'):
+ object.rows = 1
else:
- object._rows = int(object._rows)
+ object.rows = int(object.rows)
if hasattr(object,'gap'):
object.gap = int(object.gap)
@@ -370,7 +386,7 @@
self.itemHeight = -1
if not object.hidden:
- for spacer in range(int(object._rows)):
+ for spacer in range(int(object.rows)):
newWidget = self.createWidget(object, container, textWidth,
textHeight, widgetWidth, widgetHeight, interface, spacer, initialize)
self.widgets.append(newWidget)
Index: gnue/gnuef/src/UIwxpython.py
diff -u gnue/gnuef/src/UIwxpython.py:1.106 gnue/gnuef/src/UIwxpython.py:1.107
--- gnue/gnuef/src/UIwxpython.py:1.106 Thu Aug 2 20:02:28 2001
+++ gnue/gnuef/src/UIwxpython.py Sun Aug 12 12:55:27 2001
@@ -42,6 +42,32 @@
_NOTEBOOK = None
_LOOPTRAP = 0
+
+
+##
+## Only create one instance of wxApp
+## Use getWxApp() to get or create the
+## single instance
+
+class GFwxApp(wxApp):
+ def OnInit(self):
+ GDebug.printMesg(7,"WxApp initializing")
+ wxInitAllImageHandlers()
+ return true
+
+__wxApp = None
+
+def getWxApp():
+ global __wxApp
+
+ if __wxApp == None:
+ __wxApp = GFwxApp(0)
+ __wxApp.MainLoop()
+
+ return __wxApp
+
+
+
#
# Little global helper routine to set font according to options
#
@@ -79,13 +105,12 @@
# The public interface to the User Interface
# All UIs must provide this class
#
-class GFUserInterface(wxApp,GFUserInterfaceBase):
+class GFUserInterface(GFUserInterfaceBase):
def __init__(self, disableSplash = None):
+ self._wxapp = getWxApp()
self._disableSplash = disableSplash
- wxApp.__init__(self,0)
GFUserInterfaceBase.__init__(self)
- self._loginHandler = wxLoginHandler()
self.keyEvents = {WXK_PRIOR: GFEvent('requestPREVBLOCK'),
WXK_NEXT: GFEvent('requestNEXTBLOCK'),
WXK_TAB: GFEvent('requestNEXTENTRY'),
@@ -109,6 +134,10 @@
WXK_F12: GFEvent('requestNEWRECORD'),
}
self.forms = {}
+
+ self.init()
+
+ #self._loginHandler = wxLoginHandler()
#
# mainLoop
#
@@ -116,7 +145,7 @@
# fully activated
#
def mainLoop(self):
- self.MainLoop() # simply call the wxApp's MainLoop method
+ self._wxapp.MainLoop() # simply call the wxApp's MainLoop method
#
# getModule
@@ -125,21 +154,21 @@
return GFUserInterface.__module__
#
- # OnInit
+ # init
#
# Routine called by wxWindows when wxApp instance is created
# It is used the build the basic UI
#
- def OnInit(self):
- wxInitAllImageHandlers()
+ def init(self):
#
# SplashScreen
#
if not self._disableSplash:
+ print GConfig.get('splashScreenPNG')
self.splash =
SplashScreen(None,bitmapfile=GConfig.get('splashScreenPNG'),
# duration=65535, callback=self.onMain,
- duration = 2000, callback=self.onCloseSplash,
+ duration = 4000, callback=self.onCloseSplash,
style=wxSIMPLE_BORDER|wxCENTRE_ON_SCREEN )
swidth,sheight = self.splash.GetSizeTuple()
@@ -212,41 +241,41 @@
fileMenu = wxMenu()
fileMenu.Append( 100, "Commit (F6)",GConfig.get('msg_commit'))
- EVT_MENU(self, 100, lambda event, l=self:
l.dispatchEvent(GFEvent('requestCOMMIT')))
+ EVT_MENU(self._wxapp, 100, lambda event, l=self:
l.dispatchEvent(GFEvent('requestCOMMIT')))
fileMenu.Append( 102, "Rollback (F11)",GConfig.get('msg_rollback'))
- EVT_MENU(self, 102, lambda event, l=self:
l.dispatchEvent(GFEvent('requestROLLBACK')))
+ EVT_MENU(self._wxapp, 102, lambda event, l=self:
l.dispatchEvent(GFEvent('requestROLLBACK')))
fileMenu.AppendSeparator()
fileMenu.Append( 104, "&Print",GConfig.get('msg_print'))
- EVT_MENU(self, 104, lambda event, l=self:
l.dispatchEvent(GFEvent('requestPRINTOUT')))
+ EVT_MENU(self._wxapp, 104, lambda event, l=self:
l.dispatchEvent(GFEvent('requestPRINTOUT')))
fileMenu.AppendSeparator()
fileMenu.Append( 101, "E&xit",GConfig.get('msg_exit'))
- EVT_MENU(self, 101, self.menuExitEvent)
+ EVT_MENU(self._wxapp, 101, self.menuExitEvent)
dataMenu = wxMenu()
dataMenu.Append( 201, "Next Record
(Up)",GConfig.get('msg_next'))
- EVT_MENU(self, 201, lambda event, l=self:
l.dispatchEvent(GFEvent('requestNEXTRECORD')))
+ EVT_MENU(self._wxapp, 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')))
+ EVT_MENU(self._wxapp, 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)
+ EVT_MENU(self._wxapp, 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')))
+ EVT_MENU(self._wxapp, 203, lambda event, l=self:
l.dispatchEvent(GFEvent('requestNEWRECORD')))
dataMenu.Append( 204, "Delete Record
(F5)",GConfig.get('msg_delete'))
- EVT_MENU(self, 204, lambda event, l=self:
l.dispatchEvent(GFEvent('requestMARKFORDELETE')))
+ EVT_MENU(self._wxapp, 204, lambda event, l=self:
l.dispatchEvent(GFEvent('requestMARKFORDELETE')))
dataMenu.AppendSeparator()
dataMenu.Append( 205, "Next Block
(PgDn)",GConfig.get('msg_next_block'))
- EVT_MENU(self, 205, lambda event, l=self:
l.dispatchEvent(GFEvent('requestNEXTBLOCK')))
+ EVT_MENU(self._wxapp, 205, lambda event, l=self:
l.dispatchEvent(GFEvent('requestNEXTBLOCK')))
dataMenu.Append( 206, "Previous Block
(PgUp)",GConfig.get('msg_previous_block'))
- EVT_MENU(self, 206, lambda event, l=self:
l.dispatchEvent(GFEvent('requestPREVBLOCK')))
+ EVT_MENU(self._wxapp, 206, lambda event, l=self:
l.dispatchEvent(GFEvent('requestPREVBLOCK')))
dataMenu.AppendSeparator()
dataMenu.Append( 207, "Enter Query
(F8)",GConfig.get('msg_query_prep'))
- EVT_MENU(self, 207, lambda event, l=self:
l.dispatchEvent(GFEvent('requestQUERY')))
+ EVT_MENU(self._wxapp, 207, lambda event, l=self:
l.dispatchEvent(GFEvent('requestQUERY')))
dataMenu.Append( 208, "Execute Query (F9)",
GConfig.get('msg_query'))
- EVT_MENU(self, 208, lambda event, l=self:
l.dispatchEvent(GFEvent('executeQUERY')))
+ EVT_MENU(self._wxapp, 208, lambda event, l=self:
l.dispatchEvent(GFEvent('executeQUERY')))
helpMenu = wxMenu()
helpMenu.Append( 300, "&About...", GConfig.get('msg_help'))
- EVT_MENU(self, 300, lambda event, l=self:
l.dispatchEvent(GFEvent('requestABOUT')))
+ EVT_MENU(self._wxapp, 300, lambda event, l=self:
l.dispatchEvent(GFEvent('requestABOUT')))
menuBar = wxMenuBar()
menuBar.Append( fileMenu, "&File" )
@@ -279,12 +308,11 @@
mainToolBar.AddSimpleTool(102, wxImage(GConfig.get('tb_rollback'),
wxBITMAP_TYPE_PNG).ConvertToBitmap(), "Rollback Changes",
GConfig.get('msg_rollback'))
mainToolBar.Realize()
-
self.mainWindow.panel = wxPanel(self.mainWindow,-1,
wxDefaultPosition,self.mainWindow.GetSize())
EVT_CHAR(self.mainWindow.panel, self.uiEventTrap)
self.currentWidget = [self.mainWindow.panel]
- self.SetTopWindow(self.mainWindow)
+ self._wxapp.SetTopWindow(self.mainWindow)
EVT_CLOSE(self.mainWindow,self.closeTrap)
@@ -311,8 +339,6 @@
self.mainWindow.panel.SetSize(wxSize(width*int(self.widgetWidth),
int(height+self.menu_sb_space)*int(self.widgetHeight)))
self._pageList[0].Show(TRUE)
- self.dispatchEvent(GFEvent('requestPREVRECORD'))
- self.dispatchEvent(GFEvent('requestNEXTRECORD'))
# Only one page at a time can be visible
self.visiblePage = self._pageList[0]
@@ -326,6 +352,9 @@
child.Fit()
child = child.GetParent()
+ self.mainWindow.CenterOnScreen()
+
+
#############################################################################
#
# Private UIBase support functions
@@ -611,164 +640,19 @@
if action != None:
self.dispatchEvent(action)
-
- #############################################################################
- #
- # Login support
- #
- # All methods below this point are only used to present the initial login box
- #
-
- #
- # getLogin
- #
- # creates the login dialog and displays it modal
- #
- def getLogin(self, event):
- self.loginData = event.data
-
-
- if len(self.loginData[1]):
-# loginMesg = 'Login required for "%s" (%s)' % (self.loginData[1],
self.loginData[0])
- loginMesg = 'Login required for "%s"' % (self.loginData[1])
- else:
- loginMesg = 'Login required for %s' % (self.loginData[0])
-
- self.dlg = wxDialog(NULL, -1, "GNU Enterprise: Login")
-# self.dlg.SetBackgroundColour(wxWHITE)
- self.dlg.SetAutoLayout(true)
-
- bmp = wxImage(GConfig.get('smallPNG'), wxBITMAP_TYPE_PNG).ConvertToBitmap()
-
-
- self.textctrlList = []
- messageField = wxStaticText(self.dlg, 1010, str(loginMesg))
- labelList = []
-
- dlgWidth = getLargest(bmp.GetWidth(), messageField.GetSize().GetWidth()+20)
-
- dlgHeight = bmp.GetHeight() + messageField.GetSize().GetHeight() + 80
-
- xSpacing = 0
- ySpacing = 0
- fieldLabelWidth = 0
-
- for prompt in self.loginData[2]:
- s = wxStaticText(self.dlg, 1010, '%s:' % prompt[1])
- labelList.append(s)
- if prompt[2]:
- t = wxTextCtrl(self.dlg, -1,"",wxPoint(1, 1), wxSize(150, 20),
style=wxTE_PASSWORD|wxTE_PROCESS_ENTER)
- else:
- t = wxTextCtrl(self.dlg, -1,"",wxPoint(1, 1), wxSize(150, 20),
style=wxTE_PROCESS_ENTER)
- myID = len(self.textctrlList)
- self.textctrlList.append(t)
- EVT_CHAR(t, LoginFieldHandler(self, myID).loginFieldEventTrap)
-
- fieldLabelWidth = getLargest(fieldLabelWidth, \
- s.GetSize().GetWidth() + t.GetSize().GetWidth() + 10)
-
- dlgWidth = getLargest(dlgWidth, \
- s.GetSize().GetWidth() + t.GetSize().GetWidth() + 10)
-
- xSpacing = getLargest(xSpacing, s.GetSize().GetWidth())
- ySpacing = getLargest(ySpacing, s.GetSize().GetHeight())
- ySpacing = getLargest(ySpacing, t.GetSize().GetHeight())
-
-
- loginButton = wxButton(self.dlg,19998,'Login')
- cancelButton = wxButton(self.dlg,19999,'Cancel')
- EVT_BUTTON(self.dlg, 19998, self.loginButtonEventTrap)
- EVT_BUTTON(self.dlg, 19999, self.loginCancelEventTrap)
- dlgWidth = getLargest(dlgWidth, loginButton.GetSize().GetWidth() +
- cancelButton.GetSize().GetWidth() + 6) + 20
-
- dlgHeight = dlgHeight + \
- getLargest(loginButton.GetSize().GetHeight(),
- cancelButton.GetSize().GetHeight()) - 6
-
- firstY = bmp.GetHeight() + messageField.GetSize().GetHeight() + 50
- lastY = firstY
- xSpacing = xSpacing + 10 # Add whitespace between widgets
- ySpacing = ySpacing + 6 # Add whitespace between widgets
- xPos = dlgWidth/2 - fieldLabelWidth/2
-
-
- # Move the fields and labels into position
- for i in range(0, len(self.textctrlList)):
- dlgHeight = dlgHeight + ySpacing
- labelList[i].SetPosition(wxPoint(xPos, lastY))
- self.textctrlList[i].SetPosition(wxPoint(xPos + xSpacing, lastY))
- lastY = lastY + ySpacing
-
-
- # Create and position the logo
- wxStaticBitmap(self.dlg,-1, bmp,
- wxPoint((dlgWidth-bmp.GetWidth())/2, 12),
- wxSize(bmp.GetWidth(), bmp.GetHeight()))
+ # Called whenever forms goes into a "wait" state in which user cannot
+ # interact with interface (e.g., while waiting for a query or a commit)
+ def beginWait (self, event):
+ wxBeginBusyCursor()
+
+ # Called whenever forms leaves a "wait" state
+ def endWait (self, event):
+ wxEndBusyCursor()
- # Move the various widgets into position
- messageField.SetPosition(
- wxPoint(dlgWidth/2 - messageField.GetSize().GetWidth()/2,
- 30 + bmp.GetHeight()))
- cancelButton.SetPosition(
- wxPoint(dlgWidth - 10 - cancelButton.GetSize().GetWidth(),
- dlgHeight - 10 - getLargest(loginButton.GetSize().GetHeight(),
- cancelButton.GetSize().GetHeight())))
-
- loginButton.SetPosition(
- wxPoint(dlgWidth - 16 - cancelButton.GetSize().GetWidth() - \
- loginButton.GetSize().GetWidth(),
- dlgHeight - 10 - getLargest(loginButton.GetSize().GetHeight(),
- cancelButton.GetSize().GetHeight())))
-
-
- self.dlg.SetSize(wxSize(dlgWidth, dlgHeight))
-
- self.dlg.Refresh()
-
- # If user cancels, this will be set to 0
- self._completed = 0
-
- self.dlg.Fit()
- self.dlg.Raise()
- self.dlg.CenterOnScreen()
- self.dlg.ShowModal()
- self.dlg.Destroy()
-
- rv = {}
- for i in range(0, len(self.loginData[2])):
- rv[self.loginData[2][i][0]] = self.textctrlList[i].GetValue()
-
- self.loginData.append([self._completed, rv])
-
-# event.data = [self._completed, rv]
-
-
- #
- # Login is completed, for whatever reason
- #
- def loginCompleted(self, successful):
- self._completed = successful
- self.dlg.EndModal(1)
-
- #
- # Called when user clicks "login"
- #
- def loginButtonEventTrap(self, event):
- self.loginCompleted(1)
-
- #
- # Called when user clicks "login"
- #
- def loginCancelEventTrap(self, event):
- self.loginCompleted(0)
-
-
-
#############################################################################
#
# UI Objects
@@ -954,7 +838,7 @@
else:
styles = 0
- newWidget = wxTextCtrl(container, -1, object._value,
+ newWidget = wxTextCtrl(container, -1, object.getValue(),
wxPoint(int(object.x)*int(widgetWidth),
(int(object.y)+spacer+(object.gap*spacer))*int(widgetHeight)),
wxSize(int(object.width)*int(textWidth),
@@ -977,7 +861,6 @@
global _NOTEBOOK
if object.tabbed:
- print object.tabbed
if object.tabbed == 'left':
tabstyle = wxNB_LEFT
elif object.tabbed == 'right':
@@ -1030,32 +913,159 @@
-#
-# LoginHandler
-#
-# The Login Handler for this user interface
-# Will be used with new db provider interface
+#####################################################################
+#####################################################################
+##
+## Login Support
+##
+#####################################################################
+#####################################################################
+
#
+# UILoginHandler
+class UILoginHandler(GLoginHandler.LoginHandler):
+ def __init__(self):
+ self._wxapp = getWxApp()
-class wxLoginHandler(GLoginHandler.LoginHandler):
- # Obviously, this needs to be replaced with a dialog implementation :)
def getLogin(self, loginData):
+
+ if len(loginData[1]):
+# loginMesg = 'Login required for "%s" (%s)' % (loginData[1],
loginData[0])
+ loginMesg = 'Login required for "%s"' % (loginData[1])
+ else:
+ loginMesg = 'Login required for %s' % (loginData[0])
+
+ self.dlg = wxDialog(NULL, -1, "GNU Enterprise: Login")
+# self.dlg.SetBackgroundColour(wxWHITE)
+ self.dlg.SetAutoLayout(true)
+
+ bmp = wxImage(GConfig.get('smallPNG'), wxBITMAP_TYPE_PNG).ConvertToBitmap()
+
+
+ self.textctrlList = []
+ messageField = wxStaticText(self.dlg, 1010, str(loginMesg))
+ labelList = []
+
+ dlgWidth = getLargest(bmp.GetWidth(), messageField.GetSize().GetWidth()+20)
- try:
- print "*"*60
- print 'Attempting to log into "%s":' % (loginData[1] or loginData[0])
- print
- val = {}
- for prompt in loginData[2]:
- val[prompt[0]] = raw_input(" %s: " % prompt[1])
- print
- print "*"*60
- return val
- except KeyboardInterrupt:
- raise GLoginHandler.UserCanceledLogin
+ dlgHeight = bmp.GetHeight() + messageField.GetSize().GetHeight() + 80
+ xSpacing = 0
+ ySpacing = 0
+ fieldLabelWidth = 0
+
+ for prompt in loginData[2]:
+ s = wxStaticText(self.dlg, 1010, '%s:' % prompt[1])
+ labelList.append(s)
+ if prompt[2]:
+ t = wxTextCtrl(self.dlg, -1,"",wxPoint(1, 1), wxSize(150, 20),
style=wxTE_PASSWORD|wxTE_PROCESS_ENTER)
+ else:
+ t = wxTextCtrl(self.dlg, -1,"",wxPoint(1, 1), wxSize(150, 20),
style=wxTE_PROCESS_ENTER)
+ myID = len(self.textctrlList)
+ self.textctrlList.append(t)
+ EVT_CHAR(t, LoginFieldHandler(self, myID).loginFieldEventTrap)
+
+ fieldLabelWidth = getLargest(fieldLabelWidth, \
+ s.GetSize().GetWidth() + t.GetSize().GetWidth() + 10)
+
+ dlgWidth = getLargest(dlgWidth, \
+ s.GetSize().GetWidth() + t.GetSize().GetWidth() + 10)
+
+ xSpacing = getLargest(xSpacing, s.GetSize().GetWidth())
+ ySpacing = getLargest(ySpacing, s.GetSize().GetHeight())
+ ySpacing = getLargest(ySpacing, t.GetSize().GetHeight())
+
+
+ loginButton = wxButton(self.dlg,19998,'Login')
+ cancelButton = wxButton(self.dlg,19999,'Cancel')
+
+ EVT_BUTTON(self.dlg, 19998, self.loginButtonEventTrap)
+ EVT_BUTTON(self.dlg, 19999, self.loginCancelEventTrap)
+ dlgWidth = getLargest(dlgWidth, loginButton.GetSize().GetWidth() +
+ cancelButton.GetSize().GetWidth() + 6) + 20
+
+ dlgHeight = dlgHeight + \
+ getLargest(loginButton.GetSize().GetHeight(),
+ cancelButton.GetSize().GetHeight()) - 6
+
+ firstY = bmp.GetHeight() + messageField.GetSize().GetHeight() + 50
+ lastY = firstY
+ xSpacing = xSpacing + 10 # Add whitespace between widgets
+ ySpacing = ySpacing + 6 # Add whitespace between widgets
+ xPos = dlgWidth/2 - fieldLabelWidth/2
+ # Move the fields and labels into position
+ for i in range(0, len(self.textctrlList)):
+ dlgHeight = dlgHeight + ySpacing
+ labelList[i].SetPosition(wxPoint(xPos, lastY))
+ self.textctrlList[i].SetPosition(wxPoint(xPos + xSpacing, lastY))
+ lastY = lastY + ySpacing
+
+
+ # Create and position the logo
+ wxStaticBitmap(self.dlg,-1, bmp,
+ wxPoint((dlgWidth-bmp.GetWidth())/2, 12),
+ wxSize(bmp.GetWidth(), bmp.GetHeight()))
+
+
+ # Move the various widgets into position
+ messageField.SetPosition(
+ wxPoint(dlgWidth/2 - messageField.GetSize().GetWidth()/2,
+ 30 + bmp.GetHeight()))
+
+
+ cancelButton.SetPosition(
+ wxPoint(dlgWidth - 10 - cancelButton.GetSize().GetWidth(),
+ dlgHeight - 10 - getLargest(loginButton.GetSize().GetHeight(),
+ cancelButton.GetSize().GetHeight())))
+
+ loginButton.SetPosition(
+ wxPoint(dlgWidth - 16 - cancelButton.GetSize().GetWidth() - \
+ loginButton.GetSize().GetWidth(),
+ dlgHeight - 10 - getLargest(loginButton.GetSize().GetHeight(),
+ cancelButton.GetSize().GetHeight())))
+
+
+ self.dlg.SetSize(wxSize(dlgWidth, dlgHeight))
+
+ self.dlg.Refresh()
+
+ # If user cancels, this will be set to 0
+ self._completed = 0
+
+ self.dlg.Fit()
+ self.dlg.Raise()
+ self.dlg.CenterOnScreen()
+ self.dlg.ShowModal()
+ self.dlg.Destroy()
+
+ rv = {}
+ for i in range(0, len(loginData[2])):
+ rv[loginData[2][i][0]] = self.textctrlList[i].GetValue()
+
+ return rv
+
+ #
+ # Login is completed, for whatever reason
+ #
+ def loginCompleted(self, successful):
+ self._completed = successful
+ self.dlg.EndModal(1)
+
+ #
+ # Called when user clicks "login"
+ #
+ def loginButtonEventTrap(self, event):
+ self.loginCompleted(1)
+
+ #
+ # Called when user clicks "login"
+ #
+ def loginCancelEventTrap(self, event):
+ self.loginCompleted(0)
+
+
WIDGETS = {'GFLabel' : UILabel,
'GFBox' : UIBox,
'GFPage' : UIPage,
@@ -1063,4 +1073,8 @@
'GFEntry' : UIEntry,
'GFButton' : UIButton,
'GFScrollBar' : UIScrollBar}
+
+
+
+
Index: gnue/reports/src/GRDataMapper.py
diff -u gnue/reports/src/GRDataMapper.py:1.3
gnue/reports/src/GRDataMapper.py:1.4
--- gnue/reports/src/GRDataMapper.py:1.3 Wed Jun 20 15:33:38 2001
+++ gnue/reports/src/GRDataMapper.py Sun Aug 12 12:55:27 2001
@@ -216,26 +216,23 @@
GDebug.printMesg (4, 'Creating ResultSet for source %s' % source)
controlSection.resultset = self.sources.getDataSource(source)\
.getDataObject().createResultSet(readOnly=1)
-# print "controlSection=%s" % controlSection
else:
- GDebug.printMesg(4, 'Getting pre-created ResultSet for source "%s"' \
- % (source))
+ GDebug.printMesg(4, 'Getting pre-created ResultSet for source "%s";
parent=%s' \
+ % (source, controlSection.parent))
return self.getNextRecord(source)
# Returns a string containing first section to change.
- # If none, then this datasource is all used up.
+ # If None, then this datasource is all used up.
def getNextRecord(self, source):
+ GDebug.printMesg (6, 'Getting next record for source %s' % source)
if source == None:
+ GDebug.printMesg (6, 'No next record to return for source %s' % source)
return None
- GDebug.printMesg (6, 'Getting next record for source %s' % source)
controlSection = self.sourceMap[source][0]
-# print "controlSection=%s" % controlSection
-
- GDebug.printMesg (10, controlSection.resultset)
if not controlSection.resultset.nextRecord():
return None
Index: gnue/reports/src/GRLayout.py
diff -u gnue/reports/src/GRLayout.py:1.6 gnue/reports/src/GRLayout.py:1.7
--- gnue/reports/src/GRLayout.py:1.6 Wed Jun 20 15:33:38 2001
+++ gnue/reports/src/GRLayout.py Sun Aug 12 12:55:27 2001
@@ -162,7 +162,7 @@
#
# Pull value for parameters
#
- if object.getObjectType == 'GRParam':
+ if object.getObjectType() == 'GRParam':
object._value = self._parameters.getParameter(object.name)
#
@@ -176,9 +176,9 @@
structuralComment = _structuralComment
for child in self._children:
- structuralComment(dest, '<!-- <layout> -->')
- child.process(dest, self._mapper)
- structuralComment(dest, '<!-- </layout> -->\n')
+ structuralComment(dest, '<!--[layout]-->')
+ child.processAsController(dest, self._mapper)
+ structuralComment(dest, '<!--[/layout]-->\n')
@@ -205,46 +205,65 @@
# <section> tag
#
class GRSection (GRLayoutElement):
+
def __init__(self, parent):
GRLayoutElement.__init__(self, parent, 'GRSection')
- def process(self, dest, mapper):
- myTurnAtBat = 1
+ # Retrieve the first row of data, if available.
+ # Handle default data if no rows retrieved.
+ #
+ # TODO: What if the top section isn't bound to a source?
+ # TODO: Does this work?
+ #
+ def processAsController(self, dest, mapper):
- while myTurnAtBat:
- structuralComment(dest,"<!--[section:%s]-->" % self.name)
- GDebug.printMesg(10,"Repeating Section %s" % self.name)
- for child in self._children:
- if child.getObjectType() == "_content_":
- dest.write(child.getContent())
- else:
- if isinstance(child, GRSection) and child._mymapper.toplevel:
- GDebug.printMesg(10, "Getting first record for child;
(child,toplevel)=(%s,%s)" % (child.name, child._mymapper.toplevel))
- if mapper.getFirstRecord(child.source):
- # There was data returned, so process section
- child.process(dest, mapper)
- else:
- # There was no data returned, so generate default text (if any)
- for c2 in child._children:
- if isinstance (c2, GRDefault):
- c2.processDefault(dest, mapper)
- else:
- child.process(dest, mapper)
- if self._mymapper == None or not self._mymapper.toplevel:
- myTurnAtBat = 0
- else:
+ GDebug.printMesg(10, "Controlling section %s's processAsController()
called" % self.name)
+
+ if mapper.getFirstRecord(self.source):
+ # There was data returned, so process section
+
+ section = self
+ while section:
+
+ # Process the current data row starting at correct section
+ section.process(dest, mapper)
+
+ # Determine the next section to process our data.
+ # (i.e., handle section grouping)
goto = mapper.getNextRecord(self.source)
GDebug.printMesg (10, "Goto is '%s'" % goto)
- if goto == None:
- myTurnAtBat = 0
+
+ if goto == None:
+ section = None
else:
- if goto != self.name:
- GDebug.printMesg (10, "Calling process() for section '%s' (mapper
is %s)" % (goto, mapper.sectionMap[goto]))
- mapper.sectionMap[goto]._object.process(dest, mapper)
- structuralComment(dest,"<!--[/section:%s]-->" % self.name)
+ section = mapper.sectionMap[goto]._object
+
+ else:
+ # There was no data returned, so generate default text (if any)
+ for c2 in self._children:
+ if isinstance (c2, GRDefault):
+ c2.processDefault(dest, self._mapper)
+
+
+ # Generic process() method. Process the
+ # current record and handle any children.
+ def process(self, dest, mapper):
+
+ GDebug.printMesg(10,"Repeating Section %s" % self.name)
+ structuralComment(dest,"<!--[section:%s]-->" % self.name)
+
+ for child in self._children:
+ if child.getObjectType() == "_content_":
+ dest.write(child.getContent())
+ else:
+ if isinstance(child, GRSection) and child._mymapper.toplevel:
+ GDebug.printMesg(10, "Calling new controlling section")
+ child.processAsController(dest, mapper)
+ else:
+ child.process(dest, mapper)
+
GDebug.printMesg(10,"Left section %s" % self.name)
-
#
Index: gnue/reports/src/GRParser.py
diff -u gnue/reports/src/GRParser.py:1.10 gnue/reports/src/GRParser.py:1.11
--- gnue/reports/src/GRParser.py:1.10 Mon Jul 2 10:03:18 2001
+++ gnue/reports/src/GRParser.py Sun Aug 12 12:55:27 2001
@@ -35,7 +35,7 @@
from GRParameters import *
from GRSortOptions import *
from GRLayout import *
-from gnue.common import GDataSource
+from gnue.common import GDataSource, GTypecast
import copy, types
@@ -83,7 +83,7 @@
'SingleInstance': 1,
'Attributes': {
'title': {
- 'Typecast': char } } ,
+ 'Typecast': GTypecast.name } } ,
'ParentTags': None },
'parameters': {
@@ -97,22 +97,22 @@
'id': {
'Required': 1,
'Unique': 1,
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'required': {
- 'Typecast': bool,
+ 'Typecast': GTypecast.boolean,
'Default': 0 },
'limited': {
- 'Typecast': bool,
+ 'Typecast': GTypecast.boolean,
'Default': 0 },
'default': {
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'description': {
'Required': 1,
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'source': {
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'type': {
- 'Typecast': char,
+ 'Typecast': GTypecast.name,
'Default': "char" } },
'ParentTags': ('parameters',) },
@@ -127,12 +127,12 @@
'id': {
'Required': 1,
'Unique': 1,
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'description': {
'Required': 1,
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'default': {
- 'Typecast': bool,
+ 'Typecast': GTypecast.boolean,
'Default': 0 } },
'ParentTags': ('sortoptions',) },
@@ -141,7 +141,7 @@
'Attributes': {
'name': {
'Required': 1,
- 'Typecast': char } },
+ 'Typecast': GTypecast.name } },
'ParentTags': ('sortoption',) },
'layout': {
@@ -150,7 +150,7 @@
'SingleInstance': 1,
'Attributes': {
'format': {
- 'Typecast': char } },
+ 'Typecast': GTypecast.name } },
'ParentTags': ('form',) },
'section': {
@@ -160,9 +160,9 @@
'KeepWhitespace': 1,
'Attributes': {
'name': {
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'source': {
- 'Typecast': char } },
+ 'Typecast': GTypecast.name } },
'ParentTags': ('layout',) },
'default': {
@@ -176,11 +176,11 @@
'Attributes': {
'name': {
'Required': 1,
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'source': {
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'format': {
- 'Typecast': char } },
+ 'Typecast': GTypecast.name } },
'ParentTags': ('layout',) },
'summ': {
@@ -188,17 +188,17 @@
'Attributes': {
'name': {
'Required': 1,
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'function': {
- 'Typecast': char,
+ 'Typecast': GTypecast.name,
'Default': "count"},
'source': {
- 'Typecast': char,
+ 'Typecast': GTypecast.name,
'Default': None},
'section': {
- 'Typecast': char },
+ 'Typecast': GTypecast.name },
'format': {
- 'Typecast': char } },
+ 'Typecast': GTypecast.name } },
'ParentTags': ('layout',) },
'sources': {
Index: gnue/reports/src/GRQueryBuilder.py
diff -u gnue/reports/src/GRQueryBuilder.py:1.2
gnue/reports/src/GRQueryBuilder.py:1.3
--- gnue/reports/src/GRQueryBuilder.py:1.2 Mon Apr 23 09:28:06 2001
+++ gnue/reports/src/GRQueryBuilder.py Sun Aug 12 12:55:27 2001
@@ -28,6 +28,9 @@
# Database-specific QueryBuilders should extend either QueryBuilder or
# AnsiSQLQueryBuilder (normally the latter if vendor uses SQL)
#
+# *** THIS FILE IS NOT CURRENTLY USED BY THE REPORT ENGINE ***
+# *** IT IS BASICALLY A TEST PROJECT FOR LATER INCLUSION ***
+#
from GRQuery import GRQueryElement
import string
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- gnue gnue-common/setup.py gnue-common/doc/DataO...,
James Thompson <=