diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/GConditions.py up/common/src/GConditions.py --- head/common/src/GConditions.py Thu Nov 14 17:28:59 2002 +++ up/common/src/GConditions.py Fri Nov 15 12:10:08 2002 @@ -145,6 +145,14 @@ def __init__(self, parent=None): GConditionElement.__init__(self, parent, 'GCnotbetween') +class GCnull(GConditionElement): + def __init__(self, parent=None): + GConditionElement.__init__(self, parent, 'GCnull') + +class GCnotnull(GConditionElement): + def __init__(self, parent=None): + GConditionElement.__init__(self, parent, 'GCnotnull') + # build an impossible condition GCondition={0=1} GCimpossible=GCondition() _h=GCeq(GCimpossible) @@ -249,7 +257,14 @@ 'ParentTags': ('condition','and','or','not','negate') }, 'notbetween': { 'BaseClass': GCnotbetween, - 'ParentTags': ('condition','and','or','not','negate') }} + 'ParentTags': ('condition','and','or','not','negate') }, + 'null': { + 'BaseClass': GCnull, + 'ParentTags': ('FIXME') }, + 'notnull': { + 'BaseClass': GCnotnull, + 'ParentTags': ('FIXME') }, + } for alteration in updates.keys(): xmlElements[alteration].update(updates[alteration]) diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/GDataObjects.py up/common/src/GDataObjects.py --- head/common/src/GDataObjects.py Fri Nov 8 12:50:29 2002 +++ up/common/src/GDataObjects.py Wed Nov 6 18:53:48 2002 @@ -322,10 +322,17 @@ def getCacheCount(self): return len(self._cachedRecords) + # returns records currently loaded + def getCachedRecords(self): + return self._cachedRecords + # returns # of records the def getRecordCount(self): return self._recordCount > 0 and self._recordCount or self.getCacheCount() + def getCurrentRecord(self): + return self.current + # Get a specific record (0=based) def getRecord(self, record): while (record + 1 > len(self._cachedRecords)) and self._loadNextRecord(): @@ -601,7 +608,17 @@ def isEmpty(self): return self._emptyFlag - + def setUpdateFlag(self, value): + self._updateFlag = value + if not value: + self._modifiedFlags.clear() + + def getInitialData(self): + return self._initialData + + def getFields(self): + return self._fields + # Returns current value of "field" def getField(self, field): try: diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/GDataSource.py up/common/src/GDataSource.py --- head/common/src/GDataSource.py Mon Nov 11 10:34:02 2002 +++ up/common/src/GDataSource.py Thu Nov 14 16:40:20 2002 @@ -75,6 +75,7 @@ }, 'simpleQuery':{'function':self.triggerSimpleQuery, }, + 'getRecords':{'function':self.getRecords}, 'delete':{'function':self.deleteCurrentRecordsetEntry, 'global':1, }, @@ -83,6 +84,8 @@ }, 'getCondition':{'function':self.getCondition}, 'setCondition':{'function':self.setCondition}, + 'getCurrentRecord':{'function':self.getCurrentRecord}, + 'getTimeStamp':{'function':self.getTimeStamp}, } def __getattr__(self, attr): @@ -91,6 +94,21 @@ else: raise AttributeError, attr + def getCurrentResultSet(self): + return self._currentResultSet + + def getRecords(self): + lResultSet = self.getCurrentResultSet() + if lResultSet._currentRecord == -1: + return 0 + else: + while lResultSet._loadNextRecord(): + pass + return lResultSet.getCachedRecords() + + def getCurrentRecord(self): + return self.getCurrentResultSet().getCurrentRecord() + def _buildObject(self): try: for field in string.split(self.explicitfields,','): @@ -109,6 +127,9 @@ return GObjects.GObj._buildObject(self) + def getTimeStamp(self): + return self._dataObject.triggerExtensions.getTimeStamp() + def triggerSimpleQuery(self,maskDict): queryDict = {} okToProcess = 1 @@ -403,6 +424,8 @@ 'database': { 'Typecast': GTypecast.name }, 'table': { + 'Typecast': GTypecast.name }, + 'historytable': { 'Typecast': GTypecast.name }, 'cache': { 'Typecast': GTypecast.whole, diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/GObjects.py up/common/src/GObjects.py --- head/common/src/GObjects.py Wed Nov 6 15:03:59 2002 +++ up/common/src/GObjects.py Wed Nov 6 18:58:17 2002 @@ -275,7 +275,7 @@ while 1: if parentObject == None: - return None + return None elif parentObject._type == type: return parentObject diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/_dbsig/DBdriver.py up/common/src/dbdrivers/_dbsig/DBdriver.py --- head/common/src/dbdrivers/_dbsig/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/_dbsig/DBdriver.py Fri Nov 15 20:55:10 2002 @@ -38,33 +38,115 @@ class DBSIG_RecordSet(GDataObjects.RecordSet): + def _haveHistory(self, table=None): + if not table: + auxTable = string.split(string.replace(self._parent._dataObject.table,' ',''),',') + else: + auxTable = string.split(string.replace(table,' ',''),',') + + for table in auxTable: + historyFields = ("_start_t","_end_t", table) + statement = "SELECT %s, %s FROM %s WHERE (1 = 0)" % historyFields + try: + cursor = self._parent._dataObject._dataConnection.cursor() + cursor.execute(statement) + cursor.close() + return 1 + except self._parent._dataObject._DatabaseError, err: + pass + return 0 + def _postChanges(self): if not self.isPending(): return + auxTable = string.split(string.replace(self._parent._dataObject.table,' ',''),',') + + if self._haveHistory(): + return self._postChangesWHist() + + statements = [] if self._deleteFlag: - statement = self._buildDeleteStatement() + auxTable.reverse() + for table in auxTable: + statements.append(self._buildDeleteStatement(table)) elif self._insertFlag: - statement = self._buildInsertStatement() + for table in auxTable: + statements.append(self._buildInsertStatement(table)) elif self._updateFlag: - statement = self._buildUpdateStatement() + if len(auxTable) > 1: + updTables = {} + for iterField in self._modifiedFlags.keys(): + a = len (iterField.split ('.')) + if (a == 2): + [updTable, auxField]= iterField.split ('.') + updTables[updTable] = "" + else: + # raise + pass + for iterTable in updTables.keys(): + statements.append(self._buildUpdateStatement(iterTable)) + else: + statements.append(self._buildUpdateStatement(auxTable[0])) - GDebug.printMesg(5, "_postChanges: statement=%s" % statement) + for statement in statements: + GDebug.printMesg(5, "_postChanges: statement=%s" % statement) + + try: + print "statement: %s" % statement + self._parent._update_cursor.execute(statement) + + # Set _initialData to be the just-now posted values + if not self._deleteFlag: + self._initialData = {} + self._initialData.update(self._fields) + + except self._parent._dataObject._DatabaseError, err: + raise GDataObjects.ConnectionError, err + + self._updateFlag = 0 + self._insertFlag = 0 + self._deleteFlag = 0 - try: - self._parent._update_cursor.execute(statement) + return 1 - # Set _initialData to be the just-now posted values - if not self._deleteFlag: - self._initialData = {} - self._initialData.update(self._fields) + def _postChangesWHist(self): + auxTable = string.split(string.replace(self._parent._dataObject.table,' ',''),',') + auxHTable = None + if hasattr(self._parent._dataObject,"historytable"): + auxHTable = string.split(string.replace(self._parent._dataObject.historytable,' ',''),',') + statements = [] + result = 1 + if self._deleteFlag: + auxTable.reverse() + for table in auxTable: + result = self._doDeleteStatementWHist(table) + if not result: break + elif self._insertFlag: + for table in auxTable: + result = self._doInsertStatementWHist(table) + if not result: break + elif self._updateFlag: + if len(auxTable) > 1: + for iterTable in auxHTable: + result = self._doDeleteStatementWHist(iterTable) + if not result: break + result = self._doInsertStatementWHist(iterTable) + if not result: break + print iterTable + else: + result = self._doDeleteStatementWHist(auxTable[0]) + if result: result = self._doInsertStatementWHist(auxTable[0]) - except self._parent._dataObject._DatabaseError, err: - raise GDataObjects.ConnectionError, err + + # Set _initialData to be the just-now posted values + if not self._deleteFlag: + self._initialData = {} + self._initialData.update(self._fields) self._updateFlag = 0 self._insertFlag = 0 self._deleteFlag = 0 - return 1 + return result # If a vendor can do any of these more efficiently (i.e., use a known @@ -72,73 +154,234 @@ # as default. Note that these functions are specific to DB-SIG based # drivers (i.e., these functions are not in the base RecordSet class) - def _buildDeleteStatement(self): - if self._initialData.has_key(self._parent._dataObject._primaryIdField): - where = [self._parent._dataObject._primaryIdFormat % \ - self._initialData[self._parent._dataObject._primaryIdField] ] + def _buildDeleteStatement(self, table): + where = [] + if self._parent._dataObject._primaryKeys: + for iterTable in self._parent._dataObject._primaryKeys.keys(): + if iterTable != table: continue + for iterField in self._parent._dataObject._primaryKeys[iterTable]: + auxWhere = "%s = '%s'" + if self._initialData.has_key(table+"."+iterField): + where.append(auxWhere % (iterField,self._initialData[table+"."+iterField])) + else: + where.append(auxWhere % (iterField,self._initialData[iterField])) else: - where = [] for field in self._initialData.keys(): if self._parent.isFieldBound(field): + a = len(field.split ('.')) + if (a == 2): + [auxTable, auxField]= field.split ('.') + if string.count(self._parent._dataObject.table,',') and (auxTable != table): + continue + elif (a == 1): + auxField= field + else: + # raise + pass + if self._initialData[field] == None: - where.append ("%s IS NULL" % field) + where.append ("%s IS NULL" % auxField) else: - where.append ("%s=%s" % (field, + where.append ("%s=%s" % (auxField, self._parent._dataObject._toSqlString(self._initialData[field]))) statement = "DELETE FROM %s WHERE %s" % \ - (self._parent._dataObject.table, string.join(where,' AND ') ) + (table, string.join(where,' AND ') ) return statement - def _buildInsertStatement(self): + def _doDeleteStatementWHist(self, table): + if not self._haveHistory(table): return 1 + today = "'%s'" % self._parent._dataObject.triggerExtensions.getTimeStamp() + return self._parent._dataObject.triggerExtensions.atomicModify(today, \ + "%s._end_t" % (table), \ + self._parent._dataObject, \ + self, \ + "_end_t IS NULL") + + + def _buildInsertStatement(self, table): vals = [] fields = [] - + + pkFields = [] + if self._parent._dataObject._primaryKeys: + pkFields.extend(self._parent._dataObject._primaryKeys[table]) for field in self._modifiedFlags.keys(): if self._parent.isFieldBound(field): - fields.append (field) + a = len (field.split ('.')) + if (a == 2): + [auxTable, auxField] = field.split ('.') + if string.count(self._parent._dataObject.table,',') and (auxTable != table): + continue + elif (a == 1): + auxField= field + else: + # raise + pass + + try: + if self._fields[field]: + pkFields.remove(auxField) + else: + continue + except ValueError: + pass + + fields.append(auxField) if self._fields[field] == None or self._fields[field] == '': vals.append ("NULL") # % (self._fields[field])) else: vals.append (self._parent._dataObject._toSqlString(self._fields[field])) + for iterField in pkFields: + fields.append(iterField) + tmpTable = table[0:24] + seqValue = str(self._parent._dataObject.triggerExtensions.getSequence(tmpTable+"_"+iterField+"_seq")) + vals.append(seqValue) + self._fields[table+'.'+iterField] = seqValue + + for iterField in self._parent._dataObject._joinConditions.keys(): + [auxTable, auxField] = iterField.split('.') + if auxTable == table: + fields.append(auxField) + vals.append (self._parent._dataObject._toSqlString(\ + self._fields[self._parent._dataObject._joinConditions[iterField]])) + return "INSERT INTO %s (%s) VALUES (%s)" % \ - (self._parent._dataObject.table, string.join(fields,','), \ - string.join(vals,',') ) + (table, string.join(fields,','), \ + string.join(vals,',') ) + + def _doInsertStatementWHist(self, table): + vals = [] + fields = [] + + pkFields = [] + if self._parent._dataObject._primaryKeys: + pkFields.extend(self._parent._dataObject._primaryKeys[table]) + for field in self._fields.keys(): + if self._parent.isFieldBound(field): + a = len (field.split ('.')) + if (a == 2): + [auxTable, auxField]= field.split ('.') + if string.count(self._parent._dataObject.table,',') and (auxTable != table): + continue + elif (a == 1): + auxField = field + else: + # raise + pass - def _buildUpdateStatement(self): + if pkFields.count(auxField) > 0: continue + + #try: + # if self._fields[field]: + # pkFields.remove(auxField) + # else: + # continue + #except ValueError: + # pass + + fields.append(auxField) + if self._fields[field] == None or self._fields[field] == '': + vals.append ("NULL") # % (self._fields[field])) + else: + vals.append (self._parent._dataObject._toSqlString(self._fields[field])) + + for iterField in pkFields: + fields.append(iterField) + tmpTable = table[0:24] + seqValue = str(self._parent._dataObject.triggerExtensions.getSequence(tmpTable+"_"+iterField+"_seq")) + vals.append(seqValue) + self._fields[table+'.'+iterField] = seqValue + + for iterField in self._parent._dataObject._joinConditions.keys(): + [auxTable, auxField] = iterField.split('.') + if auxTable == table: + fields.append(auxField) + vals.append (self._parent._dataObject._toSqlString(\ + self._fields[self._parent._dataObject._joinConditions[iterField]])) + + if self._haveHistory(table): + fields.append("_start_t") + vals.append("'%s'" % self._parent._dataObject.triggerExtensions.getTimeStamp()) + + statement = "INSERT INTO %s (%s) VALUES (%s)" % \ + (table, string.join(fields,','), \ + string.join(vals,',') ) + print statement + try: + self._parent._update_cursor.execute("BEGIN") + self._parent._update_cursor.execute(statement) + self._parent._update_cursor.execute("COMMIT") + + except self._parent._dataObject._DatabaseError, err: + GDebug.printMesg(5, "_doInsertStatementWHist: ERROR = %s" % err) + raise GDataObjects.ConnectionError, err + + return 1 + + def _buildUpdateStatement(self, table): updates = [] for field in self._modifiedFlags.keys(): - updates.append ("%s=%s" % (field, - self._parent._dataObject._toSqlString(self._fields[field]))) + a = len (field.split ('.')) + if (a == 2): + [auxTable, auxField]= field.split ('.') + if string.count(self._parent._dataObject.table,',') and (auxTable != table): + continue + elif (a == 1): + auxField= field + else: + # raise + pass - if self._parent._dataObject._primaryIdField: - where = [self._parent._dataObject._primaryIdFormat % \ - self._initialData[self._parent._dataObject._primaryIdField] ] - else: - where = [] - for field in self._initialData.keys(): - if self._initialData[field] == None: - where.append ("%s IS NULL" % field) - else: - where.append ("%s=%s" % (field, self._parent._dataObject._toSqlString(self._initialData[field]))) + updates.append ("%s=%s" % (auxField, + self._parent._dataObject._toSqlString(self._fields[field]))) + + where = [] + if updates: + if self._parent._dataObject._primaryKeys: + for iterTable in self._parent._dataObject._primaryKeys.keys(): + if iterTable != table: continue + for iterField in self._parent._dataObject._primaryKeys[iterTable]: + auxWhere = "%s = '%s'" + where.append(auxWhere % (iterField,self._initialData[table+"."+iterField])) + else: + for field in self._initialData.keys(): + a = len (field.split ('.')) + if (a == 2): + [auxTable, auxField]= field.split ('.') + if string.count(self._parent._dataObject.table,',') and (auxTable != table): + continue + elif (a == 1): + auxField= field + else: + # raise + pass + + if self._initialData[field] == None: + where.append ("%s IS NULL" % auxField) + else: + where.append ("%s=%s" % (auxField, self._parent._dataObject._toSqlString(self._initialData[field]))) return "UPDATE %s SET %s WHERE %s" % \ - (self._parent._dataObject.table, string.join(updates,','), \ + (table, string.join(updates,','), \ string.join(where,' AND ') ) class DBSIG_ResultSet(GDataObjects.ResultSet): def __init__(self, dataObject, cursor=None, \ - defaultValues={}, masterRecordSet=None): + defaultValues={}, masterRecordSet=None, fieldNames=None): GDataObjects.ResultSet.__init__( self,dataObject,cursor,defaultValues,masterRecordSet) self._recordSetClass = DBSIG_RecordSet self._fieldNames = [] if self._cursor: - for t in(self._cursor.description): - self._fieldNames.append(t[0]) + if fieldNames != None: + self._fieldNames = fieldNames + else: + for t in(self._cursor.description): + self._fieldNames.append(t[0]) GDebug.printMesg(5, "Field names set to %s" % self._fieldNames) self._recordCount = cursor.rowcount or 0 @@ -178,28 +421,31 @@ class DBSIG_DataObject(GDataObjects.DataObject): conditionElements = { - 'add': (2, 999, '(%s)', '+' ), - 'sub': (2, 999, '(%s)', '-' ), - 'mul': (2, 999, '(%s)', '*' ), - 'div': (2, 999, '(%s)', '/' ), - 'and': (1, 999, '(%s)', ' AND ' ), - 'or': (2, 999, '(%s)', ' OR ' ), - 'not': (1, 1, '(NOT %s)', None ), - 'negate': (1, 1, '-%s', None ), - 'eq': (2, 2, '(%s = %s)', None ), - 'ne': (2, 2, '(%s != %s)', None ), - 'gt': (2, 2, '(%s > %s)', None ), - 'ge': (2, 2, '(%s >= %s)', None ), - 'lt': (2, 2, '(%s < %s)', None ), - 'le': (2, 2, '(%s <= %s)', None ), - 'like': (2, 2, '%s LIKE %s', None ), - 'notlike': (2, 2, '%s NOT LIKE %s', None ), - 'between': (3, 3, '%s BETWEEN %s AND %s', None ), + 'add': (2, 999, '(%s)', '+' ), + 'sub': (2, 999, '(%s)', '-' ), + 'mul': (2, 999, '(%s)', '*' ), + 'div': (2, 999, '(%s)', '/' ), + 'and': (1, 999, '(%s)', ' AND ' ), + 'or': (2, 999, '(%s)', ' OR ' ), + 'not': (1, 1, '(NOT %s)', None ), + 'negate': (1, 1, '-%s', None ), + 'null': (1, 1, '(%s IS NULL)', None ), + 'notnull': (1, 1, '(%s IS NOT NULL)', None ), + 'eq': (2, 2, '(%s = %s)', None ), + 'ne': (2, 2, '(%s != %s)', None ), + 'gt': (2, 2, '(%s > %s)', None ), + 'ge': (2, 2, '(%s >= %s)', None ), + 'lt': (2, 2, '(%s < %s)', None ), + 'le': (2, 2, '(%s <= %s)', None ), + 'like': (2, 2, '(%s LIKE %s)', None ), + 'notlike': (2, 2, '(%s NOT LIKE %s)', None ), + 'between': (3, 3, '(%s BETWEEN %s AND %s)', None ), + 'notbetween': (3, 3, '(%s NOT BETWEEN %s AND %s)', None ), # These two are hacks... these are not really valid tags # Used when the 2nd value of EQ or NE is NULL. - '__iseq': (2, 2, '(%s IS %s)', None ), - '__isne': (2, 2, '(%s IS NOT %s)', None )} - + # These are probably not necessary now that null and not null exist + '__iseq': (2, 2, '(%s IS %s)', None ), + '__isne': (2, 2, '(%s IS NOT %s)', None )} schema2nativeTypes={} def __init__(self, strictQueryCount=1): @@ -224,13 +470,14 @@ # the string % (fieldvalue) format applied to it. # # See Oracle drivers for example + self._primaryKeys = {} self._primaryIdField = None # Internal recordset field name (lowercase!!!) self._primaryIdSelect = "" # Select clause self._primaryIdFormat = "__gnue__ = '%s'" # Where clause format # Internal flag to avoid consistently doing the same check # If this is set to 1 initially, then the - self._primaryIdChecked = 1 # Internal flag + self._primaryIdChecked = 0 # Internal flag # The date/time format used in insert/select statements @@ -275,14 +522,36 @@ # pull a record count for the upcomming query if self._strictQueryCount: recordCount = self._getQueryCount(conditions,sql) - + cursor.arraysize = self.cache + tableCount = string.count(self.table,',')+1 + tables = string.split(string.replace(self.table,' ',''),',') + prefixedFields = None + if self._primaryKeys and self._fieldReferences: + for table in self._primaryKeys.keys(): + for field in self._primaryKeys[table]: + if not self._fieldReferences.has_key(table+"."+field) and not self._fieldReferences.has_key(field): + self._fieldReferences[table+"."+field] = "" + + prefixedFields = self._fieldReferences.keys() + + if tableCount > 1 and not prefixedFields: + prefixedFields = [] + for iterTable in tables: + cursor.execute(self._buildQuery(conditions,iterTable)) + for iterDesc in (cursor.description): + prefixedFields.append(iterTable+'.'+iterDesc[0]) + cursor.execute(self._buildQuery(conditions,sql=sql)) except self._DatabaseError, err: raise GDataObjects.ConnectionError, err - rs = self._resultSetClass(self, cursor=cursor, masterRecordSet=masterRecordSet) + if not prefixedFields: + rs = self._resultSetClass(self, cursor=cursor, masterRecordSet=masterRecordSet) + else: + rs = self._resultSetClass(self, cursor=cursor, masterRecordSet=masterRecordSet, fieldNames=prefixedFields) + if self._strictQueryCount: rs._recordCount = recordCount if readOnly: @@ -328,7 +597,7 @@ else: cond = condition - if not len(cond._children): + if not len(cond._children): return "" elif len(cond._children) > 1: chillun = cond._children[:] @@ -336,6 +605,7 @@ _and = GConditions.GCand(cond) _and._children = chillun + self._joinConditionsLoaded = 1 where = " WHERE (%s)" % (self.__conditionToSQL (cond._children[0])) GDebug.printMesg(5, where) return where @@ -352,6 +622,23 @@ # Note that we strip the GC from the object types and lowercase the rest otype = string.lower(element._type[2:]) #print "Otype: ",otype + if not self._joinConditionsLoaded and \ + otype == "eq" and \ + len(element._children) == 2 and \ + string.lower(element._children[0]._type[2:]) == "cfield" and \ + string.lower(element._children[1]._type[2:]) == "cfield": + [auxTable, auxField]= element._children[0].name.split ('.') + try: + pKeys = self._primaryKeys[auxTable] + for pKey in pKeys: + if pKey == auxField: + self._joinConditions[element._children[1].name] = element._children[0].name + break + except KeyError: + pass + if not self._joinConditions.has_key(element._children[1].name): + self._joinConditions[element._children[0].name] = element._children[1].name + if otype == 'cfield': return "%s" % element.name elif otype == 'cconst': @@ -514,7 +801,10 @@ GDebug.printMesg(0, "Database driver needs updated to not initialize DBSIG_DataObject_Object") - def _buildQuery(self, conditions={}, forDetail=None, additionalSQL=""): + def _buildQuery(self, conditions={}, forDetail=None, additionalSQL="", qTable=None): + if not qTable: + qTable = self.table + GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences) if self.distinct: distinct = "distinct " @@ -583,8 +873,3 @@ 'object': DBSIG_DataObject_Object, 'sql': DBSIG_DataObject_SQL } - - - - - diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/_pgsql/DBdriver.py up/common/src/dbdrivers/_pgsql/DBdriver.py --- head/common/src/dbdrivers/_pgsql/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/_pgsql/DBdriver.py Fri Nov 15 18:53:26 2002 @@ -83,9 +83,9 @@ class PGSQL_ResultSet(DBSIG_ResultSet): - def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None): + def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None, fieldNames=None): DBSIG_ResultSet.__init__(self, dataObject, \ - cursor, defaultValues, masterRecordSet) + cursor, defaultValues, masterRecordSet,fieldNames) self._recordSetClass = PGSQL_RecordSet class PGSQL_DataObject(DBSIG_DataObject): @@ -305,7 +305,61 @@ cursor.close() return list + +class PGSQL_DataObject_Object(PGSQL_DataObject, \ + PGSQL_DataObject_Object): + + def __init__(self): + PGSQL_DataObject.__init__(self) + self._primaryIdChecked = 0 + + + def _checkForPrimaryId(self): + self._primaryIdChecked = 1 + + #To get the names you can start a second query like: + + tables = self.table.replace(' ','').split(',') + self._primaryKeys = {} + for table in tables: + statement = "SELECT indkey FROM pg_index, pg_class c WHERE indrelid=c.oid AND indisprimary AND relname='%s' " \ + % table + cursor = self._dataConnection.cursor() + cursor.execute(statement) + indkeys = "" + fields = [] + try: + rsets = cursor.fetchmany() + except self._DatabaseError, err: + raise GDataObjects.ConnectionError, err + if rsets and len(rsets): + for rs in (rsets): + if rs: + for f in (rs): + if len(indkeys) == 0: + indkeys = indkeys + f + else: + indkeys = indkeys + "," + f + cursor.close() + + if len(indkeys) != 0: + statement = "SELECT attname FROM pg_class c, pg_attribute WHERE c.oid = attrelid and attnum in (%s) \ + AND relname='%s'" % (indkeys,table) + cursor = self._dataConnection.cursor() + cursor.execute(statement) + try: + rsets = cursor.fetchmany() + except self._DatabaseError, err: + raise GDataObjects.ConnectionError, err + if rsets and len(rsets): + for rs in (rsets): + if rs: + for f in (rs): + fields.append(f) + cursor.close() + self._primaryKeys[table] = fields + # # Extensions to Trigger Namespaces # @@ -321,6 +375,97 @@ # Return a sequence number from sequence 'name' def getSequence(self, name): return self.__singleQuery("select nextval('%s')" % name) + + def atomicModify(self, func, field, dataObject, record, cond=None): + if string.count(dataObject.table,',') == 0: + table = dataObject.table + elif field.count('.'): + table = field.split('.')[0] + else: + raise + + where = [] + + if dataObject._primaryKeys: + for iterTable in dataObject._primaryKeys.keys(): + if iterTable != table: continue + for iterField in dataObject._primaryKeys[iterTable]: + auxWhere = "%s = '%s'" + where.append(auxWhere % (iterField,record._initialData[table+"."+iterField])) + else: + for field in record._initialData.keys(): + a = len (field.split ('.')) + if (a == 2): + [auxTable, auxField]= field.split ('.') + if string.count(dataObject.table,',') and (auxTable != table): + continue + elif (a == 1): + auxField= field + else: + # raise + pass + + if record._initialData[field] == None: + where.append ("%s IS NULL" % auxField) + else: + where.append ("%s=%s" % (auxField, dataObject._toSqlString(record._initialData[field]))) + if cond: + where.append(cond) + + cursor = self.__connection.cursor() + + getValueStmt = "BEGIN; SELECT %s FROM %s WHERE %s FOR UPDATE; " % \ + (field, table, \ + string.join(where,' AND ') ) + + try: + cursor.execute(getValueStmt) + rv = cursor.fetchone() + except: + print "DBdriver.py", "error!" + GDebug.printMesg(1,"**** Unable to execute extension query") + GDebug.printMesg(1,"**** %s" % sys.exc_info()[1]) + cursor.close() + return None + + try: + lAux = rv[0] + except: + try: + cursor.execute("COMMIT") + cursor.close() + except: + print "DBdriver.py", "error!" + GDebug.printMesg(1,"**** Unable to execute extension query") + GDebug.printMesg(1,"**** %s" % sys.exc_info()[1]) + cursor.close() + return None + + if field.count('.') > 0: + auxField = field.split('.')[1] + else: + auxField = field + + if str(type(func)).count("'function'") > 0: + value = func(rv[0]) + else: + value = func + + updateStmt = "UPDATE %s SET %s WHERE %s" % \ + (table, " %s = %s " % (auxField, str(value)), \ + string.join(where,' AND ') ) + "; COMMIT" + + try: + cursor.execute(updateStmt) + cursor.close() + except: + print "DBdriver.py", "error!" + GDebug.printMesg(1,"**** Unable to execute extension query") + GDebug.printMesg(1,"**** %s" % sys.exc_info()[1]) + cursor.close() + return None + + return 1 # Run the SQL statement 'statement' def sql(self, statement): diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/cxoracle/DBdriver.py up/common/src/dbdrivers/cxoracle/DBdriver.py --- head/common/src/dbdrivers/cxoracle/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/cxoracle/DBdriver.py Fri Nov 15 17:24:03 2002 @@ -91,8 +91,10 @@ self._primaryIdChecked = 0 - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) def _checkForPrimaryId(self): diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/db2/DBdriver.py up/common/src/dbdrivers/db2/DBdriver.py --- head/common/src/dbdrivers/db2/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/db2/DBdriver.py Fri Nov 15 17:24:15 2002 @@ -231,8 +231,10 @@ def __init__(self): DB2_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail = None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class DB2_DataObject_SQL(DB2_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/gadfly/DBdriver.py up/common/src/dbdrivers/gadfly/DBdriver.py --- head/common/src/dbdrivers/gadfly/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/gadfly/DBdriver.py Fri Nov 15 17:24:22 2002 @@ -261,8 +261,10 @@ def __init__(self): Gadfly_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None, sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) def _getQueryCount(self,conditions={}): cursor = self._dataConnection.cursor() diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/informix/DBdriver.py up/common/src/dbdrivers/informix/DBdriver.py --- head/common/src/dbdrivers/informix/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/informix/DBdriver.py Fri Nov 15 17:24:27 2002 @@ -117,8 +117,10 @@ def __init__(self): Informix_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class Informix_DataObject_SQL(Informix_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/ingres/DBdriver.py up/common/src/dbdrivers/ingres/DBdriver.py --- head/common/src/dbdrivers/ingres/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/ingres/DBdriver.py Fri Nov 15 17:24:31 2002 @@ -110,8 +110,10 @@ def __init__(self): Ingres_DataObject.__init__(self) - def _buildQuery(self, conditions={},sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class Ingres_DataObject_SQL(Ingres_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/interbase/DBdriver.py up/common/src/dbdrivers/interbase/DBdriver.py --- head/common/src/dbdrivers/interbase/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/interbase/DBdriver.py Fri Nov 15 17:24:36 2002 @@ -209,8 +209,10 @@ def __init__(self): Interbase_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class Interbase_DataObject_SQL(Interbase_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/mxodbc/DBdriver.py up/common/src/dbdrivers/mxodbc/DBdriver.py --- head/common/src/dbdrivers/mxodbc/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/mxodbc/DBdriver.py Fri Nov 15 17:24:41 2002 @@ -124,8 +124,10 @@ def __init__(self): ODBC_DataObject.__init__(self) - def _buildQuery(self, conditions={}forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class ODBC_DataObject_SQL(ODBC_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/mysql/DBdriver.py up/common/src/dbdrivers/mysql/DBdriver.py --- head/common/src/dbdrivers/mysql/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/mysql/DBdriver.py Fri Nov 15 17:24:46 2002 @@ -213,8 +213,10 @@ def __init__(self): MySQL_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class MySQL_DataObject_SQL(MySQL_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/oracle/DBdriver.py up/common/src/dbdrivers/oracle/DBdriver.py --- head/common/src/dbdrivers/oracle/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/oracle/DBdriver.py Fri Nov 15 17:24:50 2002 @@ -96,8 +96,10 @@ self._primaryIdChecked = 0 - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) def _checkForPrimaryId(self): diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/popy/DBdriver.py up/common/src/dbdrivers/popy/DBdriver.py --- head/common/src/dbdrivers/popy/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/popy/DBdriver.py Fri Nov 15 17:24:54 2002 @@ -83,8 +83,10 @@ # PGSQL_DataObject_Object.__init__(self) PG_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return PGSQL_DataObject_Object._buildQuery(self, conditions, forDetail, sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class PG_DataObject_SQL(PG_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/postgresql/DBdriver.py up/common/src/dbdrivers/postgresql/DBdriver.py --- head/common/src/dbdrivers/postgresql/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/postgresql/DBdriver.py Fri Nov 15 17:25:06 2002 @@ -93,8 +93,10 @@ PGSQL_DataObject_Object.__init__(self) PG_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return PGSQL_DataObject_Object._buildQuery(self, conditions, forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class PG_DataObject_SQL(PG_DataObject, PGSQL_DataObject_SQL): def __init__(self): @@ -121,9 +123,3 @@ 'object': PG_DataObject_Object, 'sql': PG_DataObject_SQL } - - - - - - diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/psycopg/DBdriver.py up/common/src/dbdrivers/psycopg/DBdriver.py --- head/common/src/dbdrivers/psycopg/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/psycopg/DBdriver.py Fri Nov 15 18:45:00 2002 @@ -54,9 +54,14 @@ def __init__(self): PG_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None, sql=""): - return PGSQL_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return PGSQL_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) + def _checkForPrimaryId(self): + return PGSQL_DataObject_Object._checkForPrimaryId(self) + class PG_DataObject_SQL(PG_DataObject, \ PGSQL_DataObject_SQL): def __init__(self): diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/pypgsql/DBdriver.py up/common/src/dbdrivers/pypgsql/DBdriver.py --- head/common/src/dbdrivers/pypgsql/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/pypgsql/DBdriver.py Fri Nov 1 13:24:02 2002 @@ -94,8 +94,10 @@ # some of its values PG_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return PGSQL_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, qTable = None): + if not qTable: + qTable = self.table + return PGSQL_DataObject_Object._buildQuery(self, conditions, qTable) class PG_DataObject_SQL(PG_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/sapdb/DBdriver.py up/common/src/dbdrivers/sapdb/DBdriver.py --- head/common/src/dbdrivers/sapdb/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/sapdb/DBdriver.py Fri Nov 15 17:25:18 2002 @@ -263,8 +263,10 @@ def __init__(self): SAP_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class SAP_DataObject_SQL(SAP_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/sqlite/DBdriver.py up/common/src/dbdrivers/sqlite/DBdriver.py --- head/common/src/dbdrivers/sqlite/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/sqlite/DBdriver.py Fri Nov 15 17:25:23 2002 @@ -230,8 +230,10 @@ def __init__(self): SQLite_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail, sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class SQLite_DataObject_SQL(SQLite_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/sqlrelay/DBdriver.py up/common/src/dbdrivers/sqlrelay/DBdriver.py --- head/common/src/dbdrivers/sqlrelay/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/sqlrelay/DBdriver.py Fri Nov 15 17:25:28 2002 @@ -120,8 +120,10 @@ def __init__(self): SQLRelay_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class SQLRelay_DataObject_SQL(SQLRelay_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/src/dbdrivers/sybase/DBdriver.py up/common/src/dbdrivers/sybase/DBdriver.py --- head/common/src/dbdrivers/sybase/DBdriver.py Fri Nov 15 16:12:04 2002 +++ up/common/src/dbdrivers/sybase/DBdriver.py Fri Nov 15 17:25:32 2002 @@ -119,8 +119,10 @@ def __init__(self): Sybase_DataObject.__init__(self) - def _buildQuery(self, conditions={},forDetail=None,sql=""): - return DBSIG_DataObject_Object._buildQuery(self, conditions,forDetail,sql) + def _buildQuery(self, conditions={}, forDetail = None, sql="", qTable = None): + if not qTable: + qTable = self.table + return DBSIG_DataObject_Object._buildQuery(self, conditions, forDetail, sql, qTable) class Sybase_DataObject_SQL(Sybase_DataObject, \ diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/translations/README up/common/translations/README --- head/common/translations/README Wed Nov 6 15:04:00 2002 +++ up/common/translations/README Fri Nov 1 13:24:03 2002 @@ -30,4 +30,4 @@ 3. Copy there gnue.mo file from any other folder (cp ../en_US/LC_MESSAGES/gnue.mo LC_MESSAGES/gnue.mo) -And if you can - commit this folder to CVS tree or email it. Thank you :) \ No newline at end of file +And if you can - commit this folder to CVS tree or email it. Thank you :) diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/common/translations/es_AR/LC_MESSAGES/gnue.po up/common/translations/es_AR/LC_MESSAGES/gnue.po --- head/common/translations/es_AR/LC_MESSAGES/gnue.po Wed Dec 31 21:00:00 1969 +++ up/common/translations/es_AR/LC_MESSAGES/gnue.po Mon Nov 4 12:03:42 2002 @@ -0,0 +1,1458 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: GNUe\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2002-10-28 17:30-300\n" +"Last-Translator: Carlos Charlie Navarro \n" +"Language-Team: es_AR \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: UTF-8\n" + +#: ../src/GBaseApp.py:98 +msgid "Displays the version information for this program." +msgstr "Muestra la información de versión para este programa" + +#: ../src/GBaseApp.py:100 +msgid "Enables debugging messages. Argument specifies the " +msgstr "Mensajes de debug activados. El argumento especifíca " + +#: ../src/GBaseApp.py:101 +msgid "level of messages to display (e.g., \"--debug-level 5\" displays " +msgstr "nivel de mensajes a mostrar (ej. \"--debug-level 5\" muestra " + +#: ../src/GBaseApp.py:102 +msgid "all debugging messages at level 5 or below.)" +msgstr "todos los mensajes de nivel 5 o menor)" + +#: ../src/GBaseApp.py:104 +msgid "Sends all debugging messages to a specified file " +msgstr "Envia todos los mensajes de debug a el archivo especificado " + +#: ../src/GBaseApp.py:105 +msgid "(e.g., \"--debug-file trace.log\" sends all output to \"trace.log\")" +msgstr "(ej. \"--debug-file trace.log\" envia toda la salida al archivo \"trace.log\")" + +#: ../src/GBaseApp.py:107 +msgid "Specifies the location of the connection definition file. " +msgstr "Especifique el dónde está el archivo de definición de conección. " + +#: ../src/GBaseApp.py:108 +msgid " may specify a file name " +msgstr " puede especificar un nombre del archivo" + +#: ../src/GBaseApp.py:109 +msgid "(/usr/local/gnue/etc/connections.conf), " +msgstr "" + +#: ../src/GBaseApp.py:110 +msgid "or a URL location " +msgstr "o un URL de la ubicación " + +#: ../src/GBaseApp.py:111 +msgid "(http://localhost/connections.conf). " +msgstr "" + +#: ../src/GBaseApp.py:112 +msgid "If this option is not specified, the environent variable " +msgstr "Si esta opción no es especificada, la variable de entorno " + +#: ../src/GBaseApp.py:113 +msgid "GNUE_CONNECTIONS is checked." +msgstr "GNUE_CONNECTIONS es chequeada." + +#: ../src/GBaseApp.py:115 +msgid "Displays this help screen." +msgstr "Muestra esta pantalla de ayuda" + +#: ../src/GBaseApp.py:117 +msgid "Displays a list of valid configuration file entries, their purpose, and their default values." +msgstr "Muestra una lista de entradas validas de archivo de configuración, su propósito, y valores por defecto." + +#: ../src/GBaseApp.py:119 +msgid "Generates a groff-formatted man page as a file in the current directory." +msgstr "Genera un archivo en formato \"groff\" en el directorio actual" + +#: ../src/GBaseApp.py:121 +msgid "Run Python's built-in profiler and display the resulting " +msgstr "Ejecuta un un perfil interno Python y muestra el resultado " + +#: ../src/GBaseApp.py:122 +msgid "run statistics." +msgstr "ejecuta estadisticas." + +#: ../src/GBaseApp.py:124 +msgid "Run the app inside Python's built-in debugger " +msgstr "Ejecutar la aplicación con el debuger interno de Python " + +#: ../src/GBaseApp.py:130 +msgid "This application requires Python 2.0 or greater. You are running Python %s" +msgstr "Esta aplicación requiere Python 2.0 or mayor. Esta corriendo Python %s" + +#: ../src/GBaseApp.py:133 +msgid "This application requires Python 2.0 or greater." +msgstr "Esta aplicación requiere Python 2.0 o mayor." + +#: ../src/GBaseApp.py:194 +msgid "The debug_level option (\"-d\") expects a numerical value." +msgstr "La opcion debug_level (\"-d\") espera un valor numérico." + +#: ../src/GBaseApp.py:207 +msgid "The gnue.conf file is incomplete: " +msgstr "El archivo gnue.conf esta incompleto: " + +#: ../src/GBaseApp.py:213 +msgid "%s while reading gnue.conf: " +msgstr "%s mietras se lee gnue.conf: " + +#: ../src/GBaseApp.py:238 :244 +msgid "Unable to load the connections definition file.\n" +msgstr "Imposible cargar el archivo de definiciones de conección.\n" + +#: ../src/GBaseApp.py:239 +msgid "\n The connections file is in an invalid format. " +msgstr "\n El archivo de conección tiene un formato invalido. " + +#: ../src/GBaseApp.py:240 +msgid "\n %s" +msgstr "\n %s" + +#: ../src/GBaseApp.py:245 +msgid "\n The connections file specified either does " +msgstr "\n El archivo de conecciones especifica o " + +#: ../src/GBaseApp.py:246 +msgid "\n not exist or is not readable by your account.\n" +msgstr "\n que no exista o que no se lea por su cuenta.\n" + +#: ../src/GBaseApp.py:247 +msgid "\n Location: \"%s\"" +msgstr "\n Ubicación: \"%s\"" + +#: ../src/GBaseApp.py:255 +msgid "" +"\n" +"%s\n" +"Version %s\n" +msgstr "" +"\n" +"%s\n" +"Versión %s\n" + +#: ../src/GBaseApp.py:256 +msgid "GNUe Common Version %s\n" +msgstr "GNUe Versión Común %s\n" + +#: ../src/GBaseApp.py:314 +msgid "" +"Usage: %s %s\n" +"\n" +"%s\n" +"\n" +"Available command line options:\n" +"%s" +msgstr "" +"Use: %s %s\n" +"\n" +"%s\n" +"\n" +"Opciones de linea de comando disponibles:\n" +"%s" + +#: ../src/GBaseApp.py:316 +msgid "%s\n" +msgstr "" + +#: ../src/GBaseApp.py:482 +msgid "Error: %s" +msgstr "" + +#: ../src/GBaseApp.py:485 +msgid "" +"\n" +"For help, type:\n" +" %s --help\n" +msgstr "" +"\n" +"Para ayuda, tipee:\n" +" %s --help\n" + +#: ../src/GComm.py:48 +msgid "GComm adapter '%s' does not support clients" +msgstr "Adaptador GComm '%s' no soporta clientes" + +#: ../src/GComm.py:116 +msgid "GComm adapter '%s' does not support servers" +msgstr "Adaptador GComm '%s' no soporta servers" + +#: ../src/GConfig.py:108 +msgid "The file has duplicate source definitions." +msgstr "El archivo tiene duplicadas la definición de fuente de datos" + +#: ../src/GConfig.py:110 +msgid "The file has no source definitions." +msgstr "El archivo no tiene una fuente de definiciones" + +#: ../src/GConfig.py:112 +msgid "The file cannot be parsed. %s :: %s" +msgstr "El archivo no puede ser parceado. %s :: %s" + +#: ../src/GConfig.py:113 +msgid "The file cannot be parsed." +msgstr "El archivo no puede ser parceado" + +#: ../src/GConfig.py:189 +msgid "Unable to read the GNUE_INSTALLED_SITE_CFG file... There is a problem with your installation" +msgstr "No se puede leer el archivo GNUE_INSTALLED_SITE_CFG .... Hay algún problema en la instalación" + +#: ../src/GConnections.py:77 +msgid "" +"The connections file has duplicate source definitions.\n" +"\n" +"File: %s" +msgstr "" +"El archivo de configuración tiene duplicada la definición de fuente de datos.\n" +"\n" +"Archivo: %s" + +#: ../src/GConnections.py:81 +msgid "" +"The connections file has no source definitions.\n" +"\n" +"File: %s" +msgstr "" +"El archivo de conección no tiene fuente de datos\n" +"\n" +"Archivo: %s" + +#: ../src/GConnections.py:85 +msgid "" +"The connections file cannot be parsed.\n" +"\n" +"File: %s" +msgstr "" +"El archivo de conección no puede ser parseado.\n" +"\n" +"Archivo: %s" + +#: ../src/GConnections.py:134 :169 +msgid "" +"The connections file does not contain a definition \n" +" for \"%s\".\n" +"\n" +"File: %s" +msgstr "" +"El archivo de conección no contiene una definición \n" +" para \"%s\".\n" +"\n" +"Archivo: %s" + +#: ../src/GConnections.py:251 +msgid "" +"Unable to log in after 4 attempts.\n" +"\n" +"Error: %s" +msgstr "" +"Imposible loguear despues de 4 intentos.\n" +"\n" +"Error: %s" + +#: ../src/GConnections.py:256 +msgid "User canceled the login request." +msgstr "El usuario canselo el requerimiento de login." + +#: ../src/GConnections.py:271 +msgid "No database driver found for provider type '%s'" +msgstr "Driver de Base de datos no encontrado para el tipo de proveedor '%s'" + +#: ../src/GConnections.py:279 +msgid "DB Driver '%s' does not support source type '%s'" +msgstr "DB Driver '%s' no soporta el tipo '%s'" + +#: ../src/GDataObjects.py:390 +msgid "Attempted to insert into a read only datasource" +msgstr "Intentando insertar dentro de un datasource de lectura solamente" + +#: ../src/GDataObjects.py:610 +msgid "Attempted to modify read only field '%s'" +msgstr "Intentando modificar un campo de lectura solamente '%s'" + +#: ../src/GDataObjects.py:640 +msgid "Attempted to delete from a read only datasource" +msgstr "Intentando borrar de un datasource de lectura solamente" + +#: ../src/GDataSource.py:248 +msgid "Detail source '%s' references non-existant master '%s'" +msgstr "" + +#: ../src/GDateTime.py:70 +msgid "Not a valid date" +msgstr "" + +#: ../src/GParser.py:100 +msgid "Error loading %s: empty definition file" +msgstr "" + +#: ../src/GParser.py:102 +msgid "Error loading %s: not a valid %s definition (expected: %s, got: %s)" +msgstr "" + +#: ../src/GParser.py:209 +msgid "Error processing <%s> tag [I do not know what a <%s> tag does]" +msgstr "" + +#: ../src/GParser.py:221 +msgid "Error processing <%s> tag [I do not recognize the \"%s\" attribute" +msgstr "" + +#: ../src/GParser.py:223 +msgid "Error processing <%s> tag [invalid type for \"%s\" attribute; value is \"%s\"]" +msgstr "" + +#: ../src/GParser.py:228 +msgid "Error processing <%s> tag [\"%s\" attribute should be unique; duplicate value is \"%s\"]" +msgstr "Error porcesando tag <%s> [el atributo \"%s\" debe ser único; el valor duplicado es \"%s\"]" + +#: ../src/GParser.py:239 +msgid "Error processing <%s> tag [required attribute \"%s\" not present]" +msgstr "Error procesando el tag <%s> [atributo obligatorio \"%s\" no presente]" + +#: ../src/GParser.py:274 +msgid "WARNING: Markup includes namespaces, but the current tool does not include namespace support!" +msgstr "" + +#: ../src/GServerApp.py:57 +msgid "Do not send the server into the background. For a POSIX system, " +msgstr "" + +#: ../src/GServerApp.py:58 +msgid "this option keeps the server process from forking and detaching " +msgstr "" + +#: ../src/GServerApp.py:59 +msgid "from its controlling terminal." +msgstr "" + +#: ../src/GTypecast.py:156 +msgid "Whole numbers must be positive or 0" +msgstr "" + +#: ../src/GTrigger.py:587 :601 ../../forms/src/GFTrigger.py:85 +msgid "Invalid trigger " +msgstr "" + +#: ../src/RuntimeSettings.py:92 :95 +msgid "\nWarning: Unable to save session data to %s\n" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:125 +msgid "Missing Binding information. Please add binding " +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:126 +msgid "information for %s " +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:143 +msgid "GNURPC can't bind service '%s' to service '%s'" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:149 +msgid "GNURPC: cannot bind service '%s' to %s" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:172 +msgid "GNURPC can't bind method/attribut '%s' to service '%s'" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:270 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:166 +msgid "Dispatching: " +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:306 +msgid "Server XML-RPC method '%s' is not " +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:307 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:235 +msgid "bound to real method" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:311 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:238 +msgid "Server does not have XML-RPC " +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:312 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:239 +msgid "procedure %s" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:353 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:295 +msgid "Internal Server XML-RPC error: method type" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:354 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:296 +msgid "(get/set attribute) couldn't be detected (method %s)" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:368 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:246 +msgid "Server XML-RPC " +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:369 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:247 +msgid "procedure %s accepts just %s as attributs" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:385 +msgid "No help available for %s" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:388 :400 +msgid "InvalidMethodName" +msgstr "" + +#: ../src/commdrivers/_directory/DirectoryServer.py:389 :401 +msgid "Requested method does not exist" +msgstr "" + +#: ../src/commdrivers/_helpers/RpcDoc.py:44 +msgid "GNUe RPC Documentation Generator" +msgstr "" + +#: ../src/commdrivers/_helpers/RpcDoc.py:46 +msgid "Error: the module %s does not exist or cannot be loaded" +msgstr "Error: el modulo %s no existe o no puede ser cargado" + +#: ../src/commdrivers/pyro/CommDriver.py:42 +msgid "\nUnable to load pyro. To use the PYRO interface, \n" +msgstr "\nImposible cargar pyro. Para usar la Interface PYRO,\n" + +#: ../src/commdrivers/pyro/CommDriver.py:43 +msgid "please install Pyro from:\n" +msgstr "Instale Pyro desde:\n" + +#: ../src/commdrivers/proxy/CommDriver.py:61 +msgid "Proxy client adapter should be called with the server object" +msgstr "El cliente del adaptador proxy debe ser llamado con el servidor de objetos" + +#: ../src/commdrivers/pw_xmlrpc/ClientAdapter.py:76 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:68 +msgid "\nUnable to load xmlrpclib. To use the XML-RPC interface, \n" +msgstr "\nImposible cargar xmlrpclib. Para usar la interface XML-RPC,\n" + +#: ../src/commdrivers/pw_xmlrpc/ClientAdapter.py:77 +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:69 +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:76 +#: ../src/commdrivers/xmlrpc/ServerAdapter.py:62 +msgid "please install xmlrpc from:\n" +msgstr "instale xmlrpc desde:\n" + +#: ../src/commdrivers/pw_xmlrpc/ClientAdapter.py:115 +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:177 +msgid "To use XML-RPC, you must either specify a 'url' or\n" +msgstr "Para usar XML-RPC, debe o especificar una 'url' o\n" + +#: ../src/commdrivers/pw_xmlrpc/ClientAdapter.py:116 +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:178 +msgid "a 'host' and 'port' setting." +msgstr "un 'servidor' y definir un 'puerto'." + +#: ../src/commdrivers/pw_xmlrpc/ClientAdapter.py:119 +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:181 +msgid "Unable to initialize the XML-RPC interface at %s" +msgstr "Imposible inicializar la interface XML-RPC en %s" + +#: ../src/commdrivers/pw_xmlrpc/RpcDoc.py:66 :77 :99 +#: ../src/commdrivers/xmlrpc/RpcDoc.py:66 :77 :88 :99 +msgid "'doc' command expects a .grpc file as its argument." +msgstr "" + +#: ../src/commdrivers/pw_xmlrpc/RpcDoc.py:169 +#: ../src/commdrivers/xmlrpc/RpcDoc.py:182 +msgid "RpcDoc.py has to be called with an command argument. " +msgstr "" + +#: ../src/commdrivers/pw_xmlrpc/RpcDoc.py:170 +#: ../src/commdrivers/xmlrpc/RpcDoc.py:183 +msgid "call 'RpcDoc.py help' for more information." +msgstr "" + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:121 +#: ../src/commdrivers/xmlrpc/ServerAdapter.py:92 +msgid "Required parameter \"port\" not supplied" +msgstr "Parametro obligatorio \"port\" no provisto" + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:187 +msgid "Wrong format of object handle " +msgstr "Formato incorrecto de manejador de objetos " + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:188 +msgid "in method call %s" +msgstr "en el metodo %s" + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:201 +msgid "Internal XMLRPC server error: method %s can be " +msgstr "Error interno del servidor XMLRPC: metodo %s puede ser " + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:203 +msgid "found in the directory (build out of a .grpc file)," +msgstr "encontrado en el directorio (fuera de un archivo .grpc), " + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:204 +msgid " but the object doesn't contain this method/attribut." +msgstr " pero el objeto no contiene este metodo/atributo." + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:205 +msgid " Please check you .grpc file for wrong return types." +msgstr "" + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:234 +msgid "Server XML-RPC method %s is not " +msgstr "" + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:452 +msgid "Object handle not returned" +msgstr "" + +#: ../src/commdrivers/pw_xmlrpc/ServerAdapter.py:460 +msgid "Invalid object handle" +msgstr "" + +#: ../src/commdrivers/soap/CommDriver.py:45 +msgid "\nUnable to load soaplib. To use the SOAP interface, \n" +msgstr "" + +#: ../src/commdrivers/soap/CommDriver.py:46 +msgid "please install soaplib from:\n" +msgstr "" + +#: ../src/commdrivers/sockets/CommDriver.py:85 +msgid "Your configuration references a file-based sockets connection.\n" +msgstr "" + +#: ../src/commdrivers/sockets/CommDriver.py:86 +msgid "However, your operating system does not support file-based sockets." +msgstr "" + +#: ../src/commdrivers/sockets/CommDriver.py:97 +msgid "Unable to initialize the requested socket located at %s" +msgstr "" + +#: ../src/commdrivers/sockets/CommDriver.py:114 +msgid "To use the sockets commdriver, you must specify either a sockets" +msgstr "" + +#: ../src/commdrivers/sockets/CommDriver.py:115 +msgid "\nfile or a host and port number. Please see documentation." +msgstr "" + +#: ../src/commdrivers/sockets/CommDriver.py:119 +msgid "Unable to initialize the requested socket located at %s:%s" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:75 +#: ../src/commdrivers/xmlrpc/ServerAdapter.py:61 +msgid "\nUnable to load xmlrpc. To use the XML-RPC interface, \n" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:78 +msgid "the appropriate DEBIAN package is python-xmlrpc.deb" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:195 +msgid "Unable to initialize the XML-RPC interface at %s: " +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:196 +msgid "Connection refused" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:269 +msgid "Unable to connect to XML-RPC server " +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:270 +msgid "" +"at '%s' \n" +"(connection refused)\n" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:271 +msgid "please check if the server is running" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:288 +msgid "Service/Command %s does not exist on the server" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:295 +msgid "%s" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:301 +msgid "Error '%s' occured on server connected" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ClientAdapter.py:307 +msgid "Unknown XMLRPC Error: '%s' of type '%s'" +msgstr "" + +#: ../src/commdrivers/xmlrpc/RpcDoc.py:105 +msgid "Unrecognized XML-RPC doc command: %s" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ServerAdapter.py:64 +msgid "the appropriate DEBIAN package is python-xmlrpc" +msgstr "" + +#: ../src/commdrivers/xmlrpc/ServerAdapter.py:159 +msgid "Internal server error occured:\n" +msgstr "" + +#: ../src/dbdrivers/cxoracle/DBdriver.py:47 +msgid "Driver not installed: cx_Oracle for Oracle 8.x [%s]" +msgstr "" + +#: ../src/dbdrivers/db2/DBdriver.py:50 +msgid "Driver not installed: db2 for DB2 [%s]" +msgstr "" + +#: ../src/dbdrivers/_dbsig/DBdriver.py:366 +#: ../src/dbdrivers/geas/DBdriver.py:234 ../src/dbdrivers/msado/DBdriver.py:221 +#: ../src/dbdrivers/odbc/DBdriver.py:398 +msgid "Condition element \"%s\" expects at least %s arguments; found %s" +msgstr "" + +#: ../src/dbdrivers/_dbsig/DBdriver.py:370 +#: ../src/dbdrivers/geas/DBdriver.py:238 ../src/dbdrivers/msado/DBdriver.py:225 +#: ../src/dbdrivers/odbc/DBdriver.py:402 +msgid "Condition element \"%s\" expects at most %s arguments; found %s" +msgstr "" + +#: ../src/dbdrivers/_dbsig/DBdriver.py:379 +#: ../src/dbdrivers/geas/DBdriver.py:247 ../src/dbdrivers/msado/DBdriver.py:234 +#: ../src/dbdrivers/odbc/DBdriver.py:411 +msgid "Condition clause \"%s\" is not supported by this db driver." +msgstr "" + +#: ../src/dbdrivers/geas/DBdriver.py:48 +msgid "Failed to load CORBA module." +msgstr "Falla al cargar modulos CORBA" + +#: ../src/dbdrivers/geas/DBdriver.py:49 +msgid "Please see http://orbit-python.sault.org/ for the required python CORBA bindings" +msgstr "" + +#: ../src/dbdrivers/geas/DBdriver.py:147 +msgid "Unable to connect to GEAS. Is it running?" +msgstr "" + +#: ../src/dbdrivers/geas/DBdriver.py:261 +msgid "Conditions" +msgstr "" + +#: ../src/dbdrivers/informix/DBdriver.py:50 +msgid "Driver not installed: Kinfxdb for Informix [%s]" +msgstr "" + +#: ../src/dbdrivers/ingres/DBdriver.py:51 +msgid "Driver not installed: ingmod for Ingres/Ingres II/OpenIngres [%s]" +msgstr "" + +#: ../src/dbdrivers/interbase/DBdriver.py:49 +msgid "Driver not installed: Kinterbasdb for Interbase [%s]" +msgstr "" + +#: ../src/dbdrivers/mysql/DBdriver.py:44 +msgid "\nCould not load MySQLdb. For MySQL support, please install \n" +msgstr "" + +#: ../src/dbdrivers/mysql/DBdriver.py:45 +msgid "mysql-python 0.9.0 or later from" +msgstr "" + +#: ../src/dbdrivers/mysql/DBdriver.py:47 +msgid "Error: %s" +msgstr "" + +#: ../src/dbdrivers/msado/DBdriver.py:46 +msgid "" +"Driver not installed: ADO [win32all COMM drivers]\n" +"\n" +"[%s" +msgstr "" + +#: ../src/dbdrivers/mxodbc/DBdriver.py:52 +msgid "" +"Driver not installed: ODBC\n" +"Grab mxODBC from " +msgstr "" +"Driver no instalado: ODBC\n" +"Grab mxODBC desde " + +#: ../src/dbdrivers/mxodbc/DBdriver.py:82 +msgid "Invalid service string for ODBC driver.\n" +msgstr "String de servicio invalido para diver ODBC.\n" + +#: ../src/dbdrivers/mxodbc/DBdriver.py:83 +msgid "Format: service=\"Backend|DSNString\"" +msgstr "Formato: service=\"Backend|DSNString\"" + +#: ../src/dbdrivers/mxodbc/DBdriver.py:86 +msgid "Unable to load the ODBC drivers for %s" +msgstr "No se puede cargar el driver ODBC para %s" + +#: ../src/dbdrivers/odbc/DBdriver.py:46 +msgid "" +"Driver not installed: win32all ODBC driver\n" +"\n" +"[%s" +msgstr "" +"Driver no instalado: win32all ODBC driver\n" +"\n" +"[%s]" + +#: ../src/dbdrivers/oracle/DBdriver.py:48 +msgid "Driver not installed: DCOracle2 [%s]" +msgstr "Driver no instalado: DCOracle2 [%s]" + +#: ../src/dbdrivers/postgresql/DBdriver.py:43 +msgid "Driver not installed: pygresql for PostgreSQL [%s]" +msgstr "Driver no instalado: pygresql para PostgreSQL [%s]" + +#: ../src/dbdrivers/sapdb/DBdriver.py:51 +msgid "" +"Driver not installed: sapdbapi for SAP-DB 7.x \n" +"[%s]" +msgstr "" +"Driver no instalado: sapdbapi para SAP-DB 7.x \n" +"[%s]" + +#: ../src/dbdrivers/sybase/DBdriver.py:51 +msgid "Driver not installed: Sybase.py for Sybase ASE 11.0/11.9 [%s]" +msgstr "Driver no instalado: Sybase.py para Sybase ASE 11.0/11.9 [%s]" + +#: ../src/dbdrivers/sqlrelay/DBdriver.py:51 +msgid "" +"Driver not installed: SQLRelay Python API\n" +"[%s]" +msgstr "" +"Driver no instalado: SQLRelay Python API\n" +"[%s]" + +#: ../src/FormatMasks/BaseMask.py:111 +msgid "The requested format mask \"%s\" is not defined for %s fields" +msgstr "El formato de mascara requerido \"%s\" no esta definido para los campos %s" + +#: ../src/FormatMasks/BaseMask.py:125 +msgid "Unexpected character \"%s\" in %s mask." +msgstr "Caracter no esperado \"%s\" en mascara %s" + +#: ../src/FormatMasks/BaseMask.py:153 +msgid "Starting cursor: %s; shift: %s" +msgstr "Comienzo cursor: %s; corro a: %s" + +#: ../src/FormatMasks/BaseMask.py:165 +msgid "Ending cursor: %s; shift: %s" +msgstr "Fin cursor: %s; corro a: %s" + +#: ../src/FormatMasks/BaseMask.py:225 +msgid "*** moveCursorRelative(%s)" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:230 +msgid "relative=%s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:231 +msgid "direction=%s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:235 +msgid "cursor #1: %s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:244 +msgid "cursor #2: %s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:256 :326 +msgid "pos=%s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:257 :263 :272 +msgid "section=%s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:260 +msgid "cursor #2b: %s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:267 +msgid "cursor #3: %s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:275 +msgid "cursor #4: %s" +msgstr "" + +#: ../src/FormatMasks/BaseMask.py:279 +msgid "New cursor position: %s" +msgstr "Nueva posicion del cursor: %s" + +#: ../src/FormatMasks/BaseMask.py:367 +msgid "after processEdit, index=%s;cursor=%s" +msgstr "despues de processEdit, index=%s; cursor%s" + +#: ../src/FormatMasks/DateMask.py:63 ../src/FormatMasks/NumberMask.py:61 +#: ../src/FormatMasks/TextMask.py:50 +msgid "January" +msgstr "Enero" + +#: ../src/FormatMasks/DateMask.py:64 ../src/FormatMasks/NumberMask.py:62 +#: ../src/FormatMasks/TextMask.py:51 +msgid "February" +msgstr "Febrero" + +#: ../src/FormatMasks/DateMask.py:65 ../src/FormatMasks/NumberMask.py:63 +#: ../src/FormatMasks/TextMask.py:52 +msgid "March" +msgstr "Marzo" + +#: ../src/FormatMasks/DateMask.py:66 ../src/FormatMasks/NumberMask.py:64 +#: ../src/FormatMasks/TextMask.py:53 +msgid "April" +msgstr "Abril" + +#: ../src/FormatMasks/DateMask.py:67 :80 ../src/FormatMasks/NumberMask.py:65 +#: :78 ../src/FormatMasks/TextMask.py:54 :67 +msgid "May" +msgstr "Mayo" + +#: ../src/FormatMasks/DateMask.py:68 ../src/FormatMasks/NumberMask.py:66 +#: ../src/FormatMasks/TextMask.py:55 +msgid "June" +msgstr "Junio" + +#: ../src/FormatMasks/DateMask.py:69 ../src/FormatMasks/NumberMask.py:67 +#: ../src/FormatMasks/TextMask.py:56 +msgid "July" +msgstr "Julio" + +#: ../src/FormatMasks/DateMask.py:70 ../src/FormatMasks/NumberMask.py:68 +#: ../src/FormatMasks/TextMask.py:57 +msgid "August" +msgstr "Agosto" + +#: ../src/FormatMasks/DateMask.py:71 ../src/FormatMasks/NumberMask.py:69 +#: ../src/FormatMasks/TextMask.py:58 +msgid "September" +msgstr "Septiembre" + +#: ../src/FormatMasks/DateMask.py:72 ../src/FormatMasks/NumberMask.py:70 +#: ../src/FormatMasks/TextMask.py:59 +msgid "October" +msgstr "Octubre" + +#: ../src/FormatMasks/DateMask.py:73 ../src/FormatMasks/NumberMask.py:71 +#: ../src/FormatMasks/TextMask.py:60 +msgid "November" +msgstr "Noviembre" + +#: ../src/FormatMasks/DateMask.py:74 ../src/FormatMasks/NumberMask.py:72 +#: ../src/FormatMasks/TextMask.py:61 +msgid "December" +msgstr "Diciembre" + +#: ../src/FormatMasks/DateMask.py:76 ../src/FormatMasks/NumberMask.py:74 +#: ../src/FormatMasks/TextMask.py:63 +msgid "Jan" +msgstr "Ene" + +#: ../src/FormatMasks/DateMask.py:77 ../src/FormatMasks/NumberMask.py:75 +#: ../src/FormatMasks/TextMask.py:64 +msgid "Feb" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:78 ../src/FormatMasks/NumberMask.py:76 +#: ../src/FormatMasks/TextMask.py:65 +msgid "Mar" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:79 ../src/FormatMasks/NumberMask.py:77 +#: ../src/FormatMasks/TextMask.py:66 +msgid "Apr" +msgstr "Abr" + +#: ../src/FormatMasks/DateMask.py:81 ../src/FormatMasks/NumberMask.py:79 +#: ../src/FormatMasks/TextMask.py:68 +msgid "Jun" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:82 ../src/FormatMasks/NumberMask.py:80 +#: ../src/FormatMasks/TextMask.py:69 +msgid "Jul" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:83 ../src/FormatMasks/NumberMask.py:81 +#: ../src/FormatMasks/TextMask.py:70 +msgid "Aug" +msgstr "Ago" + +#: ../src/FormatMasks/DateMask.py:84 ../src/FormatMasks/NumberMask.py:82 +#: ../src/FormatMasks/TextMask.py:71 +msgid "Sep" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:85 ../src/FormatMasks/NumberMask.py:83 +#: ../src/FormatMasks/TextMask.py:72 +msgid "Oct" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:86 ../src/FormatMasks/NumberMask.py:84 +#: ../src/FormatMasks/TextMask.py:73 +msgid "Nov" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:87 ../src/FormatMasks/NumberMask.py:85 +#: ../src/FormatMasks/TextMask.py:74 +msgid "Dec" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:89 ../src/FormatMasks/NumberMask.py:87 +#: ../src/FormatMasks/TextMask.py:76 +msgid "Sunday" +msgstr "Domingo" + +#: ../src/FormatMasks/DateMask.py:90 ../src/FormatMasks/NumberMask.py:88 +#: ../src/FormatMasks/TextMask.py:77 +msgid "Monday" +msgstr "Lunes" + +#: ../src/FormatMasks/DateMask.py:91 ../src/FormatMasks/NumberMask.py:89 +#: ../src/FormatMasks/TextMask.py:78 +msgid "Tuesday" +msgstr "Martes" + +#: ../src/FormatMasks/DateMask.py:92 ../src/FormatMasks/NumberMask.py:90 +#: ../src/FormatMasks/TextMask.py:79 +msgid "Wednesday" +msgstr "Miercoles" + +#: ../src/FormatMasks/DateMask.py:93 ../src/FormatMasks/NumberMask.py:91 +#: ../src/FormatMasks/TextMask.py:80 +msgid "Thursday" +msgstr "Jueves" + +#: ../src/FormatMasks/DateMask.py:94 ../src/FormatMasks/NumberMask.py:92 +#: ../src/FormatMasks/TextMask.py:81 +msgid "Friday" +msgstr "Viernes" + +#: ../src/FormatMasks/DateMask.py:95 ../src/FormatMasks/NumberMask.py:93 +#: ../src/FormatMasks/TextMask.py:82 +msgid "Saturday" +msgstr "Sábado" + +#: ../src/FormatMasks/DateMask.py:97 ../src/FormatMasks/NumberMask.py:95 +#: ../src/FormatMasks/TextMask.py:84 +msgid "Sun" +msgstr "Dom" + +#: ../src/FormatMasks/DateMask.py:98 ../src/FormatMasks/NumberMask.py:96 +#: ../src/FormatMasks/TextMask.py:85 +msgid "Mon" +msgstr "Lun" + +#: ../src/FormatMasks/DateMask.py:99 ../src/FormatMasks/NumberMask.py:97 +#: ../src/FormatMasks/TextMask.py:86 +msgid "Tue" +msgstr "Mar" + +#: ../src/FormatMasks/DateMask.py:100 ../src/FormatMasks/NumberMask.py:98 +#: ../src/FormatMasks/TextMask.py:87 +msgid "Wed" +msgstr "Mie" + +#: ../src/FormatMasks/DateMask.py:101 ../src/FormatMasks/NumberMask.py:99 +#: ../src/FormatMasks/TextMask.py:88 +msgid "Thu" +msgstr "Jue" + +#: ../src/FormatMasks/DateMask.py:102 ../src/FormatMasks/NumberMask.py:100 +#: ../src/FormatMasks/TextMask.py:89 +msgid "Fri" +msgstr "Vie" + +#: ../src/FormatMasks/DateMask.py:103 ../src/FormatMasks/NumberMask.py:101 +#: ../src/FormatMasks/TextMask.py:90 +msgid "Sat" +msgstr "Sáb" + +#: ../src/FormatMasks/DateMask.py:170 +msgid "inputMaskPos=%s" +msgstr "" + +#: ../src/FormatMasks/DateMask.py:171 +msgid "inputMaskLen=%s" +msgstr "" + +#: ../src/FormatMasks/NumberMask.py:252 ../src/FormatMasks/TextMask.py:241 +msgid "Invalid Entry" +msgstr "Entrada invalida" + +#: ../../forms/src/GFClient.py:59 +msgid "The currently supported values for are " +msgstr "Los valores actuales para son " + +#: ../../forms/src/GFClient.py:62 +msgid "Disables the splash screen" +msgstr "" + +#: ../../forms/src/GFClient.py:65 +msgid "GNUe Forms is the primary user interface to the GNU Enterprise system." +msgstr "GNUe Forms es la principal interfaz usuario a GNU Enterprise" + +#: ../../forms/src/GFClient.py:104 +msgid "No Forms Definition File Specified." +msgstr "No se especificó un archivo de definición de Forms" + +#: ../../forms/src/GFClient.py:177 +msgid "" +"Unable to open file\n" +"\n" +" %s" +msgstr "" +"Imposible abrir archivo\n" +"\n" +" %s" + +#: ../../forms/src/GFClient.py:181 +msgid "" +"Unable to login to datasource.\n" +"\n" +" %s" +msgstr "" +"Imposible loguearse al datasource\n" +"\n" +" %s" + +#: ../../forms/src/GFClient.py:185 +msgid "" +"Error while communicating with datasource.\n" +"\n" +" %s" +msgstr "" +"Error mientras se comunicaba con el datasource.\n" +"\n" +" %s" + +#: ../../forms/src/GFDisplayHandler.py:140 +msgid "Invalid value '%s' for field" +msgstr "Valor invalido '%s' para campo" + +#: ../../forms/src/GFDisplayHandler.py:152 +msgid "The entered value\n" +msgstr "El valor ingresado\n" + +#: ../../forms/src/GFDisplayHandler.py:154 +msgid "is not a valid entry." +msgstr "no es un ingreso válido" + +#: ../../forms/src/GFDisplayHandler.py:163 +msgid "Cannot modify field. Form is read only" +msgstr "No se puede modificar el campo. Formulario de lectura solamente" + +#: ../../forms/src/GFDisplayHandler.py:170 +msgid "Cannot modify field after initial creation." +msgstr "No se puede modifucar el campo luego de la creación inicial" + +#: ../../forms/src/GFDisplayHandler.py:653 +msgid "Invalid value '%s' for keyed pull-down field" +msgstr "Valor invalid '%s' para clave en campo pull-down" + +#: ../../forms/src/GFForm.py:283 +msgid "Trigger Exception :\n" +msgstr "Excepción en trigger :\n" + +#: ../../forms/src/GFForm.py:396 ../../forms/src/GFInstance.py:363 +msgid "Data not saved. Save changes or clear the form to proceed." +msgstr "Datos no salvados. salve los datos o limpie el formulario a procesar" + +#: ../../forms/src/GFForm.py:417 +msgid "" +"Database query error:\n" +"%s\n" +"%s " +msgstr "" +"Error en consulta a Base de datos:\n" +"%s\n" +"%s" + +#: ../../forms/src/GFForm.py:434 +msgid "Form trigger returned error" +msgstr "" + +#: ../../forms/src/GFForm.py:452 +msgid "Block trigger returned error" +msgstr "Trigger retorna con error" + +#: ../../forms/src/GFForm.py:459 ../../forms/src/GFInstance.py:378 :394 +msgid "Form is readonly" +msgstr "El formulario es de lectura solamente" + +#: ../../forms/src/GFForm.py:467 +msgid "" +"Database commit error:\n" +"%s\n" +"%s " +msgstr "" +"Error en el commit de la Base de datos:\n" +"%s\n" +"%s" + +#: ../../forms/src/GFForm.py:469 +msgid "\n\nGFForm: Unexpected Exception:" +msgstr "\n\nGFForm: Exepcion no experada" + +#: ../../forms/src/GFForm.py:682 +msgid "If i was working then %s would now have focus" +msgstr "Para trabajar con %s debe estar en foco" + +#: ../../forms/src/GFInstance.py:335 +msgid "Invalid numeric value entered." +msgstr "Valor numérico ingresado erroneo" + +#: ../../forms/src/GFInstance.py:367 +msgid "Current data is saved" +msgstr "Datos actuales salvados" + +#: ../../forms/src/GFInstance.py:380 +msgid "Block does not allow delete" +msgstr "El bloque no permite borrar" + +#: ../../forms/src/GFInstance.py:396 +msgid "Block does not allow insert" +msgstr "El bloque no permite inserción" + +#: ../../forms/src/GFInstance.py:517 +msgid "Query from detail blocks currently not supported" +msgstr "Consulta al bloque de detalles actual no soportada" + +#: ../../forms/src/GFInstance.py:603 +msgid "There are no navigable widgets in this form. Unable to display." +msgstr "No hay elementos graficos (widget) en el formulario. Imposible mostrar" + +#: ../../forms/src/GFKeyMapper.py:111 +msgid "Invalid keystroke id '%s' in keymap for '%s'" +msgstr "Identificación de teclas invalida '%s' en el keymap para '%s'" + +#: ../../forms/src/GFKeyMapper.py:115 +msgid "Invalid keystroke combination '%s' in keymap for '%s'" +msgstr "Convinación de teclas invalidas '%s' en el keymap para '%s'" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:142 +msgid "GNU Enterprise Forms" +msgstr "" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:149 +msgid "Version %s" +msgstr "Versión %s" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:159 +msgid "Protected by GNU General Public Licence 2.0" +msgstr "" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:205 +msgid "Save (F6)" +msgstr "Grabar (F6)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:205 :273 +msgid "Save all changes to database." +msgstr "Salvar todos los datos a la base de datos." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:207 +msgid "Clear Form (F11)" +msgstr "Limpiar el formulario (F11)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:207 :286 :286 +msgid "Clear Form" +msgstr "Limpiar el Formulario" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:210 +msgid "&Print" +msgstr "Im&pimir" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:210 +msgid "Perform print routine for this form." +msgstr "Ejecutar la rutina de impresion para este formulario" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:213 +msgid "E&xit" +msgstr "&Salir" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:213 +msgid "Leave the application." +msgstr "Salir de la aplicación" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:217 +msgid "Cut" +msgstr "Cortar" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:217 +msgid "Cut the selected text" +msgstr "Cortar el texto seleccionado" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:219 +msgid "Copy" +msgstr "Copiar" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:219 +msgid "Copy the selected text" +msgstr "Copiar el texto seleccionado" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:221 +msgid "Paste" +msgstr "Pegar" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:221 +msgid "Paste text" +msgstr "Pegar el texto" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:225 +msgid "First Record (Shft+Up)" +msgstr "Primer registro (Shift+Arriba)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:225 :277 +msgid "Navigate to first record in memory." +msgstr "Ir al primer registro en memoria" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:227 +msgid "Previous Record (Up)" +msgstr "Registro previo (Re.Pag.)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:227 :278 +msgid "Navigate to previous record in memory." +msgstr "Ir al registro anterior en memoria" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:229 +msgid "Next Record (Down)" +msgstr "Próximo registro (Av.Pag.)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:229 :279 +msgid "Navigate to next record in memory." +msgstr "Ir al siguiente registro en memoria" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:231 +msgid "Last Record (Shft+Down)" +msgstr "Último Registro (Shift+Av.Pag.)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:231 :280 +msgid "Navigate to last record in memory." +msgstr "Ir al último registro en memoria." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:233 +msgid "Jump to Record... (F2)" +msgstr "Ir al registro (F2)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:233 +msgid "Prompts for a record number to which the system should jump." +msgstr "Número de Registro al cual el sistema debe saltar" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:235 +msgid "New Record (F12)" +msgstr "Próximo registro (F12)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:235 :274 +msgid "Create a new record for data input." +msgstr "Crea a nuevo registro para ingreso de datos" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:237 +msgid "Mark Record for Delete (F5)" +msgstr "Marcar registro para borrar (F5)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:237 :275 +msgid "Mark record for removal at next commit." +msgstr "Marcar como borrado en el próximo commit." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:240 +msgid "Next Block (PgDn)" +msgstr "Próximo Bloque (Re.Pag.)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:240 +msgid "Navigate to next data block." +msgstr "Ir al proximo bloque de datos" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:242 +msgid "Previous Block (PgUp)" +msgstr "Bloque Previo (PgUp)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:242 +msgid "Navigate to previous data block." +msgstr "Ir al bloque de datos previo." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:245 +msgid "Enter Query (F8)" +msgstr "Ingresar Consulta (F8)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:245 :283 +msgid "Switch to input query mask mode." +msgstr "Cambiar al modo de ingreso de consulta." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:247 +msgid "Execute Query (F9)" +msgstr "Ejecutar Consulta (F9)" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:247 :284 +msgid "Execute query using current mask." +msgstr "Ejecutar una consulta usando la mascara actual" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:251 +msgid "&About..." +msgstr "A&cerca...." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:251 +msgid "Display info about GNUe Forms." +msgstr "Mostrar información acerca GNUe Forms" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:255 +msgid "&File" +msgstr "&Archivo" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:256 +msgid "&Edit" +msgstr "&Editar" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:257 +msgid "&Data" +msgstr "&Datos" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:258 +msgid "&Help" +msgstr "A&yuda" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:273 +msgid "Save Changes" +msgstr "Salvar los Cambios" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:274 +msgid "Insert Record" +msgstr "Agregar un registro" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:275 +msgid "Delete Record" +msgstr "Borrar un registro" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:277 +msgid "First Record" +msgstr "Primer registro" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:278 +msgid "Previous Record" +msgstr "Registro Previo" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:279 +msgid "Next Record" +msgstr "Próximo Registro" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:280 +msgid "Last Record" +msgstr "Último registro" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:281 +msgid "Jump to Record" +msgstr "Saltar al registro" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:281 +msgid "Navigate to user specified record in memory." +msgstr "Ir a un registro específico del usuario en memoria." + +#: ../../forms/src/uidrivers/wx/UIdriver.py:283 +msgid "Prepare Query" +msgstr "Prepare una consulta" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:284 +msgid "Execute Query" +msgstr "Ejecutar una consulta" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:287 :287 +msgid "Exit Form" +msgstr "Salir del Formulario" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:509 +msgid "Enter record number to jump to" +msgstr "Ingrese Número de registro a saltar" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:510 +msgid "Which record?" +msgstr "¿Cúal registro?" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:878 +msgid "GNUE Forms" +msgstr "" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:879 +msgid " Version : " +msgstr " Versión : " + +#: ../../forms/src/uidrivers/wx/UIdriver.py:880 +msgid " Driver : UIwxpython" +msgstr "" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:881 +msgid "-= Form Info =-" +msgstr "Información del Formulario" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:882 +msgid " Name : " +msgstr " Nombre : " + +#: ../../forms/src/uidrivers/wx/UIdriver.py:883 +msgid " Version: " +msgstr " Versión: " + +#: ../../forms/src/uidrivers/wx/UIdriver.py:884 +msgid " Author : " +msgstr " Autor: " + +#: ../../forms/src/uidrivers/wx/UIdriver.py:885 +msgid " Description:" +msgstr " Descripción:" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:888 +msgid "About" +msgstr "Acerca" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:1064 +msgid "" +"Login required for\n" +"\"%s\"" +msgstr "" +"Logueo requerido para\n" +"\"%s\"" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:1066 +msgid "Login required for %s" +msgstr "Logueo requerido para %s" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:1068 +msgid "GNU Enterprise: Login to %s" +msgstr "GNU Enterprice: Login a %s" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:1114 +msgid "Login" +msgstr "" + +#: ../../forms/src/uidrivers/wx/UIdriver.py:1115 +msgid "Cancel" +msgstr "Cancelar" diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFDisplayHandler.py up/forms/src/GFDisplayHandler.py --- head/forms/src/GFDisplayHandler.py Wed Nov 6 15:04:05 2002 +++ up/forms/src/GFDisplayHandler.py Wed Nov 6 19:51:17 2002 @@ -582,11 +582,8 @@ # TODO: Replace with format mask def _buildDisplayHelper(self, value, editing): - if editing: - format = "%m/%d/%Y" - else: - format = "%m/%d/%y" - + format = "%d/%m/%Y" + if value in (None,""): return "" try: @@ -607,11 +604,11 @@ # Support for quick entry like '123102' for '12/31/02' if len(value) in (6,8) and string.find(value,'/') == -1: - month = value[:2] - day = value[2:4] + day = value[:2] + month = value[2:4] year = value[4:] else: - month, day, year = string.split(value,'/') + day, month, year = string.split(value,'/') year = int(year) if year < 100: @@ -714,7 +711,43 @@ return 0 return 1 +############################################################################# +# +# Handler for textLookups +# +class TextLookupDisplayHandler(FieldDisplayHandler): + + def __init__(self, *args, **params): + FieldDisplayHandler.__init__(self, *args, **params) + + def beginEdit(self, event): + pass + + # TODO: Replace with format mask + def _buildDisplayHelper(self, value, editing): + if value in (None,""): + return "" + descr = "" + if hasattr(self.entry,'fk_source'): + if hasattr(self.entry,'fk_key'): + foreignKeyContent = string.split(self.entry.fk_key,'.') + if len(foreignKeyContent) > 1: + tmpFieldName = foreignKeyContent[0]+'.'+foreignKeyContent[1] + else: + tmpFieldName = foreignKeyContent[0] + + lResultSet = self.entry._fk_datasource.createResultSet({tmpFieldName:value}) + if (lResultSet.firstRecord()): + if hasattr(self.entry,'fk_description'): + descr = "%s" % lResultSet.current.getField(self.entry.fk_description) + + return descr + + def _buildDisplay(self): + self.display = self._buildDisplayHelper(self.value, 0) + def endEdit(self,event): + pass ############################################################################# # diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFForm.py up/forms/src/GFForm.py --- head/forms/src/GFForm.py Mon Nov 11 10:34:09 2002 +++ up/forms/src/GFForm.py Fri Nov 15 18:28:55 2002 @@ -47,7 +47,20 @@ # Defines which objects are "Tab Stops" TabStops = ('GFEntry','GFButton') -class GFForm(GRootObj, GFObj, events.EventAware): +class GFMainMenuBar(GFObj, events.EventAware): + def __init__(self, parent=None, window=None): + GFObj.__init__(self, parent) + self._type = "GFMainMenuBar" + self._currentObject = [self] + +class GFMainToolBar(GFObj, events.EventAware): + def __init__(self, parent=None, window=None): + GFObj.__init__(self, parent) + self._type = "GFMainToolBar" + self._currentObject = [self] + + +class GFForm(GFObj, GRootObj, events.EventAware): def __init__(self, parent=None, app=None): # TODO: with a little tweaking we can now stop passing GFParser.getXMLelements GRootObj.__init__(self, 'form', GFParser.getXMLelements, GFParser) @@ -103,6 +116,8 @@ 'setStatusText':{'function':self.triggerSetStatusText, 'global': 1, }, + 'genericBox':{'function':self.triggerGenericBox}, + 'callTrigger':{'function':self.triggerCallTrigger}, 'getParameter':{'function':self.getParameter, 'global': 1, }, @@ -669,4 +684,11 @@ except KeyError: raise KeyError, "Trigger attempted to get unknown feature %s" % feature + def triggerGenericBox(self,message, buttonSet): + event = events.Event('genericBox', [message,buttonSet]) + self.dispatchEvent(event) + return event.data[0] + def triggerCallTrigger(self, triggerName): + self._triggerDictionary[triggerName](self) + diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFInstance.py up/forms/src/GFInstance.py --- head/forms/src/GFInstance.py Fri Nov 8 12:59:58 2002 +++ up/forms/src/GFInstance.py Thu Nov 14 19:01:12 2002 @@ -90,6 +90,7 @@ 'requestROLLBACK' : self.executeRollback, 'requestENTERQUERY' : self.requestQuery, 'requestEXECQUERY' : self.executeQuery, + 'requestSCROLL' : self.scroll, # Miscellaneous stuff 'requestEXIT' : self.executeExit, @@ -258,6 +259,29 @@ self.dispatchEvent(events.Event('gotoENTRY',{'object':self._form._currentEntry})) self.updateRecordCounter() self.updateRecordStatus() + + # + # scroll + # + # Called when a scrollbar is pressed. it should detect the type of scroll and call the right thing + def scroll (self, event): + (ev, page)= event.data + # print "->", ev, page + if ev==0: + self.prevRecord (event) + elif ev==1: + event.data= -page+1 + self.jumpRecords (event) + elif ev==2: + # free scroll + # dunno how to handle... + pass + elif ev==3: + event.data= page-1 + self.jumpRecords (event) + elif ev==4: + self.nextRecord (event) + # # previousRecord diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFObjects/GFBlock.py up/forms/src/GFObjects/GFBlock.py --- head/forms/src/GFObjects/GFBlock.py Fri Nov 8 12:50:39 2002 +++ up/forms/src/GFObjects/GFBlock.py Fri Nov 15 19:09:32 2002 @@ -67,6 +67,8 @@ self._autocreate = int(gConfig('autocreate')) self._gap = 0 self._rows = 1 + + self._scrollBars= [] # # Trigger exposure @@ -90,10 +92,20 @@ self._triggerGlobal = 1 self._triggerFunctions={'clear':{'function':self.processClear}, 'gotoRecord':{'function':self.jumpRecord}, - 'newRecord':{'function':self.newRecord}, - 'nextRecord':{'function':self.nextRecord}, - 'prevRecord':{'function':self.prevRecord}, + 'getRecordCount':{'function':self.getRecordCount}, + 'getCurrentRecord':{'function':self.getCurrentRecord}, + 'isSaved':{'function':self.isSaved}, 'deleteRecord':{'function':self.deleteRecord}, + 'isEmpty':{'function':self.isEmpty}, + 'nextRecord':{'function':self.nextRecord}, + 'lastRecord':{'function':self.lastRecord}, + 'firstRecord':{'function':self.firstRecord}, + 'prevRecord':{'function':self.prevRecord}, + 'newRecord':{'function':self.newRecord}, + 'initQuery':{'function':self.initQuery}, + 'processQuery':{'function':self.processQuery}, + 'commit':{'function':self.commit}, + 'processRollback':{'function':self.processRollback}, } self._triggerProperties={'parent': {'get':self.getParent}} @@ -173,6 +185,15 @@ object._gap = self._gap + def getResultSet(self): + return self._resultSet + + def getCurrentRecord(self): + return self.getResultSet().getCurrentRecord() + + def getRecordCount(self): + return self._recordCount + # # isSaved # @@ -226,6 +247,9 @@ if adjustment <> 0: self.processTrigger('ON-SWITCH') + # update the scrollbars... + for sb in self._scrollBars: + sb.update (self._currentRecord, self._recordCount) # # newRecord @@ -269,6 +293,13 @@ self._currentRecord = self._resultSet.getRecordNumber() self.switchRecord(jump) + def commit(self): + self.getForm().changeFocus(self) + self.getForm().commit() + + def getForm(self): + return self._form + # # processCommit # @@ -319,6 +350,11 @@ self._currentRecord = 0 self._recordCount = 0 self._dataSourceLink.createEmptyResultSet() + else: + tmpRecord = self._dataSourceLink.getCurrentResultSet().getCurrentRecord() + tmpRecord.getFields().update(tmpRecord.getInitialData()) + tmpRecord.setUpdateFlag(0) + self._dataSourceLink._dataObject.rollback() self.switchRecord(0) @@ -402,6 +438,13 @@ block.processTrigger('POST-QUERY') + # update the scrollbars... + for sb in self._scrollBars: + sb.update (self._currentRecord, self._recordCount) + + def registerScrollBar (self, sb): + self._scrollBars.append (sb) + def _generateConditional(block): conditionLike = {} conditionEq = {} @@ -431,7 +474,3 @@ conditions = {} return conditions - - - - diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFObjects/GFEntry.py up/forms/src/GFObjects/GFEntry.py --- head/forms/src/GFObjects/GFEntry.py Wed Nov 6 15:04:02 2002 +++ up/forms/src/GFObjects/GFEntry.py Fri Nov 15 11:38:03 2002 @@ -85,6 +85,7 @@ self._triggerFunctions={'allowedValues':{'function':self.allowedValues,}, 'autofillBySequence':{'function':self.triggerAutofillBySequence}, + 'atomicModify':{'function':self.triggerAtomicModify}, 'isEmpty':{'function':self.isEmpty}, 'resetForeignKey':{'function':self.resetForeignKey}, 'set':{'function':self.triggerSetValue}, @@ -104,6 +105,13 @@ sequenceNumber = self._block._dataSourceLink._dataObject.triggerExtensions.getSequence(sequenceName) self.setValue(sequenceNumber) + def triggerAtomicModify(self,func): + if self.getValue() or self.getValue()!="": + self._block._dataSourceLink._dataObject.triggerExtensions.atomicModify(func=func, \ + field=self.field, \ + dataObject=self._block._dataSourceLink._dataObject,\ + record=self._block._resultSet.current) + def isEmpty(self): return self.getValue() in ("",None) @@ -140,7 +148,15 @@ # Foreign keys # DEPRECATED with 0.4.x if hasattr(self,'foreign_key') and self.foreign_key: - (self.fk_source, self.fk_key) = string.split(self.foreign_key,'.') + fk_data= string.split(self.foreign_key,'.') + if len (fk_data)==2: + # no table + (self.fk_source, self.fk_key) = fk_data + elif len (fk_data)==3: + # with table + (self.fk_source, self.fk_key) = (fk_data[0], "%s.%s" % (fk_data[1], fk_data[2])) + else: + raise "bad forign key reference (name)" del self.foreign_key if hasattr(self,'foreign_key_description') and self.foreign_key_description: self.fk_description = self.foreign_key_description @@ -217,6 +233,9 @@ elif self.style == 'dropdown': self._displayHandler = GFDisplayHandler.DropdownDisplayHandler(self, self._block._form._app.eventController) + elif self.style == 'textlookup': + self._displayHandler = GFDisplayHandler.TextLookupDisplayHandler(self, + self._block._form._app.eventController) elif self.typecast == 'text': self._displayHandler = GFDisplayHandler.TextDisplayHandler(self, self._block._form._app.eventController, @@ -302,9 +321,12 @@ # # allowedValues # - def allowedValues(self): - if not self._allowedValues and hasattr(self,'_fk_datasource'): - rs = self._fk_datasource.createResultSet() + def allowedValues(self, cond=None): + if not self._allowedValues and hasattr(self,'datasource'): + if cond: + rs = self.datasource.createResultSet(cond) + else: + rs = self.datasource.createResultSet() more = rs.firstRecord() self._allowedValues = {"":""} self._allowedValuesDescr = [""] diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFObjects/__init__.py up/forms/src/GFObjects/__init__.py --- head/forms/src/GFObjects/__init__.py Wed Nov 6 15:04:02 2002 +++ up/forms/src/GFObjects/__init__.py Fri Nov 1 13:24:10 2002 @@ -24,4 +24,4 @@ #from GFObj import GFObj -from GFParameter import GFCParam \ No newline at end of file +from GFParameter import GFCParam diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/GFParser.py up/forms/src/GFParser.py --- head/forms/src/GFParser.py Mon Nov 11 10:34:09 2002 +++ up/forms/src/GFParser.py Thu Nov 14 19:02:27 2002 @@ -251,6 +251,7 @@ 'default': {}, 'dropdown': {}, 'checkbox': {}, + 'textlookup': {}, 'label': {} }, 'Default': 'default'}, 'case': { @@ -333,8 +334,11 @@ 'Typecast': GTypecast.whole }, 'y': { 'Required': 1, - 'Typecast': GTypecast.whole } }, - 'ParentTags': ('page','block','box') }, + 'Typecast': GTypecast.whole }, + 'page': { + 'Required': 1, + 'Typecast': GTypecast.whole } }, + 'ParentTags': ('block') }, 'box': { 'BaseClass': GFObjects.GFBox, @@ -541,6 +545,33 @@ 'Typecast': GTypecast.name, 'Default': "char" } }, 'ParentTags': ('form',) }, + + 'maintoolbar': { + 'BaseClass': GFForm.GFMainToolBar, + 'Required': 0, + 'SingleInstance': 1, + 'Attributes': { + 'enabled': { + 'Typecast': GTypecast.boolean, + 'Default': 1, + }, + }, + 'ParentTags': ('form',), + }, + + 'mainmenubar': { + 'BaseClass': GFForm.GFMainMenuBar, + 'Required': 0, + 'SingleInstance': 1, + 'Attributes': { + 'enabled': { + 'Typecast': GTypecast.boolean, + 'Default': 1, + }, + }, + 'ParentTags': ('form',), + }, + } @@ -583,7 +614,8 @@ # entryStyles = {'text': 'Text Field', 'dropdown': 'Drop Down Box', - 'checkbox': 'Check Box' } + 'checkbox': 'Check Box' , + 'textlookup': 'Text Lookup'} ####################################################### # diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/uidrivers/_base/UIdriver.py up/forms/src/uidrivers/_base/UIdriver.py --- head/forms/src/uidrivers/_base/UIdriver.py Wed Nov 6 15:04:05 2002 +++ up/forms/src/uidrivers/_base/UIdriver.py Wed Nov 6 20:20:01 2002 @@ -89,7 +89,7 @@ 'uiABOUT' : self.aboutBox, 'exitApplication' : self.exitApplication, 'msgBoxUI' : self.msgBox, - + 'genericBox' : self.genericBox, # Clipboard contents 'setCLIPBOARD' : self.setClipboardContents, 'getCLIPBOARD' : self.getClipboardContents, @@ -121,6 +121,8 @@ 'GFLabel' : self._stdHandler, 'GFScrollBar' : self._stdHandler, 'GFPage' : self._stdHandler, + 'GFMainToolBar' : self._stdHandler, + 'GFMainMenuBar' : self._stdHandler, } def _stdHandler(self): @@ -304,6 +306,30 @@ dialog = self._DIALOGS['messageBox'](self.mainWindow, message, caption) dialog.showModal() dialog.destroy() + + + # + # genericBox + # + def genericBox(self,event): + message = event.data[0] + caption = "Aviso" + buttonSet = event.data[1] + if len(event.data) > 2: + defaultButton = event.data[2] + else: + defaultButton = -1 + if len(event.data) > 3: + cancelButton = event.data[3] + else: + cancelButton = -1 + + self.genericBox = uiDlg = self._DIALOGS['genericBox'](self.mainWindow, caption) + self.genericBox = dlg = uiDlg.createGenericBox(message, buttonSet) + + dlg.ShowModal() + + event.data = [uiDlg.getResult()] # # updateEntryEditor diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/forms/src/uidrivers/wx/UIdriver.py up/forms/src/uidrivers/wx/UIdriver.py --- head/forms/src/uidrivers/wx/UIdriver.py Mon Nov 11 10:34:10 2002 +++ up/forms/src/uidrivers/wx/UIdriver.py Fri Nov 15 19:16:22 2002 @@ -144,6 +144,7 @@ self._DIALOGS = {'about' :UIAbout, 'messageBox' :UIMessageBox, + 'genericBox' :UIGenericBox, } self._aboutDialog = UIAbout @@ -244,9 +245,33 @@ initFont(self.statusBar,0) - #self.mainWindow.panel = wxPanel(self.mainWindow,-1, wxDefaultPosition,self.mainWindow.GetClientSize()) - self.mainWindow.panel = wxScrolledWindow(self.mainWindow,-1, wxDefaultPosition,self.mainWindow.GetClientSize()) + # This will be a dict of the form { 'requestROLLBACK': 1001 } + # where 1001 is the wxId associated with requestROLLBACK. + self.__eventActionMapping = {} + + + # add actions + self.__addAction ('requestCOMMIT') + self.__addAction ('requestROLLBACK') + self.__addAction ('requestPRINTOUT') + self.__addAction (self.menuExitEvent, '_exit_') + self.__addAction ('requestCUT') + self.__addAction ('requestCOPY') + self.__addAction ('requestPASTE') + self.__addAction ('requestFIRSTRECORD') + self.__addAction ('requestPREVRECORD') + self.__addAction ('requestNEXTRECORD') + self.__addAction ('requestLASTRECORD') + self.__addAction (_PROMPTFORRECORD, '_promptForRecord_') + self.__addAction ('requestNEWRECORD') + self.__addAction ('requestMARKFORDELETE') + self.__addAction ('requestNEXTBLOCK') + self.__addAction ('requestPREVBLOCK') + self.__addAction ('requestENTERQUERY') + self.__addAction ('requestEXECQUERY') + self.__addAction ('requestABOUT') + self.mainWindow.panel = wxPanel(self.mainWindow,-1, wxDefaultPosition,self.mainWindow.GetClientSize()) global _disabledColour _disabledColour = self.mainWindow.GetBackgroundColour() @@ -260,102 +285,6 @@ def activateForm(self, form): - - self.menu_sb_space = 0 - if not form._features['GUI:MENUBAR:SUPPRESS']: - self.menu_sb_space += 2 - - - # This will be a dict of the form { 'requestROLLBACK': 1001 } - # where 1001 is the wxId associated with requestROLLBACK. - self.__eventMenuMapping = {} - - - fileMenu = wxMenu() - self.__addMenuItem(fileMenu, _("Save (F6)"),_('Save all changes to database.'),'requestCOMMIT') - self.__addMenuItem(fileMenu, _("Clear Form (F11)"),_('Clear Form'),'requestROLLBACK') - fileMenu.AppendSeparator() - - self.__addMenuItem(fileMenu, _("&Print"),_('Perform print routine for this form.'),'requestPRINTOUT') - fileMenu.AppendSeparator() - - id = self.__addMenuItem(fileMenu, _("E&xit"),_('Leave the application.')) - EVT_MENU(self._wxapp, id, self.menuExitEvent) - self.__eventMenuMapping['_exit_'] = id - - editMenu = wxMenu() - self.__addMenuItem(editMenu, _("Cut"),_("Cut the selected text"),'requestCUT') - self.__addMenuItem(editMenu, _("Copy"),_("Copy the selected text"), 'requestCOPY') - self.__addMenuItem(editMenu, _("Paste"),_("Paste text"),'requestPASTE') - - dataMenu = wxMenu() - self.__addMenuItem(dataMenu, _("First Record (Ctrl+Up)"),_('Navigate to first record in memory.'),'requestFIRSTRECORD') - self.__addMenuItem(dataMenu, _("Previous Record (Up)"),_('Navigate to previous record in memory.'),'requestPREVRECORD') - self.__addMenuItem(dataMenu, _("Next Record (Down)"),_('Navigate to next record in memory.'),'requestNEXTRECORD') - self.__addMenuItem(dataMenu, _("Last Record (Ctrl+Down)"),_('Navigate to last record in memory.'),'requestLASTRECORD') - id = self.__addMenuItem(dataMenu, _("Jump to Record... (F2)"),_('Prompts for a record number to which the system should jump.')) - EVT_MENU(self._wxapp, id, _PROMPTFORRECORD) - self.__eventMenuMapping['_promptForRecord_'] = id - - self.__addMenuItem(dataMenu, _("New Record (F12)"),_('Create a new record for data input.'),'requestNEWRECORD') - self.__addMenuItem(dataMenu, _("Mark Record for Delete (F5)"),_('Mark record for removal at next commit.'),'requestMARKFORDELETE') - - dataMenu.AppendSeparator() - self.__addMenuItem(dataMenu, _("Next Block (PgDn)"),_('Navigate to next data block.'),'requestNEXTBLOCK') - self.__addMenuItem(dataMenu, _("Previous Block (PgUp)"),_('Navigate to previous data block.'),'requestPREVBLOCK') - - dataMenu.AppendSeparator() - self.__addMenuItem(dataMenu, _("Enter Query (F8)"),_('Switch to input query mask mode.'),'requestENTERQUERY') - self.__addMenuItem(dataMenu, _("Execute Query (F9)"), _('Execute query using current mask.'),'requestEXECQUERY') - - helpMenu = wxMenu() - self.__addMenuItem(helpMenu, _("&About..."), _('Display info about GNUe Forms.'),'requestABOUT') - - menuBar = wxMenuBar() - menuBar.Append( fileMenu, _("&File") ) - menuBar.Append( editMenu, _("&Edit") ) - menuBar.Append( dataMenu, _("&Data") ) - menuBar.Append( helpMenu, _("&Help") ) - - self._menuBar = menuBar - self.mainWindow.SetMenuBar( self._menuBar ); - - - if not form._features['GUI:TOOLBAR:SUPPRESS']: - - self.menu_sb_space += 2 - # - # There has got to be better way to call events to ride off the EVT_MENU - # Ok if i give buttons same id as menu's they share events - # I dont know if this is horribly wrong or design - # - if sys.platform == 'win32': - mainToolBar = wxToolBar(self.mainWindow, -1) - else: - mainToolBar = wxToolBar(self.mainWindow,-1, style=wxTB_HORIZONTAL|wxTB_DOCKABLE) - - mainToolBar.SetToolBitmapSize(wxSize(24,24)) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestCOMMIT'], wxImage(images_dir+gConfigForms('tb_commit'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Save Changes"), _('Save all changes to database.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestNEWRECORD'], wxImage(images_dir+gConfigForms('tb_insert'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Insert Record"), _('Create a new record for data input.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestMARKFORDELETE'], wxImage(images_dir+gConfigForms('tb_delete'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Delete Record"), _('Mark record for removal at next commit.')) - mainToolBar.AddSeparator() - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestFIRSTRECORD'], wxImage(images_dir+gConfigForms('tb_first'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("First Record"),_('Navigate to first record in memory.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestPREVRECORD'], wxImage(images_dir+gConfigForms('tb_previous'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Previous Record"),_('Navigate to previous record in memory.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestNEXTRECORD'], wxImage(images_dir+gConfigForms('tb_next'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Next Record"),_('Navigate to next record in memory.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestLASTRECORD'], wxImage(images_dir+gConfigForms('tb_last'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Last Record"),_('Navigate to last record in memory.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['_promptForRecord_'], wxImage(images_dir+gConfigForms('tb_jump'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Jump to Record"),_('Navigate to user specified record in memory.')) - mainToolBar.AddSeparator() - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestENTERQUERY'], wxImage(images_dir+gConfigForms('tb_query_prep'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Prepare Query"), _('Switch to input query mask mode.')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestEXECQUERY'], wxImage(images_dir+gConfigForms('tb_query'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Execute Query"), _('Execute query using current mask.')) - mainToolBar.AddSeparator() - mainToolBar.AddSimpleTool(self.__eventMenuMapping['requestROLLBACK'], wxImage(images_dir+gConfigForms('tb_rollback'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Clear Form"), _('Clear Form')) - mainToolBar.AddSimpleTool(self.__eventMenuMapping['_exit_'], wxImage(images_dir+gConfigForms('tb_exit'), wxBITMAP_TYPE_PNG).ConvertToBitmap(), _("Exit Form"), _('Exit Form')) - - self._mainToolBar = mainToolBar - self.mainWindow.SetToolBar( mainToolBar ); - self._mainToolBar.Realize() - - width = int(self._form.width) height = int(self._form.height) @@ -364,6 +293,12 @@ self.mainWindow.SetSize(formSize) self.mainWindow.SetTitle(str(self._form.title)) + self.mainWindow.panel = self._pageList[0] + self.mainWindow.panel.SetSize(formSize) + self._pageList[0].Show(TRUE) + + # Only one page at a time can be visible + self.visiblePage = self._pageList[0] if self._notebook: # Adjust sizes self._notebook.SetClientSize(formSize) @@ -373,27 +308,7 @@ child.Fit() child = child.GetParent() - # This is the initial panel window setup during init - # not a wxPanel set per page right after this - tempx,tempy = self.mainWindow.GetClientSizeTuple() - self.mainWindow.panel.SetScrollbars(1, 1, tempx, tempy) - - - self.mainWindow.panel = self._pageList[0] - self.mainWindow.panel.SetSize(self.mainWindow.GetClientSize()) - self._pageList[0].Show(TRUE) - - - # Only one page at a time can be visible - self.visiblePage = self._pageList[0] - self._wxapp.SetTopWindow(self.mainWindow) - - tempx,tempy = self.mainWindow.GetSizeTuple() - mainWindowSize = wxSize(20+tempx, 20+tempy) - - self.mainWindow.SetSize(mainWindowSize) - self.mainWindow.CenterOnScreen() self.mainWindow.Show(true) # Keep splash on top @@ -421,15 +336,25 @@ # # Internal helper function to add a menu item and an event # - def __addMenuItem(self, menu, text, help, event=None): + def __addAction(self, event=None, name=None): id = wxNewId() - menu.Append(id, text, help) if event: - EVT_MENU(self._wxapp, id, - lambda event, l=self, e=event: l.dispatchEvent(events.Event(e))) - self.__eventMenuMapping[event] = id + if type(event)==types.StringType: + # a 'requestTHING' event + EVT_MENU(self._wxapp, id, lambda event, l=self, e=event: l.dispatchEvent(events.Event(e))) + self.__eventActionMapping[event] = id + else: + # a simple function + EVT_MENU(self._wxapp, id, event) + self.__eventActionMapping[name] = id return id - + + def _addMenuItem (self, menu, text, help, eventName): + menu.Append(self.__eventActionMapping[eventName], text, help) + + def _addToolButton (self, toolBar, eventName, image, toolTip, sbHint): + toolBar.AddSimpleTool(self.__eventActionMapping[eventName], + wxImage(images_dir+gConfig(image),wxBITMAP_TYPE_PNG).ConvertToBitmap(), toolTip, sbHint) # # _setStatusBar @@ -689,20 +614,10 @@ try: if object.style == "dropdown" and \ not object._allowedValues == widget._origAllowedValues: - try: - # Not in wx 2.2.x - widget.Freeze() - except AttributeError: - pass widget._origAllowedValues = object._allowedValues widget.Clear() for value in object._allowedValuesDescr: widget.Append(value) - try: - # Not in wx 2.2.x - widget.Thaw() - except AttributeError: - pass except AttributeError: pass @@ -763,6 +678,92 @@ self._deleteFromCrossRef(widget, object) +class UIMainMenuBar (UIHelper, UIWidget): + def _createWidget (self, event, spacer): + iface= event.interface + window= iface.mainWindow + + fileMenu = wxMenu() + iface._addMenuItem(fileMenu, _("Save (F6)"),_('Save all changes to database.'),'requestCOMMIT') + iface._addMenuItem(fileMenu, _("Clear Form (F11)"),_('Clear Form'),'requestROLLBACK') + fileMenu.AppendSeparator() + + iface._addMenuItem(fileMenu, _("&Print"),_('Perform print routine for this form.'),'requestPRINTOUT') + fileMenu.AppendSeparator() + + iface._addMenuItem(fileMenu, _("E&xit"),_('Leave the application.'), '_exit_') + + editMenu = wxMenu() + iface._addMenuItem(editMenu, _("Cut"),_("Cut the selected text"),'requestCUT') + iface._addMenuItem(editMenu, _("Copy"),_("Copy the selected text"), 'requestCOPY') + iface._addMenuItem(editMenu, _("Paste"),_("Paste text"),'requestPASTE') + + dataMenu = wxMenu() + iface._addMenuItem(dataMenu, _("First Record (Shft+Up)"),_('Navigate to first record in memory.'),'requestFIRSTRECORD') + iface._addMenuItem(dataMenu, _("Previous Record (Up)"),_('Navigate to previous record in memory.'),'requestPREVRECORD') + iface._addMenuItem(dataMenu, _("Next Record (Down)"),_('Navigate to next record in memory.'),'requestNEXTRECORD') + iface._addMenuItem(dataMenu, _("Last Record (Shft+Down)"),_('Navigate to last record in memory.'),'requestLASTRECORD') + iface._addMenuItem(dataMenu, _("Jump to Record... (F2)"),_('Prompts for a record number to which the system should jump.'), '_promptForRecord_') + + iface._addMenuItem(dataMenu, _("New Record (F12)"),_('Create a new record for data input.'),'requestNEWRECORD') + iface._addMenuItem(dataMenu, _("Mark Record for Delete (F5)"),_('Mark record for removal at next commit.'),'requestMARKFORDELETE') + + dataMenu.AppendSeparator() + iface._addMenuItem(dataMenu, _("Next Block (PgDn)"),_('Navigate to next data block.'),'requestNEXTBLOCK') + iface._addMenuItem(dataMenu, _("Previous Block (PgUp)"),_('Navigate to previous data block.'),'requestPREVBLOCK') + + dataMenu.AppendSeparator() + iface._addMenuItem(dataMenu, _("Enter Query (F8)"),_('Switch to input query mask mode.'),'requestENTERQUERY') + iface._addMenuItem(dataMenu, _("Execute Query (F9)"), _('Execute query using current mask.'),'requestEXECQUERY') + + helpMenu = wxMenu() + iface._addMenuItem(helpMenu, _("&About..."), _('Display info about GNUe Forms.'),'requestABOUT') + + menuBar = wxMenuBar() + menuBar.Append( fileMenu, _("&File") ) + menuBar.Append( editMenu, _("&Edit") ) + menuBar.Append( dataMenu, _("&Data") ) + menuBar.Append( helpMenu, _("&Help") ) + + window.SetMenuBar( menuBar ) + + return menuBar + +class UIMainToolBar (UIHelper, UIWidget): + def _createWidget (self, event, spacer): + iface= event.interface + window= iface.mainWindow + + # + # There has got to be better way to call events to ride off the EVT_MENU + # Ok if i give buttons same id as menu's they share events + # I dont know if this is horribly wrong or design + # + if sys.platform == 'win32': + mainToolBar = window.CreateToolBar() + else: + mainToolBar = window.CreateToolBar(wxTB_HORIZONTAL|wxTB_DOCKABLE) + + mainToolBar.SetToolBitmapSize(wxSize(24,24)) + iface._addToolButton (mainToolBar, 'requestCOMMIT', 'tb_commit', _("Save Changes"), _('Save all changes to database.')) + iface._addToolButton (mainToolBar, 'requestNEWRECORD', 'tb_insert', _("Insert Record"), _('Create a new record for data input.')) + iface._addToolButton (mainToolBar, 'requestMARKFORDELETE', 'tb_delete', _("Delete Record"), _('Mark record for removal at next commit.')) + mainToolBar.AddSeparator() + iface._addToolButton (mainToolBar, 'requestFIRSTRECORD', 'tb_first', _("First Record"),_('Navigate to first record in memory.')) + iface._addToolButton (mainToolBar, 'requestPREVRECORD', 'tb_previous', _("Previous Record"),_('Navigate to previous record in memory.')) + iface._addToolButton (mainToolBar, 'requestNEXTRECORD', 'tb_next', _("Next Record"),_('Navigate to next record in memory.')) + iface._addToolButton (mainToolBar, 'requestLASTRECORD', 'tb_last', _("Last Record"),_('Navigate to last record in memory.')) + iface._addToolButton (mainToolBar, '_promptForRecord_', 'tb_jump', _("Jump to Record"),_('Navigate to user specified record in memory.')) + mainToolBar.AddSeparator() + iface._addToolButton (mainToolBar, 'requestENTERQUERY', 'tb_query_prep', _("Prepare Query"), _('Switch to input query mask mode.')) + iface._addToolButton (mainToolBar, 'requestEXECQUERY', 'tb_query', _("Execute Query"), _('Execute query using current mask.')) + mainToolBar.AddSeparator() + iface._addToolButton (mainToolBar, 'requestROLLBACK', 'tb_rollback', _("Clear Form"), _('Clear Form')) + iface._addToolButton (mainToolBar, '_exit_', 'tb_exit', _("Exit Form"), _('Exit Form')) + mainToolBar.Realize() + + return mainToolBar + # # UILabel # @@ -794,22 +795,16 @@ object = event.object # this panel makes the GFBox be a container -## -## TODO: Commented out prior to 0.4.0 release -## newPanel = wxPanel(event.container,-1, -## wxPoint(object.x*event.widgetWidth+(event.widgetWidth/2), -## (object.y+spacer+(spacer*object._gap))*event.widgetHeight+(event.widgetHeight/2)), -## wxSize((object.width-1)*event.widgetWidth, -## (object.height-1)*event.widgetHeight)) -## newWidget = wxStaticBox(newPanel,-1,str(object.label), -## wxPoint(0,0), - newWidget = wxStaticBox(event.container,-1,str(object.label), + newPanel = wxPanel(event.container,-1, wxPoint(object.x*event.widgetWidth+(event.widgetWidth/2), (object.y+spacer+(spacer*object._gap))*event.widgetHeight+(event.widgetHeight/2)), wxSize((object.width-1)*event.widgetWidth, - (object.height-1)*event.widgetHeight)) -## return newPanel - return newWidget + (object.height-1)*event.widgetHeight)) + newWidget = wxStaticBox(newPanel,-1,str(object.label), + wxPoint(0, 0), + wxSize((object.width-1)*event.widgetWidth, + (object.height-1)*event.widgetHeight)) + return newPanel # # UIScrollBar @@ -818,13 +813,52 @@ # to navigate multiple records # class UIScrollBar(UIHelper, UIWidget): + # this one maps wx's scroll to gnue's scroll. + wxToScroll= { + 10302: 0, # line up + 10304: 1, # page up + 10306: 2, # free scroll (handle move) + 10305: 3, # page down + 10303: 4 # line down + } + def _createWidget(self, event, spacer): object = event.object - newWidget =wxScrollBar(event.container,-1, + self._page= object.page + self._widget= wxScrollBar(event.container,-1, wxPoint(object.x*event.widgetWidth,(object.y+spacer)*event.widgetHeight), wxSize(object.width*event.widgetWidth,object.height*event.widgetHeight), wxSB_VERTICAL) - return newWidget + # tie + if event.initialize: + # envetHandler is the gfuserinterface's dispatchEvent... + self._eventHandler= event.eventHandler + self.update (0, 0) + EVT_SCROLL (self._widget, self.scroll) + # raise Exception + # also, hook on our block's events + # how? I need a eventAware thing! + # registerEventListeners () + # or find the block and cross register. + block= object.findParentOfType ('GFBlock') + block.registerScrollBar (self) + + return self._widget + + def scroll (self, event): + try: + action = events.Event('requestSCROLL', (self.wxToScroll[event.GetEventType()], self._page)) + self._eventHandler(action) + except KeyError, e: + # ignore; it's not a event we want to handle + # e.g., click on the sb's handle + pass + + # int position, int thumbSize, int range, int pageSize, const bool refresh = TRUE + def update (self, pos, range): + # print pos, range + self._widget.SetScrollbar (pos, 1, range, self._page-1) + # # UIButton @@ -907,6 +941,12 @@ newWidget.SetValue("") EVT_COMBOBOX(newWidget, newWidget.GetId(), self.comboHandler) + elif style == 'textlookup': + newWidget = wxStaticText(event.container, -1, "",defaultPoint,defaultSize, + wxST_NO_AUTORESIZE) + # To make the label consistent with the other entry styles... + newWidget.SetValue = newWidget.SetLabel + newWidget.GetValue = newWidget.GetLabel elif style == 'label': newWidget = wxStaticText(event.container, -1, "",defaultPoint,defaultSize, @@ -1053,6 +1093,95 @@ message = lineWrap(message,60) wxMessageDialog.__init__(self, interface, message, caption, style=wxOK|wxICON_EXCLAMATION) + +# +# UIGenericBox +# +# A generic box providing feedback info +# +class UIGenericBox(wxDialog, UIHelper): + def __init__(self, interface, caption): + self.interface = interface + self.caption = caption + + def createGenericBox(self, message, buttonSet): + self.genericBox = dlg = wxDialog(self.interface, -1, self.caption) + buttonCount = len(buttonSet) + + dlg.SetAutoLayout(true) + + #bmp = wxImage(images_dir+gConfig('smallPNG'), wxBITMAP_TYPE_PNG).ConvertToBitmap() + + messageField = WrappedStaticText(dlg, -1, str(message), 300, style=wxALIGN_CENTER) + + dlgWidth = messageField.GetSize().GetWidth() + 30 + + dlgHeight = messageField.GetSize().GetHeight() + 80 + + idx = 0 + buttonSetWidth = 0 + maxButtonHeight = 0 + button = [] + + for buttonLabel in buttonSet: + buttonId = wxNewId() + button.append(wxButton(dlg,buttonId,_(buttonLabel))) + EVT_BUTTON(dlg, buttonId, lambda event, s=self, butt=idx+1: s.setResult(butt) ) + buttonSetWidth += button[idx].GetSize().GetWidth() + if maxButtonHeight < button[idx].GetSize().GetHeight(): + maxButtonHeight = button[idx].GetSize().GetHeight() + idx += 1 + + button[0].SetDefault() + dlgWidth = max(dlgWidth, buttonSetWidth + 15 * (buttonCount- 1) + 40) + + dlgHeight += maxButtonHeight - 6 + + # Create and position the logo + #wxStaticBitmap(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 )) + idx = 0 + incr = (dlgWidth - 40 - buttonSetWidth) + if buttonCount > 1: + incr = incr / (buttonCount - 1) + + if buttonCount > 1: + currentX = 15 + else: + currentX = (dlgWidth - buttonSetWidth) / 2 + + for buttonLabel in buttonSet: + button[idx].SetPosition(wxPoint(currentX, dlgHeight - 10 - maxButtonHeight)) + currentX += button[idx].GetSize().GetWidth() + incr + idx += 1 + + dlg.SetSize(wxSize(dlgWidth, dlgHeight)) + + dlg.Refresh() + dlg.Fit() + dlg.Raise() + dlg.CenterOnScreen() + + # If user cancels, this will be set to 0 + self._result = 0 + + return dlg + + def getResult(self): + return self._result + + def setResult(self, value): + self._result = value + self.genericBox.EndModal(1) + self.genericBox.Destroy() + + ##################################################################### ## ## Keymapper Support @@ -1119,7 +1248,7 @@ global _charWidth,_charHeight object = _eventObjTowxWindow(event) - print object + # print object id = object.GetId() gfObject = _IdToGFObj[id] @@ -1476,6 +1605,8 @@ 'GFEntry' : UIEntry, 'GFButton' : UIButton, 'GFScrollBar' : UIScrollBar, + 'GFMainToolBar': UIMainToolBar, + 'GFMainMenuBar': UIMainMenuBar, } diff -Naur --exclude=.#* --exclude=CVS --exclude=*.pyc --exclude=*.pyo --exclude=*.orig --exclude=*.rej --exclude=*.png --exclude=*.log --exclude=doc --exclude=.cvsdevelbase head/reports/src/GRLayout.py up/reports/src/GRLayout.py --- head/reports/src/GRLayout.py Thu Nov 14 17:29:19 2002 +++ up/reports/src/GRLayout.py Thu Nov 14 19:38:44 2002 @@ -257,7 +257,7 @@ for child in self._children: if child._type == "_content_": - dest.write(child.getContent()) + dest.write(child.getContent()) else: # Handle GRSections specially as # they require extra logic @@ -271,7 +271,7 @@ # ..otherwise call the GRSection's process method. else: - nextSection = child.process(dest, mapper, + nextSection = child.process(dest, mapper, isfirst=1, islast=(nextSection == None) or \ (nextSection._name not in (child._childSections)),