📄 listctrl.py
字号:
except: text = '?' # BUG: for debugging only traceback.print_exc() else: text = unicode(value) return text def get_column_image(self, row): return None def _update_indexes(self, start = 0): for i in xrange(start, self.GetItemCount()): itemData = self.GetItemData(i) self.itemData_to_row[itemData].index = i self.index_to_itemData[i] = itemData # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py def SortItems(self, sorter=None): if sorter is None: sorter = self.GetColumnSorter() # TODO: # this step is to see if the list needs resorted. # improve this by stopping the first time the order would be changed. d = [None,] * self.GetItemCount() for i in xrange(len(d)): # use real GetItemData, so the sorter can translate d[i] = wx.ListCtrl.GetItemData(self, i) n = list(d) n.sort(sorter) if n != d: wx.ListCtrl.SortItems(self, sorter) self._update_indexes() self.SelectColumn(self.enabled_columns[self._col]) def SortListItems(self, col=-1, ascending=1): if col in self.enabled_columns: col = self.enabled_columns.index(col) else: col = 0 ColumnSorterMixin.SortListItems(self, col=col, ascending=ascending) def GetSelection(self): return getListCtrlSelection(self) def GetSelectionData(self): indexes = self.GetSelection() data = [] for i in indexes: data.append(self.GetItemData(i)) return data # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py def GetListCtrl(self): return self # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py def GetSortImages(self): return (1, 2) def GetColumnSorter(self): """Returns a callable object to be used for comparing column values when sorting.""" return self.__ColumnSorter def TranslateItemData(self, itemData): return itemData def __ColumnSorter(self, itemData1, itemData2): """Allows custom compare functions, in self.colcmps.""" col = self._col ascending = self._colSortFlag[col] if col < len(self.enabled_columns): name = self.enabled_columns[col] else: name = self.column_order[0] itemData1 = self.TranslateItemData(itemData1) itemData2 = self.TranslateItemData(itemData2) item1 = self.itemData_to_row[itemData1][name] item2 = self.itemData_to_row[itemData2][name] column = self.columns[name] if column.comparator != None: # use custom cmp method cmpVal = column.comparator(item1, item2) elif isinstance(item1, str) or isinstance(item2, str): # Internationalization of string sorting with locale module cmpVal = locale.strcoll(unicode(item1), unicode(item2)) else: cmpVal = cmp(item1, item2) # If the items are equal then pick something else to make the sort value unique if cmpVal == 0: cmpVal = apply(cmp, self.GetSecondarySortValues(col, itemData1, itemData2)) if ascending: return cmpVal else: return -cmpVal def RefreshCol(self, col): if col in self.enabled_columns: self.RefreshRect(self.GetColumnRect(self.enabled_columns.index(col))) def HitTestColumn(self, pos): """ pos should be in client coords """ i = self.GetTopItem() r = self.GetItemRect(i) x, y = self._get_origin_offset() if pos[1] >= (r.y - y): return None loc = 0 for n in xrange(self.GetColumnCount()): loc += self.GetColumnWidth(n) if pos[0] < loc: return n def GetVisibleViewRect(self): width = 0 for n in xrange(self.GetColumnCount()): width += self.GetColumnWidth(n) height = 0 if self.GetItemCount() > 0: i = self.GetTopItem() r1 = self.GetItemRect(i) last = min(i + self.GetCountPerPage(), self.GetItemCount() - 1) r2 = self.GetItemRect(last) height = r2.y + r2.height - r1.y x, y = self._get_origin_offset() # there is a 2 pixel strip on either side which is not part of the item if '__WXMSW__' in wx.PlatformInfo: x += 2 width -= 4 return wx.Rect(x, y, x+width, y+height) def GetViewRect(self): width = 0 for n in xrange(self.GetColumnCount()): width += self.GetColumnWidth(n) height = 0 if self.GetItemCount() > 0: r1 = self.GetItemRect(0) r2 = self.GetItemRect(self.GetItemCount() - 1) height = r2.y + r2.height - r1.y x, y = self._get_origin_offset() return wx.Rect(x, y, x+width, y+height) def _GetColumnWidthExtent(self, col): col_locs = [0] loc = 0 num_cols = min(col+1, self.GetColumnCount()) for n in xrange(num_cols): loc += self.GetColumnWidth(n) col_locs.append(loc) x0 = col_locs[col] x1 = col_locs[col+1] - 1 return x0, x1 def GetColumnRect(self, col): x0, x1 = self._GetColumnWidthExtent(col) r = self.GetItemRect(0) y0 = r.y y1 = self.GetClientSize()[1] x_scroll = self.GetScrollPos(wx.HORIZONTAL) return wx.RectPP(wx.Point(x0 - x_scroll, y0), wx.Point(x1 - x_scroll, y1)) def GetCellRect(self, row, col): x0, x1 = self._GetColumnWidthExtent(col) r = self.GetItemRect(row) y0 = r.y y1 = r.GetBottom() x_scroll = self.GetScrollPos(wx.HORIZONTAL) return wx.RectPP(wx.Point(x0 - x_scroll, y0), wx.Point(x1 - x_scroll, y1)) def DeselectAll(self): self.SetItemState(-1, 0, wx.LIST_STATE_SELECTED) # fallback. for extremely long lists a generator should be used #for i in xrange(self.GetItemCount()): # self.SetItemState(i, 0, wx.LIST_STATE_SELECTED) def InsertRow(self, itemData, lr, sort=True, colour=None, force_update_columns=[]): # pre-render all data image_id = self.get_column_image(lr) row_text = {} for i, name in enumerate(self.enabled_columns): row_text[i] = self.render_column_text(lr, name) if itemData not in self.itemData_to_row: # this is Add # TODO: insert in sorted order instead of sorting i = self.InsertStringItem(self.GetItemCount(), '') lr.index = i self.SetItemData(i, itemData) for col in xrange(len(self.enabled_columns)): self.SetStringItem(index=lr.index, col=col, label=row_text[col]) else: # this is Update old_lr = self.itemData_to_row[itemData] lr.index = old_lr.index for col, colname in enumerate(self.enabled_columns): if lr[colname] != old_lr[colname] or \ colname in force_update_columns: self.SetStringItem(index=lr.index, col=col, label=row_text[col]) self.itemData_to_row[itemData] = lr self.index_to_itemData[i] = itemData if colour is not None: if self.GetItemTextColour(lr.index) != colour: self.SetItemTextColour(lr.index, colour) self.SetItemImage(lr.index, image_id) if sort: # TODO: move to update-only once things are inserted in sorted order self.SortItems() def SetItemImage(self, index, image_id): item = self.GetItem(index) if item.GetImage() != image_id: wx.ListCtrl.SetItemImage(self, index, image_id) def DeleteRow(self, itemData): lr = self.itemData_to_row.pop(itemData) self.DeleteItem(lr.index) self._update_indexes(lr.index) def GetRow(self, index): itemData = self.index_to_itemData[index] return self.itemData_to_row[itemData] # Persistence methods def get_column_widths(self): widths = {} for name in self.column_order: column = self.columns[name] if column.enabled: column.width = self.GetColumnWidth(column.GetColumn()) widths[name] = column.width return widths def set_column_widths(self, widths): # backward compatibility with development versions if isinstance(widths, list): return for name, width in widths.iteritems(): column = self.columns[name] column.width = width if column.enabled: self.SetColumnWidth(column.GetColumn(), column.width) def update_column_widths(self): for name in self.enabled_columns: column = self.columns[name] column.width = self.GetColumnWidth(column.GetColumn()) def get_sort_column(self): if self._col < len(self.enabled_columns): sort_col = self.enabled_columns[self._col] else: sort_col = None return sort_col def get_sort_order(self): return self._colSortFlag[self._col]class HashableListView(BTListCtrl): """wx.ListCtrl expects integer identifiers for each row. This subclass lets you use any hashable as the identifier instead.""" def __init__(self, *a, **k): BTListCtrl.__init__(self, *a, **k) self.itemData_to_hashable = {} self.hashable_to_itemData = {} self.unique_index = 0 def GetNewItemData(self): self.unique_index += 1 return self.unique_index def GetItemData(self, index): itemData = BTListCtrl.GetItemData(self, index) return self.itemData_to_hashable[itemData] def SetItemData(self, index, hashable): itemData = self.hashable_to_itemData[hashable] BTListCtrl.SetItemData(self, index, itemData) def InsertRow(self, hashable, row, sort=True, colour=None, force_update_columns=[]): if hashable not in self.hashable_to_itemData: itemData = self.GetNewItemData() self.hashable_to_itemData[hashable] = itemData self.itemData_to_hashable[itemData] = hashable b = BTListCtrl.InsertRow(self, hashable, row, sort=sort, colour=colour, force_update_columns=force_update_columns) return b def DeleteRow(self, hashable): itemData = self.hashable_to_itemData.pop(hashable) del self.itemData_to_hashable[itemData] return BTListCtrl.DeleteRow(self, hashable) def TranslateItemData(self, itemData): return self.itemData_to_hashable[itemData] def GetRowFromKey(self, hashable): return self.itemData_to_row[hashable]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -