Last active
February 8, 2023 15:15
-
-
Save Bouni/d89f45cdd5533ba0e228822827a49c48 to your computer and use it in GitHub Desktop.
Allow for natural soting of wx ListCtrl data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -------------------------------------------------------------------------------------- | |
| # Original code from the exccelent Mouse vs Python | |
| # https://www.blog.pythonlibrary.org/2011/01/04/wxpython-wx-listctrl-tips-and-tricks/ | |
| # -------------------------------------------------------------------------------------- | |
| import re | |
| import wx | |
| import wx.lib.mixins.listctrl as listmix | |
| import logging | |
| LOGGER = logging.getLogger() | |
| # https://wiki.wxpython.org/How%20to%20create%20a%20list%20control%20%28info%29 | |
| partdata = { | |
| 0: ("C1", "33P", "C_0603_1608Metric", "C1663", "187154"), | |
| 1: ("C2", "2.2u", "C_1206_3216Metric", "C50254", "22975"), | |
| 2: ("C3", "10n", "C_0603_1608Metric", "C57112", "536073"), | |
| 3: ("C4", "10u", "C_0603_1608Metric", "C19702", "879880"), | |
| 4: ("D1", "LTE-4206", "LED_D3.0mm_Clear", "", ""), | |
| 5: ("F1", "1A", "Fuse_1206_3216Metric", "C369159", "28290"), | |
| 6: ("FB1", "600 @ 600MHz", "L_0805_2012Metric", "C1017", "53369"), | |
| 7: ("J1", "Conn_01x01_Female", "Pin_D1.0mm_L10.0mm", "", ""), | |
| 8: ("J2", "Conn_01x01_Female", "Pin_D1.0mm_L10.0mm", "", ""), | |
| 9: ("L1", "15uH", "L_Sumida_CDMC6D28_7.25x6.5mm", "C182182", "2510"), | |
| 10: ("Q1", "SFH 309 FA-5/6", "LED_D3.0mm_IRBlack", "", ""), | |
| 11: ("Q2", "AO3400A", "SOT-23", "C20917", "14806"), | |
| 12: ("R1", "10k", "R_0603_1608Metric", "C25804", "5135918"), | |
| 13: ("R2", "910", "R_0603_1608Metric", "C351623", "3300"), | |
| 14: ("R3", "100", "R_0603_1608Metric", "C22775", "802960"), | |
| 15: ("R4", "100", "R_0603_1608Metric", "C22775", "802960"), | |
| 16: ("R5", "10k", "R_0603_1608Metric", "C25804", "5135918"), | |
| 17: ("R7", "100k", "R_0603_1608Metric", "C25803", "765889"), | |
| 18: ("R8", "18k", "R_0603_1608Metric", "C25961", "6002"), | |
| 19: ("R9", "750", "R_0603_1608Metric", "C23241", "25248"), | |
| 20: ("R10", "750", "R_0603_1608Metric", "C23241", "25248"), | |
| 21: ("U1", "mh-et-live-minikit", "MH-ET LIVE MiniKit", "", ""), | |
| 22: ("U2", "LMR54410", "SOT-23-6", "", "2484"), | |
| 23: ("U3", "LMV7235M7X", "SOT-353_SC-70-5", "C202268", "385"), | |
| } | |
| class NaturalSortListCtrl(wx.ListCtrl, listmix.ColumnSorterMixin): | |
| def __init__(self, parent, size, columns=[]): | |
| wx.ListCtrl.__init__(self, parent, size=size) | |
| self.list_ctrl = wx.ListCtrl( | |
| self, | |
| size=size, | |
| style=wx.LC_REPORT | wx.LC_SORT_ASCENDING, | |
| ) | |
| listmix.ColumnSorterMixin.__init__(self, len(columns)) | |
| for index, column in enumerate(columns): | |
| heading = column.get("heading") | |
| fmt = column.get("format", wx.LIST_FORMAT_LEFT) | |
| width = column.get("width", wx.LIST_AUTOSIZE) | |
| self.list_ctrl.InsertColumn(index, heading=heading, format=fmt, width=width) | |
| def SetData(self, data): | |
| self.itemDataMap = data | |
| for index, value in data.items(): | |
| self.list_ctrl.InsertItem(index, index) | |
| for col, val in enumerate(value): | |
| self.list_ctrl.SetItem(index, col+1, val) # +1 because of Dummy column, hack to make it work | |
| self.list_ctrl.SetItemData(index, index) | |
| def UpdateData(self, index, value): | |
| self.itemDataMap[index] = value | |
| # for col, data in enumerate(value): | |
| # self.list_ctrl.SetItem(index, col+1, data) | |
| self.list_ctrl.SetItemData(index, index) | |
| def GetListCtrl(self): | |
| return self.list_ctrl | |
| def GetColumnSorter(self): | |
| """Returns a callable object to be used for comparing column values when sorting.""" | |
| return self.NaturalColumnSorter | |
| def NaturalColumnSorter(self, key1, key2): | |
| ascending = self._colSortFlag[self._col] | |
| a = self.itemDataMap[key1][self._col-1] # -1 because of Dummy column, hack to make it work | |
| b = self.itemDataMap[key2][self._col-1] # -1 because of Dummy column, hack to make it work | |
| 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]+)", key)] | |
| natorder = sorted([a, b], key=alphanum_key, reverse=bool(ascending)) | |
| return -1 if natorder.index(a) == 0 else 1 | |
| class Main(wx.Frame): | |
| def __init__(self, parent): | |
| wx.Frame.__init__( | |
| self, | |
| parent, | |
| id=wx.ID_ANY, | |
| title="Natural sort", | |
| pos=wx.DefaultPosition, | |
| size=wx.Size(800, 600), | |
| style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER | wx.MAXIMIZE_BOX, | |
| ) | |
| panel = wx.Panel(self) | |
| columns = [ | |
| {"heading": "ID", "width": 0}, # Dummy column, hack to make it work | |
| {"heading": "Reference"}, | |
| {"heading": "Value"}, | |
| {"heading": "Footprint"}, | |
| {"heading": "LCSC Part Number"}, | |
| {"heading": "Stock", "format": wx.LIST_FORMAT_CENTER, "width": 300}, | |
| ] | |
| self.list_ctrl = NaturalSortListCtrl(panel, size=(800, 300), columns=columns) | |
| self.list_ctrl.SetData(partdata) | |
| self.update_button = wx.Button( | |
| panel, wx.ID_ANY, "Update", wx.DefaultPosition, (175, 38), 0 | |
| ) | |
| self.update_button.Bind(wx.EVT_BUTTON, self.update) | |
| sizer = wx.BoxSizer(wx.VERTICAL) | |
| sizer.Add(self.list_ctrl, 0, wx.ALL | wx.EXPAND, 5) | |
| sizer.Add(self.update_button, 0, wx.ALL | wx.EXPAND, 5) | |
| panel.SetSizer(sizer) | |
| self.Layout() | |
| self.Centre(wx.BOTH) | |
| def update(self, evt): | |
| self.list_ctrl.UpdateData( | |
| 20, ("R100", "66P", "C_0603_1608Metric", "C1663", "187154") | |
| ) | |
| if __name__ == "__main__": | |
| app = wx.App(False) | |
| frame = Main(None) | |
| frame.Show() | |
| app.MainLoop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment