generalized the form to add inheritance options
[library/.git] / browser.py
1 import curses
2 import dbLayer as db
3 from form import bookForm
4
5 class browserWindow:
6     hl=0
7     entries = []
8     topline = 0
9     # column definitions are in (label, weight, specified width) triples
10     columnDefs = [('something',1,None)]
11     mx = my = 0
12
13
14     def clear(self):
15         self.w.erase()
16         self.w.refresh()
17
18     def __init__(self,window):
19         self.w = window
20         self.updateGeometry()
21
22     def sortByColumn(self, col):
23         self.entries.sort() # key=dict.get(col))
24
25     def updateGeometry(self):
26         (self.my,self.mx)=self.w.getmaxyx()
27         self.pageSize = self.my-3
28         self.calcColWidths()
29
30     def calcColWidths(self):
31         total_weights = 0
32         available_space = self.mx - len(self.columnDefs)
33         cols = []
34         for label,weight,value in self.columnDefs:
35             if value!=None:
36                 available_space -= value
37             else:
38                 total_weights+=weight
39
40         for label,weight,value in self.columnDefs:
41             if value!=None:
42                 cols.append((label,value))
43             else:
44                 cols.append((label,available_space*weight/total_weights))
45         self.columns=cols
46
47     def refresh(self):
48         self.displayHeader()
49         for r in range(0,self.pageSize):
50             self.displayRow(r)
51         self.w.refresh()
52         self.highlight()
53
54     def displayHeader(self):
55         cursor = 0
56         for header,width in self.columns:
57             self.w.addnstr(0,cursor,header+" "*width,width)
58             self.w.addstr(1,cursor,"-"*width)
59             cursor += width+1
60
61     def displayRow(self,row):
62         if self.topline+row < len(self.entries):
63             entry = self.entries[self.topline+row]
64             cursor = 0
65             for k,width in self.columns:
66                 if k.lower() in entry:
67                     self.w.addnstr(row+2,cursor,str(entry[k.lower()])+" "*width,width)
68                 cursor += width+1
69         else:
70             self.w.addstr(row+2,0," "*self.mx)
71
72     def highlight(self):
73         row = self.hl-self.topline+2
74         if row > 1 and row < self.my:
75             self.w.chgat(row,0,self.mx,curses.A_REVERSE)
76
77     def unHighlight(self):
78         row = self.hl-self.topline+2
79         if row > 1 and row < self.my:
80             self.w.chgat(row,0,self.mx,curses.A_NORMAL)
81
82     def mvHighlight(self,delta):
83         new = self.hl+delta
84         new = max(new,0)
85         new = min(new,len(self.entries)-1)
86         self.unHighlight()
87         self.hl = new
88         self.highlight()
89     
90     def scroll(self,delta):
91         self.unHighlight()
92         self.topline += delta
93         self.topline = max(self.topline,0)
94         self.topline = min(self.topline,len(self.entries)-1)
95         self.refresh()
96
97     def eventLoop(self):
98         self.w.keypad(1)
99         self.refresh()
100
101         ch = self.w.getch()
102         while ch != 27 and ch != 113:
103             self.handleInput(ch)
104             self.w.refresh()
105             ch = self.w.getch()
106
107     def handleInput(self,ch):
108         if ch == curses.KEY_UP or ch == 107 or ch == 16:
109             if self.hl == self.topline:
110                 self.scroll(-self.pageSize/2-1)
111             self.mvHighlight(-1)
112         elif ch == curses.KEY_DOWN or ch == 106 or ch == 14:
113             if self.hl == self.topline+self.pageSize-1:
114                 self.scroll(+self.pageSize/2+1)
115             self.mvHighlight(+1)
116         elif ch == curses.KEY_PPAGE:
117             self.scroll(-self.pageSize)
118             self.mvHighlight(-self.pageSize)
119         elif ch == curses.KEY_NPAGE:
120             self.scroll(+self.pageSize)
121             self.mvHighlight(+self.pageSize)
122
123
124
125 class bookBrowser(browserWindow):
126     columnDefs = [('ID',0,3),
127                   ('ISBN',0,13),
128                   ('Authors',30,None),
129                   ('Title',60,None)]
130     # redefinable functions
131     def updateSelection(self,book):
132         bookid = book['id']
133         
134         w=curses.newwin(1,1,20,20)
135         bf=bookForm(w)
136         bf.caption='Update Book '+str(bookid)
137         bf.blabel='update'
138         bf.updateEntries(book)
139         newbook = bf.eventLoop()
140         if len(newbook)!=0:
141             db.updateBook(newbook,bookid)
142         bf.clear()
143
144     def viewSelection(self,book):
145         bookid = book['id']
146         w=curses.newwin(1,1,20,20)
147         bf = bookForm(w)
148         bf.caption='Viewing Book '+str(bookid)
149         bf.blabel='done'
150         bf.updateEntries(book)
151         bf.eventLoop()
152         bf.clear()
153
154     def refreshBooks(self):
155         self.entries = db.getBooks()
156
157     def handleInput(self,ch):
158         browserWindow.handleInput(self,ch)
159         if ch == 117: #update on 'u'
160             book = self.entries[self.hl]
161             self.updateSelection(entries)
162             self.entries[self.hl]=db.getBookByID(book['id'])
163             self.refresh()
164         elif ch == 10:
165             book = self.entries[self.hl]
166             self.viewSelection(book)
167             self.refresh()
168
169 class categoryBrowser(browserWindow):
170     columnDefs = [('Category',100,None)]
171
172
173     def refreshCategories(self):
174         self.entries = []
175         cats = db.getCategories()
176         for c in cats:
177             self.entries.append({'category':c})
178
179     def handleInput(self,ch):
180         browserWindow.handleInput(self,ch)
181