Introduction

Sorting what's in a List Control can be a little frustrating. Here is a short example of the basic idea. I hope this help someone.

What Objects are Involved

Process Overview

The basic idea is that you keep a local dictionary of the data that appears again in the list. This is an uncomfortable thought for a lot of programmers, but it's the only way to handle the situation. The keys to this local data are also recorded within the list items (or in the List Control somewhere) so that there is a link between what's inside the List control and what's inside your local data dict.

When SortItems is called, the List Control is parsed in twos; two items, identified by a number, are sent to your custom comparison function. These two numbers are taken directly from what you dictate in the SetItemData command. You can therefore lookup the string from your locale dict by using those numbers.

I'll let the code finish the talking.

Notice the fancy opening line - that signals to Python that utf8 characters are to be expected in the source code file. It's actually the encoding of the file contents and without it you cannot hope to insert really bizarre characters. (Bizarre for a Westener :) )

Code Sample

   1 # -*- coding:utf-8 -*-
   2 import os
   3 import locale
   4 import wx
   5 # Set the locale to whatever it's supposed to be:
   6 locale.setlocale ( locale.LC_ALL,'')
   7 
   8 tmp = []
   9 path = "."
  10 tmp = os.listdir (  path  )
  11 
  12 # Some gibberish and words in Swedish (which I don't speak) pulled randomly from the net.
  13 tests = ["åÅÅÅ","ÄÄÄb","","ÖÖ","A","a","z","Z", "Mordred","Morgul", "äkta", "blåögd", "hjälplös", "märklig", "ödmjuk", "självbelåten", "utanför", "välsignad" ]
  14 
  15 # Our wx.ListCtrl
  16 class CFilelist ( wx.ListCtrl ) :
  17     def __init__ ( self, parent ) :
  18     wx.ListCtrl.__init__ ( self,parent,-1, style=wx.LC_LIST | wx.LC_AUTOARRANGE | wx.LC_SORT_ASCENDING )
  19     # Create a local dictionary to keep the words
  20     # This *is* double storage of the data, but
  21     # there seems to be no better way.
  22     self.d = {}
  23     for filename in tmp:
  24         id = wx.NewId() # make a unique number.
  25         self.d[id] = filename # link that to the filename.
  26         li = wx.ListItem() # I make an item, there are other methods.
  27         li.SetText ( filename ) # plug in the filename, here the data doubles.
  28         row = self.InsertItem( li ) # get a row back while we add li to self.
  29         self.SetItemData( row, long(id) ) # Associate our id with that row.
  30 
  31     # Custom sorting function
  32     def stepSorter (self, int1, int2):
  33         # Get string vals from my dict.
  34         # int1 and int2 come directly from SetItemData
  35         # of the couple of ListItems that are being sorted.
  36         # They are the id's we supplied in __init__
  37         val1 = self.d[int1] # get the filename from our local store
  38         val2 = self.d[int2]
  39         # use locale to compare them according to the collation
  40         # (fancy word that means sorting) of the language we are in.
  41         return locale.strcoll( val1, val2 )
  42 
  43     # Makes a new item and adds it to the list.
  44     def newitem ( self, txt ):
  45         li = wx.ListItem ( )
  46         li.SetText (txt)
  47         row = self.InsertItem ( li )
  48         id = wx.NewId()
  49         self.d[id] = txt # Again, we link the data to our new id
  50         self.SetItemData ( row, long(id) ) # Again, assoc. the row with that id.
  51         # Sort the list by using our custom function:
  52         self.SortItems ( self.stepSorter )
  53 
  54 # Just something to show:
  55 class CDlg ( wx.Dialog ):
  56     def __init__ ( self, parent ):
  57         wx.Dialog.__init__  ( self, parent,-1, "files", pos = wx.DefaultPosition )#, size = ( 450,-1) )
  58         self.fl = CFilelist ( self )
  59         self.b = wx.Button ( self, -1, "press")
  60         self.b.Bind(wx.EVT_LEFT_UP,self.go)
  61         self.s = wx.BoxSizer(wx.VERTICAL)
  62         self.s.Add (self.fl,1,wx.GROW)
  63         self.s.Add (self.b,0,wx.GROW)
  64         self.SetSizer (self.s)
  65         self.i = 0 # index into our tests array
  66 
  67     def go (self,e):
  68         print "button pressed - testing the sortorder"
  69         self.i += 1
  70         # no bounds test done, my bad.
  71         self.fl.newitem (tests[self.i])
  72 
  73 # Kick this puppy off.
  74 App = wx.App()
  75 win = wx.Frame( None )
  76 dlg = CDlg ( win )
  77 dlg.ShowModal ( )
  78 dlg.Destroy ( )

Comments

Recipes L10n I18n - How to sort ListCtrl items under a locale. (last edited 2010-07-13 20:22:44 by 80-42-186-167)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.