Add "error windows", stop crashing when editing empty list of books

This commit is contained in:
Felix Bauckholt 2016-01-30 21:20:38 -05:00
parent 89c66c8188
commit 1690ac87a8
4 changed files with 97 additions and 15 deletions

View File

@ -31,7 +31,17 @@ def menutest(s, l):
hb.refresh() hb.refresh()
w = curses.newwin(15,40,(rows-10)//2, (cols-40)//2) w = curses.newwin(15,40,(rows-10)//2, (cols-40)//2)
try:
menu(w, l) menu(w, l)
except SystemExit: pass
except:
text = """An unexpected error occured.
You can contact the librarian (librarian@csclub.uwaterloo.ca),
but given the history of the library system, it seems unlikely
that somebody will be around to care.
The program will now quit."""
form.error_form(text, stdscr, hb)
raise
curses.curs_set(1) curses.curs_set(1)

View File

@ -15,3 +15,6 @@ class PermissionsError(LibrarianException):
@property @property
def error_msg(self): def error_msg(self):
return "Need privilege level {}".format(self.permission_string) return "Need privilege level {}".format(self.permission_string)
class NoHighlightedEntry(LibrarianException):
error_msg = "No highlighted entry"

View File

@ -1,6 +1,7 @@
import curses import curses
import library.database as db import library.database as db
from library.interface.form import BookForm,CategoryForm from library.interface.form import BookForm,CategoryForm,error_form,catch_error
from library.exceptions import NoHighlightedEntry
class browserWindow: class browserWindow:
# These are actually class variables, not member variables? :< # These are actually class variables, not member variables? :<
@ -118,12 +119,18 @@ class browserWindow:
def mvHighlight(self,delta): def mvHighlight(self,delta):
new = self.hl+delta new = self.hl+delta
new = max(new,0)
new = min(new,len(self.entries)-1) new = min(new,len(self.entries)-1)
new = max(new,0)
self.unHighlight() self.unHighlight()
self.hl = new self.hl = new
self.highlight() self.highlight()
def highlightedEntry(self):
try:
return self.entries[self.hl]
except:
raise NoHighlightedEntry()
def scroll(self,delta): def scroll(self,delta):
self.unHighlight() self.unHighlight()
self.topline += delta self.topline += delta
@ -277,6 +284,7 @@ class trashBrowser(browserWindow):
bf.event_loop() bf.event_loop()
bf.clear() bf.clear()
@catch_error
def restoreSelected(self): def restoreSelected(self):
books = [] books = []
for sel,book in zip(self.selected, self.entries): for sel,book in zip(self.selected, self.entries):
@ -284,6 +292,7 @@ class trashBrowser(browserWindow):
books.append(book) books.append(book)
db.restoreBooks(books) db.restoreBooks(books)
@catch_error
def delSelected(self): def delSelected(self):
books = [] books = []
for sel,book in zip(self.selected, self.entries): for sel,book in zip(self.selected, self.entries):
@ -294,10 +303,11 @@ class trashBrowser(browserWindow):
def refreshBooks(self): def refreshBooks(self):
self.load_data(db.getRemovedBooks()) self.load_data(db.getRemovedBooks())
@catch_error
def handleInput(self,ch): def handleInput(self,ch):
browserWindow.handleInput(self,ch) browserWindow.handleInput(self,ch)
if ch == 10: if ch == 10:
book = self.entries[self.hl] book = self.highlightedEntry()
self.viewSelection(book) self.viewSelection(book)
self.refresh() self.refresh()
if ch==114: #restore books if ch==114: #restore books
@ -332,6 +342,7 @@ class bookBrowser(browserWindow):
# redefinable functions # redefinable functions
@catch_error
def updateSelection(self,book): def updateSelection(self,book):
bookid = book['id'] bookid = book['id']
@ -341,9 +352,9 @@ class bookBrowser(browserWindow):
bf.caption='Update Book '+str(bookid) bf.caption='Update Book '+str(bookid)
bf.blabel='update' bf.blabel='update'
newbook = bf.event_loop() newbook = bf.event_loop()
bf.clear()
if len(newbook)!=0: if len(newbook)!=0:
db.updateBook(newbook,bookid) db.updateBook(newbook,bookid)
bf.clear()
def viewSelection(self,book): def viewSelection(self,book):
bookid = book['id'] bookid = book['id']
@ -363,7 +374,9 @@ class bookBrowser(browserWindow):
cs.refreshCategories() cs.refreshCategories()
cs.eventLoop() cs.eventLoop()
cs.clear() cs.clear()
self.refreshBooks()
@catch_error
def delSelected(self): def delSelected(self):
books = [] books = []
for sel,book in zip(self.selected, self.entries): for sel,book in zip(self.selected, self.entries):
@ -390,22 +403,23 @@ class bookBrowser(browserWindow):
self.refreshBooks = lambda : self.load_data(db.get_onshelf_books()) self.refreshBooks = lambda : self.load_data(db.get_onshelf_books())
self.refreshBooks() self.refreshBooks()
@catch_error
def handleInput(self,ch): def handleInput(self,ch):
browserWindow.handleInput(self,ch) browserWindow.handleInput(self,ch)
if ch == 117: #update on 'u' if ch == 117: #update on 'u'
book = self.entries[self.hl] book = self.highlightedEntry()
self.updateSelection(book) self.updateSelection(book)
self.entries[self.hl]=db.get_book(book['id']) self.entries[self.hl]=db.get_book(book['id'])
self.refresh() self.refresh()
elif ch == 10: elif ch == 10:
book = self.entries[self.hl] book = self.highlightedEntry()
self.viewSelection(book) self.viewSelection(book)
self.refresh() self.refresh()
elif ch == 99: elif ch == 99: #c
book = self.entries[self.hl] book = self.highlightedEntry()
self.categorizeSelection(book) self.categorizeSelection(book)
self.refresh() self.refresh()
if ch==100: if ch == 100:
count=0 count=0
for s in self.selected[0:self.hl-1]: for s in self.selected[0:self.hl-1]:
if s: if s:
@ -425,22 +439,24 @@ class categoryBrowser(browserWindow):
self.load_data(db.getCategories()) self.load_data(db.getCategories())
self.sortByColumn('category') self.sortByColumn('category')
@catch_error
def addCategory(self): def addCategory(self):
w = curses.newwin(1,1,10,10) w = curses.newwin(1,1,10,10)
cf = CategoryForm(w,self.hb) cf = CategoryForm(w,self.hb)
self.centreChild(w) self.centreChild(w)
cat = cf.event_loop() cat = cf.event_loop()
db.addCategory(cat)
cf.clear() cf.clear()
db.addCategory(cat)
def viewCategory(self): def viewCategory(self):
w = curses.newwin(3,5) w = curses.newwin(3,5)
b = bookBrowser(w,self.hb) b = bookBrowser(w,self.hb)
self.centreChild(w) self.centreChild(w)
b.refreshBooksInCategory(self.entries[self.hl]) b.refreshBooksInCategory(self.highlightedEntry())
b.eventLoop() b.eventLoop()
b.clear() b.clear()
@catch_error
def delSelected(self): def delSelected(self):
categories = [] categories = []
for sel,cat in zip(self.selected, self.entries): for sel,cat in zip(self.selected, self.entries):
@ -496,7 +512,7 @@ class categorySelector(browserWindow):
j+=1 j+=1
self.selected = self.original[:] self.selected = self.original[:]
@catch_error
def addCategory(self): def addCategory(self):
w = curses.newwin(1,1,10,10) w = curses.newwin(1,1,10,10)
cf = CategoryForm(w,self.hb) cf = CategoryForm(w,self.hb)
@ -506,6 +522,7 @@ class categorySelector(browserWindow):
db.addCategory(c) db.addCategory(c)
cf.clear() cf.clear()
@catch_error
def updateCategories(self): def updateCategories(self):
# first removed the deselected ones # first removed the deselected ones
uncats = [] uncats = []
@ -558,8 +575,8 @@ class columnSelector(browserWindow):
ch = self.w.getch() ch = self.w.getch()
while ch != 27 and ch != 113: while ch != 27 and ch != 113:
ch = self.handleInput(ch) ch = self.handleInput(ch)
if ch==10: if ch == 10:
col = self.entries[self.hl] col = self.highlightedEntry()
return col['column'] return col['column']
self.w.refresh() self.w.refresh()
ch = self.w.getch() ch = self.w.getch()

View File

@ -1,4 +1,5 @@
import curses import curses
from library.exceptions import LibrarianException
class TextEntry: class TextEntry:
@ -316,3 +317,54 @@ class CategoryForm(FormWindow):
def _return_values(self): def _return_values(self):
return self.entries[0].value return self.entries[0].value
class DummyTextEntry(TextEntry):
def redraw(self): pass
class ErrorForm(FormWindow):
caption = "Error"
blabel = "OK"
def __init__(self,window,helpbar,errortext,width=50):
self.labels = errortext.split("\n")
super().__init__(window, helpbar, width=width)
self.bt = 1
def _make_entries(self):
self.entries = []
for e in range(len(self.labels)):
self.entries.append(DummyTextEntry(self.w))
def redraw(self):
self.w.box()
self.w.addstr(0,(self.mx-len(self.caption))//2,self.caption)
r=0
for l in self.labels:
c = 2
self.w.addstr(r+self.top,c,l)
self.entries[r].redraw()
r+=1
self.w.addstr(self.brow,self.bcol[1], "<"+self.blabel+">")
self.w.chgat(self.brow, self.bcol[1], len(self.blabel)+2, curses.A_REVERSE)
self.w.refresh()
def _mv_focus(self,delta): pass
def error_form(text, w, hb):
width = max([len(l) for l in text.split("\n")]) + 4
child=curses.newwin(1,1)
f = ErrorForm(child, hb, text, width)
(my,mx)=w.getmaxyx()
(r,c)=child.getmaxyx()
child.mvwin((my-r)//2,(mx-c)//2)
w.refresh()
f.event_loop()
f.clear()
def catch_error(fn):
def wrapper_fun(self, *args, **kwd):
try:
return fn(self, *args, **kwd)
except LibrarianException as e:
error_form(str(e), self.w, self.hb)
self.refresh()
return wrapper_fun