520b5d46d059507dc3fe58d709c18e4b6c131ee9
[public/library.git] / librarian.py
1 #!/usr/bin/env python
2
3 import curses
4
5 stdscr=0
6
7 def menutest(s, l):
8     global stdscr
9     stdscr=s
10     curses.curs_set(0)
11     (rows,cols)=stdscr.getmaxyx()
12     w = curses.newwin(10,40,(rows-10)/2, (cols-40)/2)
13
14     menu(w, l)
15     
16     curses.curs_set(1)
17
18 # item is a list of (string, callable) tuples
19 def menu(w, items):
20     w.keypad(1)
21     highlight=0
22     redrawMenu(w,items,highlight)
23
24     w.refresh()
25     ch=w.getch()
26     while (ch!=113 or ch!=27): # leave on q or ESC
27         if ch==curses.KEY_UP:
28             if highlight!=0:
29                 w.chgat(highlight,0, 0)
30                 highlight -= 1
31                 while(items[highlight][0]==""):
32                     highlight -=1
33                 w.chgat(highlight,0, curses.A_REVERSE)
34         if ch==curses.KEY_DOWN:
35             if highlight!=len(items)-1:
36                 w.chgat(highlight,0, 0)
37                 highlight += 1
38                 while(items[highlight][0]==""):
39                     highlight +=1
40                 w.chgat(highlight,0, curses.A_REVERSE)
41         if ch==114 or ch==10:
42             (s,f)=items[highlight]
43             f()
44             redrawMenu(w,items,highlight)
45         w.refresh()
46         ch = w.getch()
47
48 def redrawMenu(w,items,highlight):
49     i=0
50     for (mitem,fun) in items:
51         w.addstr(i,0, mitem)
52         i +=1
53     w.chgat(highlight, 0, curses.A_REVERSE)
54     w.refresh()
55
56 # items is a list of (label, value) pairs
57 def redrawForm(w, caption, items, buttonlabel, m):
58     (y,x)=w.getmaxyx()
59     w.border()
60     curses.curs_set(1)
61     w.addstr(1,1,caption)
62     r=3
63     for l,v in items:
64         c = m-len(l)-2
65         w.addstr(r,c,l+":")
66         w.addstr(r,m,v)
67         r+=2
68     w.addstr(r,x-len(buttonlabel)-len("<cancel>")-6, "<cancel>  <"+buttonlabel+">")
69     w.refresh()
70
71
72 #the final form for book data entry - takes caption and book info.
73 def bookForm(caption, book, buttonlabel):
74     labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
75               "Publisher", "Publish Date", "Publish Year", "Publish Month", "Publish location",
76               "Pages", "Pagination", "Weight"]
77     entries = []
78     m = 0
79     for l in labels:
80         m = max(len(l),m)
81         if l.lower() in book:
82             entries.append(book[l.lower()])
83         else:
84             entries.append("")
85     m+=4
86
87     w=curses.newwin(34,50,1,10)
88     (y,x)=w.getmaxyx()
89     w.keypad(1)
90     redrawForm(w,caption,zip(labels,entries),buttonlabel,m)
91     bcol = [x-len(buttonlabel)-len("<cancel>")-6, x-len(buttonlabel)-4]
92     bwidth = [8,len(buttonlabel)+2]
93     
94     highlight=0
95     b = -1
96     r=3
97     w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
98     w.move(r,m+len(entries[highlight]))
99     cursor = len(entries[highlight])
100     ch = w.getch()
101     while (1==1):
102         if ch==27: #escape key
103             curses.curs_set(0)
104             w.clear()
105             w.refresh()
106             return {}
107         if ch==curses.KEY_UP:
108             if highlight == len(labels):
109                 w.chgat(r,bcol[b],bwidth[b],curses.A_NORMAL)
110                 highlight = len(labels)-1
111                 b = -1
112                 r=3+2*highlight
113                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
114                 cursor = len(entries[highlight])
115                 w.move(r,m+cursor)
116                 curses.curs_set(1)
117             elif highlight!=0:
118                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
119                 highlight -= 1
120                 r=3+2*highlight
121                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
122                 cursor = len(entries[highlight])
123                 w.move(r,m+cursor)
124         elif ch==curses.KEY_DOWN:
125             if highlight >= len(labels) -1:
126                 highlight = len(labels)
127                 b += 1
128                 b = min(b,1)
129                 curses.curs_set(0)
130                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
131                 r = y-3
132                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
133             else:
134                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
135                 highlight += 1
136                 r=3+2*highlight
137                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
138                 cursor = len(entries[highlight])
139                 w.move(r,m+cursor)
140         elif ch==curses.KEY_LEFT:
141             if highlight == len(labels):
142                 w.chgat(r,bcol[b],bwidth[b],curses.A_NORMAL)
143                 b=0
144                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
145             else:
146                 if cursor>0:
147                     cursor-=1
148                     w.move(r,m+cursor)
149         elif ch==curses.KEY_RIGHT:
150             if highlight == len(labels):
151                 w.chgat(r,bcol[b],bwidth[b],curses.A_NORMAL)
152                 b=1
153                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
154             else:
155                 if cursor < len(entries[highlight]):
156                     cursor+=1
157                     w.move(r,m+cursor)
158         elif ch>19 and ch<127:
159             if highlight != len(labels):
160                 entries[highlight]=entries[highlight][:cursor] + curses.keyname(ch) + entries[highlight][cursor:]
161                 cursor+=1
162                 w.addnstr(r,m, entries[highlight]+(" "*40), x-m-2)
163                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
164                 w.move(r,m+cursor)
165         elif ch==curses.KEY_BACKSPACE:
166             if highlight != len(labels):
167                 cursor-=1
168                 entries[highlight]=entries[highlight][:cursor] + entries[highlight][cursor+1:]
169                 w.addnstr(r,m, entries[highlight]+(" "*40), x-m-2)
170                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
171                 w.move(r,m+cursor)
172         elif ch==10:
173             if b != -1:
174                 if b == 0:
175                     w.clear()
176                     w.refresh()
177                     return {}
178                 elif b == 1:
179                     w.clear()
180                     w.refresh()
181                     return {"title": "I was 'added'"}
182             elif highlight == len(labels)-1:
183                 highlight = len(labels)
184                 b=0
185                 curses.curs_set(0)
186                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
187                 r = y-3
188                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
189             else:
190                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
191                 highlight += 1
192                 r=3+2*highlight
193                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
194                 cursor = len(entries[highlight])
195                 w.move(r,m+cursor)
196
197
198         w.refresh()
199         ch = w.getch()
200
201     curses.curs_set(0)
202     w.clear()
203     w.refresh()
204     return {"title":"this is what I returned"}
205
206
207 def addForm():
208     book = {"title":"A Book of Tests", "pages":"123"}
209     book = bookForm("Add a book", book, "add")
210     stdscr.getch()
211     bookForm("View the book", book, "done")
212
213
214 def updateMenu():
215     w=curses.newwin(1,50,10,10)
216     w.addstr("I will be used to update or modify book records")
217     w.refresh()
218
219 def deleteMenu():
220     w=curses.newwin(1,50,10,10)
221     w.addstr("I will be used to delete book records")
222     w.refresh()
223
224 def browseMenu():
225     w=curses.newwin(1,50,10,10)
226     w.addstr("I will be used to browse book records")
227     w.refresh()
228
229 m = [("Browse Library", browseMenu),
230      ("Add Book or other item", addForm),
231      ("Modify/Update record", updateMenu),
232      ("Remove book from catalogue", deleteMenu),
233      ("",exit),
234      ("Exit", exit)]
235 curses.wrapper(menutest, m)