PyScore

001: # -*- python -*-
002: ## boatscon.py ## python package PyScore.timesheet module boats.controller ##
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: ## boatscon.py ## python package PyScore.timesheet module boats.controller ##
013: 
014: import re
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 boatsview as view
020: 
021: # the initial model and model constants
022: 
023: chuck=re.compile(r"""[.:;,\s]""")
024: mastermodel=filtmaster.FiltMaster(
025:     rows=[
026:         tuple(map(lambda e: re.sub(chuck," ",e), b))+(pango.STYLE_NORMAL,)
027:         for b in Entries.boatlist.certified_boats_tab()
028:     ],
029:     wcols=[True,False,False,False],xcols=[(pango.STYLE_ITALIC,int)]
030: )
031: mastermodel.add_strikethrough_attribute()
032: view.listview.set_model(mastermodel.FiltCombo())
033: 
034: # the external boat tracking interface for populating during initialization
035: 
036: def boat_zipnum_enter(zipnum):
037:     mastermodel.set_strikethrough(zipnum)
038: 
039: # the entry interface
040: 
041: def entry_open(zipnum,insertionfield=None,*b):
042:     mastermodel.clear_strikethrough(zipnum)
043:     s=":".join(utils.whittle(*b))
044:     model=mastermodel.FiltCombo(s)
045:     reset_entry(model,s)
046: 
047: def entry_close(zipnum):
048:     clear_entry()
049:     mastermodel.set_strikethrough(zipnum)
050: 
051: # constants and boats globals # (re)initialization interface
052: 
053: basecolour=view.listview.get_style().base[gtk.STATE_NORMAL]
054: colcolour=gtk.gdk.color_parse("#ffcc99")
055: 
056: class Boats(object):
057:     model=view.listview.get_model()
058:     parse=filttab.SplitColumns(ncols=4)
059:     activecol=0
060:     currentf=""
061: 
062: view.renderer[0].set_property("cell-background-gdk",colcolour)
063: 
064: if Boats.model.filter_nonempty():
065:     view.listview.set_cursor((0,),view.column[Boats.activecol])
066: 
067: # more complex than necessary to be consistent with other modules
068: # also allows me to have idempotent behaviour for this case without
069: # using a global variable
070: def reset_entry(model,text,insertionpoint=None):
071:     view.box.set_text(text)
072:     Boats.model=model
073:     #newcol=Boats.model.filter_comprehend(text,insertionpoint)
074:     (newgrp,newcol)=Boats.parse.split_comprehend(text,insertionpoint)
075:     chainf=":".join(utils.whittle(*Boats.parse.get_split_chain()))
076:     Boats.model.filter_comprehend(chainf)
077:     # pretty background colour
078:     newcolumn=(view.column[newcol] if 0<=newcol<4 else None)
079:     if newcolumn<>None:
080:         view.renderer[newcol].set_property("cell-background-gdk",colcolour)
081:     Boats.activecol=newcol
082:     # set cursor --- force idempotency of FiltCombo model
083:     view.listview.set_model(Boats.model)
084:     assert Boats.model.filter_nonempty()
085:     view.listview.set_cursor((0,),newcolumn)
086:     Boats.currentf=chainf
087: 
088: def clear_entry():
089:     view.listview.set_model(None)
090:     Boats.model=None
091:     if Boats.activecol<>None and 0<=Boats.activecol<4:
092:         oldrenderer=view.renderer[Boats.activecol]
093:         oldrenderer.set_property("cell-background-gdk",basecolour)
094:     Boats.activecol=None
095:     Boats.currentf=""
096:     view.box.set_text("")
097: 
098: # gui callbacks
099: 
100: def on_box_changed(box):
101:     assert box==view.box
102:     if not Boats.model: return
103:     comp=box.get_text()
104:     insertionpoint=None #insertionpoint=box.get_position()
105:     #newcol=Boats.model.filter_comprehend(comp)
106:     (newgrp,newcol)=Boats.parse.split_comprehend(box.get_text(),insertionpoint)
107:     chainf=":".join(utils.whittle(*Boats.parse.get_split_chain()))
108:     Boats.model.filter_comprehend(chainf)
109:     # pretty background colour
110:     newcolumn=(view.column[newcol] if 0<=newcol<4 else None)
111:     if newcol<>Boats.activecol:
112:         if 0<=Boats.activecol<4:
113:             oldrenderer=view.renderer[Boats.activecol]
114:             oldrenderer.set_property("cell-background-gdk",basecolour)
115:         if newcolumn<>None:
116:             view.renderer[newcol].set_property("cell-background-gdk",colcolour)
117:         view.listview.queue_draw()
118:         Boats.activecol=newcol
119:     # set cursor
120:     if Boats.currentf<>chainf:
121:         bestfit=Boats.model.best_fit()
122:         assert bestfit<>None
123:         view.listview.set_cursor(bestfit,newcolumn)
124:         Boats.currentf=chainf
125:     # instead of directly using raw text we process is through
126:     # a parser which splits the columns and reassembles them
127:     # this allows us to keep the cursor fixed unless the canonical text
128:     # actually changes --- this is consistent with all other completions
129: 
130: def on_box_key_press(widget,event):
131:     assert widget==view.box
132:     if not Boats.model: return
133:     k=event.keyval
134:     if k in guiutils.cursor_mover:
135:         view_move_cursor(view.listview,*guiutils.cursor_mover[k])
136:         return 1
137: 
138: def view_move_cursor(tree,*mover):
139:     assert tree==view.listview
140:     if Boats.model.filter_nonempty():
141:         rsize=Boats.model.filtered_size()
142:         (r,c)=view.listview.get_cursor()
143:         r=guiutils.page_cursor_move(r,rsize,*mover)
144:         view.listview.set_cursor(r,c)
145:     return 1
146: 
147: def on_view_cursor_changed(tree):
148:     assert tree==view.listview
149:     (r,c)=view.listview.get_cursor()
150:     (zipnum,row)=Boats.model.get_zipped_row(r)
151:     if zipnum==-1:
152:         # if not an identified competitor
153:         # sail number and name can positively identify boat
154:         (bestzip,bestrow)=Boats.model.get_zipped_row(Boats.model.best_fit())
155:         if row[0:2]==bestrow[0:2]:
156:             zipnum=bestzip
157:     modeller.set_boat_entry(zipnum,*row[0:2])
158: 
159: # register reloadables
160: 
161: reloadables+=[guiutils]
162: reloadables+=[filttab,filtmaster,utils]
163: 
164: ## boatscon.py ## python package PyScore.timesheet module boats.controller ##