PyScore

001: # -*- python -*-
002: ###### Entries.py ###### python package PyScore.timesheet module Entries ######
003: 
004: # PyScore
005: # a race scoring programme
006: # written by Matt Draisey
007: # 2004 April 6
008: 
009: reloadables=[]
010: 
011: ###### Entries.py ###### python package PyScore.timesheet module Entries ######
012: 
013: import gtk,gobject
014: 
015: # this is in effect a global available object
016: # variables (objects) which represent mutable values are exported
017: # state is preserved across reloads
018: # there is minimal code here and none directly exported
019: #   the history singleton hardly counts
020: 
021: # set controller globals that must survive a reload
022: 
023: # immutable
024: 
025: datafile=None
026: dataname=None
027: from standing import boatinit as boatlist
028: 
029: # mutable
030: 
031: activecol=None
032: curpath=None
033: commentisopen=False
034: 
035: # the edit history a mutable singleton but bound constantly to attr history
036: 
037: class History(object):
038:     def __init__(self):
039:         self.committed=[]
040:         self.cursor=0
041:         self.tag=None
042:         self.provisional=[]
043:     def display(self):
044:         for (undo,redo) in self.committed:
045:             print " (%-37s, %-37s)"%(undo.__doc__,redo.__doc__)
046:     def truncate(self,tag):
047:         assert tag<>None
048:         self.tag=tag
049:         self.provisional=[]
050:     def append(self,undo=(lambda *p,**pp: p),redo=(lambda *p,**pp: p)):
051:         assert self.tag<>None
052:         try:
053:             self.provisional.append((undo,redo))
054:         except KeyError:
055:             raise TypeError
056:     def transaction(self):
057:         assert self.tag<>None
058:         return self.tag
059:     def transact(self,tag):
060:         if self.tag==tag:
061:             self.rollback()
062:         else:
063:             self.commit()
064:     def commit(self):
065:         assert self.tag<>None
066:         self.committed[self.cursor:]=self.provisional
067:         self.cursor=len(self.committed)
068:         self.tag=None
069:         self.provisional=[]
070:     def rollback(self):
071:         assert self.tag<>None
072:         self.tag=None
073:         self.provisional=[]
074:     def undo(self,**pp):
075:         assert self.tag==None and self.provisional==[]
076:         context=()
077:         while self.cursor>0:
078:             self.cursor-=1
079:             change=self.committed[self.cursor]
080:             assert isinstance(change,tuple) and len(change)==2
081:             context=change[0](*context,**pp)
082:             if isinstance(context,dict): return context
083:             if context==None: context=()
084:             elif not isinstance(context,tuple): context=(context,)
085:         else:
086:             return {"context":context}
087:     def redo(self,**pp):
088:         assert self.tag==None and self.provisional==[]
089:         context=()
090:         maxcursor=len(self.committed)
091:         while self.cursor<maxcursor:
092:             change=self.committed[self.cursor]
093:             assert isinstance(change,tuple) and len(change)==2
094:             context=change[1](*context,**pp)
095:             self.cursor+=1
096:             if isinstance(context,dict): return context
097:             if context==None: context=()
098:             elif not isinstance(context,tuple): context=(context,)
099:         else:
100:             return {"context":context}
101: history=History()
102: 
103: # the model for the main data table
104: 
105: model=gtk.ListStore(int,int,str,str,str,str,gobject.TYPE_BOOLEAN,bool,bool,bool,bool,bool,str,str,str,str,str)
106: ##### ##### silly documentation ##### #####
107: 
108: """
109: Open an entry edit:
110: 
111: numbers.open_entry(existing entry to reopen?)
112:     update used and unused entry numbers
113:     determine default entry number
114:     attach completion model
115:     set entry text
116:         trigger entries.set_number_entry()
117: boats.open_entry(existing entry to reopen?)
118:     possibly increase list of potential finishers
119:     attach completion model
120:     set entry text
121:         trigger entries.set_boat_entry()
122: finishes.open_entry(existing entry to reopen?)
123:     set initial default time based on set entry number
124:         keeping entries sorted by entry number
125:         get last finish time preceeding this entry in list
126:         (will refresh whenever current entry number changed)
127:     attach completion model
128:     set entry text
129:         trigger entries.set_finishes_entry()
130: classes.open_entry(existing entry to reopen?)
131:     set initial classes entry model
132:         if set boat entry known
133:             determine list of registered classes
134:         else
135:             fallback to list of all potential classes
136:         (will refresh whenever current boat entry changed)
137:     attach completion model
138:     set entry text
139:         trigger entries.set_finishes_entry()
140: 
141: Note on completions:
142:     For this simple scheme to work, completions must be
143:     idempotent.  The default entry must exactly match any valid
144:     input.
145: """
146: 
147: """
148: Close an entry edit in progress:
149: 
150: focus notebook page on summary
151: numbers.entry_close()
152:     detach completion model
153:     clear entry box
154:     update used and unused entry numbers
155: boats.entry_close()
156:     detach completion model
157:     clear entry box
158:     if identified boat reduce list of potential finishers
159: finishes.entry_close()
160:     detach completion model
161:     clear entry box
162: classes.entry_close()
163:     detach completion model
164:     clear entry box
165: """
166: 
167: ###### Entries.py ###### python package PyScore.timesheet module Entries ######