PyScore

001: # -*- python -*-
002: ###### sorttab.py ###### python package PyScore.treemodel module sorttab ######
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: ###### sorttab.py ###### python package PyScore.treemodel module sorttab ######
013: 
014: import bisect
015: import gtk,pango
016: from utility import utils
017: 
018: class SortMaster(object):
019:     """
020:     A factory object to quickly stamp out a SortCombo object
021:     maintains a set of positive numbers
022:     and another set of numbers
023:     consisting of one and
024:     those one greater than each number in the original
025:     and also not in the original itself
026:     """
027: 
028:     def __init__(self,set=[],multiset=[],xcols=[],*p,**pp):
029:         self.master=[]
030:         self.shifted=[1]
031:         self.xcols=xcols[:]
032:         self.p=p
033:         self.pp=pp
034:         for n in set:
035:             self.add_to_set(n)
036:         for n in multiset:
037:             self.add_to_multiset(n)
038: 
039:     # ideally log order operations
040: 
041:     def add_to_set(self,n):
042:         assert n>=1
043:         #print "add to set: %i"%n
044:         mj=bisect.bisect_left(self.master,n)
045:         if not(mj<len(self.master) and self.master[mj]==n):
046:             self.master.insert(mj,n)
047:             self.add_to_shifted_set(n)
048: 
049:     def add_to_multiset(self,n):
050:         assert n>=1
051:         #print "add to multiset: %i"%n
052:         mj=bisect.bisect_left(self.master,n)
053:         if not(mj<len(self.master) and self.master[mj]==n):
054:             self.master.insert(mj,n)
055:             self.add_to_shifted_set(n)
056:         else:
057:             self.master.insert(mj,n)
058: 
059:     def add_to_shifted_set(self,n):
060:         # if n is already in shifted set remove it
061:         sj=bisect.bisect_left(self.shifted,n)
062:         if sj<len(self.shifted) and self.shifted[sj]==n:
063:             del self.shifted[sj]
064:         # add n+1 to shifted set if not already there
065:         # and if n+1 is not in the master set
066:         mk=bisect.bisect_left(self.master,n+1)
067:         if not(mk<len(self.master) and self.master[mk]==n+1):
068:             sk=bisect.bisect_left(self.shifted,n+1)
069:             if not(sk<len(self.shifted) and self.shifted[sk]==n+1):
070:                 self.shifted.insert(sk,n+1)
071:         #print "master: ",`self.master`
072:         #print "shifted: ",`self.shifted`
073: 
074:     def remove_from_set(self,n):
075:         assert n>=1
076:         #print "remove from set: %i"%n
077:         mj=bisect.bisect_left(self.master,n)
078:         if mj<len(self.master) and self.master[mj]==n:
079:             del self.master[mj]
080:             self.remove_from_shifted_set(n)
081: 
082:     def remove_from_multiset(self,n):
083:         assert n>=1
084:         #print "remove from multiset: %i"%n
085:         mj=bisect.bisect_left(self.master,n)
086:         if mj<len(self.master) and self.master[mj]==n:
087:             del self.master[mj]
088:             if not(mj<len(self.master) and self.master[mj]==n):
089:                 self.remove_from_shifted_set(n)
090: 
091:     def remove_from_shifted_set(self,n):
092:         # if n+1 is in shifted set remove it
093:         sk=bisect.bisect_left(self.shifted,n+1)
094:         if sk<len(self.shifted) and self.shifted[sk]==n+1:
095:             del self.shifted[sk]
096:         # add n to the shifted set if not already there
097:         # and if n-1 is in the master set
098:         # make a special case of n == 1
099:         mi=bisect.bisect_left(self.master,n-1)
100:         if n==1 or mi<len(self.master) and self.master[mi]==n-1:
101:             sj=bisect.bisect_left(self.shifted,n)
102:             if not(sj<len(self.shifted) and self.shifted[sj]==n):
103:                 self.shifted.insert(sj,n)
104:         #print "master: ",`self.master`
105:         #print "shifted: ",`self.shifted`
106:         
107:     def get_shifted(self):
108:         return self.shifted[0]
109: 
110:     def get_available_with_lower_bound(self,n=0):
111:         if n:
112:             # is n available
113:             mj=bisect.bisect_left(self.master,n)
114:             if not(mj<len(self.master) and self.master[mj]==n):
115:                 return n
116:             else:
117:                 # else some larger number must be in shifted set
118:                 sj=bisect.bisect_left(self.shifted,n)
119:                 assert sj<len(self.shifted)
120:                 return self.shifted[sj]
121:         else:
122:             return self.shifted[0]
123: 
124:     def SortShiftedCombo(self,comp=""):
125:         return SortShiftedCombo(self,comp,self.xcols,*self.p,**self.pp)
126: 
127: class SortShiftedCombo(gtk.ListStore):
128:     """
129:     list of integers unused in main entry list as a treemodel.
130:     defines initial 2 columns as (string,style)
131:     """
132:     
133: 
134:     def __init__(self,factory,comp="",xcols=[]):
135:         gtk.ListStore.__init__(self,str,int,*tuple([t for (n,t) in xcols]))
136:         self.factory=factory
137:         self.default=self.factory.get_shifted()
138:         tail=tuple([n for (n,t) in xcols])
139:         self.append((comp,pango.STYLE_ITALIC)+tail)
140:         self.comp=comp
141:         for n in factory.shifted:
142:             self.append((str(n),pango.STYLE_NORMAL)+tail)
143: 
144:     def filter_comprehend(self,comp,inpt=None):
145:         self.set_value(self.get_iter_first(),0,comp)
146:         self.comp=comp
147: 
148:     def filter_nonempty(self):
149:         return True
150: 
151:     def filtered_size(self): 
152:         assert self.iter_n_children(None)>1
153:         return self.iter_n_children(None)
154: 
155:     def best_fit(self):
156:         n=utils.safe_int(self.comp)
157:         if n>0:
158:             return (0,)
159:         else:
160:             return (1,)
161: 
162:     def get_row(self,indexpath):
163:         if isinstance(indexpath,tuple) and len(indexpath)==1:
164:             (index,)=indexpath
165:         else:
166:             index=indexpath
167:         if isinstance(index,int) and 0<=index<self.filtered_size():
168:             i=self.iter_nth_child(None,index)
169:             n=utils.safe_int(self.get_value(i,0))
170:             if n>0:
171:                 return (n,)
172:             else:
173:                 return (self.default,)
174:         else:
175:             return None
176:         
177: ###### sorttab.py ###### python package PyScore.treemodel module sorttab ######