Patch from FN that fixes bug in RefreshItem on an item that has no
corresponding node in the tree yet (because its parent isn't expanded yet) triggered an exception. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45503 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1,10 +1,6 @@
|
|||||||
import wx, wx.lib.customtreectrl, wx.gizmos
|
import wx, wx.lib.customtreectrl, wx.gizmos
|
||||||
try:
|
import treemixin
|
||||||
import treemixin
|
|
||||||
except ImportError:
|
|
||||||
from wx.lib.mixins import treemixin
|
|
||||||
|
|
||||||
overview = treemixin.__doc__
|
|
||||||
|
|
||||||
class TreeModel(object):
|
class TreeModel(object):
|
||||||
''' TreeModel holds the domain objects that are shown in the different
|
''' TreeModel holds the domain objects that are shown in the different
|
||||||
@@ -153,7 +149,7 @@ class VirtualCustomTreeCtrl(DemoTreeMixin,
|
|||||||
wx.lib.customtreectrl.CustomTreeCtrl):
|
wx.lib.customtreectrl.CustomTreeCtrl):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.checked = {}
|
self.checked = {}
|
||||||
kwargs['ctstyle'] = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | \
|
kwargs['style'] = wx.TR_HIDE_ROOT | \
|
||||||
wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT
|
wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT
|
||||||
super(VirtualCustomTreeCtrl, self).__init__(*args, **kwargs)
|
super(VirtualCustomTreeCtrl, self).__init__(*args, **kwargs)
|
||||||
self.Bind(wx.lib.customtreectrl.EVT_TREE_ITEM_CHECKED,
|
self.Bind(wx.lib.customtreectrl.EVT_TREE_ITEM_CHECKED,
|
||||||
|
@@ -1,8 +1,4 @@
|
|||||||
import wx, wx.gizmos, wx.lib.customtreectrl, unittest
|
import wx, wx.gizmos, wx.lib.customtreectrl, unittest, treemixin
|
||||||
try:
|
|
||||||
import treemixin
|
|
||||||
except ImportError:
|
|
||||||
from wx.lib.mixins import treemixin
|
|
||||||
|
|
||||||
|
|
||||||
# VirtualTree tests
|
# VirtualTree tests
|
||||||
@@ -171,6 +167,14 @@ class VirtualTreeCtrlTest_OneRoot(unittest.TestCase):
|
|||||||
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
self.assertEqual(wx.RED, self.tree.GetItemTextColour(item))
|
self.assertEqual(wx.RED, self.tree.GetItemTextColour(item))
|
||||||
|
|
||||||
|
def testRefreshItemThatHasNoCorrespondingNodeInTheTree(self):
|
||||||
|
# The item to refresh might be in a collapsed branch of the tree
|
||||||
|
# and not present yet.
|
||||||
|
self.tree.PrepareChildrenCount((0,), 1)
|
||||||
|
self.tree.RefreshItem((0,0))
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.failIf(self.tree.ItemHasChildren(item))
|
||||||
|
|
||||||
|
|
||||||
# TreeAPIHarmonizer tests
|
# TreeAPIHarmonizer tests
|
||||||
|
|
||||||
@@ -240,6 +244,10 @@ class TreeAPIHarmonizerCommonTests(object):
|
|||||||
self.tree.ExpandAllChildren(self.item)
|
self.tree.ExpandAllChildren(self.item)
|
||||||
self.failUnless(self.tree.IsExpanded(self.item))
|
self.failUnless(self.tree.IsExpanded(self.item))
|
||||||
|
|
||||||
|
def testGetFirstVisibleItem(self):
|
||||||
|
self.tree.DeleteAllItems()
|
||||||
|
self.failIf(self.tree.GetFirstVisibleItem())
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerNoTreeListCtrlCommonTests(object):
|
class TreeAPIHarmonizerNoTreeListCtrlCommonTests(object):
|
||||||
''' Tests that should succeed for all tree controls, except the
|
''' Tests that should succeed for all tree controls, except the
|
||||||
@@ -707,6 +715,7 @@ class VanillaTreeCommonTests(object):
|
|||||||
self.assertEqual(1, len(self.eventsReceived))
|
self.assertEqual(1, len(self.eventsReceived))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class VanillaTreeCtrlTestCase(VanillaTreeCommonTests, VanillaTreeTestCase):
|
class VanillaTreeCtrlTestCase(VanillaTreeCommonTests, VanillaTreeTestCase):
|
||||||
TreeClass = wx.TreeCtrl
|
TreeClass = wx.TreeCtrl
|
||||||
|
|
||||||
@@ -724,31 +733,9 @@ class VanillaCustomTreeCtrlTestCase(VanillaTreeCommonTests,
|
|||||||
TreeClass = wx.lib.customtreectrl.CustomTreeCtrl
|
TreeClass = wx.lib.customtreectrl.CustomTreeCtrl
|
||||||
|
|
||||||
|
|
||||||
# Tests of the tree controls without any mixin, to document behaviour
|
class VanillaTreeItemIdTestCase(unittest.TestCase):
|
||||||
# that is either different between tree control widgets or undesired
|
def testTreeItemIdIsFalseDefault(self):
|
||||||
# behaviour.
|
self.failIf(wx.TreeItemId())
|
||||||
|
|
||||||
class TreeCtrlTestCase(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.frame = wx.Frame(None)
|
|
||||||
self.tree = wx.TreeCtrl(self.frame, style=wx.TR_HIDE_ROOT)
|
|
||||||
|
|
||||||
def testSelectHiddenRootItem(self):
|
|
||||||
root = self.tree.AddRoot('Hidden root')
|
|
||||||
self.tree.SelectItem(root)
|
|
||||||
self.assertEqual(root, self.tree.GetSelection())
|
|
||||||
|
|
||||||
|
|
||||||
class CustomTreeCtrlTestCase(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.frame = wx.Frame(None)
|
|
||||||
self.tree = wx.lib.customtreectrl.CustomTreeCtrl(self.frame,
|
|
||||||
style=wx.TR_HIDE_ROOT)
|
|
||||||
|
|
||||||
def testSelectHiddenRootItem(self):
|
|
||||||
root = self.tree.AddRoot('Hidden root')
|
|
||||||
self.tree.SelectItem(root)
|
|
||||||
self.assertEqual(root, self.tree.GetSelection())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -25,8 +25,8 @@ The VirtualTree and DragAndDrop mixins force the wx.TR_HIDE_ROOT style.
|
|||||||
|
|
||||||
Author: Frank Niessink <frank@niessink.com>
|
Author: Frank Niessink <frank@niessink.com>
|
||||||
License: wxWidgets license
|
License: wxWidgets license
|
||||||
Version: 0.9.1
|
Version: 1.0
|
||||||
Date: 26 March 2007
|
Date: 15 April 2007
|
||||||
|
|
||||||
ExpansionState is based on code and ideas from Karsten Hilbert.
|
ExpansionState is based on code and ideas from Karsten Hilbert.
|
||||||
Andrea Gavana provided help with the CustomTreeCtrl integration.
|
Andrea Gavana provided help with the CustomTreeCtrl integration.
|
||||||
@@ -40,14 +40,6 @@ class TreeAPIHarmonizer(object):
|
|||||||
''' This class attempts to hide the differences in API between the
|
''' This class attempts to hide the differences in API between the
|
||||||
different tree controls that are part of wxPython. '''
|
different tree controls that are part of wxPython. '''
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
# CustomTreeCtrl uses a different keyword for the window style
|
|
||||||
# argument ('ctstyle'). To hide this, we replace the 'style' keyword
|
|
||||||
# by 'ctstyle' if we're mixed in with CustomTreeCtrl.
|
|
||||||
if isinstance(self, wx.lib.customtreectrl.CustomTreeCtrl):
|
|
||||||
kwargs['ctstyle'] = kwargs.pop('style', wx.TR_DEFAULT_STYLE)
|
|
||||||
super(TreeAPIHarmonizer, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def __callSuper(self, methodName, default, *args, **kwargs):
|
def __callSuper(self, methodName, default, *args, **kwargs):
|
||||||
# If our super class has a method called methodName, call it,
|
# If our super class has a method called methodName, call it,
|
||||||
# otherwise return the default value.
|
# otherwise return the default value.
|
||||||
@@ -148,13 +140,21 @@ class TreeAPIHarmonizer(object):
|
|||||||
else:
|
else:
|
||||||
selections = []
|
selections = []
|
||||||
# If the root item is hidden, it should never be selected,
|
# If the root item is hidden, it should never be selected,
|
||||||
# unfortunately, CustomTreeCtrl and TreeCtrl allow it to be selected.
|
# unfortunately, CustomTreeCtrl allows it to be selected.
|
||||||
if self.HasFlag(wx.TR_HIDE_ROOT):
|
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||||
rootItem = self.GetRootItem()
|
rootItem = self.GetRootItem()
|
||||||
if rootItem and rootItem in selections:
|
if rootItem and rootItem in selections:
|
||||||
selections.remove(rootItem)
|
selections.remove(rootItem)
|
||||||
return selections
|
return selections
|
||||||
|
|
||||||
|
def GetFirstVisibleItem(self):
|
||||||
|
# TreeListCtrl raises an exception or even crashes when invoking
|
||||||
|
# GetFirstVisibleItem on an empty tree.
|
||||||
|
if self.GetRootItem():
|
||||||
|
return super(TreeAPIHarmonizer, self).GetFirstVisibleItem()
|
||||||
|
else:
|
||||||
|
return wx.TreeItemId()
|
||||||
|
|
||||||
def SelectItem(self, item, *args, **kwargs):
|
def SelectItem(self, item, *args, **kwargs):
|
||||||
# Prevent the hidden root from being selected, otherwise TreeCtrl
|
# Prevent the hidden root from being selected, otherwise TreeCtrl
|
||||||
# crashes
|
# crashes
|
||||||
@@ -197,7 +197,7 @@ class TreeAPIHarmonizer(object):
|
|||||||
super(TreeAPIHarmonizer, self).ExpandAll(item)
|
super(TreeAPIHarmonizer, self).ExpandAll(item)
|
||||||
|
|
||||||
def ExpandAllChildren(self, item):
|
def ExpandAllChildren(self, item):
|
||||||
# TreeListCtrl doesn't have ExpandallChildren
|
# TreeListCtrl and CustomTreeCtrl don't have ExpandallChildren
|
||||||
try:
|
try:
|
||||||
super(TreeAPIHarmonizer, self).ExpandAllChildren(item)
|
super(TreeAPIHarmonizer, self).ExpandAllChildren(item)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -352,7 +352,12 @@ class VirtualTree(TreeAPIHarmonizer, TreeHelper):
|
|||||||
|
|
||||||
def RefreshItem(self, index):
|
def RefreshItem(self, index):
|
||||||
''' Redraws the item with the specified index. '''
|
''' Redraws the item with the specified index. '''
|
||||||
|
try:
|
||||||
item = self.GetItemByIndex(index)
|
item = self.GetItemByIndex(index)
|
||||||
|
except IndexError:
|
||||||
|
# There's no corresponding item for index, because its parent
|
||||||
|
# has not been expanded yet.
|
||||||
|
return
|
||||||
hasChildren = bool(self.OnGetChildrenCount(index))
|
hasChildren = bool(self.OnGetChildrenCount(index))
|
||||||
self.DoRefreshItem(item, index, hasChildren)
|
self.DoRefreshItem(item, index, hasChildren)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user