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