See the Subversion log for all the details.

Dabo 0.9.4 (2011-10-05) Revision 6879):
===============================================================================
Recommended Python: 2.6.5 (still some reported problems with 2.7)
Recommended wxPython: 2.8.12.1

We let it go over a year again. The following changes are copied from the Web Update release notes. The
first set is organized under headings for framework chagnes, bizobj, and ui changes. The following 
sections are not. 

General Framework Changes:
- Lots of docstring changes to improve Sphinx documentation
- You can now override the setting of the language defined by locale.
- Changed default Encoding for datasets to the one declared for the backend.
- Added dApp.displayInfoMessage() which presents a dialog with a checkbox for the user to choose if they will see this particular message in the future.
- Added getSharedAppDataDirectory() fuction, which returns application shared data directory.
- Improved debugging by including the current call stack in every callAfter/setAfter call, so that errors can show the path that led to the *after method being called.
- Fixed an issue where calling the _initModuleNames() method would not update with any changes since the app first launched. With this change, bizobjs created or changed in the Class Designer will now be available when test running the class.

Bizobj/DB Layer Changes:
- Augmented the Data Type Mismatch error to show the table name and not just the field name.
- Fixed an issue where newly-added records in cursors that had never been requeried didn't know their data structure, even though DataStructure had been set explicitly.
- Improved the getDataSet() method to eliminate the need for looping through all rows.
- Fixed issue with dBizobj wrong cursor assignment for newly created grandchild cursors.
- Added argument to biz.save() to optionally prevent child bizobjs from getting saved.
- Added the Connection property to dBizobj.
- Multiple improvements in the handling of child bizobjs and changed rows in dBizobj.
- Added an optional TypeStructure property to dDataSet to provide 'hints' to the class in determining data types.
- Fixed the case where seek(..., near=True) worked correctly except in the case where we were seeking a value greater than that of the last row, in which case it would stick the record pointer on the first row instead of the last row.
- Added helper getBizobj() function to dDialog so that controls in the dialog can still find their bizobjs with 'self.Form.getBizobj()'.
- Added basic methods to dBizobj and dCursorMixin for handling many-to-many (M-M) relationships.
- Changed the logic for data binding with bizobjs. Now you can bind to any attribute of the bizobj, not just columns in the bizobj's data set.
- Made some improvements to support for MS SQL connections.
- Changed the value returned by dCursorMixin's RowCount to 0 from -1 for the case where the cursor has not yet been requeried. Logically it makes more sense, and we don't rely on a value of -1 for this anywhere.
- Improved the way that dBizobj's isAnyChanged() method determines changes.

UI Changes:
- Added the 'ChildObjects' property to sizers. This will return a list of the objects managed by the sizer, whether they be controls, sizers, or spacers. The 'Children' property still returns a list of sizer items.
- Fixed the dDockForm and dDockPanel classes so that the properties work again.
- The DataSource property for controls can now be set to a callable, which will be evaluated each time the property is accessed. This makes it possible to have a dynamic DataSource.
- Added the 'moveTabOrderBefore()' and 'moveTabOrderAfter()' methods to improve control over tab order.
- Added the ability to flip displayed images in the dImage control horizontally or vertically.
- Added the ability for dImage to recognize rotation information in image files that store it, and adjust its display accordingly.
- The grid's header area now defaults to white, while the default grid column header background color is grey.
- dGrid's SelectionForeColor and SelectionBackColor weren't settable from initProperties() or from the constructor. Fixed.
- Added the 'UpdateInactivePages' property to the paged controls; this limits propagation of update event to the active page only when set to False
- Pages now have the DeferredUpdates property to handle delayed updates, until page become selected.
- Fixed some flushValue() problems in dTextBoxMixin, and improved its internal data type support.
- Added the ButtonShape property to dBorderlessButton.
- Added ability to associate a node in dTreeView with a file path.
- Fixed the issues with the segfault/bus error with dGrid that was being seen when running the Class Designer under Python 2.7.
- Changed the header context menu in dGrid so that if ResizableColumns is False, the options to autosize the column is not available.
- Changed the background color of column 1 in the demo code for dGrid to something a little less ugly.
- Enhanced the 'makeDirTree()' method to accept a list of file patterns for both including and excluding. Also added checks for upper/lower case versions of those patterns.
- Added the DataUpdateDelay property to dForm to control delay between when business data changes and UI controls get updated; setting to None means that controls are immediately updated with changes.
- Fixed some flickering issues with dForm when refreshing.
- Added the convenience classes dSizerH and dSizerV for making horizontal and vertical sizers, respectively. Yes, I am lazy.
- Fixed problem with some paged controls not properly working with setAll() method.
- The dDockForm classes use the agw version of the AUI libraries if available.
- Added the 'MovableTabs' property to the dDockTabs class; when False, the tabs cannot be rearranged or docked. This must be specified when the control is instantiated.
- Added helper getBizobj() function to dDialog so that controls in the dialog can still find their bizobjs with 'self.Form.getBizobj()'.
- Added the UseSmartFocus property to dPageFrame, which will 'remember' the control that had focus on a page, and reset focus to that control when the page becomes active.
- Fixed dSpinner control flush on update issue.
- Added dDatePicker control based on native wx.DatePickerCtrl.
- Changes the InteractiveChange event so that it is raised after the data source update to better synchronize between biz and UI layers.
- Added global setting autoDisableDataControls to handle new data controls behavior on empty dataset.
- Added ReadOnly property to dRichTextBox.
- Added the ShellCommandRun event, which is raised whenever dShell executes a command in its interpreter.
- Added the PersistSecretData property that overrides IsSecret property allowing to store sensitive data in encrypted form.
- Added the NumericBlankToZero property to dTextBoxMixin. When true, blanking a numeric field will be interpreted as setting it to zero.
- Fixed an issue with dPageStyled where 'select' parameter was by default set to True and fired the PageChanging event on every newly added page.
- Added a Rounded Rectangle to the available DrawObjects.

ReportWriter Changes:
- Deprecated Frameset/Paragraph; Added Memo which accomplishes the same thing in the same way without the developer needing to know about the hierarchy.
- Removed the auto-updating of the _def default properties when the main property changes, as it was causing unneeded cruft in the rfxml.
- Changed default expr of String and Memo to "String" and "Memo", respectively.
- Improved Memo's Leading property to easily be able to specify single- or double-space, and to modify that with any number of + or - chars, like "single+++" to have single-space plus a little bit.
- Added a new report object, "Defaults", with one initial default to set: FontName. If String or Memo don't have FontName explicitly set, the report default will be queried. If that isn't explicitly set, the base default will be queried. The base default is Helvetica, but I suggest installing DejaVuSans or some other true-type font that has extended symbols that will likely be encountered in user data, expecially in non-US locales.
- Bad font names will no longer crash the reportWriter, they'll simply be substituted with Helvetica, Helvetica-Bold, Helvetica-Oblique, or Helvetica-BoldOblique.
- Added code to defend against converting anything other than the most common Frameset/Paragraph. It is possible but unlikely that rfxml's exist in the wild with multiple subobjects of Frameset, and this will keep those from getting converted.
- Add the system truetype font paths to reportWriter, which will result in auto-registration of specific fonts upon first use.
- Fixed an issue with Memos in which data that was too long resulted in nothing being printed. Instead, the message '<<< string too long >>>' will be printed so the developer knows what needs to be fixed.
- Fixed the reprinting of group headers from the printing of a detail band so that they only reprint group headers higher in the list than the current group
- Allow for the image expression to evaluate to None, and just don't print anything in that case.

Report Designer Changes:
- Enhanced the ReportDesigner by making Shift+Enter on an object activate the propsheet editor for the currently selected property in the propsheet.
- Enhanced ReportDesigner to show the paragraph object expression on the design surface. In addition, made it so when you click on the Frameset, the Paragraph is what gets selected. You can still select the Frameset object by clicking on it in the object tree.
- Deprecated Frameset/Paragraph; Added Memo which accomplishes the same thing in the same way but the appdev doesn't need to know about the hierarchy.
- Changed default expr of String and Memo to "String" and "Memo", respectively.
- Changed dynamically-sized bands (height = None) to use height_def for display in the designer, instead of the hard-coded 75pt used previously. If no height_def has been explicitly set, the 75 is still used to avoid the default of 0, which would be confusing.
- ReportDesigner looked horrible on Mac because of dark default background. Fixed.
- Fixed a bug in the designer when changing the height of a band where the height was None (dynamic) previously.

Class Designer Changes:
- Replaced the painted of dSizerPanel with a nested panel. I prefer the look of the painted border, but it flickers way too much due to the excessive number of repaints.
- Added needed self.refresh() after a Zoom operation to avoid artifacts.
- Added code to save/restore the zoom level.
- Changes the layout when editing sizers so that the two panels are horizontally arranged. Previously, the vertical arrangement was too tall for some screen resolutions. Thought I had committed this a while ago.
- The search dialog of the Class Designer Editor will search *all* of your code for the class, and not just the currently displayed method.
- There is now a popup that allows you to quickly navigate to any existing method of any object. To access that popup, click the down triangle in the top left corner of the editor window, or press Ctrl+J to activate the method list.
- Incorporated the ability to edit text files while remaining in the Class Designer.
- Changed the Class Designer to use the directory in which it was started, not the 'ide' directory, as its HomeDirectory.

- dCursorMixin: Refactored CursorRecord out of dabo.db.dCursorMixin into dabo.db. Now both dCursorMixin and dBizobj can use the class to instantiate their own Record instances. This effectively means that assigning to biz.Record.field no longer calls cur.setFieldVal() directly but instead calls biz.setFieldVal(), allowing easy interference to be run by appdev code.
- dBizobj, dCursorMixin: improved handling of compound primary keys.
- New: Wrapped the wx.media.MediaCtrl to create the Dabo dMediaControl, which allows you to add video and audio to your app.
- dPref: Added 'prefDb' parameter that allows to specify an explicit preferences database.
- dBizobj, dCursorMixin: Added the ability to specify which record to setFieldVal() on, by sending the pk of the row to set.
- dGrid: Added the VerticalHeaders property. When True, the header captions are written vertically; i.e., at a 90 degree angle, which is useful if you have narrow columns and need to display a label for the column. Thanks to Bronwyn Woods for the idea.
- dGrid: Added the AutoAdjustHeaderHeight property. When True, the HeaderHeight of the grid will change to fit the Captions, whether they are written vertically or not.
- dGrid: Added dColumn.CellFontBold and DynamicCellFontBold. However, it isn't displaying on Linux. Left comments in place to tackle later.
- dPemMixin: Changed the draw object routines to accept an optional dc for drawing.
- dGrid: Changed the grid header drawing to use the same dc as the rest of the header.
- Added the Object Inspector, which allows you to "inspect" objects in a running Dabo application. It can be activated by pressing Ctrl-Shift-I.
- dPemMixin: Added code to account for platform differences in the way that forms report their absolute position on the screen. Under Windows, instead of the position of the entire form, the position of the interior (minus title bar, menus, borders) is returned.
- dDockForm: Added import of agw version of the AUI classes, if available. Noted that several properties no longer seem to have any effect when changed; will need to look at this in more depth.
- dPemMixin: Improved the calculation for absoluteCoordinates(). It was failing to take into account that for forms, we should always use (0, 0) as the Position from which we calculate.
- dBizobj: Improved the DataStructure changes detection.
- dSizerMixin: Added the 'Form' property to sizers. It will return the form with which the sizer is associated, or None.
- dSizerMixin: Added the getContainingWindow() method that will return the window that contains the sizer, even if the sizer is nested within other sizers.
- Added the ability to embed the _Shell class of dShell in non-dShell forms.
- dToolBar: Added the ToolbarItemClass property, allowing you to define your own subclasses for a toolbar's items. The default remains dToolBarItem.
- dbPostgreSQL: Made a change to the way the rollback was being called, based on a suggestion from Jacek Kałucki who experienced issues with losing a transaction.
- dDateTextBox: Fixed problem with the calendar ignoring the setting for FirstDayOfWeek
- Added some saner minimum sizes in dPemMixin.
- Change in getEncoding() behaviour to use getdefaultlocale() instead of getlocale() function, which returns values usable in the rest of the framework.
- Changed how the UI module is imported into the main dabo namespace.
- Changed the default for self._fontSize from None to 10, as some routines were expecting it to be an int and throwing errors on receiving a NoneType value.
- dabo module: Now initialize localization services *after* the logging system is in place, or dLocalize will cause a traceback when trying to log problems.
- dApp: Refactored dApp.default_form and dApp.formsToOpen into properly-named properties.
- dbFirebird: changed rdb$field_length to rdb$character_lenth on request of Werner F. Bruhin.
- dbFirebird: Improved handling of non-ASCII values in connection parameters.
- dBizobj: Added suppoort for the scanRequeryChildren parameter in the scanRows method to override ScanRequeryChildren property.
- dBizobj: Added the _CurrentCursorKey property.
- dBizobj: Clear the bizobj's cursorRecord when DataStructure and VirtualFields are set, as well as in requery().
- dBizobj: Fix for ticket #1351, where the scan method doesn't update grandchildren bizobjs.
- dBizobj: Limited child bizobj FK updates to the new rows only.
- dBizobj: Moved the setCurrentParent() call outside the check for RequeryWithParent, as the setting of the parent should happen unconditionally. However, this will result in the side-effect of an implicit requery() if the cursor for that key doesn't exist yet, *and* RequeryOnLoad is True.
- dBizobj: Refactored cacheExpired() a bit, with a check for lastRequeryTime being None.
- dBizobj: Removed the recently-added force argument from requeryAllChildren, in favor of adding a note to the docstring that developers should explicitly call self.expireCache() before requerying, which ensures all cursors (not just the current one) in a bizobj will get requeried next time the record becomes active.
- dBizobj: setFieldVals() now calls setFieldVal() for each field, so that the afterSetFieldVal() hook will be fired when the field changes.
- dCursorMixin: Added some verbosity to the class exceptions.
- dCursorMixin: Fixed issue with updating field that is part of compound PK. Now _newRecords reflects such changes.
- dEditBox: Improved the handling of the WordWrap property. Fixed some punctuation in the Love Boat lyrics in the test code that had been annoying me for some time. NOTE: the horizontal scrollbar doesn't seem to be drawn in OS X.
- dEditor: Implemented the select() method for dEditor.
- dEvents: Event logging was displaying '?' when getAboluteName() couldn't find a name for the object. Better to use the default __str__().
- dGrid: Added DrawObject.draw() positioning condition to fix header captions display out of the visible area issue.
- dGrid: Added the SortIndicatorSize and SortIndicatorColor properties, which allow you some control over the appearance of the little sort triangle displayed in the header when that column is sorted.
- dGrid: Fixed _paintHeader() issue if it's called from outside of the OnPaint event.
- dGrid: When using dynamic properties, if you need to call grid.getValue() to determine what dynamic value to return, you would hit an infinite loop. I added a parameter to the overridden GetValue() method to control this.
- dLabel: Fixed an issue where resizing could cause an infinite loop.
- dLabel: Made some changes to how WordWrap works; it was behaving incorrectly on some platforms.
- dLabel: Reduced the flickering in the dLabel demo.
- dLed: control wasn't always resizing properly because of the underlying panel's minimum sizer settings. Fixed.
- dMediaControl: Added the ability to clear the control by setting Source = None.
- dMediaControl: Added the ability to drop Source files on the control and have them loaded.
- dPemMixin: Removed manual Ctrl+A support code for Windows platform, since it works properly since wxPython 2.8.10 version at last.
- dPref: Added the __contains__() method so that pref objects support the "x in y" syntax for determining if a key exists in a given preference object.
- Fixed a problem that was due to the way we were calling the super() of __init__(): we were taking the keyword params 'properties' and 'attProperties' and passing them as non-keyword params. This was causing some subtle errors that mostly manifested in the Class Designer.
- Fixed test.py to set the width of the frame, and not the object themselves. Previously, the MinSize for the object was being set via an explicit Width setting, making resizing problematic. Now the form is sized, allowing the sizer to handle the sizing of the object.
- Grabbed the latest translations from launchpad and added them to the locale directory.
- Modified the getItemIndex() of dMenu method to take either a caption (existing behavior), or an actual menu item.
- Moved the methods that gather system information out of the About dialogs and into the uiwx module.
- On Windows, scriptDir was 'C:\\ss\\ui' while appDir was 'c:\\ss', causing isSubDir() to fail. Fixed but will cause problems if someone has meaningful case-sensitive directory names, but that would seem to be stupid so I'm not worrying about it.
- reportWriter: Added CurrentBandName and CurrentBandObj reportWriter properties, inspired by Nate's ticket #1380.
- reportWriter: Raise an exception if invalid rfxml passed, instead of printing the message and then having an exception thrown because form isn't defined.
- ui module: Added the sendIdle() method to help with thread message processing.
- ui module: the latest wxPython changed the return value of HitTest() to sometimes return a single value instead of a 2-tuple, so code was added to handle this properly.
- Updated dLocalize to not prevent the program from running if the translation for the language is not found. Added support for additional aliases for languages.
- ClassDesigner: Added an option to the dialog that appears when you first run the Class Designer to re-open the last class that you worked on.
- ClassDesigner: added the dMediaControl to the Class Designer
- ClassDesigner: Fixed an issue reported by Sibylle Koczian in which running the wizard for adding controls from the data environment would throw a "String must be present in the choices" error.
- ClassDesigner: Fixed an issue with the restoration of lists and tuples as values in cdxml files. Trac issue #1406.
- CxnEditor: Added provisions for handling application CryptoKey values. Note that when the file is saved, the encrypted password is saved, but not the encryption key, for obvious reasons. In order to re-edit the file, you will have to enter the CryptoKey when opening up a saved file. If the PyCrypto package is not installed, none of the CryptoKey changes will be visible.
- PrefEditor: Removed the custom PrefDialog class, as it is no longer needed.

- Fixed a potential problem when starting Dabo if a default encoding was not set.

- Fixed some WordWrap issues with labels.
- Updated the bizIterator classes. They now have two more optional parameters: 'reversed' (default=False): when True, the rows are returned in reverse order; and 'restorePointer' (default=False): when True, the RowNumber is reset when the iteration is complete. The reverse() method has been removed, as it is no longer needed.
- Removed inconsistencies in the code with respect to the use of 'dabo.settings.something' vs. 'dabo.something' to only use the latter form.
- Fixed some display issues with dSpinner.
- Corrected a problem noted by Fraser Burns in which pathing in file names was effectively doubled, causing "File not found" errors.
- Fixed the menu handling issues that prevented the Most Recently Used ("MRU") functionality from working. Also added support for using MRU with submenus.
- Added optional 'multiple' parameter to promptForFileName().
- Modified the appendMenu(), prependMenu(), and insertMenu() methods to return the menu reference instead of a boolean indicating success. While these methods require the reference to be passed in, I felt that it was confusing since every other append, prepend and insert method returned the reference to the item being added.
- Added references for all the included menus and menuitems to the menu bar. This will allow you to reference them in your code instead of having to constantly locate them.
- Changed the hotkey for Redo to 'Ctrl+Shift+Z' to remove the conflict with the Command Window history shortcut, and to keep it in line with 'Ctrl+Z' for Undo.
- Activating the Code Editing page of dShell now sets focus to the editor automatically.
- Added the 'importDebugger' setting. Default=True, which preserves current behavior. If you are using an environment with its own debugger, override this setting to False.
- Changed the internal order that we process bound events.
- Added type conversion in dSpinner if Max/Min and Value were not both Decimal or Float.
- Fixed incorrect handling of properties when running a design using dBorderSizer.
- Added a 'force' parameter (default=False) to dBizobj.requeryAllChildren() to override any cache settings in those child bizobjs.
- Saving a document in dEditor no longer clears the Undo buffer.
- Added the dBizobj.expireCache() method, which will ensure child records will requery during the next cycle.
- Added the MinSizerWidth and MinSizerHeight properties to dSlidePanelControl, and set them both to default to 100px initially. This will ensure that the control is never sized to zero pixels when given a proportion of 0, as was happening previously.
- Removed duplicate MySQL transaction logging.
- Modified the behavior when setting the Picture property of dImage. Instead of raising an error when set to a non-existent file, it will write to the error log and return.
- Updated the buildwin.bat file in AppWizard-generated apps to better explain the steps needed to build exe files under WinXP.
- Changed the hotkeys in the Class Designer for 'Run Script' and 'Hide/Show Output' to 'Ctrl+Shift+R' and 'Ctrl+Shift+O', respectively, to be more consistent with other tools. Thanks to Fraser Burns for catching this.
- Aded a menu item for "Open Recent" to both the Class Designer and the Editor.
- Fixed a bug that caused a crash when running the Class Designer without an initial file path
- Improved the layout of the "Edit Sizer Properties" dialog of the Class Designer
- Fixed an error when opening a saved non-sizer cdxml form.

- Abstracted out the columns in dListControl. You can now change column captions without losing your data and other column settings.
- General improvement of the dPageFrameNoTabs class
- At the suggestion of Jacek Kałucki, I've added a variation of the bizIterator named 'bizDataIterator', which returns a dict containing the columns/values of the current record in the iteration.
- Added a code editor to the dShell class, allowing you to easily edit blocks of code, and then execute it in the shell.
- Added the locate() method, which returns True/False based on whether the value passed was found in the data. By default the pointer is moved to the matching record, but passing 'movePointer=False' will not change the current RowNumber.
- Added the method 'getEncoding()' to the main dabo module. Updated all code to reference this method when looking for encoding settings. This will make using Dabo with non-ASCII strings much more consistent.
- Added several patches to localization problems courtesy of Jacek Kałucki.
- Fixed an issue in which child bizobjs that did not link to the parent's PK column threw exceptions.
- Converted all the deprecated usages of dict.has_key() to use either the 'in' syntax, or a try/except block.
- Several bug fixes to dMaskedTextBox.
- Added the NoneDisplay property and several unicode patches to reportWriter.py
- Added ability to register TrueType Font files and directories to ReportWriter.
- Fixed a long-standing problem in the reportWriter where the group header would sometimes get
printed twice on a new page.
- Modified dMenuBar so that the DynamicEnabled property is evaluated on each update() call.
- Added the 'charsBeforeCursor()' and 'charsAfterCursor()' methods to text controls, as requested by Brendan Barnwell. By default, they return the character immediately before/after the insertion point, or if there is selected text, before/after the selection. You can optionally pass the number of characters to return if you want more than one. You can also specify that any selected text be included in the return value; by default it is not.
- Made the Choices property of list controls dynamic, in that changes to the value returned by that property will modify the list options of the control. Formerly, you would have to get the Choices, modify them, and then re-apply them to the property. Now you can modify them directly, and have the change reflected in the control.
- Refactored the Ruler class in the ReportDesigner so the instance knows its position, not merely its orientation. This should fix the error Jacek's been getting on Windows XP that I wasn't able to reproduce but could have happened if the Paint event occurred at an unexpected time.
- Added support for dListControl properties to the Class Designer.
- Added support for dMaskedTextBox to the Class Designer.
- Added the newer manifest for setup.py.
- Fixed a bug reported by Jim Byrnes in which dPage instances in the Class Designer did not display a context menu.

+ Cleaned up the code base by removing all trailing whitespace.

+ Removed the ref to md5 and replaced with hashlib. haslib is currently already being used in dDataSet.py and md5 has been deprecated (those users of python 2.4 or less need to install the hashlib.py)

+ Added dabo.lib.reportUtils.printPDF(), and added a print button to FrmReportBase in the AppWizard generated code.

+ On Windows, where the status text can go to the main frame, hidden forms were writing their current record text to the status bar on update. This fixes that awkwardness.

+ Eliminated (or at least greatly reduced) the grid header flickering on Windows.

+ Fixed a bug reported by Mark Rajcok in which the WordWrap property grid columns was only affecting those with str DataType, and was ignoring unicode DataType.

+ Switched all of Dabo's logging to use standard Python logging.

+ Switched from os.system() and os.popen2() to subprocess.call() in previewPDF() and printPDF(). Removes DeprecationWarnings in Python 2.6 and above.

+ Added some logic to prevent infinite loops when using field-level validation.

+ Added a fix so that previewing and printing should be modeless by default.

+ Updated the internal cache code to handle permissions better when running under mod_wsgi.

+ Added the 'SelectedText' and 'Text' read-only properties to dHtmlBox.

+ Added the reports folder to the resolvePathAndUpdate method in the utils module. Added a conditional check in the reportWriter to call the resolvePathAndUpdate method if the path is a valid absolute path. So, now you can specify the ReportFormFile property of the ReportWriter object is a relative path.


Dabo 0.9.3 (2010-09-12) Revision 6018):
===============================================================================
We dragged our feet in making this release, because both of us were very busy, and frankly, between Subversion and Web Update, most Dabo developers had the latest changes already. But there have been several big changes in the last 15 months, including, but not limited to:
	- integration of the native Python logging module for all Dabo logging
	- support for DES3 cryptography in Dabo encryption
	- changed all pathing to be relative to the app's HomeDirectory
	- full parameterization of SQL calls
	- addition of the dRichTextBox control
	- improvement of unicode support with the dabo.lib.ustr() method


Here is a summary of all the changes since the 0.9.2 release:

+ Cleaned up the code base by removing all trailing whitespace.

+ Removed the ref to md5 and replaced with hashlib.  haslib is currently already being used in dDataSet.py and md5 has been deprecated (those users of python 2.4 or less need to install the hashlib.py)

+ Added dabo.lib.reportUtils.printPDF(), and added a print button to FrmReportBase in the AppWizard generated code.

+ On Windows, where the status text can go to the main frame, hidden forms were writing their current record text to the status bar on update. This fixes that awkwardness.

+ Eliminated (or at least greatly reduced) the grid header flickering on Windows.

+ Fixed a bug reported by Mark Rajcok in which the WordWrap property grid columns was only affecting those with str DataType, and was ignoring unicode DataType.

+ Switched all of Dabo's logging to use standard Python logging.

+ Switched from os.system() and os.popen2() to subprocess.call() in previewPDF() and printPDF(). Removes DeprecationWarnings in Python 2.6 and above.

+ Added some logic to prevent infinite loops when using field-level validation.

+ Added a fix so that previewing and printing should be modeless by default.

+ Updated the internal cache code to handle permissions better when running under mod_wsgi.

+ Added the 'SelectedText' and 'Text' read-only properties to dHtmlBox.

+ Added the reports folder to the resolvePathAndUpdate method in the utils module.  Added a conditional check in the reportWriter to call the resolvePathAndUpdate method if the path is a valid absolute path.  So, now you can specify the ReportFormFile property of the ReportWriter object is a relative path.

+ Reverts a behavioral change introduced accidentally in r5846. Now scan() will requery child bizobjs by default.

+ Created the 'ustr()' method in dabo.lib.utils. This is designed to replace all of our calls to str() in order to eliminate the unicode encoding errors that pop up frequently when non-American developers use Dabo.
To use, include the line:
   from dabo.lib.utils
    import ustr
in your import statements, and then replace all instances of str(val) with ustr(val).

+ Added some sizer outline code to dFormMixin that was inadvertantly left out of the last Web Update.

+ dRichTextBox: Changed the 'InsertionPoint' property to 'InsertionPosition' to be consistent with other editing controls.

+ dRichTextBox: Renamed the 'loadFromFile()' and 'saveToFile()' methods to 'load()' and 'save()', respectively, as they can use any file-like object.

+ Added the dRichTextBox class, which allows for basic rich text editing and display.

+ Fixed a bug in Web Update that prevented apps from recognizing that Web Update had not yet been run for that Dabo installation.

+ Changed the PreferenceDialog to use a basic dPageFrame instead of dPageList, due to wx warnings.

+ Fixed a potential problem in list controls where the control could try to access its value before the correct DataSource had been set.

+ Added code to reduce dGrid flickering under Windows.

+ Added the ImageRenderer class to display images in grid cells.

+ The code that handles dropped text/files now preserves the x,y location of the drop so that you can tell where on the control the user dropped.

+ Added a textbox-level NoneDisplay property so that individual text box controls can determine how they display None values instead of all controls using dApp.NoneDisplay.

+ Fixed an incompatibility with a recent wxPython change to the foldpanelbar class.

+ Several visual improvements to the dPageStyled class.

+ Fixed a bug in dSlider that prevented reversed display.

+ Fixed some inheritance issues with sizers.

+ Improved sizer outlining to be more flexible. This is mostly for app design uses.

+ Added support for the dPageStyled class to the Class Designer.

+ Added visual indication of sizers in the Class Designer when a sizer is the selected object.

+ Added the HomeDirectoryStatusBar to the visual tools to display your current app's HomeDirectory.

+ Updated the standard directory structure for Dabo apps to include 'cache' and 'lib' directories.

+ Fixed some import errors in reportWriter.py

+ Added an optimization to dDataSet that improves performance when doing multiple queries against the same data.

+ Added an optional optimization to dBizobj that avoids having to requery child bizobjs during a scan().

+ Fixed a bug in the JsonConverter imports.

+ Corrected the bizobj isChanged() function to reflect new records as well as modified records.

+ Added dApp.AutoImportConnections property. When False, dApp will skip the process of finding and loading dConnectInfo objects from found cnxml files. My app is being enhanced to use cnxml files, but I use my own logic on which cnxml file to use.

+ Augmented biz.getTempCursor() with some optional arguments, allowing the appdev to set sql, params, and have automatic requerying before returning the cursor reference.

+ dSlider: added the Reversed and TickPosition properties, as requested by Mike Mabey.

+ Finally fixed a dMenuItem bug that's been bothering me for (I think) years now. On Windows, sometimes there would be double captions, and the "Close Window" item in the File menu would be corrupted. Apparently, the timing of calling SetBitmap() is crucial: it must happen before SetText().

+ Fixed the language problems withthe code to find menus in AppWizard applications.

+ dDateTextBox: allows the user to clear the date (set to None) by adding a shortcut ('N')

+ dReportWriter: Fixed bug with spanning objects: if the group didn't print for whatever reason, the spanning never started. Therefore, we can't try to draw the object.

+ Fixed a bug in dGrid's incremental search on Windows.

+ Refactored the 'resolvePathAndUpdate()' method into dabo.lib.utils instead of dabo.ui.uiwx

+ Added window scrolling events to dGrid and dScrollPanel, so that your code can now handle them if needed.

+ Added optional argument to cur.execute() to convert any ?'s to the backend's paramPlaceholder.

+ Made the localization installation process a little more sane, as it seems that it is especially prone to errors. Now, instead of abending when the dabo localization file isn't found, it prints an error and continues. The app will continue to work fine, but no translations will be done.

+ Fixed a bug that prevented boolean values in grid columns from being properly restored. Trac issue #1247.

+ Added a flag to avoid an unnecessary pointer movement caused by setting the DataSource of the grid to a bizobj after the bizobj had already been created and had its record pointer set. Trac issue #1314.

+ The logic for constructing the filtering WHERE clause in child bizobjs has been corrected to by fully paramterized, instead of 'injecting' the value directly into the SQL.

+ Fixed a problem when re-opening designs for custom classes. Reported by Martinecz Miklós.

+ Added the 'GridCellEditEnd' event, which is raised when a grid cell editor is hidden, whether the value has been changed or not.

+ Fixed a potential issue in the Class Designer Property Sheet in which you could be editing the value of a property of one control, and then navigate to a different control and have your change accidentally be applied to the second control.

+ Fixed the Crypto property so that setting it to a crypto object will result in the encrypt() and decrypt() methods using that object.

+ Fixed a bug in the filterByExpression() method that only replace the first occurrence of a field name in the expression. Reported by Ricardo Aráoz.

+ Changed the Face setter to ignore attempts to set it to 'MS Shell Dlg*' font face names, which can happen when a cdxml file created on Windows is opened on Mac or Linux.

+ Changed the HomeDirectory setter to write an errorLog entry instead of throwing an exception when an invalid path is passed. Again, this is an issue with moving a cdxml from one system to another.

+ Changed the behavior when attempting to set the Face to a non-existent fontface. Instead of throwing an error, an entry is written to the Dabo error log describing the issue.

+ Updated dLed to make it data-aware. It can now be bound to a DataSource and DataField, and have its Color reflect the underlying boolean value.

+ Revamped the handling of pathing. If you have file path references in your cdxml or cnxml files, this could break your old files. Pathing is now relative to the HomeDirectory of your app, instead of the location of the tool that created the file.

+ Updated the internal encryption code to support the use of DES3 cryptography if you have the PyCrypto package installed. There is also a write-only property of dApp called 'CryptoKey': when you set that property, if you have PyCrypto installed, it will create a new SimpleCrypt instance that uses DES3 encryption, with that value as the encryption key. And to avoid having to pass a plain-text value to the app creation, you can set this property at any time, passing either a string or any callable. By passing a callable, you can more effectively hide the way your key is stored; the actual key never has to appear in your code at all. If you have cnxml files created with the old code, they may no longer work. Simple re-run the CxnEditor to re-save them with the new encryption.

+ Added the UIAppClass property to dApp. It can be set to a custom subclass of dabo.ui.uiApp, to enable developers to add ui toolkit-specific behaviors.

+ Fixed an issue with the cursor's _mementos attribute getting inadvertantly altered by record cloning. Trac #1316

+ Overrode the removeAll() method of this control to work properly with the underlying wx control. Trac #1308

+ Added some code to ensure a minimal wx version.

+ Fixed the problem where the cursor won't save a new unchanged record even if the bizobj is set to SaveNewUnchanged.

+ Fixed a problem in the seek() method when called from the bizobj when the table has a compound pk. Also improved the algorithm for matching and near-matching. Trac issue #1330.

+ Major fix to how resizing is handled for panels. Previously, there were cases where panels would get "stuck" at a large size and were not able to be resized smaller. This should fix that problem. Also added the 'Square' property. When set to True, the panel will confine itself to a square shape.

+ If a dBizobj.filter() call filters out all records, a NoRecordsException was being raised. This is generally not necessary, so this is now caught. Trac #1331

+ Added code to handle the case in dGrid where a case-insensitive search is being done on a string type column with null values.

+ Corrects a problem identified by Jacek Kałucki in which some columns that don't have defined data types only get their type corrected the first time a query is run.

+ Fixed a bug that only happened if you called the layout() method of the StatusBar. The attribute '_platformIsWindows' had been previously defined in dPanel, but dStatusBar no longer inherits from that.

+ Fixed getCaptureBitmap() to use a WindowDC for panels and dialogs instead of the parent's ClientDC.

+ Added the StatusBarClass property, which will allow a form to create any status bar subclass that is needed. Defaults to the standard dStatusBar.

+ Fixed a problem when using direct object references as the DataSource, discovered by Jacek Kałucki.

+ Added biz.hasPK() method. It answers the question "is this PK value present in the dataset?" It doesn't move the pointer or have any side-effects, and is optimized to return the answer to this question as fast as possible.

+ Fixed a bug in cdxml rendering: if it contained a boolean value False, it was stored as the word 'False'. But when the attProperties were being read back in, we were doing bool(val) to convert it back, and bool("False") is True.

+ Added a bit of verbosity to quickStart(). Also changed it so that it requires an app name.

+ Deprecated ShowColumnLabels; added ShowHeaders. Fixed ShowHeaders and HeaderHeight to not have side-effects on each other.

+ Fixed some display issues when the grid has at least one column with Expand=True.

+ Made history searches in the Command Window case-insensitive.

+ Fixed an issue when opening up the preferences dialog for the first time: since no update frequency preference had been set, an error was raised when the frequency radio list was bound to that pref.

+ Changed the order in which we import the app subdirectory modules. This is necessary when using a customized uiApp subclass, which would typically be added as a class in the ui module, and then used by overriding the app creation line: app = App(SourceURL=remotehost, UIAppClass=ui.MyCustomUIClass)

+ Fixed a typo that caused an exception when pressing when a report object was selected. Now it brings up the default property in the property sheet like was intended.

+ Corrected an error when saving/running a non-sizer-based form.

+ Enhanced copy/paste in the report designer: if objects from multiple bands are selected when copied, paste them into the same bands instead of the currently selected band. Allows for copy/pasting a header and a detail item, for example.

+ The recent change to make dImage a data-aware control had an unintended effect in the Class Designer: saving an image resulted in not only saving the path, but also the complete byte stream of that image in the Value property. This fixes that oversight.

+ Added build scripts for Linux to AppWizard. Now you can 'buildwin', 'buildmac' *and* 'buildlin'.

+ Added support for the pudb debugger if it is installed.

+ Improved the flow when controls have their value changed from an update() call. Now the flushValue() is no longer called, which avoids unnecessary data validation calls.

+ Fixed some issues with establishing HomeDirectory when running from the runtime engine.

+ Restored the call to flushValue() that was removed in the recent changes to dSpinner. It was breaking anything that used a data-bound spinner, especially the Class Designer.

+ Corrected the issues raised by Jacek Kałucki regarding the navigation problems of dComboBox under Windows.

+ Made some changes designed to better support images as data-bound controls. Also allowed for the image's Picture property to accept a wx.Bitmap as the image source, as that's what is returned from the clipboard methods.

+ Added the convenience methods dabo.ui.copyToClipboard() and dabo.ui.getFromClipboard(). They work with both text and bitmap types.

+ Added a menu option to the Dabo Editor for toggling whitespace visibility.

+ Fixed the download_url in setup.py to match the current download location. I guess easy_install has been broken for a while. Thanks Carl Karsten for finding and reporting the problem, along with a solution!

+ Fixed setup.py to work with pip, per Carl Karsten.

+ Fixed a problem in the SQL generation of AppWizard-generated apps when using full text searches.

+ Fixed the issues with custom classes in the Class Designer not being properly inherited when running inside other class designs. The problem came down to pathing, as have most similar issues, so I approached it by adding some smarter pathing code.

+ Consolidated the logic for app standard directories. Recent changes had not kept the different locations where they were referenced in sync, so now there is an attribute of dApp called '_standardDirs' that is a tuple of the subdirectory names. There is also now a method of dApp called 'getStandardDirectories()' that will return a tuple containing the HomeDirectory and the full paths to all these subdirectories.

+ Enhanced the Editor app by adding an option for setting the number of characters before AutoAutoComplete fires, and another option for toggling whether line numbers are visible.

+ Added some events to dReportWriter: ReportCancel, ReportBegin, ReportEnd, and ReportIteration. Your code can bind to them like any other Dabo event.

+ Fixed an issue when setting the DataSource to a dPref object.

+ Wrapped the creation of the status bar to hopefully not give artifacts when created too close to form creation/resize time.

+ Updated dSecurityManager and added dApp.LoginDialogClass.

+ Fixed color settings in dLed.

+ Added the EditorStyleNeeded event to support custom styling in dEditor.

+ Fixed an occasional problem with dObject.__repr__() calls.

+ Removed code that was slowing searches on virtual fields.

+ Implemented full parameter passing to backend SQL instead of using string substitution.

+ Added a lib directory into the standard Dabo structure.

+ Fixed datanav Form to not keep the edit page active after a delete or cancel if that action resulted in the RowCount going to 0.



Dabo 0.9.2 (2009-05-27) Revision 5238):
===============================================================================
There were two unfortunate bugs that made it into the 0.9.1 release that prevented new installs of that release from working. I'm embarrassed that it took us over 4 months to fix this, but since most active developers are using subversion, it didn't seem like much of a problem. But newcomers who downloaded the release version were turned off, so this finally addresses the problem.

In addition, there were several other significant changes since then.

+ Added the ability to filter data in the current dataset rather than running another query against the database.

+ Improved the wizard for adding data-bound controls to handle cases where you are not working in a standard directory structure.

+ Improved cursor handling when running as a web app.

+ Added a reverse argument to dBizobj.scan().

+ Fixed type issues when working with StatusText in dialogs. Also removed a call that was occasionally clearing StatusText when it shouldn't have.

+ Fixed pathing and name issues in CxnEditor.

+ Added parent/child support to RemoteBizobjs. Prior versions only supported single, unrelated tables.

+ Fixed a bug in the grid's incremental search that ignored non-alphanumeric keys.

+ Removed the CxnFile property from forms, as some people consistenly mis-interpreted how it was to be used.

+ Fixed an issue with escaping/unescaping ampersands being saved in XML files.

+ Improved encoding detection with databases that have a default encoding.

+ Moved the image files for the playing cards to the demo directory.

+ Added the code for Springboard into the repository.

+ Improved error reporting when parsing XML strings.

+ Many improvements to the ReportWriter / ReportDesigner affecting performance, display and usability.

+ Added a Show property to bands in the ReportDesigner.

+ Fixed bug in which 'Save As' in the Editor wasn't saving a file if it wasn't modified.

+ Improved handling of compound PKs in child requeries.

+ Fixed problem with handling nested splitters in the Class Designer.

+ Re-wrote the Web Update code to update the entire Dabo codebase (framework, demo, ide) instead of updating each piece separately. Added more information as to what is being updated.



Dabo 0.9.1 (2009-01-25) Revision 4976):
===============================================================================
Lots and lots of bug fixes as more people worked with the 0.9.0 changes. Here are some of the changes:

+ Some improvements of the PostgreSQL support (see ticket #1189).

+ Fixed an issue where a table with a column with the same name as a bizobj property (such as 'Name') would throw an error.

+ Added the ability to reload a live form when it is based on a .cdxml file. This is analogous to reloading a web page, except that all the bizobj information is preserved.

+ Removed the pre-wx2.7 code that handled skipping a spurious second Activate event.

+ Asking for the values of the properties ToolBar and StatusBar resulted in the side-effect of creating the ToolBar or StatusBar if they weren't already created, which it really shouldn't do. Fixed to create ToolBar and StatusBar at the appropriate time, if not already created by user code.

+ Setting ToolBar had the side-effect of creating a reference to the Form property, which isn't necessary because Form is derived from Parent, and Parent gets set when the toolbar is constructed. Removed the Form property from dToolBar.py (so now it comes from dPemMixinBase like all other controls).

+ Consistently use new style of raise statement (this is actually not necessary but will make transition to Python 3.0 easier).

+ Fixed reportwriter so if the image to draw is invalid or not found, we don't get a reportlab traceback. Just display text in the report.

+ Moved the importing of settings above dLocalize, to make it possible to run the dLocalize.py as a script.

+ Got a step closer to fixing the problem where NonUpdateFields isn't automatically set anymore for foreign fields. This workaround fills in '_foreign_field_' for the table name in DataStructure. The better fix will be to get the actual foreign table name filled in, but this at least makes the NonUpdateFields work again, I believe.

+ addJoin() was adding join conditions in backwards order:
  addFrom("customers")
  addJoin("invoices", "invoices.customer_id = customers.id")
  addJoin("invoice_lines", "invoice_lines.invoice_id = invoices.id")
 would result in:
 from customers
  inner join invoice_lines on invoice_lines.invoice_id = invoices.id
  inner join invoices on invoices.customer_id = customers.id
 which would result in an error in the sql.

+ Added the method 'setValues()' to allow setting several fields with new values by passing them to the bizobj as a dictionary in the form of: fieldName: newValue. No UI updating is done.

+ dSpinner was firing ValueChanged and InteractiveChange with each keypress in the textbox (IOW, these events fired as often as Hit). For text controls, ValueChanged should fire if the value was changed from _oldVal, when the focus is lost.

+ This should fix some of the problems noticed by Ricardo Aráoz concerning the placement of the calendar when editing the dDateTextBox control.

+ Added the 'cloneRecord()' method to dBizobj. This will make a copy of the current record and append it as a new record in the dataset. The copy will contain all of the columns of the current record except for PK columns.

+ Added the 'appendDataSet()' method to dCursorMixin. This assumes that the dataset to be appended has the same table structure as the current dataset; if not, an error is raised.

+ Added the 'isRemote()' method to dBizobj. This returns True if the connection for the bizobj is a remote web connection.

+ Implemented remote proxy support in the getFieldNames() method.

+ Implemented the getFieldNames() method to support remote discovery of table structures.

+ Improved the code for determining the remote URL.

+ Improved the reload() functionality to better handle changes on the server.

+ Added the resyncFiles() method to dApp(). This is needed for reloading parts of the app while the app is running.

+ For performance reasons, we were storing an actual bizobj reference instead of the DataSource string in the grid's DataSource property. This was interfering with reloaded forms, since the bizobjs have to be changed. Now this performance shortcut is only used if the bizobj is not remote.

+ Added KeepAliveInterval to dBackend, which by default is None so has the old behavior. But set it to a number of seconds, if desired, to cause a small query to the server to be made in order to keep the connection alive. This is useful to me for a MySQL app I have. Currently, there's no way to set this other than e.g.:
   form.getBizobj()._CurrentCursor.BackendObject.KeepAliveInterval = 3600

+ Added lots of changes to better handle unicode within the editor and the Class Designer. I've adopted the convention that all of the Dabo files will be written and read using utf-8 encoding, making the handling of any non-ASCII text much simpler.

+ Also fixed a bug when a field in the DataSource is named the same as a method in the DataSource. Previously we looked for methods in the DataSource first, and then tried to call get/setFieldVal(); this would cause Dabo to call the method instead of getting the field value. Now we look for fields first, and only look for methods if there is no such field in the dataset.

+ Initial work on implementing an ID-based system for menus and menu items. They now have MenuID and ItemID properties, respectively. dMenuBar.getMenu() now will find based on MenuID or Caption, and dMenu.getItem() will likewise search on ItemID or Caption.

+ Fixed some bugs in the filter() method for dDataSet reported by Sibylle Koczian. Also added support for 'not equals', using either '!=' or 'ne'.

+ FIxed menu problems in DaboDemo. Also added code to re-use the modules if you re-selected the same sample.

+ Fixed an error that only happened on Gtk, where the font metric call was referring to a released window, causing a segfault.

+ Improved the DE Wizard so that newly-created bizobjs are added to the app's biz module namespace.

+ Fixed a bug that would incorrectly store a CxnName if happened to be the same as an existing directory or file.

+ Adopted the standard that all Class Designer files will be written/read with utf-8 encoding.

+ Fixed a problem in which a newline was added to code, which didn't affect execution, but dirtied the buffer when nothing had actually changed.

+ Updated the QuickLayoutWizard to recognize web-based connections and notify the user that they cannot use that wizard with remote connections.



Dabo 0.9.0 (2008-12-10) Revision 4816):
===============================================================================
+ Removed the conditional import on the decimal module, as we are now requiring Python 2.4.

+ Removed bare 'except:' from the code. Errors are now explicitly caught and handled. This allowed us to identify and fix several insidious bugs that were suppressed by these bare exception handlers.

+ Major re-write to the dDialog subclasses. Specifically, there is now a subclass called 'dStandardButtonDialog' that can accept one or more of the following parameters when it is created:
	OK
	Cancel
	Yes
	No
	Help
It uses the wx standard button sizer methods to create the buttons following platform-specific layout guidelines. Each button has a corresponding on* (e.g., onYes, onHelp) handler which is called when the button is clicked.

+ There are two subclasses of dStandardButtonDialog included: dOkCancelDialog, and dYesNoDialog. dOkCancelDialog is pretty much the same as before; while dYesNoDialog is like dOkCancelDialog, except with Yes/No buttons. If you call dStandardButtonDialog without passing any parameters, a single OK button will be displayed.

+ Removed the ReleaseOnEscape property from dDialog. Added the CancelOnEscape property to dStandardButtonDialog; when this is True (default), pressing the Escape key will be handled by the appropriate standard button handler.

+ Re-instituted the ButtonSizerPosition property.

+ Deprecated onOK() and onCancel(). The methods that will be used by developers to react to standard buttons being clicked are now named run*; e.g., runOK(), runHelp().

+ Fixed a bug that has been around in dDialog for years. It used to be that pressing the Escape key destroyed the dialog if ReleaseOnEscape was True; the code in the class would still try to access the now-destroyed object, throwing an error. Now dialogs are never destroyed in these classes; if you create them, you have to manually call their release() method.

+ Changed the default for output to not print all the infoLog messages to stdout. Instead, infoLog messages are ignored unless the dabo.verboseLogging setting is set to False. The errorLog still prints to stderr, of course.

+ Added the FloatingPanel property. This references a borderless dialog that can be used similarly to a context menu, but which can contain any controls you want. Additionally, it will guarantee that it is displayed completely within the available screen real estate.
It has two properties itself:
	Above: by default the dialog is positioned below its owning control. This changes the behavior so that it is positioned above the control.
	Owner: this is the control used to position the dialog.
Typical usage (written in a custom control):
	fp = self.Form.FloatingPanel
	fp.clear()
	# Add controls
	ctrl = dabo.ui.dTextBox(fp, ...)
	ctrl2 = ...
	# Set the Owner to the control
	fp.Owner = self
	fp.show()
The controls in the FloatingPanel should hide or release it, depending on whether you expect to re-use it. See the update to dDateTextBox for an implementation of it.

+ Re-write the way that the calendar is displayed. It now is contained by the FloatingPanel of the form, and thus is not bound by panels or other container.

+ Also added the ExtendedCalendar property. When True, the larger version of the calendar control is used. This version has additional controls for quickly moving to any date.

+ Added the method 'resolvePathAndUpdate()' to dabo.ui. This introduces much more robust path resolution, especially in cases where files are within a project structure. It also allows to dynamically updated files via the changes in dApp.

+ Changed several of the creation routines to use resolvePathAndUpdate().

+ Changed several 'has_key()' calls to try/except structures. Profiling showed has_key() to be very slow. It is also deprecated for Python 3.0

+ Changed the way 'special' items are handled in menus. Previously, the only way that the About and Preference menu items were handled on OS X was some special code inserted in dBaseMenuBar. That code is now abstracted out to dMenu and dMenuItem; there is now an additional parameter that can be included called 'special': right now, the only special item is 'pref', indicating the Preferences menu. The About menu is keyed off of the id of wx.ID_ABOUT. If either of these two cases are found, the appropriate Mac-specific menu handling will occur.

+ Added 'scrollVertically()' and 'scrollHorizontally()' methods to dScrollPanel, allowing for external scrolling.

+ Added the 'SourceURL' property to dApp, along with the 'urlFetch()' method. The main idea behind this is that if this property is filled in, calls to dabo.ui.resolvePathAndUpdate() will also check the URL specified in SourceURL for updates to the file, enabling more dynamic deployments. This feature is largely untested and should be considered experimental for the time being.

+ Added a call to resolvePathAndUpdate() to the DesignerXmlConverter.

+ Removed all the deprecated code for 0.9.

+ Added a property entry for ShowColumnLabels for a dGrid in the ClassDesigner.

+ Moved the Transparency property from dFormMixin to dPemMixin, as it is possible to set it for individual controls. This doesn't break any existing uses at the form level, but enables control-by-control adjustment of transparency.

+ Added pageUp, pageDown, pageLeft and pageRight methods to dScrollPanel.

+ Changed the 'LineNumber' property in dEditor to be one-based, to match the displayed line numbers in the editor. Added the '_ZeroBasedLineNumber' property that does the actual communication with the wx layer.

+ Added the TransparencyDelay property. It is simply eye candy; it smooths out changes in transparency over the time specified in this property (default=0.25 sec.).

+ Changed strToBmp() to use app.HomeDirectory as the cwd, if there's an app defined, as app.HomeDirectory always refers to the app's root directory, even if the cwd is somewhere else, even if the app is frozen with py2exe.

+ Added the 'afterFinish()' hook method. This fires after the app has terminated, allowing you to do cleanup stuff in the app instead of in the calling program.

+ Moved the 'getPositionInSizer()' method to the module level, allowing it to be called for any object, even a non-Dabo item. Changed the version in dPemMixin to call the module method.

+ Fixed an error when using a bizobj without a data connection.

+ Added VisibleOnScreen property to all ui controls. This is a read-only property that tells you if the object is actually visible or not, taking into account visibility of parent objects and sizers.

+ Fixed the datanav2 Grid to only process the double-click if it happened in an actual cell. Prior to this, I was getting NoRecordsException from my app when the user double-clicked an empty grid. Also, clicking in an area of a grid with no cells will no longer do the processEditRecord(), which is what we really expect.

+ Enabled skipping the dialog-ending behavior by returning False from the runOK/Cancel/Yes/No methods.

+ Added before- and after- hooks to the onEditPreferences() handler, enabling you to hook into preference changes and fire any appropriate update code.

+ Added the Borderless property. When True, the dialog will have no title bar or border.

+ Updated dApp to optionall raise a 404 Not Found error if a requested file is not found from urlFetch(). Also fixed a potential bug in which setting the SourceURL property could get erased by the init code in dApp.

+ Updated the resolvePathAndUpdate() method of dabo.ui to also check for code files when updating a .cdxml file.

+ Added the 'webHeaderFormat()' method that takes a datetime value and returns a formatted string that conforms with the standard expected by HTTP headers.

+ Extended the handling of attProperties to all classes, not just those that inherit from dPemMixin. This was the cause of the problems reported by Nate Lowrie regarding grids created in the ClassDesigner, since dColumn is subclassed directly from dObject, and setting the properties of dColumn objects from attProperties was not being handled.

+ Added an EOLMode property.  The property the is stored as a string and allows you to set the EOLMode of the file to CRLF, LF, or CR standards.  If not explicitly set by the user, the standard will default to the OS standard.  Upon setting the EOLMode, all end of line markers are automatically converted to the new standard.

+ Tracked down and found the errors associated with the dMenu problems I was having.  The main problem was that in the mnxml files, a Caption and Hotkey would be specified separately, but they would be combined into the Caption property by createMenuBar and that would cause a slew of problems.  In addition, if you had a Caption w/ a hotkey in it and then specified the hotkey property, wx would have a conniption fit.  I added a check to the Caption property to raise an error if the Caption has a HotKey in it.

+ Removed the raising of the ValueError if you set a menu item Caption in the form of "Open\tCtrl+O". Instead, simply override any existing HotKey with the hotkey provided in the string, and only set the caption part to the Caption property.
The only potential problem with this is in this example:
item.Caption = "Open\tCtrl+O"
...
item.Caption = "Close"
In this case, the item will still have the Ctrl+O hotkey, and if you didn't want a hotkey, you'd have to then set it explicitly with:
item.HotKey = None

+ Added explicit setting of Accepted to False to the _onCancel() and _onNo() methods. If a dialog was re-used, and Accepted was set to True in the first use, clicking Cancel the second time resulted in Accepted=True again, which is not correct.

+ Added features similar to the bash history and reverse-i-search to the shell. Pressing Ctrl-R will bring up a dialog containing your previous commands; you can type to filter only those containing your search string. You can then press Enter or double-click on the command, and it will be entered into the shell.

+ For some reason, the dShell form was intercepting key characters with "Ctrl+Character" and stopping the KeyDown event from firing on Windows.  Now, instead of catching the KeyDown event and looking for the specific sequence, the form's bindKey method is used instead.  This works on Windows.  I have bound cmd+R to Mac, but I need someone to test the changes.

+ Fixed a typo in _LookupPanel's onListKey.  dKeys.arrows should be dKeys.arrowKeys.  arrowKeys is a dict, so we need to reference values. Again, test the changes on Mac.

+ Changed the key binding for the history search to be Ctrl-R on all platforms. On the Mac, Cmd-R is the 'Redo' command, and anyways, the Mac Terminal works just like Linux terminals, in that Ctrl-R is what is used to bring up command history searching.

+ Added a new class dDropTarget.  The drop target using the wx.DataObjectComposite class to be able to handle both files and text drops.  The class is built to allow for easy interfacing with the DroppedTextHandler and DroppedFileHandler properties in dPemMixin.

+ Modified the DroppedTextHandler and DroppedFileHandler properties to support the new drop target.  User code shouldn't need to change.

+ Revamped the code for how file extension limits are handled in the getFile classes. Instead of hardcoding the allowed types into the dabo.ui.uiwx.__init__.py file, I've moved them to a dict in dabo.settings. I've also added an empty dict named 'custom_extensions' to dabo.settings that can be used by developers in case they want to add additional extensions with custom descriptions.

+ Added code to prevent saving a file that has been modified on disk since it was opened in the editor.

+ Added the method checkForDiskUpdate(). This will return True or False, depending on whether the file on disk has been modified since it was opened in the editor.

+ Added the isChanged() method as a wrapper around the wxPython GetModify().

+ Moved the dDropTarget class definition into dPemMixin.py, and renamed it _DropTarget. The reason is that this is a wxPython-specific implementation detail, and we don't want to expose this as a Dabo base class to users.

+ Added the 'colorNameFromTuple()' method. Given an RGB color tuple, it will return a list of the common names for that tuple, or an empty list if there is no match. If the 'firstOnly' parameter is passed as True, only the first element in the list will be returned as a simple string value, or an empty string if there are no matches.

+ I found the filt argument to setAll() to be hard to use: the expression has to be written so that the leftmost word is a member of the current child object being evaluated, and any names in the expression need to be local to dPemMixin, not the caller. So the simple case in the docstring works, but how to evaluate if the child is an instance of my special subclass?
I couldn't do filt="'TxtFraction' in str(BaseClass)" because of the requirement that the left-most word must be an attribute or member of the child being evaluated.
I couldn't do filt="BaseClass == TxtFraction" because TxtFraction doesn't exist in dPemMixin's namespace.
So, I added a instancesOf argument, that accepts a single or sequence of class(es), and added logic to setAll() to handle this. It shouldn't have any effect on current uses of filt, but I feel this better satisfies the common case of wanting to call setAll() only on instances of specific classes.
Perhaps an improvement to filt would be to add a placeholder, instead of it being fixed to the left. Another improvement could be to pass in the locals and/or globals to setAll(), so the eval() takes place in the environment of the caller.

+ I added two user level hooks to dDialog called beforeAddControls and afterAddControls.  If you design a dialog in the ClassDesigner, addControls is already used internally by the framework to add the controls.  So, both these hooks make it possible to add controls afterward and set the dialog's sizer properties before.

+ This commit fixes some problems with the menu hot key editor in the preference pages.  First, fixed the issue where the clear key button wasn't getting updated after clear and set events.  Second, if you cleared a key using the clear key button, that key wasn't clear from the hotkey map so if you tried to set a control with the cleared key combo, it would give you an erroneous warning.  Fixed that.  Last, if you clicked the cancel button, you menu changes were not rolled back.  Fixed that.

+ Fixed the submenu display problem when using mnxml format.  Instead of creating a dMenu with no parent, we would create a menu with the menubar as the parent and that would lead to trying to set the top label upon setting the caption which we don't want.

+ Finally fixed the bug in the Mac font scaling logic. The problem is that when *any* font property changed, the font would be re-set, and the scaling factory re-applied, making the font size shrink. Now it keeps track of when it applies the scaling, and only re-applies it if a different FontSize value is passed.

+ Made it simple to create custom grid editors using Dabo controls.
To create the editor, just pass the control that you want to use to dabo.ui.makeGridEditor(). It will return a class that you can then assign to a column's CustomEditorClass property.
Since editors by default will be sized to the grid cell they are editing, I added two optional parameters to makeGridEditor(). You can pass 'minWidth' and 'minHeight' values; the class will then ensure that the editor is displayed with at least those dimensions.

+ Renamed the dFoldPanelBar/dFoldPanel classes to dSlidePanelControl/dSlidePanel, repectively. Added deprecation warnings if the old names are used.

+ dColors adds randomColorName(), which returns a random color name instead of a random color tuple. dEvents has been updated to use the dSlidePanelControl naming.

+ The setDefaults method of dEditor was interfering with the setting of the FontFace and FontSize properties from application.  It would override the settings on the Wx level.  So, I pulled the setting of the font out of setDefaults and merged it with the setting of the font from the preference setting.  If there is a preference setting, it will be used.  Else, the face and size used are the defaults specified in the module level variables fontFace and fontSize.

+ Fixed a long-standing bug in this composite control. There were several situations where it appeared that the spin buttons stopped responding to clicks, even though the displayed value was within range. The problem turns out to be that while we were correctly setting the textbox's value, we were not setting the spinner's value; instead, it was incrementing by +1/-1 for each click. This commit fixes that problem by eliminating the spinner's settings from the mix; instead, we govern min/max/wrap through our own code.

+ I also fixed the problem with the collision between float and Decimal values. All values in the comparisons are now cast to the type of the edited value when there is a conflict.

+ Fixed the missing docstring for the class, and added some other docstrings to methods.

+ Renamed dSpinButton to _dSpinButton, as it is not meant to be a public class, and is not available in dabo.ui.uiwx.__init__.py.

+ Fixed up the setting of KeyValue in dControlItemMixin, so that if KeyValue is getting set to a non-existent key, the control will have nothing selected and the Value will be None. This I believe was the intent all along but visually, at least dDropdownList wasn't doing it, and confusing infoLog messages were being generated.

+ Changed KeyValue in subclasses of dControlItemMixin to raise a ValueError if you try to set the Value to a non-existent key.

+ Changed the name of dCheckListBox to dCheckList, which is consistent with dRadioList. Deprecated the old name, and fixed all references.

+ Created a decorator to detect dead objects so that we no longer encounter wx._core.PyDeadObjectError exceptions. I created it in the dabo.ui module, as it needs to be able to be referenced during loadUI().

+ Replaced the dead object trapping code in dGrid.py and decorated the affected methods instead.

+ Fixed much of the flickering problems with dGrid on Windows, which had to do with the way we were painting the grid header. Reworked it to be called from EVT_PAINT instead. Played around with various options such as using a PaintDC or a BufferedPaintDC, and overriding EVT_ERASE_BACKGROUND, but the tradeoffs weren't worth it. As it is, I don't know if I haven't harmed Linux or Mac.

+ Changed the "Please wait... requerying dataset" busyinfo to just push it to the StatusText.

+ [3996] and [3998] added property TabStop, which when True allows focus to the control (the default). However, I've run into oddities when creating panels with some controls with TabStop=False. Turns out, I was calling Navigate() without a needed argument, the event needs to be skipped, and the Navigate() needs to be done in a callAfter().

+ Implemented a basic debugging output window. It's fairly simple now, but can be customized further based on feedback.

+ There is a new menu item in the base menubar class "Debug Output Window". It's designed to be a checked menu item, but the check always appears to be out of sync with the debug window. Selecting that menu shows/hides the debug output window.
To add debug output, add this line to your app where you want to record information:
	debugout("Some stuff")
You can add multiple items, much like the print command, and they will be output with a space separator
	debugout("Status", self.status)

+ Fixed the issue with AutoIndent not working.  The issue was that GetLineIndentation wanted wx's zero based line number instead of the 1 based line number we use.  We were using the 1 based line number, and the indentation level of the new blank line was returned and always zero.  This fixes that.

+ Added a new property to the dEditor widget which exposes the ability to show indentation guides.  The property is called ShowIndentationGuides.

+ Improved VirtualFields by adding the option to set a given VirtualField to a dict instead of a function. Currently, this dict has one required key, "func", that stores the function object, and an optional key, "requery_children", that determines whether or not child records are requeried before the virtual field function is run.

+ Changed default behavior to *not run* the child requeries, as this was a performance hog for an uncommon case. If your VirtualFields function requires that child records have been requeried before running, then you can either requery them inside the function itself, or define the VirtualFields like the following:
old:
  self.VirtualFields["myfield"] = myFunc
new:
  self.VirtualFields["myfield"] = {"func": myFunc, "requery_children": True}

+ Worked around a substantial source of the flickering of dGrid on Windows, by caching the cell values for 10 seconds to avoid unneccesary calls to biz.getFieldVal(). This will probably improve performance on Mac and Lin as well, even though those platforms didn't exhibit the flickering. Now, the windows grid will flicker at most once every 10 seconds. Call grid.update() or grid.refresh() will clear all cached values immediately.

+ Added the deleteByValue() method to dPref. This enables you to delete all pref entries that contain the passed value.

+ Updated dShell so that if you re-use a command from its history, the old entry for the command is deleted. The effect is that the history only contains one instance of each command, with the most recent usage at the top.

+ When calling getPrefs(), you can now indicate a key that is relative to the current pref by prefixing it with a period.

+ Deprecated the SQL property. It now issues a deprecation warning, and then passes the values through to the UserSQL prop.

+ Added 2 new properties to the dEditor widget.  They are ShowEdgeGuide and EdgeGuideColumn.  Basically, ShowEdgeGuide will display a line at the specified column position.  Note that if the editor has a variable spaced font set, wx uses the average of the characters' widths to determine where to put the line.  Also note that wx will only allow for either HiliteCharsBeyondLimit or ShowEdgeGuide to be True, not both.  So, when one is set to True, the other is set to False.

+ Removed the setting of UserSQL when setSql() called without arguments. Removed setting the SQL property, and instead set UserSQL directly.

+ Changed the superclass of dEvent from dObject to the base Python object class.

+ Fixed the goNextBookMark and goPrevBookMark function.  The mask trouble was that the marker identifier is really a bit in a marker mask.  Since, _bmkPos was 5, it was the 5th bit which corresponds to the integer value 32.  So, by doing a left shift on the marker, we can get the proper mask.

+ Also, fixed the issue with zero based line numbers and the line number being off by one.  Furthermore, if there was a marker on the line, we had to move to the next line to search otherwise MarkerNext would return the line to search from.

+ Wrapped the wx.Toolbook class.  It's another dPageFrame like widget, only it uses a ToolBar instead of tabs.  Things to note:

+ Images must be 32x32 or they fail to add (same as the other page frame widgets except they are 16x16).  Also, images cannot be changed after a page is created.

+ Wrapped the wx PlateButton widget into Dabo.  Everything works and is tested.  I did a minimalist wrap for the things I needed.  If somebody wants another feature wrapped, let me know.  I called it dBorderlessButton because it seemed to fit well.

+ Fixed the bug that failed to discern that a new record with a manually-populated PK was in fact new. Thanks to Dr. Sibylle Koczian for reporting this and working with me to help track it down.

+ Tracked down and fixed the problem that caused all those 'GTK-Critical' messages.

+ Added an 'OK' button to make it clear how to dismiss the dialog when running under a window manager that does not have a title bar present.

+ Refactored the imports to better catch cases where simplejson is not installed.

+ Changed the way that 'IsAdding' is determined to take into account manually-entered PKs.

+ Added a fix to dSizerMixin when setting the Spacing property - sometimes the value can come from the edited grid cell in the Property sheet as a string instead of an int. I think I fixed the prop sheet, but I left this fix in just in case.

+ Fixed a problem when running designs containing unfilled LayoutPanels. The default settings of the panel were being ignored, resulting in a zero-sized panel in the runtime.

+ Worked around an apparent bug with MDI Child Windows on Mac, where calling Maximize(False) will maximize instead of restore the window.

+ Fixed the status bar displaying "Record 1/0" when there are no records.

+ Fixed status text to still go to the MDI child form on Mac, instead of the MDI parent. On Mac, the MDI parent frame isn't shown and the children are still fully SDI so the whole MDI thing is kind of a misnomer.

+ Fixed dGrid.addColumn() to accept not just a custom dColumn instance, but also a custom dColumn subclass, which it'll instantiate with any passed property settings. If an instance is passed, the properties will be applied to the instance.

+ Added [Dynamic]CellBackColor property to dColumn.

+ Commented out the code that allows for an optional main panel to be added to a form upon creation. I left the code in while we test existing code, but I haven't found anything in the framework that uses this. Trac issue #1033.

+ Modified the firing of the Hit event when the slider is set to Continuous=True. Now it will only fire if the underlying value changes. This may be what was responsible for Trac Issue #1054, in which multiple events were recorded.

+ Fixes the issues noted in Trac #1114: WordWrap was not showing properly on Mac and Windows when a label was initially shown.

+ Changed the order that the update() steps are carried out. I had noticed a bug in some of my Dynamic* properties that depended on the control's Value. The cause was that the dynamic props are evaluated *before* the Value gets updated.

+ Moved the sizer default logic into the DesignerUtils script.

+ Enhanced the getDefaultSizerProps() method to handle the mangled names that the Class Designer sometimes creates.

+ Changed the way that the import statement block is handled in the .cdxml. This *should* be backwards-compatible, but may require re-creating your import statements in your design.

+ The change was required because the previous code sometimes resulted in import statements not being run before code that depended on those names was called.

+ Added the dabo.ui.spawnProcess() method. This allows to to run another application in a completely independent process.

+ Added the method 'appendDataSet()'.

+ This fixes the issue with the Font property and dMaskedTextBox. We were only checking for the existence of a '_font' attribute, and apparently the masked classes defined that att themselves.

+ Changed the field validation so that it is triggered by any call to flushValue(). Previously it only fired on LostFocus events, meaning that you could set the Value directly in code without validation.

+ Fixed the call to activeControlValid() to only be made if there is an active control, and it's not the current control.

+ added support to allow the retrieval of un-masked values or masked values for the dMaskTextBox.

+ dApp wasn't allowing the setting of a custom Crypto instance in initProperties, because it was reinitializing self._cryptoProvider to None *after* the custom Crypto was already set by the user. Fixed, by taking away the unneeded assignment in __init__, and adding a getattr() wrapper in _getCrypto().

+ Changed the default for SQLite to not create the database file if it doesn't already exist. This setting is controlled by dabo.createDbFiles, which defaults to False.

+ Added dException.DBFileDoesNotExistException class. This is raised if you try to connect to an SQLite file that does not exist and dabo.createDbFiles is False. This exception can be caught in the calling routines and handled appropriately. dConnection now takes an optional constructor parameter 'forceCreate'; if that is True (default=False), the db file will be created no matter what the system setting is. dbSQLite.getConnection() takes that same parameter, and passes it to the connection constructor. dPref, which is supposed to create the DaboPreferences.db file no matter what, has been modified to pass  forceCreate=True to the connection.

+ Added the improvement provided by 'cowo' for proper importing of project subdirectory modules. Added the method 'getStandardAppDirectory()'. This takes one of the following standard Dabo directory names and returns the path to that directory. It takes an optional path location to start looking from; it will also search the app's HomeDirectory. The standard directory names are:
"biz", "cache", "db", "main.py", "reports", "resources", "test", "ui"
If the user requests a non-standard directory, a message is printed to the errorLog and None is returned.
If the specified standard directory cannot be found, None is returned.

+ Removing the deprecated first datanav classes.

+ Moved the datanav2 code into 'datanav'. Modified the datanav2 __init__.py to import datanav classes so as not to break existing references to datanav2.

+ Improved the handling of empty datasets. No longer will exceptions be raised; instead, None will be returned on an execute against an empty dataset, and the original will be returned on a filter on an empty dataset.

+ Added an afterSetup() hook method at the suggestion of Henning Hraban Ramm.

+ Added the ValueMode property to dMaskedTextBox. This will control whether the Value property returns the masked value or the plain value. Default is plain.

+ Improved the import logic in test.py. Also fixed the import of dBorderlessButton so that when it is run inside of test.py it doesn't break the test.

+ Added a check for non-date values in dDateTextBox to prevent the errors reported earlier this week.

+ Reworked the column.Visible functionality, and as of now it displays the test correctly in dGrid, although I'm sure I've missed some things. I tested on Linux.

+ Changed the way that the Visible property works with columns. Now the column is not removed from the grid's Columns collection; instead, its Visible status is taken into account when drawing the grid.

+ Added the 'addSizerDefaults()' method. This is to be used by external tools to set defaults for controls that are not part of dabo.ui.

+ Found a case where a Designer tool (the view palette) had controls that were bound to properties that not all the controls they were modifying had. This may be related to some of the abends encountered when using the View Palette on Windows and Linux.

+ Improved the drag/drop behavior of grids.

+ Fixed Bottom and Right properties to get set after the wx object is fully instantiated. Thanks to Alex Tweedly for reporting the issue.

+ Implemented the ResetPageNumber property of reportwriter group objects. If it evaluates to True, the page number will be reset when the group expr evaluates differently.

+ Added PageNumber read-only (runtime) property of the Report object, accessible from report designs by 'self.PageNumber'. For example, put this in an expr for a string object:
	"Page %s" % self.PageNumber
This is just the first step. The PageNumber at this point will just keep incrementing with no way to reset it during the report run.

+ Added handlers in the UI layer for some of wxPython's AppleEvent handler methods. These catch the methods and propagate them to the dApp layer, where they can be overridden in an app subclass.



Dabo 0.8.4 (2008-06-03) Revision 4111):
===============================================================================
Dabo:
+ Bugfix: grid can now search by non-string/non-numeric fields. Thanks Dennis Meulensteen
  for pointing out the problem

+ Deprecated bad spelling: unBindEvent()

+ Web Update now works for ide and demo, as well as the base framework.

+ Fixed WordWrap in dGrid.

+ Fixed Windows dTextBox problem, which would change ReadOnly back to False when changing
  the Alignment.

+ Added StrictNumericEntry property to dTextBox and dSpinner.

+ Linked the Find/Replace dialog to dGrid's findReplace() method, enabling finding in a dGrid.
  (ticket #1126)

+ Replace All bugfixes.

+ Forms were always restoring their default size, even when explicit sizes were given. Fixed.

+ Fixes from Kevin Edwards to make sizing sub-panels perform better, and to propertly set the
  background color of the dGrid bool renderer checkbox.

+ Fixed the getLastInsertID() for dbPostgreSQL, to work with non-serial PK's as well. Thanks
  to John Fabiani, Adrian Klaver, and Lorenzo Alberton.

+ Added dabo.settings.dateFormat, dateTimeFormat, and timeFormat. If None (the default) the
  formatting of these date types will be dependent on the user's settings in the operating
  system. This lets the appdev specify the format desired for display and editing in text
  controls and the grid. Prior to this, the only format was YYYY-MM-DD, which was satisfying
  to nobody.

+ Added dabo.ui.getObjectAtPosition(x,y), which returns an object reference based on the
  screen coordinates passed.

+ Removed unneeded, hackish code from datanav2, thanks to Pedro Vale de Gato.

+ John Fabiani fixed some issues with port in dbMSSQL.py.

+ Added dataToXML() to dBizobj.

+ Nate Lowrie added some niceties to dEditor, including better code folding.

+ Added code to allow biz.DefaultValues being set to None. If the field values are
  still null when saving, the insert statement won't include them, allowing
  database defaults to be used.

+ dCursorMixin no longer raises NoRecordsException from sort().. it merely returns.

Dabo 0.8.3 (2007-12-11) Revision 3793):
===============================================================================
Field types in the data layer are now covered better (previously only non-
joined fields were massaged).

Transaction tokens are now per-connection, not per-bizobj. Thanks Uwe Grauer
for the nudge.

dGrid performs better when changing rows.

Fixed check/radio menu items to work under GTK and Windows.

Fixed display problems with word-wrapped labels in dDialog.

Fixed some report writer xml conversion problems.

Enabled setting report writer's OutputFile property to a file-like object, and
not strictly a file object.

Fixed unicode-xml saving/loading in ReportDesigner.

Added default size and position for forms (they tended to be much too small
before).

Web update fit and finish.

Added defensive code to dBizobj when running without primary keys.

Added dabo.ui.getDisplaySize()

Fixed sending Enabled property to dToolbar constructor.

Refactored masked functionality out of dTextBox into dMaskedTextBox.

Improved Class Designer and Property Sheet.

Experimental replacement for dSpinner added: dSpinnerX.

Fixed relative pathing problem in .cdxml files.

Fixed dEditor to gracefully handle cases where we don't have read/write
permissions on the file.

Added getDisplayLocker(), which gracefully handles unlocking the display
when it goes out of scope.

AppWizard-generated apps running in Python 2.4 and earlier could fail due
to recent changes in dApp. Fixed.

Fixed several bugs in the handling of compound cursor.KeyField values.

Can now set dColumn.Resizable, not just dGrid.ResizableColumns.

Tickets fixed:
#1070
#1072
#1108
#1109
#1110
#1117
#1121
#1123

Thanks to suggestions, patches, and contributions from:
Carl Karsten
Uwe Grauer
Pedro Vale de Gato
Orcun Avsar
Heling Yao
Nate Lowrie
Lukasz Szybalski


===============================================================================
Dabo 0.8.2 (2007-10-24) (Revision 3580):

Most Notable Things:
+ The dabodemo and daboide repositories are now inside the main dabo repository.

+ We no longer maintain separate stable branch; point releases are snapshots of
  the development branch instead of merely backported bugfixes.

+ Web Update is available; after downloading and installing this version of
  Dabo, you can turn Web Update on in the new Edit|Preferences window and
  be notified when updates are available. Dabo will then update itself if you wish.


UI:
+ Added masking ability to dTextBox and dEditBox, via the Mask and
  MaskedValue properties.

+ Added dRadioMenuItem

+ dEditor now formats lots of languages, not just python. Thanks Nate!

+ Improved the code completion logic of dEditor to not just blindly execute code,
  which is slow and dangerous.

+ Added dEvents.InteractiveChange,

+ dLinePlot added thanks to Nate.

+ Fixed ShowBox property in dRadioList (#1093).

+ Fixed Enter not firing Hit in dComboBox (#1061).

+ Fixed dEditor bug if a def statement was the last line in the file. (#1031).

+ Fixed problem in dGrid where a column sizing operation would sometimes start
  a sort operation. Thanks Larry!

+ Put in Kevin Edward's solution for replacing deprecated calls in dGridSizer.py.
  Thanks Kevin!

+ Grid selection wasn't updating correctly when navigating with the keyboard. Thanks
  Simen for reporting and helping to fix the problem.

+ Added FrameCount and PictureIndex properties to dImage to deal with multi-image
  files.

+ Added PreferenceDialog class, a central place for putting application preferences.

+ Added the HotKey property to dMenuItem, allowing for setting the hotkeys separately
  from the Caption. Added ui.dialogs.HotKeyEditor, for use by the user in the new
  PreferenceDialog to remap hotkeys.

+ Enhanced dPageList to be better behaved when resizing.

+ Added Transparency property to forms. 255 is totally opaque; 0 is totally transparent.

+ Disabled the calendar and shortcut keys in dDateTextBox when ReadOnly=True. (#1103).

+ The RowNumChanged event now passes the old and new row numbers, and the bizobj
  that changed rows.

+ Improved performance of refreshes for dLabel with WordWrap=True. (#1105).

+ Fixed dHtmlBox to find inline images on Windows.

+ Corrected a problem with text controls losing their selection information when they
  lose focus. (#1104).


db:
+ Improved the firebird code to get the pk of the table. Thanks Uwe!

+ John made improvements to dbPostgres.py

+ Fixed problem in determining NonUpdateFields.


biz:
+ Found and fixed bugs related to parent/child relationships

+ Major improvements to transaction handling.


General Framework:
+ dLocalize now converts strings into the given language. Set your language
  using dApp.setLanguage(). The locales have been added to Launchpad, and we'll
  regularly sync up with LP for our translations.

+ Fixed case mismatch in dLocalize (#1086).

+ Added dApp.makeDaboDirectories() and quickStart(), which set up a structure for
  dabo-based applications.


Reporting:
+ Fixed the Show property to evaluate correctly at runtime.

+ BarGraph added, thanks to Gary.

+ Fixed a traceback when trying to start ReportDesigner. (#1106).


===============================================================================
Dabo 0.8.1 (2007-07-13) (Revision 3251):

+ Added ScanRestorePosition property to dBizobj. Added optional parameter
  scanReverse to scan(). This fixes the fact that previously user code
  didn't have access to the __scanRestorePosition and __scanReverse
  attributes.

+ Refactored/fixed the case of an exception happening during scan: previously,
  another exception would happen because we tried to restore the row number
  even if we saved the PK value instead. (Ticket #1064)

+ The "Preferences" menu item in dBaseMenuBar's Edit menu used a hotkey of "P",
  which conflicted with Paste. Checked around and other apps use the "e" for
  the hotkey instead. Fixed in trunk and stable.

+ Fixed a problem where textboxes would lose their selection when moving
  focus.

+ Fixed a KeyError in dTreeView's makeDirTree() function, thanks to a fix
  by hraban in ticket #1076.

+ Fixed some unicode issues in paths in 3 places in the framework, thanks to
  Wolfram Hinderer in ticket #1083.

+ Fixed copy/paste in dShell. Ticket #1039.


===============================================================================
Dabo 0.8 (2007-05-09) (Revision 3111):

Enhancements:

	===== General Stuff =====
+ Improved a lot of the handling of paths. It is now possible to correctly
  resolve a relative path when the source file and the contained file are in
  different directories, while the app is running from a third directory.

+ Added datanav2; deprecated datanav. datanav2 no longer supports fieldSpecs,
  relationSpecs, and other things. The general theme is that the generated
  code is meant to be taken as boilerplate to be edited by the developer to
  achieve the desired results.

+ Began work on new unit testing harness, with Nate Lowrie at the helm.

+ Added/enhanced unit tests for dCursor, dBizobj, dTextBox, and dForm.

+ Big fixes and enhancements, as always, to runtime cdxml instantiation,
  including much better inheritance of properties.

+ General move away from accepting specific keyword arguments to class
  constructors, in favor of accepting property values instead.

	===== UI Tier =====
+ Began work getting grid cell properties set up. IOW, being able to set the
  ForeColor of a specific row in a column (a single cell), including
  dynamic cell properties. Currently, it works, but the only property
  I've added yet is CellForeColor and DynamicCellForeColor.

+ Removed the requirement that objects used as DataSources have to inherit
  from dObject. Thanks Carl for pointing out the limitation.

+ Added dDockForm to the main trunk, which is Dabo's wrapper for wxAUI.

+ Added the option of passing complex filter expressions to setAll(). This
  function now accepts a tuple of filter expressions of the format
  'att comp val', which will be eval'd with the child objects inn order to
  determine if the filter applies. Each expression in the tuple is ANDed
  with the others; all the tuple elements must evaluate to True for the
  value to be set.

+ Added the dHtmlBox.HtmlLinkClicked event.

+ Added the HatchStyle property to draw objects. This gives you the option
  of specifying that the fill for drawn objects can be one of the following
  hatch patterns:

    Solid (default)
    Transparent
    Cross
    Horizontal
    Vertical
    Diagonal
    ReverseDiagonal
    CrossDiagonal

+ EasyDialogBuilder - minor improvements by Nate Lowrie.

+ Added ensureLineVisible() method in dEditor, which even unfolds if needed.

+ Added WordWrap to dGrid columns while in edit mode.

+ Enhanced dShell to have Dabo property access, including Font properties.

+ Improved dDateTextBox.

+ Coerce dMessageBox messages into strings, which is convenient.

+ dGrid's navigation now traps and responds to business rule violations, with
  mediation by the form if possible.

+ dTreeView supported in ClassDesigner-designed files.

+ Added Icon property to dApp, which will become the default Icon for all
  forms and dialogs, if not overridden at the form level.

+ Simplified drag/drop in dabo.ui.

+ Added dabo.ui.getChoice() and getChoices(), which present a list of choices
  to the user, and return the user's selection(s).

+ Added TextLength property to dTextBox, to limit the number of characters
  that can be typed in by the user. Courtesy Nate Lowrie.

+ Improved font zooming. Improved handling of resizing fonts for different
  platforms (Mac), so that you have cross-platform consistency. Thanks to
  Dj Gilcrease for help in working this out.

+ Added Continuous property to dSlider, which determines whether Hit is
  raised while the slider is being changed, or only after the user has
  finished sliding.

+ Improved autocompletion in dEditor.

+ Added AutoAutoCompletion option to dEditor.

+ Added methods to dabo.ui: isMouseLeftDown(), isMouseRightDown(),
  and isMouseMiddleDown().

+ Added tango icon theme and changed our toolbars/menus to reference the new
  icons. (Ticket # 1037)

+ Added Modal property to dForm, settable only by sending the property to the
  constructor. When Modal, a dialog instead of a form will be instantiated.

+ dEditor now properly syntax-colors dabo-based xml files such as .cdxml
  and .rfxml. Previously, it displayed these files using Python coloring.

+ Removed IconBundle property from dFormMixin. Added the ability to set Form.Icon
  to a sequence of filenames which Dabo will convert to a wx.IconBundle
  automatically.

+ Added property WordWrap to dEditBox. Default is True.

	===== Data Tier =====
+ Added the option of passing additional keyword arguments to db.dConnection.
  Thanks Uwe for noting the limitation.

+ dbFirebird - Minor improvements by Uwe Grauer.

+ dbPostgreSQL - Improvements by John Fabiani, including some missing data
  types and support for schemas.

+ Added support for SQL-JOIN clauses in the sql builder.

+ Added database logging, an optional feature.

+ Improved SQLite by providing DictCursors.

+ Added enclosing of table, field, and other names in the appropriate quote
  character for the database backend in use. This allows for cases such as
  spaces in field names. Control whether quoting happens automatically using
  the dBizobj.AutoQuoteNames property.

	===== Bizobj Tier =====
+ Added the concept of VirtualFields to dBizobj, which provides a simple,
  flexible interface to reference calculated fields on the fly.

+ Added the 'SaveNewUnchanged' property to dBizobj. When this is True, new
  records that have not been modified from their defaults are saved; the
  default remains to not insert such records.

+ Improved data binding to bizobjs on a parent form.

+ Added dBizobj.deleteAllChildren()

+ Added ability to set parameters to pass to default values in dBizobj.

+ Added oldVal() method to dBizobj, which takes a field name and returns the
  value of the field at the time of the last requery.

+ Added moveToPK() method in dBizobj


Bug Fixes:
+ dRadioList.ButtonSpacing wasn't able to be set from initProperties() or
  as an argument to the constructor. Fixed.

+ Starting in wxPython 2.7, our dialogs weren't giving focus to the first
  control. Fixed.

+ More wxPython 2.8 bugfixes in dMenu, dPageFrame

+ Fixed dConnection and dConnectInfo to raise exceptions if improper
  arguments are passed. Ditto for dSizer*.

+ Fixed dBorderSizer's box to stay in back of the controls contained within it.

+ Fixed ForeColor to work immediately on Gtk.

+ Controls were flushing their value, and raising ValueChanged events, too
  many times. Fixed.

+ Dialogs and forms weren't able to set things like whether they have a
  close box, from within initProperties. Fixed.

+ Message dialogs invoked like dabo.ui.areYouSure() weren't getting attached
  to the appropriate parent form, so that the message displayed wouldn't
  activate the form that it applied to first. Fixed.

+ Fixed rapid flashing in a sorted dGrid when an editable column was selected.

+ Fixed bug that prevented adding new records when child bizobjs existed.
  (Ticket #1027). Thanks to Larry Long and John Fabiani for continued
  assistance in tracking these problems down.

+ setWhereClause() method missing in dBizobj. Fixed.

+ Fixed dCursor.getChangedRows() to not take into account new records that
  have no changes.

+ Fixed the dBizobj.save() process to not scan all child bizobj's repeatedly.
  This fixes some problems, and speeds up save() considerably.

+ Fixed a problem where canceling a bizobj that had no records caused an
  exception that was being displayed with notifyUser(). Normally, a bizobj
  with no records does not need canceling, so raising such an error is not
  appropriate. You can still have the old behavior by calling cancel() with
  'ignoreNoRecords = False'.

+ Fixed a bug reported by Larry Long and John Fabiani that involved requerying
  one bizobj resulted in checking for pending changes in other bizobjs that
  were not involved in the requery.

+ Descending sorts created infinite loop with duplicate values. Fixed.
  (Ticket #1041). Thanks Jussi.

+ Fixed status text to clear the old field validation failed message when the
  user fixes the value and the field now passes validation.

+ Fixed the geometry persistence to only restore the size of the form from
  user settings if BorderResizable is set to True.

+ Fixed dGrid's AlternateRowColoring to be settable from the constructor
  or initProperties (previously, it was only settable in afterInit() or
  later).

+ Dynamic props on dColumn were not working: fixed.

+ Fixed a bug that confused the string 'None' with the null value None when
  setting BorderStyle from a cdxml. Thanks to Miguel for catching this one.

+ Fixed a couple of bugs related to the dSizer.BorderSides property.
  Previously it was not retrieving that property correctly from the internal
  wx flag.


===============================================================================
Dabo 0.7.2 (2007-01-18) (Revision 2716):

Additions, all minor, backported to stable only to keep compatibility with the
stable versions of daboide and/or dabodemo:
+ Enhanced the getImagePath() function to work better with Windows pathing.
+ Refactored dPanel into a common mixin class.
+ Added getBaseNodeClass() function to dTreeView.

Bug Fixes:
+ Fixed the stable branch to work with wxPython 2.7 and 2.8, which was a fairly
  large backport of relevant changes from the development trunk.
+ Fixed a form activation problem that would happen in some cases on Windows,
  particularly with the Class Designer.
+ Fixed incremental search in dGrid, which was broken by earlier unicode fixes.
+ dBizobj.onSaveNew() user hook never being called. Fixed.
+ Fixed but in dUserSettingProvider if setting/retrieving nested settings.
+ dForm not updating field values after a save(), which is sometimes needed.
  Fixed.
+ Fixed dForm to explicitly cancel bizobj changes if the user answers "no" to
  the "do you wish to save?" message. Otherwise, the application would never
  finish.
+ Fixed dGrid and dImage's attProperties.
+ Fixed bug in dGrid.HeaderHeight resulting in a traceback if you tried to set
  it in initProperties() or as a kwarg to the constructor.
+ Fixed dabo.ui.busyInfo() to actually show the specified text instead of just
  an ugly grey box on Gtk.
+ Fixed a bug in dbFirebird that was caused by initializing more than once.
+ Fixed a problem with the date textbox in the datanav select page adding 1
  to each month, resulting in an incorrect select statement.
+ Fixed some minor wording and behavior problems with the Quick Report option
  in AppWizard apps, thanks to Ted Roche.
+ Fixed htmlAbout to not return the html tags to the clipboard.
+ Fixed dToggleButton to always flush its data, not just on LostFocus.


===============================================================================
Dabo 0.7.1 (2006-11-21) (Revision 2490):

Bugfixes:
+ Segfault in dSplitter when dragging the sash. Fixed.
+ __init__() of the wx classes happening twice. Fixed.
+ Setting Caption sometimes required a subsequent refresh(). Fixed.


===============================================================================
Dabo 0.7 (2006-11-16) (Revision 2464):

It has sure been a while, but we haven't been resting. Lots of new stuff
as we move one step forward to Dabo 1.0. Here are the most important
things to mention.

Notable things:
+ SQLite is now required.
+ wxPython 2.7 and 2.8 DO NOT WORK yet, but will soon, so stick with 2.6
  for now.
+ Dabo preferences are no longer saved in .ini files, but as sqlite databases.
+ The old shortcut of referencing fields in bizobjs like:
    fname = biz.first_name
  no longer works. You need to change all such code to read:
    fname = biz.Record.first_name

Known Issues:
+ FireBird Requery problem (see http://dabodev.com/tracker/0229)


Bug Fixes:
+ Replace function in dTextBox and dEditBox causing traceback. Fixed.
+ Incremental search in dGrid now works with unicode data.
+ Double select page on Mac and Win. Fixed.
+ Datanav select page scrollbar doesn't show. Fixed.
+ Ignore Tab and Shift+Tab in grid searching, so they can navigate.
+ Setting AutoPopulatePK on the bizobj doesn't propagate to cursor. Fixed.
+ Entering a unicode character in a dTextBox set up with a str value doesn't
  stick. Fixed.
+ Fixed unicode problems in dEditor.
+ Fixed problem where fast cpu's could generate non-unique object names.
+ Fixed showModal() to reactivate previously deactivated windows accordingly.
+ dCursor's initProperties() called twice. Fixed.
+ Spacers not working correctly in class designer generated files. Fixed.
+ Fixed dabo.ui.getMouseObject() to always return the dabo object, not the
  wx one. This would happen with grids, for example.
+ Border sizer caption not showing. Fixed.
+ Connection information not properly escaped in default.cnxml. Fixed.
+ Fixed layout of nested sizers.
+ Fixed running class-within-a-class (class designer generated).
+ Fixed paged controls to work when generated from the Class Designer.
+ Grid mouse events duplicated. Fixed.
+ Can't set RegID from within initProperties(). Fixed.
+ stderr and stdout not restored if intellisense processing caused exception.
  Fixed.
+ Fixed login form to look okay at low resolutions.
+ Removed old, lingering requirement for mx.DateTime.
+ dSpinner doesn't work correctly unless initialized to '0'. Fixed.
+ dForm.ActiveControl would return controls in other forms, if they were the
  current active control with keyboard focus, when clearly we want the active
  control of *this* form. Fixed.
+ Fixed function in dbSQLite to find and set the pk field.
+ Fixed __version__.py to work outside the expected directory naming
  structure.
+ Report writer wasn't initializing report variables before starting the
  iteration of the cursor, resulting in errors if you referred to the
  variables from inside the page header, for example. Fixed.
+ Setting the Value of a data-bound control programatically wasn't propagating
  to the underlying bizobj. Fixed.
+ New reportlab can only handle utf-8, causing errors otherwise. Added a
  friendly message in case this happens to you when running the Quick Report
  option in AppWizard-generated apps.

Enhancements:
+ Added Visible property to grid dColumns.
+ Added column information to the EventData of grid events.
+ Removed RequeryOnLoad property from datanav.Form to dabo.ui.dForm.
+ Can now send kwargs to grid.addColumn(), which get sent to the column's
  constructor.
+ Added self.super() to replace cls.doDefault, thanks to Timothy Delaney.
+ Added exception handling to requerying. If exception happens, the
  transaction will be rolled back.
+ Enhanced the process used to determine field types. In addition to better
  automatic deduction of types, you can now explicitly set the DataStructure
  property of dBizobj and Dabo will respect that.
+ Added Alt+Up and Alt+Down to AppWizard Apps, which bring you to first and
  last records, respectively.
+ Added properties for getting/setting the selection and insertion point for
  text controls. These are InsertionPosition, SelectedText, SelectionEnd,
  SelectionLength, and SelectionStart.
+ Compound primary keys can now be used.
+ Dabo icon now has an alpha channel and looks much better. Thanks to Kenneth
  Ismert for doing a great job of this.
+ Added Expanded property for treeview nodes.
+ Can now set PageClass property of dPageFrame to a cdxml file.
+ Added dRadioList to replace dRadioGroup. Pure Dabo control.
+ Added ability to set a bizobj LinkField property to a table.field reference.
+ Added RequeryWithParent property to dBizobj, True by default. Allows for
  user code to determine when to requery the child, for performance reasons.
+ Added Selection property to dGrid, which returns the list of selected rows
  or columns.
+ Added AutoBizobj, thanks to Echo.
+ Added Count property to dMenu, to return the number of child menus.
+ Changed most initial dEditor settings into configurable properties.
+ Drag/Drop for tree nodes begun.
+ Added getCurrentRecord() that returns the actual record data.
+ Added dPref for managing application preferences, and switched the default
  way to save/restore settings to use this class. Your application can define
  whatever hierarchy you see fit. See also the new BasePrefKey and
  PreferenceManager properties of dObject.
+ Added ForceCase property to dTextBox and dEditBox. Forces to upper, lower,
  or title case as the user types.
+ Added getTempCursor() to facilitate ad-hoc data queries.
+ Added dApp.Encoding property, a single place to get the unicode encoding. To
  set the default encoding, use dabo.defaultEncoding = "latin-1", for example.
+ Added clear() method to sizers, to remove all items from the sizer, and to
  optionally destroy the items as well.
+ Added Precision property to dColumn, which specifies the number of places to
  show for float columns.
+ Added preliminary support for BLOB fields. Works at least with MySQL.
+ Added GridBeforeSort and GridAfterSort events.
+ Added itemNode entry to the eventData for Tree events.
+ dToggleButton now uses GenBitmapTextToggleButton, allowing for text and
  images.
+ Added some filtering functions to dDataSet, for selecting which records
  to return.
+ Added transparency and drawGradient to drawing objects. Thanks to Andrea
  Galvana for the gradient code.
+ Added WordWrap property to dColumn, which will wrap the text appropriately.
+ Added cut/copy/paste hooks at the grid level.
+ Added dabo.ui.getFormMousePosition (position relative to active form)
+ Added DrawMode property, the logical function to use for draw operations.
+ Added ability for About dialog subclasses to add their own version info.
+ Added helper functions to dabo.ui: isControlDown(), isShiftDown(),
  isAltDown(), and isCommandDown() which will return True/False depending
  on whether the key is down while the call is made.
+ Added containerCoordinates() and formCoordinates() method, to get the
  current mouse position relative to the container or form.
+ Added objectCoordinates(), which is relative to the object.
+ Made dForm.ActiveForm settable as well as gettable.
+ Added isContainedBy() function, returning True if the object is contained
  inside the passed container.
+ Made dEditor a data-aware control (cool!)
+ Added Encoding property to dDataSet. Thanks to Simen Haugen.
+ Can now send extra keyword args to bindKey(), which will get included in
  the eventData dictionary, just like it works with bindEvent().
+ Added Dabo data type code "L" for blobs, "G" for longs, and "F" for floats.
+ Added 'sort none' option to dGrid. Now, the third mouse click on the header
  will be 'no sort'.
+ Added accelerator keys to the datanav Actions menu. Added Select All to the
  Edit menu.
+ Added dabo/ui/uiwx/concordance.py, which shows a listing of all the Dabo
  ui classes, and the wx Class from which they descend. Then, it shows the
  wx classes, and the list of Dabo classes that descend from it. Should help
  people with questions like "where is wx.TextCtrl in Dabo? (dTextBox).
+ Added MultipleSelection property to dGrid.
+ Improved dPageList, allowing setting the spacing of the list items with
  ListSpacing, and catching right-clicks smartly (the correct item gets
  referenced).
+ Added function dabo.lib.getRandomUUID(). Thanks to Ka-Ping Yee.
+ Added method afterInitAll(), which gets called after all child objects have
  been initialized and are live.
+ Added helpful treeFromStructure() method to dTreeView, which takes a
  hierarchy (in list or tuple form) and constructs the tree nodes accordingly.
+ Added ability to send sequences of 3-sequences to the ok/cancel dialog to
  automatically construct labels and controls on the dialog.
+ Couldn't use the same RegID for objects, even if the prior object was
  destroyed. Relaxed the requirements to allow for this.
+ Added dHtmlBox, which wraps wx.html.HtmlWindow, for displaying formatted
  text simply. Thanks to Nate Lowrie.
+ Added showContainingPage() method to all ui controls, which will recursively
  show any pages in any pageframes that contain this control.
+ Added showCurrentLine() to dEditor. Does what it says.
+ Datanav forms (AppWizard-generated) now look better as they have a bigger
  default size. Thanks to Bill Anderson for bringing up lots of such issues.
+ Added AddChildEditPages property to datanav apps. Set it to False and you
  stop getting the annoying edit pages for the child bizobjs.
+ Previously, you could only set page sizes in reports to strings like
  "letter", "a4", etc. Now, you can also set explicit sizes such as
  (100, 75) or ("1.75 in", "1 in").
+ Added preliminary support for Microsoft SQL Server. This isn't usable yet
  for any but the most tenacious developers, and likely quite buggy. If you
  want to try it out or help develop it, please post a message to the dabo
  developer's list (dabo-dev@leafe.com).


===============================================================================
Dabo 0.6 (2006-03-27) (Revision 2043):

+ Fixed a problem when switching to the Browse page of the datanav grid without
  first running a query. Also, there was an error being thrown if a previous
  query had results, and a subsequent query had no results.

+ Modified the code in _setCurrentRow() of dGrid so that it wasn't calling
  SetGridCursor() unless the position had actually changed. I had recorded up to
  10 calls to this function, all with the exact same values each time I switched
  to the Browse page.

+ Removed the code that lower-cased field names, as it was preventing the code
  from working with case-sensitive backends and columns containing capital
  letters.

  Fixed a problem where str values were not able to be properly converted to
  unicode.

+ Added a parameter to the promptForFileName() method to specify the default
  path for the dialog.

+ Added the TreeItemContextMenu event. This differs from the normal
  ContextMenuEvent in that it returns the itemID of the node that was
  right-clicked.

+ Added code in the event data gathering code to store the tree item ID for
  these events in EventData.itemID.

+ Changed all the names '_id' in the dTreeView.py file to the clearer 'itemID'.

+ Fixed an oversight in the dSizerMixin that didn't remove the Box for a
  dBorderSizer when the sizer was released.

+ The double-Activate on Windows is really getting in the way. I haven't heard
  anything from my bug report yet, so I added workaround code to ignore the
  first Activate.

+ Cleaned up the order of releasing child objects for sizers. Also fixed problem
  with releasing the box for border sizers.

+ Added getFunctionList() method to return a list of all 'class' and 'def'
  statements in the current file.

+ First pass at integrating the dTable class into the dabo.db framework. Right
  now, if this works at all, it only works for SQLite.

+ Fixed a bug wherein multiply-nested sizers might not release all of their
  content when release(True) is called.

+ Added a 'setInactive()' method that will hide the auto-complete popup if one
  is visible.

+ Disabled the fillGrid()'s setting of focus to the grid, as it causes problems
  with stealing focus away from another active form, at least on Windows. Also,
  it seems that such code really doesn't belong inside the function to build the
  grid, but perhaps we'll find it belongs somewhere else.

+ The xml header wasn't being converted to native line endings. Fixed.

+ No need to explicitly do the unicode conversion in the report fields, as that
  is done in the report writer.

+ Added a Refresh event. This is raised when dForm.refresh() is called. All
  dPemMixin classes will receive it, and fire their refresh() hook method.

+ Added dynamic properties to most normal static properties. Example: given a
  label and a function 'currTime()' in a form that returns the current time,
  issuing the following:
    label.DynamicCaption = label.Form.currTime
  will result in the label's Caption property being updated every time
  label.Form.refresh() is called.

+ Added two methods to dabo.ui for converting image data back to bitmaps and
  images. These were necessary because I noticed that when Editor.py was called
  from locations other than its own directory, the image file for the function
  button was not found. The solution was to convert the .png file to a data
  stream using wx.tools.img2py.py, and store that in Editor.py.

+ Can now set dApp.UI=None, and setup() won't try to load a UI. You have to do
  it explicitly, though, such as:
    app = dabo.dApp()
    app.UI = None
    app.setup()
  --or--
    app = dabo.dApp(UI=None)
    app.setup()

+ First crack at creating a double-buffered drawing surface. The new class,
  'dDrawPanel', is a subclass of dPanel, but has its repainting handled through
  the double-buffer techniques outlined on the wxPython wiki.

+ Bookmarks in dEditor now persist when you save the file. If you re-open a
  saved file with bookmarks, they are restored.

+ Refactored dUserSettingProvider a little bit. Fixed a bug in
  getUserSettingKeys() that resulted in it always returning an empty list. Added
  deleteUserSetting() and deleteAllUserSettings(); these do just what you think
  they would.

+ Changed a couple exec() calls to setattr() calls instead, which may be safer
  if not faster, but definitely more explicit and easier to understand.

+ Implemented the handling of RowSpan/ColSpan for grid sizers.  Added a
  GridSizerSpanException class that is raised if an attempt to set the span to a
  location that is already occupied.

+ Revamped the entire flow for transactions. These changes have been tested on
  MySQL and SQLite, but still need to be tested with Firebird and PostgreSQL.

+ Changed the default for bizobjs, cursors, etc., to not autocommit. The
  AutoCommit property of the bizobj is simply a pass-through to the cursor's
  AutoCommit property.

+ Also cleaned up some inconsistent spacing and method ordering.

+ Modified datanav to allow for manual setups that don't use fieldSpecs or
  relationSpecs. I'll be committing a change to the AppWizard that allows
  for this option soon.

+ Moved SelectPageClass, BrowsePageClass, and EditPageClass from PageFrame
  to Form, since that is a better central location for these properties.

+ Added a splash screen to the Dabo app startup. This is based on Andrea
  Gavana's AdvancedSplash class, and allows for cool shaped windows, etc.

+ Added the ability to set the DataSource to an object, rather than just a
  string that can be eval'd to an object.

+ Changed the 'getMaxRow/Col' methods to 'getHighRow/Col' in order to avoid
  confusion with the MaxRows/Cols props in dGridSizer.

+ Modified both sizer classes to accept windows and not just SizerItems when
  setting/getting prop values.

+ Added the movePage() method, which takes either a page reference or a page
  index, and moves the page to the specified position. The page is then
  selected, unless the third parameter 'selecting' is False.

+ Added a getInt() method to dabo.ui.uiwx.

+ Fixed the splashscreen display on Windows.

+ Added the ability to set the font face and size for the editor.

+ Added the setCheck() method to dMenu. Given a caption, it will check any menus
  whose captions match. By default it will uncheck any that don't match; you can
  pass False as the second argument and leave non-matchers alone. Also added
  clearChecks() to uncheck all menu items in a menu.

+ Exposed the FileName and FilePath properties in dEditor.

+ Added some syntax sugar for referring to fields and variables in reports.
  Where you used to have to refer to self.Record["clientname"], you can now do
  self.clientname. Same with self.Variables.

+ Added the 'callEvery' function to dabo.ui. This function accepts an interval
  (in milliseconds), and callable reference, and optional arguments to that
  callable. It then creates a timer that fires the callable every <interval>
  milliseconds, passing along any optionally included arguments. The timer
  reference is then returned, where it can be controlled by calling stop(),
  start() or release(). This is based on the dCallEvery class that Brandon
  Singer proposed. I made it a function in dabo.ui because I felt it was more
  consistent with the existing functions callAfter() and callAfterInterval().

+ Changed the default for forms to not automatically show "Record 1 of 0" or
  similar meaningless database information in the status bar. Set it back to
  True for the datanav Form class, so all datanav apps should remain unchanged.
  All of the apps in the demo and IDE directories that don't query data, though,
  no longer show that message.

+ Creating an instance of dApp doesn't automatically create an instance of
  uiApp. Instead, it now asks dabo.ui to get it a reference, and dabo.ui either
  returns the current instance if one already exists, or creates one if not.
  This allows you to run wxPython apps from within wxPython apps.

+ Added some rudimentary support for file drag/drop. Right now, you can call
  'createFileDropTarget' on an object to make it able to respond to files
  dropped on it. Pass in an optional handler object reference; otherwise, the
  handler is set to the object itself. The drop event is passed on to the
  handler by calling its 'processDroppedFiles' method, which should be
  overridden in the handler object to do the specific processing of the files.

+ Added a 'Column' property to dEditor; this represents the column position in
  the current line, and can be changed to move the cursor within the line.

+ Added option in getItemByRowCol() to return the sizer item in the given
  position instead of the object managed by that sizer item.

+ Added method 'isItemChecked()' to allow you to determine the checked status of
  any menu item.

+ Added dabo.ui.getMousePosition(), which returns the position of the mouse
  on the screen. This is in contrast to dPemMixin.getMousePosition(), which
  gets the position of the mouse inside the client window.

+ Update to allow execution of SQL statements without affecting the current data
  set. The bizobj has a new pass-through method named 'execute()', which takes a
  statement understood by the backend database and passes it to its cursor's
  execute method.

+ The cursor class has been modified to run all statements that don't begin with
  'select' through its auxiliary cursor, thereby preserving its data set.
  Preliminary tests that I've run have confirmed that these are working
  correctly, but there should be a lot more testing done before I am confident
  that these changes are truly sound and can handle whatever we can toss at them.

+ You can now set the DataSource to an actual object, instead of having to set
  it to a string that could be resolved to an object.

+ Added basic support for storing lists/tuples in the user settings.

+ Added a simple way of persisting MRU lists in applications. A new dApp
  property, '_persistentMRUs' is a dict that contains the name of the menu as
  the key for the entry, and the function to bind the items to as the value. The
  framework will then handle saving and restoring MRU lists upon app startup and
  closing.

+ Modified the uiApp to accept just the menu caption as an identifier instead of
  requiring the actual menu. This is necessary to create MRU lists for context
  menus, or for restoring menus at app startup.

+ Updated the requirement that a bizobj be found for all data sources. Since
  that was written, Dabo's use of data binding has expanded to lots of
  non-bizobj uses.

+ Completed the majority of the work needed to implement saved classes that can
  be used in other class designs; it was working from the Designer, but not when
  you ran the form. These changes implement the whole inheritance structure so
  that if you change the underlying class, any changes not explicitly overridden
  in the design that uses that class are reflected. This works for both property
  changes as well as code changes.

+ Switched the default order of arguments in callAfterInterval(). It makes more
  sense to specify the interval first, followed by the function and its
  arguments. Sticking the interval between the function and its arguments seems
  very awkward. I added code to callAfterInterval() to check if it received a
  call in which the interval is the second argument (i.e., the original style)
  and switch them around in that event.

+ Removed dDrawPanel as a class. Turns out that adding double-buffering to
  panels doesn't affect their performance noticeably, so it made sense to turn
  this on for all dPanel objects by default. However, if you run into a
  situation where this adversely affects your app, there is a new property named
  'Buffered' that will turn this behavior off (i.e., make it work like it used
  to) when set to False.

  *IF YOU USED dDrawPanel IN YOUR CODE, THIS WILL BREAK IT!* You must update by
  changing all references to dDrawPanel to simply dPanel.

+ Removed the old syntax for begin/commit/rollbackTransaction. The default for
  these actions in dBackendObject is to call the appropriate method on the
  connection, not to execute a command on the cursor.

+ Removed the call to cursor.connection.begin() in the beginTransaction()
  method. This does not seem to be needed for most backends; in fact, it is
  typically used to override autocommit to create temporary explicit
  transactions.

+ Table creation now works for MySQL also. The class dAutoBizobj is a bizobj
  that has a dTable. The function AutoCreateTables() will try to create all the
  tables that have been setup with dAutoBizobj objects. If it can't create the
  tables, a message pops up for the user and the db admin. The db admin can
  enter the username and password for access to create tables or the db admin
  can manualy execute the queries in the queries.sql.

+ Converted the dTimer from a bitmap to a non-visible control based directly on
  wx.Timer. This makes it fit in much better with dabo.ui.callEvery(), which is
  much more convenient to use in many cases.

+ Began coding for the Hover property, which will allow for easier visual coding
  of MouseOver events. It isn't fully implemented yet, so don't try working with
  it.

+ Implemented the Hover property in dPemMixin. The reason for this rather than
  relying on MouseLeave to terminate the effect is that there are many time when
  it seems that the mouse leaves the area without triggering the MouseLeave
  event. The Hover mechanism employs a timer to check for mouse position, and
  fire the MouseLeave code if it detects that the mouse position is outside of
  the control.

+ Added a CustomSQL property to the datanav form. If set, the settings in the
  select page will be ignored and the contents of CustomSQL used instead.

+ Added defaults to dGrid.getValue(). If no row or col is specified, it defaults
  to the current row/column, respectively.

+ Added fontMetricFromDrawObject() to dabo.ui. This enables simple calculation
  of the width/height of a drawn text object.

+ Added a fitToSizer() method to dPemMixin. This will resize the object to fit
  the size required by the sizer represented in its Sizer property. You can also
  pass in extraWidth and extraHeight values to adjust the size further.

+ Added 'Alignment' to the pre-init properties of dCheckBox. Cleaned up the
  property methods and definitions to make them alphabetized, and to make the
  strings localized. Also relaxed the values accepted for the Alignment
  property.

+ Added an option to dEditor.changeFontSize() to accept strings in the format
  "+n" or "-n". These will increment or decrement the font size by 'n' points.

+ Moved the _addCode() method out of dFormMixin, since it really is more generic
  than that. It now lives in dObject._addCodeAsMethod(), which takes a dict of
  method name/code pairs and adds them as methods of the object. dPemMixin now
  looks for a keyword argument called 'srcCode', and if found, adds it to the
  object.

+ You can now call addObject() and pass a cdxml file instead of a Dabo class
  reference, and the class defined in the cdxml will be added to the parent.

+ Cleaned up the dynamic code creation routines in dObject and
  DesignerXmlConverter.

+ Modified xmltodict to handle property declarations.

+ Added setAfter() and setAfterInterval() to dabo.ui. These work the same as
  callAfter() and callAfterInterval(), except you use them to set properties to
  particular values.

+ Added the following properties to dGrid: MovableColumns, ResizableColumns, and
  ResizableRows. When any of these are set to False, the user cannot move/resize
  the column or row.

+ Changed the keyboard datanav navigation from Ctrl+, and Ctrl+. to Ctrl+LEFT
  and Ctrl+RIGHT on Mac, and Alt+LEFT and Alt+RIGHT on Linux and Windows. I've
  The original configuration, in addition to being nonintuitive, didn't work on
  Windows.

+ Added the ability to save screenshots in one of several graphics formats.
  While this was part of the Bubblet demo originally, it could have uses
  elsewhere. For example, combining this with dabo.ui.callAfterInterval() would
  enable timed screen shots.

+ Hacked a bit to get getCaptureBitmap() to work well on GTTK, but it's still
  a bit of a mess. GTK doesn't capture the title bar, menu bar or frame
  decorations of a window, and I tried to compensate the sizing accordingly.
  Individual controls don't seem to work at all. I don't have more time to
  play around with this now, but this is hardly a show-stopper for release.


===============================================================================
Dabo 0.5.1 (2006-01-25) (Revision 1860):

+ Additional MDI/SDI improvements and fixes. By default, dForm on Windows will
  be a MDI child, which is what most Windows users will expect.

+ Fixed PageFrame background color to take the background color from the form,
  not unconditional white. Only on Windows - Gtk and Mac do the right thing by
  default.

+ Fixed various issues with getting icon files and converting them to bitmaps.

+ Set the default grid font to Arial,9 on Windows, as the wx-default was just
  plain ugly.

+ Added getPositionInSizer() method to sizers, since they may also be contained
  within sizers.

+ Reworked dShell. Now it appears as a split window, with the standard command
  area on the top, and the output in the lower pane.

+ Changed dGridSizer to raise an exception if the insert method is called
  instead of just returning False.

+ Added SashPositionChanged event. Updated dSplitter to raise this event when
  the sash position changes.

+ Added scrollToBeginning() and scrollToEnd() methods to dEditBox.

+ Added pass-through properties for dSplitForm's splitter's panels.

+ Added the property 'SplitState' to the dShell class. By right-clicking on the
  shell, you can toggle between the new split behavior and the "traditional"
  single pane behavior.

+ Added a right-click menu to the output pane. Right now all it can do is clear
  itself, but we could add other stuff such as font selection, etc.

+ Fixed a bug in uiApp that prevented Cut(), Copy() and Paste() from working in
  the shell (and other non-Daboized controls that only have wx versions of these
  methods).

+ Added a menu command to the shell to clear the output window using
  Ctrl-Backspace.

+ Added the MenuOpen event to dEvents. This allows us to create dynamic menus by
  intercepting this event and updating the prompts of the menu items as needed.
  Added the event data code to save the prompt and menu object that triggered
  the event.

+ Added 'deadObjectException' as an alias to wx._core.PyDeadObjectError to the
  dabo.ui.uiwx module. This will enable Dabo code to handle this condition
  without having to use wx code.

+ Added a bunch on internationalization to the dShell script.

+ Made the dMessageBox titles come from Application.getAppInfo(appName) by
  default.

+ Added handling for situations where a bizobj is used with a data connection.

+ Added a sizeToColumns() method. This will set the width of the grid equal to
  that of its component Columns.

+ Fixed copy to clipboard in about.py to use CRLF on Windows.

+ Added new properties to grid:
    HorizontalScrolling
    VerticalScrolling
    ShowColumnLables
    ShowCellBorders
  The scrolling properties are booleans, and will hide/show the scrollbars.

+ Fixed some problems with setting the column's Width. For a number of reasons,
  when you created a grid from scratch and then added columns using addColumn,
  the columns widths you'd specify weren't being respected. Fixed.

+ Moved the code for the dEditor class from ide/dEditor.py into its own
  uiwx-level class. This will allow other apps (I'm thinking Designer here!) to
  instantiate code editors where they need.

+ Revamped the layout of the dOkCancelDialog class to create the panel and sizer
  that is needed in addControls().

+ Cleaned up some of the default spacing so that with AutoSize=True, the form
  still looks OK.

+ Removed the split sash code from the dEditor. That stuff belongs in the form
  the editor is located, not in the editor itself.

+ Fixed a bug in dGrid that only seemed to pop up when the grid was located on a
  form with a bizobj but that wasn't a dForm. The presets dialog in minesweeper
  fit that description, and it was throwing errors when you navigated through
  the grid.

+ Added methods for getting/setting the back color of individual items.

+ Added property CellHighlightWidth to dGrid, and used that property in the
  about dialog.

+ Made dPanel.addControls() better behaved.

+ Reworked/improved the Quick Report dialog in datanav.

+ Updated dPageFrameNoTabs to raise the same events as the 'tabbed' versions do.
  Added a 'getPageNumber()' method.

+ Added PNG files for rotating images clockwise and counter-clockwise.

+ Improved dImage to support 90 degree rotation in either direction. Added
  rotation to the the demo.

+ Fixed a bug in dListControl's StringValue prop, and any other place where the
  framework was trying to call the control's GetString() method, since it
  doesn't have one.

+ Added SearchDelay property to dApp, which becomes the default SearchDelay for
  dGrid. The dGrid SearchDelay can get set to any int but that won't override
  the dApp setting. If dGrid.SearchDelay is set to None (the default), that is
  when the dApp setting gets used. Set the default SearchDelay to 300 - better
  than the previous 600 IMO but still not too fast. Eventually, when we provide
  a default system preference screen, we should expose this property for the
  user to tweak how they like.

+ Cleaned up and consolidated lots of stuff in dGrid, which shouldn't have any
  effect on runtime performance. Made SameSizeRows into an actual property.

+ Using the standard button sizer in the okay/cancel dialog is good, because it
  lets wx handle the platform-convention rules. However, even though it handles
  rearranging the order of the buttons as needed, it doesn't rearrange tab
  order. So I added code to do that.

+ Reworked the login dialog to subclass from dOkCancelDialog.

+ Reworked dGrid to sync the rowcount in refresh() calls. Fixed bug in syncing
  of column counts.

+ The entire populate() cycle was happening every time you entered the browse
  page in datanav apps, when in reality the only thing you need to do in current
  dGrids when the dataset has been requeried is a simple refresh().

+ Added an initial call to _clearDocument(), which is where all the defaults are
  set for the editor. The DesignerEditor would not indent properly without this.

+ Added moveToBeginning() and moveToEnd() methods to position the pointer at the
  beginning and end of the document, respectively.

+ Added functions to dBizobj, dCursor, and dBackend to get the data structure
  from the cursor description, instead of querying the backend based on a table
  name. This is more likely to contain correct information, but will need work
  for other backends besides MySQL. Also, getting the pkid is still problematic
  - but IMO it isn't a big deal to just have the user tell us which field to use
  as the PK.

+ Fixed dGrid's buildFromDataSet() to use the new function so it will work even
  if the bizobj has no records at the time of creation.

+ Fixed dGrid.sort() to not care if sort is done on an empty bizobj. Added the
  logic to restore code saved in the Designer so that it functions properly in
  the re-created form.

+ This is big - really big. For the first time, you can create a form in the
  Designer, add code to be bound to events, or create custom methods, and that
  code will work in the form created from the .cdxml file exactly the same as if
  you had written those methods in a regular .py script.

+ Improved the card deck pictures.

+ Fixed some problems in the Icon setter that would cause errors if None was
  passed, or if the icon path didn't exist, as would be the case if you were
  running with py2exe and didn't include the icon files as resources.

+ Added a significant change to eventMixin.py's auto event binding logic. The
  code now first looks at the object itself before looking up its family tree.
  This is critical for the event binding when running a cdxml file, where
  methods are added to the object at runtime, and are not present in the class
  definition.

+ Cleaned up some spacing in dEvents; also fixed some "appliesToClass" logic
  that had events 'applying' to incorrect classses. There are still some
  anomalies, I'm sure; the event listing in the Designer will reveal these.

+ Modified the dynamic code binding to fix the problem with modifying the
  object's class definition in the current namespace. Also fixed a problem where
  code for dPage objects was not getting assigned.

+ Fixed a bug in the dListControl's _getValue() method when there were no items
  in the list.

+ Added alias 'dragging' for 'mouseDown' in the EventData for mouse events.

+ Added method 'getMousePosition()' to dPemMixin. This returns the mouse
  position in relative coordinates to the object that called it.

+ Added 'drawBitmap()' method to dPemMixin. Like the other wx.DC drawing
  methods, this wraps the wx.DC.DrawBitmap() method into an object interface
  that Dabo objects can use.

+ Changed getSQL() so that if no FROM clause has been specified, it defaults to
  a FROM clause using the cursor's Table.

+ Added properties SettingsFileName and SettingsDirectoryName to the app's
  UserSettingProvider. The defaults for both come from
  app.getAppInfo("appShortName"), and determine the name of the directory and
  file name of the user settings file. The directory name will be lower()'d and
  have a '.' prepended automatically.

+ Created the dFoldPanel and dFoldPanelBar classes, which wrap the built-in
  wx.lib.FoldPanel classes. Modified __init__.py to include these, and added
  some hacks to dPemMixin to enable them to work with the event structure.

+ Added the dCalendar control. This wraps the wx.calendar.CalendarCtrl, making
  it simpler and more Pythonic to work with.

+ Added a setting 'firstDayOfWeek' to dabo.settings

+ Moved the method _getWxColour() from dFoldPanelBar into dPemMixin, as it is
  needed in both dFoldPanelBar as well as dCalendar, and possibly other wx
  controls that expect a wx.Colour object instead of a color tuple.

+ Added the calendar events and their processing.

+ Added a form subclass named 'dBorderlessForm'. This creates a form with no
  visible border or title bar. Renamed the base form class in dForm.py from
  'dFormBase' to 'BaseForm'. I felt that the 'd' prefix was misleading, as it
  isn't meant to be a Dabo base class at all.

+ Updated dDateTextBox to use regular datetime values internally instead of
  wx.DateTime. Updated the calendar to use the new Dabo dCalendar instead of the
  raw wx version.

+ Added row and column highlighting to the dGrid class. Default is to only show
  the selected cell, but that can be changed by setting the SelectionMode
  property to either "rows" or "columns". The color used to highlight the
  selected row/col is controlled by the new SelectionBackColor and
  SelectionForeColor properties; defaults are yellow background and black text.

+ Added a GridRangeSelected event to dEvents, and added the code to raise it to
  dGrid.

+ Changed the default SelectionMode for the datanav grid to 'row'.

+ Added some additional properties and functionality to the dFoldPanelBar class.
  First is the 'Singleton' property, which controls a behavior in which one and
  only one panel is open at any time. Expanding a different panel collapses the
  currently open one, and attempting to collapse the expanded panel does
  nothing.

  Second, there is a 'SingleClick' property that controls whether you need to
  double-click on a panel's caption bar (default behavior) to toggle it, or
  whether a single click will suffice.

  Finally, the 'CollapseToBottom' property determines whether any collapsed
  panels are positioned at the bottom of the control, or whether they remain in
  their natural position.

  I added the FoldPanelCaptionClick and FoldPanelChange events to dEvents in
  order to implement these features. They are available to instances of the
  dFoldPanelBar class for hooking additional behaviors to these events.

  I updated the test form for dFoldPanelBar to enable you to play with these
  settings.

+ Fixed a bug in dGrid's new SelectionMode property. I had previously checked
  for only 'r' or 'c' at the beginning of the setting, forgetting that 'cells'
  is a valid setting, so I fixed that to check the first two letters.

+ Added the property 'AlternateRowColoring' to dGrid. When True, rows in the
  grid will be colored depending on the RowColorOdd and RowColorEven properties.

+ Changed the datanav grid to use alternate row coloring.

+ Added some changes to the column Width setting that were necessary for working
  correctly in the Designer.

+ Fixed a bug with MultipleSelect in the dTreeView class. Added some navigation
  methods for returning adjacent nodes. Fixed a selection bug when working with
  MultipleSelect=True.

+ Added code to properly escape characters that should not be in XML attributes.
  Also cleaned up some uneven spacing in the created XML.

+ Fixed a bug in dGrid that didn't allow the ColumnCount to be reduced.

+ Fixed a bug in dPage that happened when the page was instantiated separately
  from the pageframe, since it wasn't yet in the Pages collection.

+ Added 'dEditableList', which is a wrapping of the wx.gizmos.EditableListBox.
  This control takes a list and allows the user to add/edit/delete items from
  the list, as well as re-order them. There are properties to enable/disable any
  of the following: edit, add, delete, order. All are enabled by default.

+ Fixed a bug in dGridSizer. Apparently, calling 'AddGrowableRow/Col' multiple
  times increments an internal counter, and a subsequent 'RemoveGrowableRow/Col'
  will only decrement it, and will not set it to be not growable unless the
  counter has dropped to zero. Now setting a row as growable won't do anything
  if it already is.

+ Added the drawText() method, along with the text draw objects.

+ Added columns to reportWriter. Added smarter sorting of elements in the xml
  output, for instance putting the report title up top instead of on bottom, and
  putting the bands in order that they appear and not alpha order.

+ Changed all the sizer routines to return the SizerItem managing the object
  that was just added to the sizer.

+ Sizer.Children now modified the SizerItem objects to include a
  'ControllingSizer' attribute that references the parent sizer.

+ Modified the dFoldPanelBar class to better time its refreshes. It's still a
  bit funky, but does seem to work better.

+ Modified dFormMixin to handle the new Spacer panels correctly.

+ Added a 'Children' property to dFoldPanelBar that returns the child panels,
  instead of the layout panel that it uses to manage the visible panels.

+ Added a return value to setItemProp() in the sizers so that we can tell if a
  value was successfully applied.

+ Fixed the problem with propertyHelperMixin.getPropertyList(): it was caching
  the list of properties across the class hierarchy, instead of caching just for
  this one class definition. Good catch, Ed!

+ Wrapped the wx.CheckListBox for Dabo.

+ Changed the parameter to sizer for setting the sides that the Border property
  applies to from 'borderFlags' to 'borderSides', as this seems much more
  appropriate. Updated the sizers to properly get/set this prop from a list of
  values.

+ Changed all hard-coded "\n" in dicttoxml to the more crossplatform idiom
  "%s" % os.linesep.

+ Fixed a problem whereby nested sizers did not get their Parent property set.
  Thanks to Casey McGuire for catching this bug.

+ Added the GridCellEditBegin event, which is raised when a grid cell editor is
  shown. This allows you to record the value of a cell before it is modified by
  the user.

+ Added StayOnTop property to dFormMixin.

+ Added ShowMenuBar property, so I can avoid showing the Dabo menubar on my
  property sheet and object tree forms.

+ Added groups and variables elements to a newly created report form.

+ Changed the default position to (-1, -1), since (0, 0) places the form under
  the menu bar when running on OS X.

+ Fixed a problem with dGrid on Windows where the propsheet was stealing the
  focus

+ Added ForegroundColor and BackgroundColor to dColumn. These props apply to all
  cells in a column that don't have custom renderers.

+ Fleshed out the 'nextNode()' and 'priorNode()' methods to provide true flat
  navigation through the tree. Also cleaned up several other methods that dealt
  with nodes and their objects.

+ Added font properties to treeview nodes.

+ Wrapped the wx.Font object into dFont. This breaks the font editing on the
  PropSheet, and possibly a few other places that use the font prop, but we'll
  have to find those afterwards. All previous references to Font have to be
  changed to GetFont() instead; likewise, all assignments to Font must be
  replaced with calls to SetFont().

+ Revamped the internals of dFont.

+ Added 'defaultFontSize' to settings.py

+ Updated the font handling in dGrid and dTreeView.

+ Cleaned up some spacing in dLabel.

+ Added the default wx IDs to the About and Quit menu items so that they appear
  in the proper place on OS X.

+ Updated the long-neglected BorderSizer class, which wraps the
  wx.StaticBoxSizer class. You can now pass either a pre-made dBox object to the
  constructor, or pass a parent object, and the constructor will create the box
  for you.

+ Added a Caption property to dBorderSizer. This will update the caption
  displayed on the sizer's box.

+ Refactored the getItemProp() method so that dBorderSizer will use the same
  functionality.

+ Added getAvailableFonts() method. Returns a list of all font faces installed
  on the current system.

+ Updated dFormMixin to handle dBorderSizer objects in .cdxml files

+ Changed the prompt and shortcut for the 'Quit' item in dBaseMenuBar to be
  'Quit' and 'Ctrl-Q' on all platforms.

+ Added additional properties to dBorderSizer that are basically proxies to the
  box's caption.

+ Added a Dabo wrapper for wx._core._wxPyDeadObject.

+ Added a couple helper functions for converting between 0-255 rgb
  format and 0-1 format.

+ Added basic MRU (Most Recently Used) capabilities to Dabo. I had looked at the
  wx.FileHistory class, but it seemed a bit too rigid to work with our design.
  To use MRU in a menu, the menu should be created by passing 'MRU=True' in the
  constructor.

+ Added Variables, Groups, and Objects as ReportObjectCollections.

+ Changed dEvents.ContextMenu to derive from Event instead of MenuEvent, since
  the contextmenu event is a request for a context menu to be displayed, and not
  generated from any existing menu.

+ Added an addObject() function to report objects. Changed the sorting of report
  elements so that Variables appears before Groups. Fixed a bug which sometimes
  kept variables and groups from getting their xml generated.

+ Modified xmltodict to properly escape any internal ampersands.

+ Modified the Quick Report (list format) to generate the report form not by
  crafting the XML by hand, but by using the object interface and then finally
  having the report writer return the XML. This results in quick reports getting
  the same XML format as if the Designer were used.

+ Added the dHyperLink control. This is a wrapped version of the
  wx.lib.hyperlink.HyperLinkCtrl.

+ Added a new function to dabo.ui, callAfterInterval(func, interval). It will
  call the passed function after the interval has elapsed. Additionally, if
  callAfterInterval() is called again with the same function before the original
  timer had elapsed, the old timer is destroyed and the new one instantiated,
  making the function only run once, after a timer finally reaches the interval.


+ Added 'removePage()' and 'cyclePages()' functions to the dPageFrameMixin
  class. The former allow for a specific page to be removed, while the latter
  accepts an integer value and cycles the selected page forward (positive) or
  backwards (negative).

+ Added a clear() function to dMenu() for removing all current items.

+ Thanks to Brandon Singer, I've fixed a problem where passing kwargs to the
  constructor of any dObject subclass would silently pass any unhandled kwargs.
  The fix to the base problem was easy, but it turns out lots of our code was
  relying on this. I fixed the obvious places (code that gets run from dabo/ui
  /uiwx/test.py) but I suspect I've missed a few. If you get the exception:
    TypeError: __init__() got an unexpected keyword argument '<argument>'
  then it is due to this fix.

+ The minesweeper demo uses dabo.fastNameSet when creating the squares, and it
  turns out that when fastNameSet is True, autoBindEvents() doesn't run. Fixed.

+ Fixed dApp to raise the Activate/Deactivate events properly. Fixed dApp to
  raise Key events. The app gets key events if no window has stopped the event
  along the way. So now we can dApp.bindEvent(dEvents.KeyChar, func). Fixed dApp
  to autoBindEvents().

+ The menutype keyword can now be used to specifiy about, exit and preferences
  menu item. Dabo will then automatically use the correct wxID, so the menu
  items are automatically moved to the MacOS application menu.

+ Modified colorTupleFromName() to also attempt to interpret strings as
  HTML-style hex values.


===============================================================================
Dabo-0.5 (2005-11-30) (Revision 1610):

Added a new class, DataSet, which lets you issue sql queries against local
Dabo data, not just against the backend. You can query, sort, and update
individual DataSets, and even join multiple DataSets - all without making a
call to the backend database server.

Began the work of making an embedded, internal, database engine (SQLite).
Starting with future releases, SQLite will be an integral part of Dabo.

Improved the autoBindEvents() to bind to matching methods in all parent
containers, not just the form. Auto-binding of events now works so well that
it is the default; you no longer have to manually call it. This is now
*really cool*.

Added a basic framework for drawing shapes on any window. Once created, the
shapes are accessible with an object reference. This should make dealing with
DC's a thing of the past for most uses. Way cool!

Sorted out MDI/SDI issues. By default, dForm on Windows MDI children and
dFormMain on Windows will be MDI parents. On other platforms, both dForm and
dFormMain will be SDI by default. The above statement is true for datanav
applications (ones generated by the AppWizard). The pure-Dabo default is for
SDI forms. In any case, you may change this by setting dabo.MDI.

Improved the datanav Quick Report feature, which can print a list of the
current records, mimicing the browse page, or a whole page of information on
one record, mimicing the edit page. Added the ability for the user to save
the generated report form for editing with the Report Designer or editing the
rfxml directly.

Improved showContextMenu(), and sorted out the difference between
MouseRightClick and ContextMenu events.

Fixed bug in Find dialog which would segfault on Windows and Mac. Added
replace functionality.

dCheckBox now supports 3 state mode, (True, False and None).

Fixed bug in dbMySQL that would interpret longtext or longblob fields as
ints.

Fixed dBackend to properly send Python None values as NULLs.

dForms now know how to read in cdxml files, created by the upcoming UI
Designer.

Fixed a bug in colorTupleFromString() that failed to return the correct
value.

Fixed some encoding issues with dReportWriter.

Added some handling for broken database connections.

Added some useful properties to dTreeView that improve its display and
editability.

Fixed some problems with the Hit event and dSpinner.

Improved report writer's paragraph handling.

Further removed user code from direct wx access in a few places. User code
can still get at the wx structures though, just not quite as easily.

Fixed mixed indentation problems, made some code cleaner, and added/edited
lots of docstrings.

Added some useful functions to dMenu to remove items and get references to
menu items.

Added a DynamicEnabled property to dMenuItem. Set this to a function which
will get run when the parent menu is shown to determine whether the menu
item is enabled or not.

Menu.Children will now contain object references to Dabo menus and menu
items.

Improved dToolbar somewhat, in anticipation of fully objectifying the
individual toolbar items. The ultimate goal is for the interface to
a dToolbar to be similar to that of dMenu.

Fixed some problems in dBizobj that make working with multi-table select
statements more sane.

Fixed a bug in dGrid which resulted in very slow deletion of rows, for
instance
after requerying the recordset and getting fewer rows that were in the grid
before.

Added properties ShowInTaskBar and FloatOnParent to dForm, and actually
made the following properties work: ShowMinButton, ShowMaxButton,
ShowCloseButton, ShowSystemMenu, TinyTitleBar.

Added a picklist mode to datanav Forms, showing only the select and browse
pages for a user to pick a record. The form dismisses on escape, and returns
the selected row's pk on enter.

Handling of None values in many UI controls, the bizobj, and the database is
much improved.

Added middle button and scroll mouse events.

Added some hooks to datanav.Form that allow developers to control the
select options for given fields. This would allow you to put, for example,
a radiogroup with a few choices instead of the default textbox.

Added connection manager to dApp, which maintains a set of open database
connections that your forms can reference by name. Added Connection property
to dForm.

Fixed bugs in and improved dSplitter, dListControl, dControlItemMixin, and
dListBox.

Phwew! All that in 7 weeks.


===============================================================================
Dabo-0.4.2 (2005-10-07) (Revision 1418):

Added PrimaryBizobj property to dForm, which can replace calls to
getPrimaryBizobj().

Added Accepted property to dOkCancelDialog, which gets set automatically if the
user pressed "OK".

Added AutoSQL, UserSQL, CurrentSQL, LastSQL properties to dCursor and dBizobj.
When time to requery, the SQL will come from UserSQL if set, or AutoSQL will
be regenerated.

Fixed a bug that kept changes to a new record from getting committed.

Added DefaultValues property to bizobj.

Added ListSelection and ListDeselection events to dListControl. Added properties
MultipleSelect, HitIndex, LastSelectedIndex, HeaderVisible, HorizontalRules,
and VerticalRules. Changed the behavior of both dListControl and dListBox so
that merely selecting an item doesn't raise the Hit event; instead, it raises a
ListSelection event, and if another item had been previously selected, it raises
 a ListDeselection event. Hit is only raised from double-clicking on an item, or
 by pressing Enter.

Added new property to dTextBox: StrictDateEntry. Changed the code for
interpreting dates entered by the user to allow for some less explicit
formats (YYYYMMDD, YYMMDD, and MMDD). If StrictDateEntry is False (the
default), these other formats will be used when interpreting dates
entered by the user.

Added field-level validation to the framework.

Improved support for decimal.Decimal, both at the database level and in
dTextBox.

Added new auto event binding, which automatically binds events based on any
defined callback functions. For example, if you have a method onMouseEnter()
defined, the dEvents.MouseEnter will automatically be bound to that method.
Inspired by PythonCard.

Added RegID property to forms, that allows for object registration
with the form. Not all objects require RegIDs, but if they have one,
they must be unique among all objects in a form. A reference to that
object can then be gotten from any other object by calling
'self.Form.getObjectByRegID(<regid>)'.

Linked RegID to the auto event binding, so that if a form has a method
of onHit_cmdOK(), and has a button with a RegID of 'cmdOK', the
cmdOk's Hit will get bound to the form's callback, automatically.

Improved dGrid and dColumn. Many properties added, and you are now in much
finer control over the display of grid column headers, grid cell attributes,
grid cell editors and renderers, and the grid itself.

Began work of allowing case-insensitive property values for properties that
take string values, and for properties that take a limited number of values
where the first letter is unique, you can set the property by just using the
first letter. dTextBox.Alignment = "c" sets the property to "Center", for
example.

Modified dBizobj, dCursorMixin, and dBackend so that the user can specify
the Unicode Encoding to use. Changed the default encoding from latin-1 to
utf-8.

Added feature to optionally draw sizer outlines on any form that uses dSizers.
This is currently accessible via an option in the View menu when the base
menu bar is in use, or you can turn it on/off programatically.

Grids now remember the column that is sorted, and resort when next instantiated.

Added support in dReportWriter for report groups and report variables, and
dynamic band heights (based on the height of contained objects). Added showExpr,
which is an expression that evaluates at runtime and if true, shows the object
in the report, and not if false.

Improved the automatic print preview report format in datanav. It now:

	+ prints column headers

	+ mirrors the font size, column width, cell vertical and horizontal
	  alignment, and column height of the grid

	+ mirrors the font size, header height, vertical and horizontal
	  alignment of the grid headers

	+ automatically reorients to landscape if the detail flows beyond the width
	  of portrait

	+ stops printing more columns if doing so would result in overflowing the
	  right margin

Key bindings are now case-insensitive.

Improved docstrings and API documentation.


===============================================================================
Dabo-0.4.1 (2005-08-30) (Revision 1226):

Improved test framework for uiwx. Now you can run ui/uiwx/test.py and get
almost all of the dabo controls in one form, and they are the same tests
that you get when you run an individual control directly.

Factored out the saving/restoring of user settings out of dApp into
the separate dUserSettingProvider class, which can be subclassed or
overridded by the developers. Added properties UserSettingProvider
and UserSettingProviderClass to dApp.

Dabo user settings are no longer saved to .userSettings.ini in the app
directory, but are saved to the user's home directory (in ~.dabo/) or
if on Windows, in <User Profile>/Application Data/Dabo/.

Support for SQLite added. As of this moment, Dabo supports several major
open-source database backends: MySQL, PostgreSQL, Firebird, and SQLite.
Next on the list should be Oracle, Sybase, and MS-SQL.

Started work implementing a Quick Report in the datanav library, which
replaces the old HTML Print Preview. This uses the fledgling Dabo Report
Writer to create a PDF rendition of the dataset.

Added new property for all controls: StatusText. When set, and when the
form has a status bar, that text will show in the form's status bar when
the mouse enters the control.

Expanded the dabo.ui.strToBmp() function to accept an optional scale factor
or width/height values. If they are passed, the returned bitmap image is
sized to those values.

Added an optional parameter to the bizobj and cursor's getDataSet() method.
If you send a list of field names, only those fields are returned.

Fixed some lingering bugs in the dabo.ui.uiwx package and the datanav
lib. dWizard works better now. Improved dGauge, dLine, dBox, dRadioBox,
dListBox, dToolBar, and dSizers.

Added simple decimal support to dTextBox.

Work continues on dGrid, specifically dColumn is now better worked
into the "Dabo Way".

Added dabo.trace() function, that will drop you into pdb.

dConnectInfo reworked to have better property names.

Removed dependency on PIL and reportlab from Dabo. These are dependencies
still, but only if you try to run a report.

Added dabo.lib.StopWatch.StopWatch class, which is a light Python
stopwatch with start(), stop(), reset() methods and Value property.

This is a partial list. Both Ed and Paul have been very busy with Dabo
since 0.4 a few weeks ago. Lots of bugfixes and enhancements were made,
and we encourage everyone to upgrade.


===============================================================================
Dabo-0.4 (2005-08-08) (Revision 1132):

Cleaned up the initialization of properties. No more initStyleProperties();
user code just puts their props in initProperties() or sends them to the
constructor in the properties arg or as separate named arguments. The
framework sorts out when the properties need to be set in the object
construction cycle.

Improved sizers by separating out the Halign and Valign properties,
eliminating the need to use the 'alignment' flags parameter. Added the
'Parent' property, making it easy to reference the control that 'owns'
the sizer. Also added the convenience method 'append1x(item)', which is
shorthand for writing 'append(item, 1, "expand")', since it is used so
frequently. The grid sizers now have 'isRowGrowable()' and 'isColGrowable()'
methods for checking the status of any row/column.

New dGrid, with dColumn and Header objects available for reference.

Lots of convenience functions written, such as those designed for simplified
access to common dialogs, are now built into the dabo.ui module. Examples:
getFile(), getColor(), getBitmap(), and the getString() functions, which all
create, show and destroy the required dialog window, and then return the
result. So, to present the user with a font selection dialog, just call
dabo.ui.getFont(), and the selected font will be returned (or None if they
canceled). Similarly, to show a common messagebox and get the response,
just use dabo.ui.info(), dabo.ui.stop(), or dabo.ui.areYouSure().

doDefault() much faster now (thanks to Alex Martelli)

Support for decimal.Decimal.

New classes: dColorDialog, dToolBar.

Work on the report writer and report designer progresses. The report designer
is now in the daboide project, not here in dabo anymore.

We finally have distutils support. To install Dabo, do the standard
"python setup.py install". Thanks to limodou for submitting the patch.


Dabo-0.3.2 (2005-03-21) (Revision 959):

Work continued on the Dabo report writer and report designer. The
writer will now read and write the rfxml file format, and will do some
simple reports. The designer will edit the rfxml files, again, with simple
formats. This isn't ready to use yet but the foundation is in place.

cursorToXML() added.

Encoding property added to databases.

dBitmap introduced.
dWizard introduced.
dTreeView introduced.

dGrid is being refactored, and is almost done. For a short time, it can
be found as dGridX.

We worked hard trying to get window closing not to segfault on Windows,
to get icons to display correctly on Mac, and to optimize Dabo in some key
bottleneck areas. We've greatly improved Dabo's performance on all platforms,
and Dabo now behaves less differently on each platform.

Improved data binding: controls don't need to bind to a bizobj, but to any
object expression.

Improved Firebird and PostgreSQL support.

Lots of improvements and bug fixes, in all three tiers.


===============================================================================
Dabo-0.3.1 (2005-02-16) (Revision 802):

Separated creation of dCursor from dBizobj.
Added option to automatically create a dPanel in dForm.
Further Daboized dListControl.
Fixed display of a few of our icons on Mac.
Added bindKey() method, which binds a keycombo like "Ctrl+D" to a function.
Daboized dMenu, dMenuItem, and dMenuBar.
Minimal Tkinter (dCheckbox) working again (testing only).
Added ActiveControl property to dForm.
Various dSizer improvements were made.
We moved various things to better places in the source tree.
Connection info now saved in XML format.
Localization framework added. Courtesy Vladimir Sekissov.
Added Children property, which contains a list of a container's children.
dCommandButton is now known as dButton.


===============================================================================
Dabo-0.3 (2005-01-10):

New UI controls added:
    dFileDialog.py
    dListBox.py
    dListControl.py
    dSplitForm.py
    dSplitter.py

GridSizer added. Method calls to all sizers greatly simplified.

Menus simplified, removing wx-specific calls.

My favorite UI debugging tool: getMouseObject()

Framework classes now consistently use the standard initialization
methods: initProperties, initEvents, etc.

Child requeries and transaction support added to bizobj

Bizobjs now support the relationSpecs.rsxml format for adding child
relations.

Support for fulltext-type searches by word added.

Auxiliary (one-shot) cursors added to main cursors for better support
of different backends.

Improved unicode support in cursors.

Added support for PostgreSQL. Added template to ease creation of new
backend support scripts.

appWizard: added support for parent/child/grandchild/... relationships;
improved FieldSpecEditor.

appWizard/dDataNav* classes:
    + changed all wx.Sizers to dSizers
    + added "-ignore-" to visually indicate search criteria to ignore
    + added save/restore of values on search page.
    + added 'Matches Words' option for fulltext searches
    + fixed bugs with searches for boolean values

Controls:
    + Now auto-name themselves. Unique name enforcement added.
    + Added _IsContainer attribute to distinguish controls that can add other
      controls to themselves.
    + Added support for setting colors by name instead of RGB tuple.
    + Fixed resizing bug that would not allow a resized object to be made
      smaller.


===============================================================================
Dabo-0.2 (2004-09-20):

Continued improving FireBird database support, improved MySQL support. Added
preliminary SQLite support.

Save passwords encrypted.

Added logger objects to send program output to, instead of directly to stdout.

Began abstraction of Tkinter at purely an experimental level.

Added some new controls, such as a better date control and a combo box.

Brought in some Foxpro string functions from the openfox project.

New event model, greatly simplifying the binding of events, the raising of
events, and the subclassing of events to define new events.

Added preliminary unicode support to the cursor level.


===============================================================================
Dabo-0.1.1 (2004-06-13):


===============================================================================
Dabo-0.1 (2004-05-10):

