[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r9450 - in trunk/gnue-forms/src: . GFObjects input/displayHandler
From: |
reinhard |
Subject: |
[gnue] r9450 - in trunk/gnue-forms/src: . GFObjects input/displayHandlers |
Date: |
Tue, 27 Mar 2007 13:13:58 -0500 (CDT) |
Author: reinhard
Date: 2007-03-27 13:13:56 -0500 (Tue, 27 Mar 2007)
New Revision: 9450
Modified:
trunk/gnue-forms/src/GFForm.py
trunk/gnue-forms/src/GFObjects/GFField.py
trunk/gnue-forms/src/input/displayHandlers/Cursor.py
Log:
Update field value on every keypress in an entry, not only on focus-out. This
makes sure the field value and record status are as correct as possible at any
given point in time.
Modified: trunk/gnue-forms/src/GFForm.py
===================================================================
--- trunk/gnue-forms/src/GFForm.py 2007-03-27 18:12:35 UTC (rev 9449)
+++ trunk/gnue-forms/src/GFForm.py 2007-03-27 18:13:56 UTC (rev 9450)
@@ -685,23 +685,16 @@
def event_begin (self):
"""
- Set the form into a defined state to prepare event handling.
+ Start handling of a user event.
- This function sets the form into a consistent and defined state so that
- event handling code (like triggers and actions) can rely on everything
- being ok.
-
- Most notably, this function updates the field value for the currently
- edited entry and shows an hourglass mouse cursor.
-
This function has to be called at the beginning of each user event
being handled. At the end of handling the user event, L{event_end} has
to be called.
+
+ Currently, these functions only turn on and off the hourglass mouse
+ cursor.
"""
- if hasattr(self._currentEntry, '_displayHandler'):
- # FIXME: what if this fails?
- self._currentEntry._displayHandler.updateFieldValue()
if self.uiWidget is not None:
self.uiWidget._ui_begin_wait_()
@@ -712,17 +705,13 @@
def event_end (self):
"""
- Set the form into a defined state to finalize event handling.
+ End handling of a user event.
- This function sets the form into a consistent and defined state after
- event handling code (like triggers and actions) has been run.
-
- Most notably, this function resets the mouse cursor from hourglass to
- normal and updates the field values shown on the form to reflect any
- data modifications done in the event handling code.
-
This function has to be called at the end of each user event being
handled, just like L{event_begin} is called at the beginning.
+
+ Currently, these functions only turn on and off the hourglass mouse
+ cursor.
"""
if self.uiWidget is not None:
@@ -1405,17 +1394,19 @@
Enters the form into Query mode.
"""
- # self.endEditing() # happens via _focus_out()
+ # self.endEditing() # happens via _focus_out()
- try:
- # We *must* run _focus_out() here: letting the user leave an entry
- # with an invalid value here would make it possible to enter an
- # invalid value, switch to query mode, move the focus somewhere
- # else, cancel the query (and so getting back the original result
- # set) and then saving the unchecked data.
- if self._currentBlock is not None:
- self._currentBlock._focus_out()
+ # We *must* run _focus_out() here: letting the user leave an entry
+ # with an invalid value here would make it possible to enter an
+ # invalid value, switch to query mode, move the focus somewhere
+ # else, cancel the query (and so getting back the original result
+ # set) and then saving the unchecked data.
+ # The _focus_out() can run outside the try-except block because it
+ # already does the beginEditing in case of an exception.
+ if self._currentBlock is not None:
+ self._currentBlock._focus_out()
+ try:
if not self._must_save():
# We must refresh the UI events now as otherwise the query
# button will stick in.
@@ -1439,13 +1430,14 @@
Copies the Query, ie brings back conditions from the last query.
"""
- # self.endEditing() # happens via focus_out()
+ # self.endEditing() # happens via focus_out()
- try:
- if self._currentBlock is not None:
- self._currentBlock._focus_out()
+ if self._currentBlock is not None:
+ self._currentBlock._focus_out()
+ try:
if not self._must_save():
+ self.refreshUIEvents()
self.beginEditing()
return
@@ -1683,13 +1675,6 @@
@return: boolean, True if all the blocks are committed.
"""
- # Is the current entry changed?
- if (self._currentEntry is not None and \
- self._currentEntry._type != 'GFButton' and \
- self._currentEntry._field._bound and \
- self._currentEntry._displayHandler.isPending()):
- return False
-
# Are there any not yet posted changes in any of the blocks?
for block in self._logic._blockList:
if block.is_pending():
@@ -1697,8 +1682,8 @@
# Does a connection have any pending (already posted but not yet
# committed) changes?
- for connection in (self.__get_connections ()).values ():
- if connection.isPending ():
+ for connection in (self.__get_connections()).itervalues():
+ if connection.isPending():
return False
return True
Modified: trunk/gnue-forms/src/GFObjects/GFField.py
===================================================================
--- trunk/gnue-forms/src/GFObjects/GFField.py 2007-03-27 18:12:35 UTC (rev
9449)
+++ trunk/gnue-forms/src/GFObjects/GFField.py 2007-03-27 18:13:56 UTC (rev
9450)
@@ -75,6 +75,10 @@
self.__lookup_dict = None # {db_value: user_value}
self.__lookup_dict_reverse = {} # {user_value: db_value}
+ # Autoquery support
+ self.__autoquery_value = None
+ self.__in_autoquery = False
+
# These are only here because "rows" and "gap" is passed from GFBlock
# through GFField to GFEntry.
self._rows = 1
@@ -292,6 +296,8 @@
if value is None:
return None
+ elif isinstance(value, datatypes.InvalidValueType):
+ return value
elif value in self.__lookup_dict_reverse:
return self.__lookup_dict_reverse[value]
else:
@@ -347,6 +353,9 @@
value = self._block.get_value(self, offset)
+ if isinstance(value, datatypes.InvalidValueType):
+ raise value.exception
+
# FIXME: This conversion should be in gnue-common.
try:
value = datatypes.convert(value, self.datatype, self.length,
@@ -385,23 +394,22 @@
if self.ltrim:
value = value.lstrip()
- if self.minLength and value is not None and len(value) \
+ if self.minLength and isinstance(value, basestring) \
and len(value) < self.minLength:
raise MinimumLengthError(self.name, value, self.minLength)
- # Auto-query support
- if self._block.mode != 'query' \
- and ((self.autoquery == 'Y') \
- or (self.autoquery == 'new' \
- and self._block.get_record_status() == 'empty')):
- self._block.query({self.field: value})
- if self._block.get_record_status() == 'empty':
- # Query returned no result, so set the field value
- self._block.set_value(self, value)
- else:
- self._block.set_value(self, value)
+ # If this is an autoquery field, don't pass the value to the block, but
+ # save it for later.
+ if (self.autoquery == 'Y') \
+ or (self.autoquery == 'new' \
+ and self._block.get_record_status() == 'empty'):
+ if not self.__in_autoquery:
+ self.__autoquery_value = value
+ return
+ self._block.set_value(self, value)
+
# -------------------------------------------------------------------------
# Notification of value change
# -------------------------------------------------------------------------
@@ -466,6 +474,20 @@
if self._block.mode == 'normal':
self.processTrigger('PRE-FOCUSOUT', ignoreAbort=False)
+ if self.__autoquery_value is not None and not self.__in_autoquery:
+ if (self.autoquery == 'Y') \
+ or (self.autoquery == 'new' \
+ and self._block.get_record_status() == 'empty'):
+ self.__in_autoquery = True
+ try:
+ self._block.query({self.field: self.__autoquery_value})
+ if self._block.get_record_status() == 'empty':
+ # Query returned no result, so set the field value
+ self.__set_value(self.__autoquery_value)
+ self.__autoquery_value = None
+ finally:
+ self.__in_autoquery = False
+
# -------------------------------------------------------------------------
def focus_out(self):
Modified: trunk/gnue-forms/src/input/displayHandlers/Cursor.py
===================================================================
--- trunk/gnue-forms/src/input/displayHandlers/Cursor.py 2007-03-27
18:12:35 UTC (rev 9449)
+++ trunk/gnue-forms/src/input/displayHandlers/Cursor.py 2007-03-27
18:13:56 UTC (rev 9450)
@@ -36,6 +36,7 @@
import sys
from gnue.common import events
+from gnue.common.utils import datatypes
class BaseCursor(events.EventAware):
@@ -131,12 +132,6 @@
selection1, selection2 = selection
self.entry.uiWidget._ui_set_selected_area_(index, selection1,
selection2)
- def isPending(self):
- """
- Return True if the display handler is in edit mode and has modified
text
- """
- return self.editing and self.modified
-
#####################
#
# Editing methods
@@ -342,9 +337,8 @@
self.entry._form.refreshUIEvents()
# Update the field. This means PRE-CHANGE and POST-CHANGE will get
- # fired now. For now, only do this here if we are a lookup.
- if hasattr(self.field, 'fk_source'):
- self.updateFieldValue()
+ # fired now.
+ self.updateFieldValue()
# -------------------------------------------------------------------------
# Do autocompletion
@@ -591,13 +585,18 @@
"""
try:
self.__updateFieldValue()
- except:
- pass
+ except Exception, exception:
+ # We don't want to raise the exception now as the user is still
+ # typing. However, we archive the exception in an InvalidValueType
+ # object and store that as the current field value. If any trigger
+ # code now tries to access the field, the GFField.get_value will
+ # raise the exception.
+ self.field.set_value(datatypes.InvalidValueType(exception))
def __updateFieldValue(self):
- if not self.__updating and self.isPending():
+ if not self.__updating and self.modified:
# Make sure that this function isn't called twice recursively. This
# would happen when the field is autoquery, so the
# field.set_value() would cause a query to run, which in turns
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r9450 - in trunk/gnue-forms/src: . GFObjects input/displayHandlers,
reinhard <=