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