001:
002:
003:
004:
005:
006:
007:
008:
009: reloadable=True
010: reloadables=[]
011:
012:
013:
014: import itertools,random
015: import gtk,pango
016: from treemodel import filttab,filtmaster
017: from utility import utils,guiutils
018: from timesheet import Entries,entriesmod as modeller
019: from timesheet import classesview as view
020:
021:
022:
023: def initialize_model():
024: pass
025:
026: classes_defaults=[("","")]+Entries.boatlist.classes_defaults_tab
027:
028: mastermodel=filtmaster.FiltMaster(
029: rows=[
030: (division,fleet,{
031: "":0,"PHRF A":1,"PHRF B":2,"JOG A":3,"JOG B":4,"Shark":5,
032: }[division])
033: for (division,fleet) in classes_defaults
034: ],
035: wcols=[True,False],xcols=[(0,int)]
036: )
037: mastermodel.add_strikethrough_attribute()
038: view.listview[0].set_model(mastermodel.FiltTable())
039:
040: affirmmaster=filtmaster.FiltMaster(
041: rows=[
042: ("", pango.STYLE_NORMAL,),
043: ("Deny", pango.STYLE_ITALIC,),
044: ("Race", pango.STYLE_NORMAL,),
045: ("Series", pango.STYLE_NORMAL,),
046: ("Year", pango.STYLE_NORMAL,),
047: ],
048: ncols=1,xcols=[(pango.STYLE_NORMAL,int)]
049: )
050: affirmmaster.add_strikethrough_attribute()
051: view.listview[1].set_model(affirmmaster.FiltTable())
052:
053: mastercascade=[
054: filtmaster.FiltMaster(
055: rows=[(str(p),pango.STYLE_NORMAL,) for p in ratingsranges],
056: ncols=1,xcols=[(pango.STYLE_ITALIC,int)],
057: )
058: for ratingsranges in [
059: [],
060: [126,145,176],
061: [177,192,225],
062: [126,145,200],
063: [201,213,225],
064: [228],
065: ]
066: ]
067: view.listview[2].set_model(mastercascade[0].FiltCombo())
068:
069:
070:
071: def working_model(zipnum):
072: classrows=[c[:2] for c in Entries.boatlist.sample_boats_class[zipnum]]
073: classratings=dict([
074: (c[:2],c[2])
075: for c in Entries.boatlist.sample_boats_class[zipnum]
076: ])
077: workingmodel=mastermodel.clone_master()
078: workingcascade=mastercascade[:]
079: def workingappend(c):
080: l=len(workingcascade)
081: workingcascade.append(filtmaster.FiltMaster(
082: rows=[(str(p),pango.STYLE_NORMAL,) for p in [classratings[c]]],
083: ncols=1,
084: xcols=[(pango.STYLE_ITALIC,int)],
085: ))
086: return l
087: for (i,c) in enumerate(classes_defaults):
088: if c in classrows:
089: classrows.remove(c)
090: workingmodel.set_field(i,2,workingappend(c))
091: else:
092: workingmodel.set_strikethrough(i)
093: for c in classrows:
094: workingmodel.append_to_master(c)
095: workingappend(c)
096: return (workingmodel,workingcascade)
097:
098:
099:
100: def entry_open(zipnum,insertionfield=None,*c):
101: s=":".join(utils.whittle(*c))
102: if zipnum>=0:
103: working=working_model(zipnum)
104: model=working[0].FiltTable()
105: workingcascade=working[1]
106: else:
107: model=mastermodel.FiltTable()
108: workingcascade=mastercascade
109: if insertionfield==0:
110: insertionpoint=len(c[0])
111: elif insertionfield==1:
112: insertionpoint=len(c[0])+1+len(c[1])
113: else:
114: insertionpoint=None
115: reset_entry(model,workingcascade,s,insertionfield,insertionpoint)
116:
117: def entry_is_open():
118: return is_entry()
119:
120: def entry_tweak(zipnum):
121: if zipnum>=0:
122: working=working_model(zipnum)
123: tweakmodel=working[0].FiltTable()
124: tweakmastercascade=working[1]
125: else:
126: tweakmodel=mastermodel.FiltTable()
127: tweakmastercascade=mastercascade
128: tweak_entry(tweakmodel,tweakmastercascade)
129:
130: def entry_close():
131: clear_entry()
132:
133:
134:
135: basecolour=view.listview[0].get_style().base[gtk.STATE_NORMAL]
136: colcolour=gtk.gdk.color_parse("#ffcc99")
137:
138: class Classes(object):
139: model=[view.listview[i].get_model() for i in [0,1,2]]
140: cascademaster=mastercascade
141: currentcascade=-1
142: parse=filttab.SplitColumns(2,1,1)
143: activemod=0
144: currentf=["","",""]
145: activecol=0
146:
147: view.renderer[0].set_property("cell-background-gdk",colcolour)
148:
149: if Classes.model[0].filter_nonempty():
150: view.listview[0].set_cursor((0,),view.column[0])
151: if Classes.model[1].filter_nonempty():
152: view.listview[1].set_cursor((0,))
153: if Classes.model[2].filter_nonempty():
154: view.listview[2].set_cursor((0,))
155:
156: def reset_entry(model,cascademaster,text,insertionfield,insertionpoint):
157: view.box.set_text(text)
158: Classes.model[0]=model
159: Classes.cascademaster=cascademaster
160: Classes.currentcascade=-1
161: insertionpoint=None
162:
163: (newmod,newcol)=Classes.parse.split_comprehend(text,insertionpoint)
164: chain=Classes.parse.get_split_padded()
165: Classes.model[0].filter_comprehend(chain[0])
166:
167: newcolumn=(view.column[newcol] if 0<=newcol<4 else None)
168: if newcolumn<>None:
169: view.renderer[newcol].set_property("cell-background-gdk",colcolour)
170: Classes.activecol=newcol
171:
172: view.listview[0].set_model(Classes.model[0])
173: bestfit=Classes.model[0].exact_fit(2)
174: if bestfit==None:
175: Classes.model[0].filter_comprehend(chain[0])
176: bestfit=Classes.model[0].best_fit()
177: if bestfit<>None:
178: if 0<=newcol<2:
179: view.listview[0].set_cursor(bestfit,newcolumn)
180: else:
181: view.listview[0].set_cursor(bestfit)
182: zipdiv=Classes.model[0].get_row(bestfit)[2]
183: else:
184: modeller.set_class_subentry(0,"","")
185: zipdiv=-1
186: Classes.currentf[0]=chain[0]
187:
188: if zipdiv>=0:
189: tweakmaster=Classes.cascademaster[zipdiv]
190: else:
191: tweakmaster=mastercascade[0]
192: Classes.currentcascade=zipdiv
193: Classes.model[1]=affirmmaster.FiltTable()
194: Classes.model[1].filter_comprehend(chain[1])
195: Classes.model[2]=tweakmaster.FiltCombo()
196: Classes.model[2].filter_comprehend(chain[2])
197:
198: view.listview[1].set_model(Classes.model[1])
199: assert Classes.model[1].filter_nonempty()
200: view.listview[1].set_cursor((0,))
201: Classes.currentf[1]=chain[1]
202:
203: view.listview[2].set_model(Classes.model[2])
204: assert Classes.model[2].filter_nonempty()
205: view.listview[2].set_cursor((0,))
206: Classes.currentf[2]=chain[2]
207: Classes.activemod=newmod
208:
209: def is_entry():
210: return Classes.model[0]<>None
211:
212: def tweak_entry(tweakmodel,tweakmaster):
213: if not Classes.model[0]: return
214: s=Classes.currentf[0]
215: tweakmodel.filter_comprehend(s)
216: Classes.cascademaster=tweakmaster
217: Classes.currentcascade=-1
218: bestfit=tweakmodel.best_fit()
219: view.listview[0].set_model(tweakmodel)
220: Classes.model[0]=tweakmodel
221: if bestfit<>None:
222: view.listview[0].set_cursor(bestfit)
223: else:
224: modeller.set_class_subentry(0,"","")
225: tweak_cascade_model(-1)
226:
227: def tweak_cascade_model(zipdiv):
228: if not Classes.model[1]: return
229: if Classes.currentcascade==zipdiv:
230: return
231: if zipdiv>=0:
232: tweakmaster=Classes.cascademaster[zipdiv]
233: else:
234: tweakmaster=mastercascade[0]
235: tweakmodel=tweakmaster.FiltCombo(Classes.currentf[2])
236:
237:
238:
239: Classes.currentcascade=zipdiv
240: Classes.model[1]=affirmmaster.FiltTable()
241: Classes.model[2]=tweakmodel
242: view.listview[2].set_model(tweakmodel)
243: if tweakmodel.filtered_size()==2:
244: view.listview[2].set_cursor((1,))
245:
246:
247: else:
248: view.listview[2].set_cursor((0,))
249:
250: def clear_entry():
251: for i in [0,1,2]:
252: view.listview[i].set_model(None)
253: Classes.model[i]=None
254: Classes.cascademaster=[]
255: if Classes.activecol<>None and 0<=Classes.activecol<4:
256: oldrenderer=view.renderer[Classes.activecol]
257: oldrenderer.set_property("cell-background-gdk",basecolour)
258: Classes.activecol=None
259: Classes.currentf=["","",""]
260: Classes.currentcascade=-1
261: view.box.set_text("")
262:
263:
264:
265: def on_box_changed(box):
266: assert box==view.box
267: if not Classes.model[0]: return
268: insertionpoint=None
269:
270: (newmod,newcol)=\
271: Classes.parse.split_comprehend(box.get_text(),insertionpoint)
272: chain=Classes.parse.get_split_padded()
273:
274: Classes.model[0].filter_comprehend(chain[0])
275:
276: newcolumn=(view.column[newcol] if 0<=newcol<4 else None)
277: if newcol<>Classes.activecol:
278: if 0<=Classes.activecol<4:
279: oldrenderer=view.renderer[Classes.activecol]
280: oldrenderer.set_property("cell-background-gdk",basecolour)
281: if newcolumn<>None:
282: view.renderer[newcol].set_property("cell-background-gdk",colcolour)
283: for i in [0,1,2]:
284: view.listview[i].queue_draw()
285: Classes.activecol=newcol
286:
287:
288:
289: if Classes.currentf[0]<>chain[0]:
290: bestfit=Classes.model[0].best_fit()
291: if bestfit<>None:
292: if 0<=newcol<2:
293: view.listview[0].set_cursor(bestfit,newcolumn)
294: else:
295: view.listview[0].set_cursor(bestfit)
296: zipdiv=Classes.model[0].get_row(bestfit)[2]
297: else:
298: modeller.set_class_subentry(0,"","")
299: zipdiv=-1
300: Classes.currentf[0]=chain[0]
301:
302: tweak_cascade_model(zipdiv)
303:
304: Classes.model[1].filter_comprehend(chain[1])
305:
306: if Classes.currentf[1]<>chain[1]:
307: bestfit=Classes.model[1].best_fit()
308: if bestfit<>None:
309: view.listview[1].set_cursor(bestfit)
310: else:
311: modeller.set_class_subentry(1,"")
312: Classes.currentf[1]=chain[1]
313:
314: Classes.model[2].filter_comprehend(chain[2])
315:
316: if Classes.currentf[2]<>chain[2]:
317: bestfit=Classes.model[2].best_fit()
318: if bestfit<>None:
319: view.listview[2].set_cursor(bestfit)
320: else:
321: modeller.set_class_subentry(2,"")
322: Classes.currentf[2]=chain[2]
323: Classes.activemod=newmod
324:
325: def on_box_key_press(widget,event):
326: assert widget==view.box
327: if not Classes.model[Classes.activemod]: return
328: k=event.keyval
329: if k in guiutils.cursor_mover:
330: view_move_cursor(
331: view.listview[Classes.activemod],*guiutils.cursor_mover[k])
332: return 1
333:
334: def view_move_cursor(tree,*mover):
335: assert tree==view.listview[Classes.activemod]
336: if Classes.model[Classes.activemod].filter_nonempty():
337: rsize=Classes.model[Classes.activemod].filtered_size()
338: (r,c)=view.listview[Classes.activemod].get_cursor()
339: r=guiutils.page_cursor_move(r,rsize,*mover)
340: view.listview[Classes.activemod].set_cursor(r,c)
341: return 1
342:
343: def on_view_cursor_changed(tree,i):
344: assert tree==view.listview[i]
345: (r,c)=view.listview[i].get_cursor()
346: if i==0:
347: row=Classes.model[0].get_row(r)
348: modeller.set_class_subentry(0,*row[:2])
349: tweak_cascade_model(row[2])
350: elif i==1:
351: modeller.set_class_subentry(1,*Classes.model[1].get_row(r)[:1])
352: elif i==2:
353: modeller.set_class_subentry(2,*Classes.model[2].get_row(r)[:1])
354:
355:
356:
357: reloadables+=[guiutils]
358: reloadables+=[filttab,filtmaster,utils]
359:
360: