Skip to content

Instantly share code, notes, and snippets.

@Bouni
Last active February 9, 2023 13:38
Show Gist options
  • Save Bouni/c5f035df354eba66c5347e3a84886863 to your computer and use it in GitHub Desktop.
Save Bouni/c5f035df354eba66c5347e3a84886863 to your computer and use it in GitHub Desktop.
NaturalSortedListCtrl
"""ListCtrl with Natural sorting capability"""
import re
import wx
import wx.lib.mixins.listctrl as listmix
class NaturalSortedListCtrl(wx.ListCtrl, listmix.ColumnSorterMixin):
"""ListCtrl with Natural sorting capability"""
def __init__(self, parent, columns):
wx.ListCtrl.__init__(self, parent, style=wx.LC_REPORT)
self.itemDataMap = {} # pylint: disable=invalid-name
for index, col in enumerate(columns):
self.InsertColumn(index, col)
listmix.ColumnSorterMixin.__init__(self, numColumns=0)
def AddData(self, data: dict):
"""Add or Update one or multiple items"""
for item in data:
# Update existing entry
if item in self.itemDataMap:
self.itemDataMap[item] = data[item]
index = self.FindItem(0, data[item][0])
self.SetItemData(index, item)
for n, value in enumerate(data[item]):
self.SetItem(index, n, value)
self.SetColumnWidth(n, wx.LIST_AUTOSIZE)
# Insert new entry
else:
self.itemDataMap[item] = data[item]
index = self.InsertItem(0, data[item][0])
self.SetItemData(index, item)
for n, value in enumerate(data[item]):
self.SetItem(index, n, value)
self.SetColumnWidth(n, wx.LIST_AUTOSIZE)
self.SetColumnCount(len(self.itemDataMap))
def DeleteData(self, data: list):
"""Delete one or multiple items from the list by their id"""
for number in data:
item = self.itemDataMap[number]
self.DeleteItem(self.FindItem(0, item[0]))
del self.itemDataMap[number]
self.SetColumnCount(len(self.itemDataMap))
def GetListCtrl(self):
"""Required by ColumnSorterMixin"""
return self
def GetColumnSorter(self):
"""Returns a callable object to be used for comparing column values when sorting."""
return self.NaturalColumnSorter
def NaturalColumnSorter(self, key1, key2):
"""Compare two values and return 0 if equal, 1 or -1 if sort up or down"""
ascending = self._colSortFlag[self._col]
a = self.itemDataMap[key1][self._col]
b = self.itemDataMap[key2][self._col]
if a == b:
return 0
def convert(text):
return int(text) if text.isdigit() else text.lower()
def alphanum_key(key):
return [convert(c) for c in re.split("([0-9]+)", str(key))]
natorder = sorted([a, b], key=alphanum_key, reverse=bool(ascending))
return -1 if natorder.index(a) == 0 else 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment