diff --git a/browser.py b/browser.py index 88a78f0..b384728 100644 --- a/browser.py +++ b/browser.py @@ -4,6 +4,10 @@ import db_layer as db from form import BookForm,CategoryForm class browserWindow: + # These are actually class variables, not member variables? :< + _default_height=25 + _default_width=60 + hl=0 topline = 0 entries = [] @@ -18,13 +22,21 @@ class browserWindow: last_search = "" found_index = 0 - def __init__(self,window,helpbar, height=50, width=80): + def __init__(self,window,helpbar, height=0, width=0): + if not(height and width): + height = browserWindow._default_height + width = browserWindow._default_width + sys.stderr.write(str(height)+', '+str(width)+'\n') self.w = window self.hb = helpbar self.w.resize(height,width) self.updateGeometry() self.commands = self.cs+self.commands + def load_data(self, data=[]): + self.entries = data + self.selected = list(map(lambda x:False, self.entries)) + def sortByColumn(self, col): self.entries.sort(key=lambda k: k.get(col,"")) # key=dict.get(col)) self.selected = list(map(lambda x: False, self.selected)) @@ -255,6 +267,7 @@ class trashBrowser(browserWindow): ('Title',60,None)] cs = [(' r', 'restore selected'), (' d', 'delete selected')] + # redefinable functions def viewSelection(self,book): @@ -282,8 +295,7 @@ class trashBrowser(browserWindow): db.deleteBooks(books) def refreshBooks(self): - self.entries = db.getRemovedBooks() - self.selected = list(map(lambda x:False, self.entries)) + self.load_data(db.getRemovedBooks()) def handleInput(self,ch): browserWindow.handleInput(self,ch) @@ -320,6 +332,7 @@ class bookBrowser(browserWindow): ('Title',60,None)] cs = [(' u', 'update'), (' d', 'delete selected')] + # redefinable functions def updateSelection(self,book): @@ -362,19 +375,17 @@ class bookBrowser(browserWindow): db.removeBooks(books) def refreshBooks(self): - self.entries = db.getBooks() - self.selected = list(map(lambda x:False, self.entries)) + self.load_data(db.get_books()) def refreshBooksInCategory(self,cat): - self.entries = db.getBooksByCategory(cat) - self.selected = list(map(lambda x:False, self.entries)) + self.load_data(db.getBooksByCategory(cat)) def handleInput(self,ch): browserWindow.handleInput(self,ch) if ch == 117: #update on 'u' book = self.entries[self.hl] self.updateSelection(book) - self.entries[self.hl]=db.getBookByID(book['id']) + self.entries[self.hl]=db.get_book(book['id']) self.refresh() elif ch == 10: book = self.entries[self.hl] @@ -400,23 +411,20 @@ class categoryBrowser(browserWindow): columnDefs = [('Category',100,None)] cs = [(' a', 'add category'), (' d', 'delete selected')] - def refreshCategories(self): - self.entries = db.getCategories() + self.load_data(db.getCategories()) self.sortByColumn('category') - self.selected = list(map(lambda x:False, self.entries)) def addCategory(self): w = curses.newwin(1,1,10,10) cf = CategoryForm(w,self.hb) self.centreChild(w) - cats = cf.event_loop() - for c in cats: - db.addCategory(c) + cat = cf.event_loop() + db.addCategory(cat) cf.clear() def viewCategory(self): - w = curses.newwin(20,80,20,20) + w = curses.newwin(3,5) b = bookBrowser(w,self.hb) self.centreChild(w) b.refreshBooksInCategory(self.entries[self.hl]) diff --git a/checkout.py b/checkout.py new file mode 100644 index 0000000..02227c2 --- /dev/null +++ b/checkout.py @@ -0,0 +1,99 @@ +import sys +import curses +from form import FormWindow,BookForm +import db_layer as db + + +class BookIDForm(FormWindow): + caption = "Enter the book ID" + blabel = "Check" + labels = ["Book ID"] + + def _return_values(self): + if self._confirm_book(): + return self.entries[0].value + else: + return False + + def _confirm_book(self): + self.clear() + bookid = self.entries[0].value + book = db.get_book(bookid) + bf = BookForm(self.w, self.hb, book, width=self.mx-10) + (y,x) = self.w.getbegyx() + (r,c) = self.w.getmaxyx() + self.w.mvwin( y+(self.my-r)//2,x+(self.mx-c)//2) + bf.caption='Confirm the Book '+str(bookid) + bf.blabel='Correct' + result = bf.event_loop() + bf.clear() + if result: + return True + + +class UWIDForm(FormWindow): + caption = "Enter the Patron's username" + blabel = "Next" + labels = ["Username"] + + def _return_values(self): + return self.entries[0].value + +class FinalCheck(FormWindow): + caption = "Is this information correct?" + blabel = "Check Out" + labels = ["Username", "Book ID"] + + def _return_values(self): + return True + +def checkout_procedure(w, hb, cy, cx, mx): + """Procedure to check out a book + + w: ncurses window for the routine + cy,cx: centre coordinates of the screen + mx: max width of screen + """ + # Get the book ID + step1 = BookIDForm(w,hb,width=mx-20) + (r,c)=w.getmaxyx() + w.mvwin(cy-r//2,cx-c//2) + book_id = step1.event_loop() + step1.clear() + if not(book_id): + return + + # Get the uwid + step2 = UWIDForm(w,hb,width=mx-20) + (r,c)=w.getmaxyx() + w.mvwin(cy-r//2,cx-c//2) + username = step2.event_loop() + step2.clear() + if not(username): + return + + # Confirm the result + step3 = FinalCheck(w,hb,book={"username":username,"book id":book_id}, width=mx-20) + (r,c)=w.getmaxyx() + w.mvwin(cy-r//2,cx-c//2) + correct = step3.event_loop() + step3.clear() + if correct: + db.checkout_book(book_id,username) + +def return_procedure(w, hb, cy, cx, mx): + """Procedure to return a book + + w: ncurses window for the routine + cy,cx: centre coordinates of the screen + mx: max width of screen + """ + # Get the book ID + step1 = BookIDForm(w,hb,width=mx-20) + (r,c)=w.getmaxyx() + w.mvwin(cy-r//2,cx-c//2) + book_id = step1.event_loop() + step1.clear() + if book_id: + db.return_book(book_id) + diff --git a/db_layer.py b/db_layer.py index 0d9111b..47ecf96 100644 --- a/db_layer.py +++ b/db_layer.py @@ -111,7 +111,7 @@ def updateBook(book, bookID): conn.commit() c.close() -def getBooks(): +def get_books(): conn = sqlite3.connect(_catalogue_db_file) c = conn.cursor() query = "SELECT * FROM "+_book_table+" WHERE deleted=0;" @@ -144,7 +144,7 @@ def getRemovedBooks(): c.close() return books -def getBookByID(bookid): +def get_book(bookid): conn = sqlite3.connect(_catalogue_db_file) c = conn.cursor() query = "SELECT * FROM "+_book_table+" WHERE id = "+str(bookid)+";" @@ -346,7 +346,7 @@ def get_onshelf_books(): " LEFT JOIN co."+_checkout_table+ " USING (id) WHERE uwid ISNULL;") c.execute(query) - books = [_query_to_book_checkout(b) for b in c] + books = [_query_to_book(b) for b in c] c.close() return books diff --git a/form.py b/form.py index 8e927bf..d084c75 100644 --- a/form.py +++ b/form.py @@ -322,4 +322,4 @@ class CategoryForm(FormWindow): labels = ["Category"] def _return_values(self): - return self.entries + return self.entries[0].value diff --git a/librarian.py b/librarian.py index 9415321..edabe4c 100755 --- a/librarian.py +++ b/librarian.py @@ -8,6 +8,8 @@ import help_bar as helpBar import book_data +import checkout as co + stdscr=0 hb=0 @@ -20,11 +22,14 @@ def menutest(s, l): stdscr=s curses.curs_set(0) (rows,cols)=stdscr.getmaxyx() + # set the default for the browser windows + browser.browserWindow._default_height = rows-10 + browser.browserWindow._default_width = cols-10 bar = curses.newwin(1,cols-2,rows-1,1) hb = helpBar.helpBar(bar) hb.command=menu_commands hb.refresh() - w = curses.newwin(10,40,(rows-10)//2, (cols-40)//2) + w = curses.newwin(15,40,(rows-10)//2, (cols-40)//2) menu(w, l) @@ -94,31 +99,61 @@ def addForm(): if len(book)!=0: db.addBook(book) -def updateMenu(): - w=curses.newwin(1,50,10,10) - w.addstr("I will be used to update or modify book records") - w.refresh() +def browseMenu(): + w=curses.newwin(3,5) + b = browser.bookBrowser(w,hb) + (r,c) = w.getmaxyx() + (my,mx)=stdscr.getmaxyx() + w.mvwin((my-r)//2 -2, (mx-c)//2) + b.refreshBooks() + b.eventLoop() + b.clear() def trashMenu(): - (my,mx)=stdscr.getmaxyx() w=curses.newwin(3,5) - b = browser.trashBrowser(w,hb,my-10,mx-10) + b = browser.trashBrowser(w,hb) (r,c) = w.getmaxyx() + (my,mx)=stdscr.getmaxyx() w.mvwin((my-r)//2 -2, (mx-c)//2) b.refreshBooks() b.eventLoop() b.clear() -def browseMenu(): - (my,mx)=stdscr.getmaxyx() +def checkedout_menu(): w=curses.newwin(3,5) - b = browser.bookBrowser(w,hb, my-10, mx-10) + b = browser.bookBrowser(w,hb) (r,c) = w.getmaxyx() + (my,mx)=stdscr.getmaxyx() w.mvwin((my-r)//2 -2, (mx-c)//2) - b.refreshBooks() + b.load_data(db.get_checkedout_books()) + b.columnDefs = [("id",0,3), + ("uwid",0,8), + ("date",0,10), + ("title",100,None)] + b.calcColWidths() b.eventLoop() b.clear() +def onshelf_menu(): + w=curses.newwin(3,5) + b = browser.bookBrowser(w,hb) + (r,c) = w.getmaxyx() + (my,mx)=stdscr.getmaxyx() + w.mvwin((my-r)//2 -2, (mx-c)//2) + b.load_data(db.get_onshelf_books()) + b.eventLoop() + b.clear() + +def co_menu(): + w=curses.newwin(1,1) + (my,mx)=stdscr.getmaxyx() + co.checkout_procedure(w,hb,my//2,mx//2,mx) + +def return_menu(): + w=curses.newwin(1,1) + (my,mx)=stdscr.getmaxyx() + co.return_procedure(w,hb,my//2,mx//2,mx) + def catMenu(): (my,mx)=stdscr.getmaxyx() w=curses.newwin(3,5) @@ -138,6 +173,12 @@ if __name__ == "__main__": ("Categories", catMenu), ("View Trash", trashMenu), ("",exit), + ("Check Out a Book", co_menu), + ("Return a Book", return_menu), + ("",exit), + ("View Checked Out Books", checkedout_menu), + ("View On Shelf Books", onshelf_menu), + ("",exit), ("Exit", exit)] curses.wrapper(menutest, m)