PyScore

001: # -*- python -*-
002: #### filtmaster.py #### python package PyScore.treemodel module filtmaster ####
003: 
004: # PyScore
005: # a race scoring programme
006: # written by Matt Draisey
007: # 2004 April 6
008: 
009: reloadable=True
010: reloadables=[]
011: 
012: #### filtmaster.py #### python package PyScore.treemodel module filtmaster ####
013: 
014: import itertools,bisect
015: import gtk
016: from treemodel import filttab
017: from filttab import canonical
018: 
019: # FiltMaster
020: 
021: class FiltMaster(object):
022:     """
023:     A factory object to quickly stamp out FiltTable and FiltCombo objects
024:     """
025: 
026:     def __init__(self,rows=[],ncols=None,wcols=None,xcols=[],*p,**pp):
027:         if ncols==None and wcols==None:
028:             ncols=1
029:             wcols=[False]
030:         elif ncols==None:
031:             assert isinstance(wcols,list)
032:             ncols=len(wcols)
033:         elif wcols==None:
034:             assert isinstance(ncols,int) and ncols>=1
035:             wcols=[False]*ncols
036:         else:
037:             assert isinstance(ncols,int) and ncols>=1
038:             assert isinstance(wcols,list) and len(wcols)==ncols
039:         assert isinstance(xcols,list)
040:         if rows:
041:             assert isinstance(rows[0],tuple)
042:             mcols=len(rows[0])
043:             assert mcols==ncols+len(xcols)
044:         else:
045:             mcols=ncols+len(xcols)
046:         self.presorted=zip(itertools.count(),rows) # forces sort order
047:         for s in self.presorted:
048:             assert isinstance(s[1],tuple) and len(s[1])==mcols
049:         self.mcols=mcols
050:         self.ncols=ncols
051:         self.wcols=wcols
052:         self.xcols=xcols[:]
053:         self.p=p
054:         self.pp=pp
055:         self.master=[
056:             ((0,),(0,s[1][0]<>""),[],s,True,canonical(s[1][0]))
057:             for s in self.presorted
058:         ]
059:         #self.perm=range(len(rows))
060: 
061:     def clone_master(self):
062:         clone=FiltMaster(
063:             rows=[],
064:             ncols=self.ncols,
065:             wcols=self.wcols,
066:             xcols=self.xcols,
067:             *self.p,**self.pp
068:         )
069:         clone.presorted=self.presorted
070:         clone.master=self.master[:]
071:         try:
072:             clone.category=dict(self.category)
073:             clone.sortable=list(self.sortable)
074:         except AttributeError:
075:             pass
076:         return clone
077: 
078:     def activate_category_attribute(self):
079:         self.sortable=[(c,s[0]) for (c,x,xs,s,q,y) in self.master]
080:         self.category=dict([(i,c) for (c,i) in self.sortable])
081: 
082:     def add_strikethrough_attribute(self):
083:         self.xcols.append((False,bool))
084:         self.master=[
085:             (c,x,xs,(s[0],s[1]+(False,)),q,y)
086:             for (c,x,xs,s,q,y) in self.master
087:         ]
088:         self.activate_category_attribute()
089: 
090:     def factory_init(self,filt,comp,inpt):
091:         filt.history=[("",0,filt.filtered_nil()+self.master)]
092:         if not comp:
093:             filt.clear()
094:             for (c,x,xs,s,q,y) in self.master:
095:                 filt.append(s[1])
096:         else:
097:             filt.filter_comprehend(comp,inpt)
098: 
099:     def FiltTable(self,comp="",inpt=None):
100:         filt=filttab.FiltTable(
101:             rows=[],
102:             ncols=self.ncols,
103:             wcols=self.wcols,
104:             xcols=self.xcols,
105:             *self.p,**self.pp
106:         )
107:         self.factory_init(filt,comp,inpt)
108:         return filt
109: 
110:     def FiltCombo(self,comp="",inpt=None):
111:         filt=filttab.FiltCombo(
112:             rows=[],
113:             ncols=self.ncols,
114:             wcols=self.wcols,
115:             xcols=self.xcols,
116:             *self.p,**self.pp
117:         )
118:         self.factory_init(filt,comp,inpt)
119:         if not comp:
120:             filt.show_filter()
121:         return filt
122: 
123:     def set_strikethrough(self,index):
124:         self.change_master(
125:             index,
126:             (2,),
127:             lambda c,x,xs,s,q,y: ((2,),x,xs,(s[0],s[1][:-1]+(True,)),q,y),
128:         )
129: 
130:     def clear_strikethrough(self,index):
131:         self.change_master(
132:             index,
133:             (0,),
134:             lambda c,x,xs,s,q,y: ((0,),x,xs,(s[0],s[1][:-1]+(False,)),q,y),
135:         )
136: 
137:     def set_field(self,index,f,v):
138:         def field(c,x,xs,s,q,y):
139:             slist=list(s[1])
140:             slist[f]=v
141:             return (c,x,xs,(s[0],tuple(slist)),q,y)
142:         self.change_master(index,None,field)
143: 
144:     def change_master(self,index,newcategory,modifier):
145:         assert isinstance(index,int)
146:         if not 0<=index<len(self.presorted): return
147:         # find row in master
148:         masteri=bisect.bisect_left(
149:             self.sortable,(self.category[index],index)
150:         )
151:         assert self.sortable[masteri]==(self.category[index],index)
152:         if newcategory==None:
153:             oldrow=self.master[masteri]
154:             newrow=modifier(*oldrow)
155:             self.master[masteri]=newrow
156:         else:
157:             # change data in category, sortable and master
158:             self.category[index]=newcategory
159:             oldkey=self.sortable.pop(masteri)
160:             newkey=(newcategory,index)
161:             oldrow=self.master.pop(masteri)
162:             newrow=modifier(*oldrow)
163:             # maintain the correct order as determined by sortable
164:             insort=bisect.bisect_left(self.sortable,newkey)
165:             self.sortable.insert(insort,newkey)
166:             self.master.insert(insort,newrow)
167: 
168:     def append_to_master(self,row):
169:         n=len(self.master)
170:         assert isinstance(row,tuple)
171:         assert 0<=len(row)-self.ncols<=len(self.xcols)
172:         self.presorted=self.presorted+[(n,row[:self.mcols])]
173:         ext=tuple([xnil for (xnil,x) in self.xcols[len(row)-self.ncols:]])
174:         bisect.insort(
175:             self.master,
176:             ((0,),(0,row[0]<>""),[],(n,row+ext),True,canonical(row[0]))
177:         )
178: 
179:     def get_row(self,index):
180:         if isinstance(index,int) and 0<=index<len(self.presorted):
181:             return self.presorted[index][1]
182:         else:
183:             return None
184: 
185: #### filtmaster.py #### python package PyScore.treemodel module filtmaster ####