001:
002:
003:
004:
005:
006:
007:
008:
009: reloadable=True
010: reloadables=[]
011:
012:
013:
014: import bisect
015: from timesheet import Entries,entriesview as view
016:
017:
018:
019: def init_history():
020: assert not Entries.curpath
021: do_new(next_available_number(0))
022:
023: def delete_clicked():
024:
025: assert Entries.curpath
026: do_update()
027: do_new(do_close(deletion=True))
028:
029: def enter_clicked():
030:
031: assert Entries.curpath
032: do_update()
033: do_new(next_available_number(do_close(deletion=not nonempty_entry())))
034:
035: def cursor_change():
036:
037: assert Entries.curpath
038: oldr=Entries.curpath
039: (r,c)=view.listview.get_cursor()
040: assert isinstance(r,tuple) and len(r)==1
041: if r<>oldr:
042: do_update()
043: deletion=not nonempty_entry()
044: do_close(deletion)
045: if deletion and r>oldr:
046: (k,)=r
047: r=(k-1,)
048: do_open(r)
049: return (Entries.curpath,c)
050:
051: def on_do(doing):
052:
053: import boats
054:
055: assert Entries.curpath
056: do_update()
057: lastnumber=do_close(deletion=not nonempty_entry())
058: context=doing()
059: if "openpath" in context:
060: do_open(context["openpath"])
061: view.listview.set_cursor(Entries.curpath)
062: view.listview.grab_focus()
063: else:
064: if "lastnumber" in context:
065: do_new(next_available_number(context["lastnumber"]))
066: elif "newnumber" in context:
067: do_new(context["newnumber"])
068: else:
069: do_new(next_available_number(0))
070: view.listview.set_cursor(Entries.curpath)
071: boats.view.box.grab_focus()
072:
073:
074:
075: def transaction_tag():
076: assert Entries.curpath
077:
078:
079:
080: return (Entries.curpath,tuple(Entries.model[Entries.curpath]))
081:
082: def do_new(newnumber):
083: import boats
084:
085: assert not Entries.curpath
086: assert isinstance(newnumber,int)
087: def redo(*p,**pp):
088:
089: assert not Entries.curpath
090: new_entry(newnumber)
091: view.listview.set_cursor(Entries.curpath)
092: boats.view.box.grab_focus()
093: def undo(*p,**pp):
094:
095: assert Entries.curpath
096: close_entry(deletion=True)
097: return {"newnumber":newnumber}
098: redo()
099: Entries.history.truncate(tag=transaction_tag())
100: Entries.history.append(undo=undo,redo=redo)
101:
102: def do_open(openpath):
103: assert not Entries.curpath
104: assert isinstance(openpath,tuple) and len(openpath)==1
105: assert isinstance(openpath[0],int)
106: def redo(*p,**pp):
107:
108: assert not Entries.curpath
109: open_entry(openpath)
110: view.listview.set_cursor(Entries.curpath)
111: view.listview.grab_focus()
112: def undo(*p,**pp):
113:
114: assert Entries.curpath
115: close_entry(deletion=False)
116: return {"openpath":openpath}
117: redo()
118: Entries.history.truncate(tag=transaction_tag())
119: Entries.history.append(undo=undo,redo=redo)
120:
121: def do_update():
122: assert Entries.curpath
123: (beforepath,beforerow)=Entries.history.transaction()
124: (afterpath,afterrow)=transaction_tag()
125: def redo(*p,**pp):
126:
127: assert Entries.curpath==beforepath
128: Entries.model[beforepath]=afterrow
129: move_entry(beforepath,afterpath)
130: Entries.curpath=afterpath
131: def undo(*p,**pp):
132:
133: assert Entries.curpath==afterpath
134: Entries.model[afterpath]=beforerow
135: move_entry(afterpath,beforepath)
136: Entries.curpath=beforepath
137: Entries.history.append(undo=undo,redo=redo)
138:
139: def do_close(deletion):
140: assert Entries.curpath
141: (closepath,closerow)=transaction_tag()
142: closenumber=closerow[0]
143: if deletion:
144: closerow=(closerow[0],-1,"","","","",False,False,False,False,False,False,"","","","","")
145: def redo(*p,**pp):
146:
147: close_entry(deletion=True)
148: return {"newnumber":closenumber}
149: def undo(*p,**pp):
150:
151: assert not Entries.curpath
152: new_entry(closenumber)
153: move_entry(Entries.curpath,closepath)
154: else:
155: def redo(*p,**pp):
156:
157: close_entry(deletion=False)
158: return {"openpath":closepath}
159: def undo(*p,**pp):
160:
161: assert not Entries.curpath
162: open_entry(closepath)
163: Entries.history.append(undo=undo,redo=redo)
164: (transpath,transrow)=Entries.history.transaction()
165: if (transpath,transrow)==(closepath,closerow)\
166: or transrow[1:]==(-1,"","","","",False,False,False,False,False,False,"","","","","")==closerow[1:]:
167: Entries.history.rollback()
168: else:
169: Entries.history.commit()
170: lastnumber=close_entry(deletion)
171: return lastnumber
172:
173:
174:
175: class NumberBisectAdapter(object):
176: def __getitem__(self,k):
177: if not isinstance(k,int): raise TypeError
178: return Entries.model.get_value(Entries.model.get_iter((k,)),0)
179: entries_n=NumberBisectAdapter()
180:
181: def next_available_number(lastnumber=0):
182:
183: import numbers
184:
185: assert isinstance(lastnumber,int)
186: return numbers.controller.default_number(lastnumber+1)
187:
188: def new_entry(newnumber):
189:
190: import numbers,boats,finishes,classes
191:
192: assert not Entries.curpath
193: assert isinstance(newnumber,int)
194: n=newnumber
195: k=bisect.bisect_right(entries_n,n,0,Entries.model.iter_n_children(None))
196: Entries.curpath=(k,)
197: Entries.model.insert(k,row=(
198: n,
199: -1,"","",
200: "","",False,False,False,False,False,False,
201: "","","","",
202: "",
203: ))
204:
205: numbers.controller.entry_open(n)
206: boats.controller.entry_open(-1,None,"","")
207: finishes.controller.entry_open(
208: get_last_finish(),None,"","",False,False,False,False,False,False
209: )
210: classes.controller.entry_open(-1,None,"","","")
211: Entries.commentisopen=True
212: view.commentbox.set_text("")
213:
214:
215: def open_entry(openpath):
216:
217: import numbers,boats,finishes,classes
218:
219: assert not Entries.curpath
220: assert isinstance(openpath,tuple) and len(openpath)==1
221: assert isinstance(openpath[0],int)
222: Entries.curpath=openpath
223:
224: currenti=Entries.model.get_iter(Entries.curpath)
225: n=Entries.model.get_value(currenti,0)
226: numbers.controller.number_rollback(n)
227: numbers.controller.entry_open(n)
228: zipnum=Entries.model.get_value(currenti,1)
229: boats.controller.entry_open(
230: zipnum,
231: None,
232: Entries.model.get_value(currenti,2),
233: Entries.model.get_value(currenti,3),
234: )
235: finishes.controller.entry_open(
236: get_last_finish(),
237: None,
238: Entries.model.get_value(currenti,4),
239: Entries.model.get_value(currenti,5),
240: Entries.model.get_value(currenti,6),
241: Entries.model.get_value(currenti,7),
242: Entries.model.get_value(currenti,8),
243: Entries.model.get_value(currenti,9),
244: Entries.model.get_value(currenti,10),
245: Entries.model.get_value(currenti,11),
246: )
247: classes.controller.entry_open(
248: zipnum,
249: None,
250: Entries.model.get_value(currenti,12),
251: Entries.model.get_value(currenti,13),
252: Entries.model.get_value(currenti,14),
253: Entries.model.get_value(currenti,15),
254: )
255:
256: comments=Entries.model.get_value(currenti,16)
257: Entries.commentisopen=True
258: view.commentbox.set_text(comments)
259:
260:
261: def nonempty_entry():
262:
263: assert Entries.curpath
264: currenti=Entries.model.get_iter(Entries.curpath)
265: for f in range(2,11):
266: if Entries.model.get_value(currenti,f):
267: return True
268:
269: def close_entry(deletion=False):
270:
271: import numbers,boats,finishes,classes
272:
273: assert Entries.curpath
274:
275: currenti=Entries.model.get_iter(Entries.curpath)
276: n=Entries.model.get_value(currenti,0)
277: numbers.controller.entry_close()
278: zipnum=Entries.model.get_value(currenti,1)
279: boats.controller.entry_close(zipnum)
280: finishes.controller.entry_close()
281: classes.controller.entry_close()
282: Entries.commentisopen=False
283: view.commentbox.set_text("")
284: if deletion:
285: Entries.model.remove(currenti)
286: else:
287: numbers.controller.number_enter(n)
288: Entries.curpath=None
289: return n
290:
291:
292:
293: def move_entry(pivot,dest):
294:
295:
296:
297: currenti=Entries.model.get_iter(pivot)
298: destinationi=Entries.model.get_iter(dest)
299: if dest<pivot:
300: Entries.model.move_before(currenti,destinationi)
301: elif dest>pivot:
302: Entries.model.move_after(currenti,destinationi)
303:
304: def resort_by_entry_number(n):
305: assert isinstance(n,int)
306:
307: currenti=Entries.model.get_iter(Entries.curpath)
308: (pivot,)=Entries.curpath
309: k=bisect.bisect_right(entries_n,n,0,pivot)
310:
311: if k<pivot:
312: destinationi=Entries.model.get_iter((k,))
313: Entries.model.move_before(currenti,destinationi)
314: Entries.curpath=(k,)
315: view.listview.set_cursor(Entries.curpath)
316: return
317:
318: k=bisect.bisect_left(
319: entries_n,n,pivot+1,Entries.model.iter_n_children(None)
320: )-1
321: if k>pivot:
322: destinationi=Entries.model.get_iter((k,))
323: Entries.model.move_after(currenti,destinationi)
324: Entries.curpath=(k,)
325: view.listview.set_cursor(Entries.curpath)
326: return
327:
328: def set_number_entry(n):
329: import finishes
330:
331: assert isinstance(n,int)
332: currenti=Entries.model.get_iter(Entries.curpath)
333: if entries_model_change_value(currenti,0,n):
334: resort_by_entry_number(n)
335: finishes.controller.entry_tweak(get_last_finish())
336: view.listview.scroll_to_cell(Entries.curpath)
337:
338: def set_boat_entry(zipnum,*b):
339: import classes
340:
341: assert len(b)==2
342: assert isinstance(zipnum,int) and zipnum>=-1
343: currenti=Entries.model.get_iter(Entries.curpath)
344: changedzip=entries_model_change_value(currenti,1,zipnum)
345: entries_model_change_value(currenti,2,b[0].strip())
346: entries_model_change_value(currenti,3,b[1].strip())
347: if changedzip:
348: classes.controller.entry_tweak(zipnum)
349: view.listview.scroll_to_cell(Entries.curpath)
350:
351: def set_finish_entry(*f):
352: assert len(f)==2
353: currenti=Entries.model.get_iter(Entries.curpath)
354: entries_model_change_value(currenti,4,f[0].strip())
355: entries_model_change_value(currenti,5,f[1].strip())
356: view.listview.scroll_to_cell(Entries.curpath)
357:
358: def set_finish_subentry(i,t):
359: assert 0<=i<=1
360: currenti=Entries.model.get_iter(Entries.curpath)
361: entries_model_change_value(currenti,4+i,t.strip())
362: view.listview.scroll_to_cell(Entries.curpath)
363:
364: def set_finish_toggle(i,b):
365: assert 0<=i<=5
366: currenti=Entries.model.get_iter(Entries.curpath)
367: entries_model_change_value(currenti,6+i,bool(b))
368: view.listview.scroll_to_cell(Entries.curpath)
369:
370: def set_class_entry(*c):
371: assert len(c)==4
372: currenti=Entries.model.get_iter(Entries.curpath)
373: entries_model_change_value(currenti,12,c[0].strip())
374: entries_model_change_value(currenti,13,c[1].strip())
375: entries_model_change_value(currenti,14,c[2].strip())
376: entries_model_change_value(currenti,15,c[3].strip())
377: view.listview.scroll_to_cell(Entries.curpath)
378:
379: def set_class_subentry(i,*c):
380: assert 0<=i<=2
381: assert i==0 and len(c)==2 or i in [1,2] and len(c)==1
382: currenti=Entries.model.get_iter(Entries.curpath)
383: if i==0:
384: entries_model_change_value(currenti,12,c[0].strip())
385: entries_model_change_value(currenti,13,c[1].strip())
386: else:
387: entries_model_change_value(currenti,13+i,c[0].strip())
388: view.listview.scroll_to_cell(Entries.curpath)
389:
390: def set_comment_entry(comments):
391: assert isinstance(comments,str)
392: currenti=Entries.model.get_iter(Entries.curpath)
393: entries_model_change_value(currenti,16,comments)
394: view.listview.scroll_to_cell(Entries.curpath)
395:
396:
397:
398:
399:
400: def iter_numbers():
401: i=Entries.model.get_iter_first()
402: while i:
403: yield Entries.model.get_value(i,0)
404: i=Entries.model.iter_next(i)
405:
406:
407:
408:
409:
410: def entries_model_change_value(i,f,v):
411: oldv=Entries.model.get_value(i,f)
412: if oldv<>v:
413: Entries.model.set_value(i,f,v)
414: return True
415:
416:
417:
418: def get_boat_zip_entry():
419:
420: currenti=Entries.model.get_iter(Entries.curpath)
421: return Entries.model.get_value(currenti,1)
422:
423:
424:
425: def get_last_finish(defaultt="20:00:00"):
426:
427:
428:
429:
430: if Entries.curpath:
431: (i,)=Entries.curpath
432: while i:
433: i-=1
434: iter=Entries.model.get_iter((i,))
435: finish=Entries.model.get_value(iter,5)
436: if finish:
437: return finish
438: return defaultt
439:
440: