From 1690ac87a8732f2eb156cb836fe7134bb3304a78 Mon Sep 17 00:00:00 2001 From: Felix Bauckholt Date: Sat, 30 Jan 2016 21:20:38 -0500 Subject: [PATCH] Add "error windows", stop crashing when editing empty list of books --- librarian | 12 ++++++++- library/exceptions.py | 3 +++ library/interface/browser.py | 45 +++++++++++++++++++++---------- library/interface/form.py | 52 ++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/librarian b/librarian index 5335954..bbbbd18 100755 --- a/librarian +++ b/librarian @@ -31,7 +31,17 @@ def menutest(s, l): hb.refresh() w = curses.newwin(15,40,(rows-10)//2, (cols-40)//2) - menu(w, l) + try: + 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) diff --git a/library/exceptions.py b/library/exceptions.py index a82df8a..5ae429b 100644 --- a/library/exceptions.py +++ b/library/exceptions.py @@ -15,3 +15,6 @@ class PermissionsError(LibrarianException): @property def error_msg(self): return "Need privilege level {}".format(self.permission_string) + +class NoHighlightedEntry(LibrarianException): + error_msg = "No highlighted entry" diff --git a/library/interface/browser.py b/library/interface/browser.py index 7a610a8..e1eef10 100644 --- a/library/interface/browser.py +++ b/library/interface/browser.py @@ -1,6 +1,7 @@ import curses 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: # These are actually class variables, not member variables? :< @@ -118,12 +119,18 @@ class browserWindow: def mvHighlight(self,delta): new = self.hl+delta - new = max(new,0) new = min(new,len(self.entries)-1) + new = max(new,0) self.unHighlight() self.hl = new self.highlight() + def highlightedEntry(self): + try: + return self.entries[self.hl] + except: + raise NoHighlightedEntry() + def scroll(self,delta): self.unHighlight() self.topline += delta @@ -277,6 +284,7 @@ class trashBrowser(browserWindow): bf.event_loop() bf.clear() + @catch_error def restoreSelected(self): books = [] for sel,book in zip(self.selected, self.entries): @@ -284,6 +292,7 @@ class trashBrowser(browserWindow): books.append(book) db.restoreBooks(books) + @catch_error def delSelected(self): books = [] for sel,book in zip(self.selected, self.entries): @@ -294,10 +303,11 @@ class trashBrowser(browserWindow): def refreshBooks(self): self.load_data(db.getRemovedBooks()) + @catch_error def handleInput(self,ch): browserWindow.handleInput(self,ch) if ch == 10: - book = self.entries[self.hl] + book = self.highlightedEntry() self.viewSelection(book) self.refresh() if ch==114: #restore books @@ -332,6 +342,7 @@ class bookBrowser(browserWindow): # redefinable functions + @catch_error def updateSelection(self,book): bookid = book['id'] @@ -341,9 +352,9 @@ class bookBrowser(browserWindow): bf.caption='Update Book '+str(bookid) bf.blabel='update' newbook = bf.event_loop() + bf.clear() if len(newbook)!=0: db.updateBook(newbook,bookid) - bf.clear() def viewSelection(self,book): bookid = book['id'] @@ -363,7 +374,9 @@ class bookBrowser(browserWindow): cs.refreshCategories() cs.eventLoop() cs.clear() + self.refreshBooks() + @catch_error def delSelected(self): books = [] 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() + @catch_error def handleInput(self,ch): browserWindow.handleInput(self,ch) if ch == 117: #update on 'u' - book = self.entries[self.hl] + book = self.highlightedEntry() self.updateSelection(book) self.entries[self.hl]=db.get_book(book['id']) self.refresh() elif ch == 10: - book = self.entries[self.hl] + book = self.highlightedEntry() self.viewSelection(book) self.refresh() - elif ch == 99: - book = self.entries[self.hl] + elif ch == 99: #c + book = self.highlightedEntry() self.categorizeSelection(book) self.refresh() - if ch==100: + if ch == 100: count=0 for s in self.selected[0:self.hl-1]: if s: @@ -425,22 +439,24 @@ class categoryBrowser(browserWindow): self.load_data(db.getCategories()) self.sortByColumn('category') + @catch_error def addCategory(self): w = curses.newwin(1,1,10,10) cf = CategoryForm(w,self.hb) self.centreChild(w) cat = cf.event_loop() - db.addCategory(cat) cf.clear() + db.addCategory(cat) def viewCategory(self): w = curses.newwin(3,5) b = bookBrowser(w,self.hb) self.centreChild(w) - b.refreshBooksInCategory(self.entries[self.hl]) + b.refreshBooksInCategory(self.highlightedEntry()) b.eventLoop() b.clear() + @catch_error def delSelected(self): categories = [] for sel,cat in zip(self.selected, self.entries): @@ -496,7 +512,7 @@ class categorySelector(browserWindow): j+=1 self.selected = self.original[:] - + @catch_error def addCategory(self): w = curses.newwin(1,1,10,10) cf = CategoryForm(w,self.hb) @@ -506,6 +522,7 @@ class categorySelector(browserWindow): db.addCategory(c) cf.clear() + @catch_error def updateCategories(self): # first removed the deselected ones uncats = [] @@ -558,8 +575,8 @@ class columnSelector(browserWindow): ch = self.w.getch() while ch != 27 and ch != 113: ch = self.handleInput(ch) - if ch==10: - col = self.entries[self.hl] + if ch == 10: + col = self.highlightedEntry() return col['column'] self.w.refresh() ch = self.w.getch() diff --git a/library/interface/form.py b/library/interface/form.py index 619f3ae..85c09f0 100644 --- a/library/interface/form.py +++ b/library/interface/form.py @@ -1,4 +1,5 @@ import curses +from library.exceptions import LibrarianException class TextEntry: @@ -316,3 +317,54 @@ class CategoryForm(FormWindow): def _return_values(self): 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