import wx
import sys
from wx.lib import masked
#from Utility.compat import convertINI
################################################################
#
# Class: ColumnsDialog
#
# Allows a user to alter the settings and appearance of
# columns in a ManagedList.
#
################################################################
class ColumnsDialog(wx.Dialog):
def __init__(self, list):
self.utility = list.utility
title = self.utility.lang.get('columns')
pre = wx.PreDialog()
pre.Create(list, -1, title)
self.this = pre.this
outerbox = wx.BoxSizer(wx.VERTICAL)
self.columnsPanel = ColumnsPanel(self, list)
applybtn = wx.Button(self, -1, self.utility.lang.get('apply'))
self.Bind(wx.EVT_BUTTON, self.onApply, applybtn)
okbtn = wx.Button(self, -1, self.utility.lang.get('ok'))
self.Bind(wx.EVT_BUTTON, self.onOK, okbtn)
cancelbtn = wx.Button(self, wx.ID_CANCEL, self.utility.lang.get('cancel'))
# setDefaultsbtn = wx.Button(self, -1, self.utility.lang.get('reverttodefault'))
buttonbox = wx.BoxSizer(wx.HORIZONTAL)
buttonbox.Add(applybtn, 0, wx.ALL, 5)
buttonbox.Add(okbtn, 0, wx.ALL, 5)
buttonbox.Add(cancelbtn, 0, wx.ALL, 5)
outerbox.Add(self.columnsPanel, 0, wx.EXPAND|wx.ALL, 5)
outerbox.Add(buttonbox, 0, wx.ALIGN_CENTER)
self.SetAutoLayout(True)
self.SetSizer(outerbox)
self.Fit()
def onOK(self, event = None):
if self.onApply(event):
self.EndModal(wx.ID_OK)
def onApply(self, event = None):
self.columnsPanel.apply()
return True
################################################################
#
# Class: ColumnsPanel
#
# Contains the interface elements for a ColumnsDialog
#
################################################################
class ColumnsPanel(wx.Panel):
def __init__(self, parent, list):
wx.Panel.__init__(self, parent, -1)
# Constants
self.RANK = 0
self.COLID = 1
self.TEXT = 2
self.WIDTH = 3
self.utility = parent.utility
self.list = list
self.columns = list.columns
self.changed = False
self.changingvalue = False
self.leftid = []
self.rightid = []
self.leftindex = -1
self.rightindex = -1
sizer = wx.BoxSizer(wx.VERTICAL)
listsizer = wx.BoxSizer(wx.HORIZONTAL)
# unselected list ctrl
self.checklistbox = wx.CheckListBox(self, -1, size = wx.Size(150, 200), style = wx.LB_SINGLE)
listsizer.Add(self.checklistbox, 0, wx.ALL, 5)
# Up & Down button
###################
self.upbutton = self.utility.makeBitmapButton(self, 'moveup.bmp', 'move_up', self.OnMove)
self.downbutton = self.utility.makeBitmapButton(self, 'movedown.bmp', 'move_down', self.OnMove)
updownsizer = wx.BoxSizer(wx.VERTICAL)
updownsizer.Add(self.upbutton, 0, wx.BOTTOM, 5)
updownsizer.Add(self.downbutton, 0, wx.TOP, 5)
listsizer.Add(updownsizer, 0, wx.ALL, 5)
sizer.Add(listsizer, 0)
labelbox = wx.BoxSizer(wx.HORIZONTAL)
labelbox.Add(wx.StaticText(self, -1, self.utility.lang.get('displayname')), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
columnlabel = ""
self.labelsetting = wx.TextCtrl(self, -1, columnlabel)
labelbox.Add(self.labelsetting, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(labelbox, 0, wx.ALL, 5)
widthbox = wx.BoxSizer(wx.HORIZONTAL)
widthbox.Add(wx.StaticText(self, -1, self.utility.lang.get('columnwidth')), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
initialvalue = 0
self.widthsetting = self.utility.makeNumCtrl(self, initialvalue, integerWidth = 4, max = 2000)
widthbox.Add(self.widthsetting, 0, wx.ALIGN_CENTER_VERTICAL)
sizer.Add(widthbox, 0, wx.ALL, 5)
self.getDefaultValues()
self.labelsetting.Enable(False)
self.widthsetting.Enable(False)
self.SetSizerAndFit(sizer)
# Add Event
#########################
self.Bind(wx.EVT_LISTBOX, self.OnSelect, self.checklistbox)
self.Bind(wx.EVT_TEXT, self.OnChangeLabel, self.labelsetting)
self.Bind(masked.EVT_NUM, self.OnChangeWidth, self.widthsetting)
def getDefaultValues(self):
unselected = []
selected = []
for colid in range(self.columns.minid, self.columns.maxid):
rank = self.utility.config.Read(self.list.prefix + str(colid) + "_rank", "int")
text = self.utility.lang.get(self.list.prefix + str(colid) + "_text")
width = self.utility.config.Read(self.list.prefix + str(colid) + "_width", "int")
if colid in self.list.exclude:
pass
elif rank == -1:
unselected.append([rank, colid, text, width])
else:
selected.append([rank, colid, text, width])
unselected.sort()
selected.sort()
self.columnlist = selected + unselected
self.checklistbox.Set([item[2] for item in self.columnlist])
for i in range(len(self.columnlist)):
if self.columnlist[i][0] != -1:
self.checklistbox.Check(i)
# Select one of the items in the list
def OnSelect(self, event):
# The index of the selection within the checklistbox
index = self.checklistbox.GetSelection()
if index == wx.NOT_FOUND:
self.labelsetting.Enable(False)
self.widthsetting.Enable(False)
return
self.labelsetting.Enable(True)
self.widthsetting.Enable(True)
textstring = self.checklistbox.GetString(index)
self.changingvalue = True
self.labelsetting.SetValue(textstring)
self.widthsetting.SetValue(self.columnlist[index][self.WIDTH])
self.changingvalue = False
def OnChangeLabel(self, event):
if self.changingvalue:
return
index = self.checklistbox.GetSelection()
if index == wx.NOT_FOUND:
return
oldlabel = self.columnlist[index][self.TEXT]
newlabel = self.labelsetting.GetValue()
if oldlabel == newlabel:
return
self.columnlist[index][self.TEXT] = newlabel
self.checklistbox.SetString(index, newlabel)
def OnChangeWidth(self, event):
if self.changingvalue:
return
index = self.checklistbox.GetSelection()
if index == wx.NOT_FOUND:
return
self.columnlist[index][self.WIDTH] = self.widthsetting.GetValue()
# Move a list item up or down
def OnMove(self, event):
# Move up
if event.GetId() == self.upbutton.GetId():
direction = -1
# Move down
else:
direction = 1
index = self.checklistbox.GetSelection()
if index == wx.NOT_FOUND:
# Nothing is selected:
return
if (direction == 1) and (index == self.checklistbox.GetCount() - 1):
#Last Item can't move down anymore
return
elif (direction == -1) and (index == 0):
# First Item can't move up anymore
return
else:
self.columnlist[index], self.columnlist[index + direction] = self.columnlist[index + direction], self.columnlist[index]
col1text = self.checklistbox.GetString(index)
col2text = self.checklistbox.GetString(index + direction)
col1checked = self.checklistbox.IsChecked(index)
col2checked = self.checklistbox.IsChecked(index + direction)
#Update display
self.checklistbox.SetString(index + direction, col1text)
self.checklistbox.SetString(index, col2text)
self.checklistbox.Check(index + direction, col1checked)
self.checklistbox.Check(index, col2checked)
self.checklistbox.SetSelection(index + direction)
def apply(self):
selected = 0
for i in range(0, self.checklistbox.GetCount()):
colid = self.columnlist[i][1]
if self.checklistbox.IsChecked(i):
self.columnlist[i][self.RANK] = selected
selected += 1
else:
self.columnlist[i][self.RANK] = -1
# Check to see if anything has changed
overallchange = False
for item in self.columnlist:
colid = item[self.COLID]
rank = item[self.RANK]
changed = self.utility.config.Write(self.list.prefix + str(colid) + "_rank", rank)
if changed:
overallchange = True
changed = self.utility.lang.writeUser(self.list.prefix + str(colid) + "_text", item[self.TEXT])
if changed:
overallchange = True
width = item[self.WIDTH]
changed = self.utility.config.Write(self.list.prefix + str(colid) + "_width", width)
if changed:
overallchange = True
# APPLY on-the-fly
if overallchange:
self.utility.config.Flush()
self.utility.lang.flush()
self.list.updateColumns()
################################################################
#
# Class: ColumnManager
#
# Keep track of the settings for order and appearance of
# columns in a ManagedList
#
################################################################
class ColumnManager:
def __init__(self, list):
self.utility = list.utility
self.minid = list.minid
self.maxid = list.maxid
self.prefix = list.prefix
self.exclude = list.exclude
self.active = []
self.getColumnData()
# Method used to compare two elements of self.active
def compareRank(self, a, b):
if a[1] < b[1]:
return -1
if a[1] > b[1]:
return 1
else:
return 0
def getNumCol(self):
return len(self.active)
def getRankfromID(self, colid):
return self.utility.config.Read(self.prefix + str(colid) + "_rank", "int")
def getIDfromRank(self, rankid):
return self.active[rankid][0]
def getTextfromRank(self, rankid):
colid = self.active[rankid][0]
return self.utility.lang.get(self.prefix + str(colid) + "_text")
def getValuefromRank(self, rankid):
colid = self.active[rankid][0]
return self.utility.config.Read(self.prefix + str(colid) + "_width", "int")
def getColumnData(self):
self.active = []
# Get the list of active columns
for colid in range(self.minid, self.maxid):
rank = self.utility.config.Read(self.prefix + str(colid) + "_rank", "int")
if (rank < 0 or colid in self.exclude):
self.utility.config.Write(self.prefix + str(colid) + "_rank", -1)
elif (rank > -1):
self.active.append([colid, rank])
# Sort the columns by rank
self.active.sort(self.compareRank)
# Make sure that the columns are in an order that makes sense
# (i.e.: if we have a config with IDs of 4, 99, 2000 then
# we'll convert that to 0, 1, 2)
for i in range(len(self.active)):
colid = self.active[i][0]
rank = i
self.active[i][1] = rank
self.utility.config.Write(self.prefix + str(colid) + "_rank", rank)
self.utility.config.Flush()
def getSortedColumn(self):
sorted_column = self.utility.config.Read(self.prefix + "_sortedcolumn", "int")
reversesort = self.utility.config.Read(self.prefix + "_reversesort", "int")
return sorted_column, reversesort
def writeSortedColumn(self, sorted_column, reversesort):
self.utility.config.Write(self.prefix + "_sortedcolumn", sorted_column)
self.utility.config.Write(self.prefix + "_reversesort", reversesort)
################################################################
#
# Class: ManagedList
#
# An extension of wx.ListCtrl that keeps track of column
# settings in a unified manner.
#
################################################################
class ManagedList(wx.ListCtrl):
"""
IDs in rightalign and centeralign must be set in Utility.constants;
Column labels must be set in the language file;
If some columns are not displayed by default, they can be set in
Utility.utility.setupConfig()
"""
def __init__(self, parent, style, prefix, minid, maxid, exclude = [], rightalign = [], centeralign = []):
wx.ListCtrl.__init__(self, parent, -1, style = style)
self.parent = parent
self.prefix = prefix
self.minid = minid
self.maxid = maxid
self.exclude = exclude
self.rightalign = rightalign
self.centeralign = centeralign
self.utility = parent.utility
self.columns = ColumnManager(self)
self.Bind(wx.EVT_LIST_COL_END_DRAG, self.OnResizeColumn)
self.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnColRightClick)
self.loadColumns()
self.loadFont()
# Add to the list of ManagedList objects
self.utility.lists[self] = True
def loadFont(self):
# Get font information
fontinfo = self.utility.config.Read('listfont', "bencode-fontinfo")
font = self.utility.getFontFromInfo(fontinfo)
# Only change if we've gotten an acceptable font
if font.Ok():
# Jump to the top of the list
# self.EnsureVisible(0) #_# remove this line to be compatible on linux
# Change the font
self.SetFont(font)
# Refresh to make the change visable
self.Refresh()
def loadColumns(self):
# Delete Old Columns (if they exist)
#################################################
numcol = self.GetColumnCount()
for i in range(numcol):
self.DeleteColumn(0)
# Read status display
####################################
for rank in range(self.columns.getNumCol()):
colid = self.columns.getIDfromRank(rank)
if colid in self.rightalign:
style = wx.LIST_FORMAT_RIGHT
elif colid in self.centeralign:
style = wx.LIST_FORMAT_CENTER
else:
style = wx.LIST_FORMAT_LEFT
text = self.columns.getTextfromRank(rank)
width = self.columns.getValuefromRank(rank)
# Don't allow a column to have a size of 0
if width == 0:
width = -1
self.InsertColumn(rank, text, style, width)
# Save the width of the column that was just resized
def OnResizeColumn(self, event):
if self.utility.config.Read('savecolumnwidth', "boolean"):
rank = event.GetColumn()
width = self.GetColumnWidth(rank)
colid = self.columns.getIDfromRank(rank)
self.utility.config.Write(self.prefix + str(colid) + "_width", width)
self.utility.config.Flush()
# Create a list of columns that are active/inactive
def OnColRightClick(self, event):
if not hasattr(self, "columnpopup"):
self.makeColumnPopup()
# Check off columns for all that are currently active
for colid in range(self.minid, self.maxid):
if colid in self.exclude:
continue
if self.utility.config.Read(self.prefix + str(colid) + "_rank", "int") > -1:
self.columnpopup.Check(777 + colid, True)
else:
self.columnpopup.Check(777 + colid, False)
self.lastcolumnselected = event.GetColumn()
self.PopupMenu(self.columnpopup, event.GetPosition())
def makeColumnPopup(self):
self.columnpopup = wx.Menu()
for colid in range(self.minid, self.maxid):
if colid in self.exclude:
continue
text = self.utility.lang.get(self.prefix + str(colid) + '_text')
self.columnpopup.Append(777 + colid, text, text, wx.ITEM_CHECK)
self.columnpopup.AppendSeparator()
self.utility.makePopup(self.columnpopup, self.onColumnDialog, 'more')
startid = 777 + self.minid
endid = 777 + (self.maxid - 1)
self.Bind(wx.EVT_MENU, self.onSelectColumn, id=startid, id2=endid)
def onColumnDialog(self, event = None):
dialog = ColumnsDialog(self)
dialog.ShowModal()
dialog.Destroy()
def onSelectColumn(self, event):
eventid = event.GetId()
colid = eventid - 777
oldrank = self.utility.config.Read(self.prefix + str(colid) + "_rank", "int")
if oldrank > -1:
# Column was deselected, don't show it now
# (update ranks for the rest of the columns that appeared after it)
for i in range (self.minid, self.maxid):
temprank = self.utility.config.Read(self.prefix + str(i) + "_rank", "int")
if (i == colid):
self.utility.config.Write(self.prefix + str(i) + "_rank", -1)
elif (temprank > oldrank):
self.utility.config.Write(self.prefix + str(i) + "_rank", temprank - 1)
else:
self.utility.config.Write(self.prefix + str(i) + "_rank", temprank)
else:
# Column was selected, need to show it
# Put it after the closest column
if hasattr(self, 'lastcolumnselected'):
if self.lastcolumnselected == -1:
newrank = self.GetColumnCount()
else:
newrank = self.lastcolumnselected # + 1
# (just tack it on the end of the display)
else:
newrank = self.GetColumnCount()
for i in range (self.minid, self.maxid):
temprank = self.utility.config.Read(self.prefix + str(i) + "_rank", "int")
if (i == colid):
self.utility.config.Write(self.prefix + str(i) + "_rank", newrank)
elif (temprank >= newrank):
self.utility.config.Write(self.prefix + str(i) + "_rank", temprank + 1)
else:
self.utility.config.Write(self.prefix + str(i) + "_rank", temprank)
self.utility.config.Flush()
# Write changes to the config file and refresh the display
self.updateColumns()
def updateColumns(self):
self.columns.getColumnData()
self.loadColumns()
self.parent.updateColumns(force = True)
def getSelected(self, firstitemonly = False, reverse = False):
selected = []
index = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
while index != -1:
selected.append(index)
if (firstitemonly):
return selected
index = self.GetNextItem(index, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
selected.sort()
if reverse:
selected.reverse()
return selected
def selectAll(self):
for index in range(self.GetItemCount()):
self.Select(index)
def invertSelection(self):
for index in range(self.GetItemCount()):
self.SetItemState(index, 4 - self.GetItemState(index, wx.LIST_STATE_SELECTED), wx.LIST_STATE_SELECTED)
|