291 lines
9.4 KiB
Python
291 lines
9.4 KiB
Python
import urwid
|
|
from ceo import members
|
|
from ceo.urwid import search
|
|
from ceo.urwid.widgets import *
|
|
from ceo.urwid.window import *
|
|
|
|
import ceo.library as lib
|
|
|
|
|
|
|
|
def library(data):
|
|
menu = make_menu([
|
|
("Checkout Book", checkout_book, None),
|
|
("Return Book", return_book, None),
|
|
("Search Books", search_books, None),
|
|
("Add Book", add_book, None),
|
|
#("Remove Book", remove_book, None),
|
|
("Back", raise_back, None),
|
|
])
|
|
push_window(menu, "Library")
|
|
|
|
def checkout_book(data):
|
|
"should only search signed in books"
|
|
view_books(lib.search(signedout=False))
|
|
|
|
def return_book(data):
|
|
"should bring up a searchbox of all the guys first"
|
|
view_books(lib.search(signedout=True))
|
|
|
|
def search_books(data):
|
|
push_window(urwid.Filler(SearchPage(), valign='top'), "Search Books")
|
|
|
|
def view_book(book):
|
|
"this should develop into a full fledged useful panel for doing stuff with books. for now it's not."
|
|
push_window(urwid.Filler(BookPage(book), valign='top'), "Book detail")
|
|
|
|
def view_books(books):
|
|
#XXX should not use a hardcoded 20 in there, should grab the value from the width of the widget
|
|
#TODO: this should take the search arguments, and stash them away, and everytime you come back to this page it should refresh itself
|
|
widgets = []
|
|
for b in books:
|
|
widgets.append(urwid.AttrWrap(ButtonText(view_book, b, str(b)), None, 'selected'))
|
|
widgets.append(urwid.Divider())
|
|
push_window(urwid.ListBox(widgets))
|
|
|
|
def add_book(data):
|
|
push_wizard("Add Book", [AddBookPage])
|
|
|
|
#def remove_book(data):
|
|
# pass
|
|
|
|
|
|
def parse_commaranges(s):
|
|
"""parse a string into a list of numbers"""
|
|
"""Fixme: this should be in a different module"""
|
|
def numbers(section):
|
|
if "-" in section:
|
|
range_ = section.split("-")
|
|
assert len(range_) == 2
|
|
start = int(range_[0])
|
|
end = int(range_[1])
|
|
return range(start, end+1) #+1 to be inclusive of end
|
|
else:
|
|
return [int(section)]
|
|
|
|
l = []
|
|
for y in s.split(","):
|
|
l.extend(numbers(y))
|
|
return l
|
|
|
|
|
|
class AddBookPage(WizardPanel):
|
|
def init_widgets(self):
|
|
self.author = SingleEdit("Author: ")
|
|
self.title = SingleEdit("Title: ")
|
|
self.year = SingleIntEdit("Year(s): ")
|
|
self.widgets = [
|
|
urwid.Text("Add Book"),
|
|
urwid.Divider(),
|
|
self.author,
|
|
self.title,
|
|
self.year,
|
|
]
|
|
|
|
def check(self):
|
|
author = self.author.get_edit_text()
|
|
if author == "":
|
|
author = None #null it so that searching ignores
|
|
title = self.title.get_edit_text()
|
|
if title == "":
|
|
title = None
|
|
try:
|
|
year = self.year.get_edit_text()
|
|
if year == "":
|
|
year = None
|
|
else:
|
|
year = int(year)
|
|
except:
|
|
self.focus_widget(self.year)
|
|
set_status("Invalid year")
|
|
return True
|
|
lib.add(author, title, year)
|
|
raise_back()
|
|
|
|
|
|
|
|
class SearchPage(urwid.WidgetWrap):
|
|
"""
|
|
TODO: need to be able to jump to "search" button quickly; perhaps trap a certain keypress?
|
|
"""
|
|
def __init__(self):
|
|
self.author = SingleEdit("Author: ")
|
|
self.title = SingleEdit("Title: ")
|
|
self.year = SingleEdit("Year(s): ")
|
|
self.ISBN = SingleEdit("ISBN: ")
|
|
self.description = urwid.Edit("Description: ", multiline=True)
|
|
self.signedout = urwid.CheckBox(": Checked Out")
|
|
self.ok = urwid.Button("Search", self.search)
|
|
self.back = urwid.Button("Back", raise_back)
|
|
widgets = [
|
|
#urwid.Text("Search Library"),
|
|
#urwid.Divider(),
|
|
self.author,
|
|
self.title,
|
|
self.year,
|
|
self.ISBN,
|
|
self.description,
|
|
self.signedout,
|
|
urwid.Divider(),
|
|
urwid.Text("String fields are regexes.\nYear is a comma-separated list or a hyphen-separated range")
|
|
]
|
|
buttons = urwid.GridFlow([self.ok, self.back], 10, 3, 1, align='right')
|
|
urwid.WidgetWrap.__init__(self, urwid.Pile([urwid.Pile(widgets), buttons]))
|
|
|
|
def search(self, *sender):
|
|
author = self.author.get_edit_text()
|
|
if author == "":
|
|
author = None #null it so that searching ignores
|
|
title = self.title.get_edit_text()
|
|
if title == "":
|
|
title = None
|
|
try:
|
|
years = self.year.get_edit_text()
|
|
if years == "":
|
|
years = None
|
|
else:
|
|
#try to parse the year field
|
|
years = parse_commaranges( years )
|
|
except:
|
|
raise
|
|
self.focus_widget(self.year)
|
|
set_status("Invalid year")
|
|
return True
|
|
ISBN = self.ISBN.get_edit_text()
|
|
if ISBN == "": ISBN = None
|
|
description = self.description.get_edit_text()
|
|
if description == "": description = None
|
|
signedout = self.signedout.get_state()
|
|
view_books(lib.search(author, title, years, ISBN, description, signedout))
|
|
|
|
|
|
|
|
#DONTUSE
|
|
class CheckoutPage(urwid.WidgetWrap):
|
|
def __init__(self, book):
|
|
self.book = SingleEdit("Book: ") #this needs to be a widget that when you click on it, it takes you to the search_books pane, lets you pick a book, and then drops you back here
|
|
self.user = SingleEdit("Checkoutee: ")
|
|
self.widgets = [
|
|
urwid.Text("Checkout A Book"),
|
|
urwid.Divider(),
|
|
self.book,
|
|
self.user,
|
|
]
|
|
urwid.WidgetWrap.__init__(self, urwid.Pile(self.widgets))
|
|
|
|
#DONTUSE
|
|
class ConfirmDialog(urwid.WidgetWrap):
|
|
def __init__(self, msg):
|
|
raise NotImplementedError
|
|
|
|
#DONTUSE
|
|
def Confirm(msg):
|
|
#this should be in widgets.py
|
|
push_window(ConfirmDialog(msg))
|
|
|
|
#DONTUSE
|
|
class InputDialog(urwid.WidgetWrap):
|
|
def __init__(self, msg=None):
|
|
msg = urwid.Text(msg)
|
|
self.input = SingleEdit("")
|
|
ok = urwid.Button("OK", self.ok)
|
|
cancel = urwid.Button("Cancel", self.cancel)
|
|
buttons = urwid.Columns([ok, cancel])
|
|
display = urwid.Pile([msg, self.input, buttons])
|
|
urwid.WidgetWrap.__init__(self, display)
|
|
def ok():
|
|
self.result = self.input.get_edit_text()
|
|
raise Abort() #break out of the inner event loop
|
|
def cancel():
|
|
self.result = None
|
|
raise Abort()
|
|
|
|
#DONTUSE
|
|
def urwid_input(msg):
|
|
#this should be in widgets.py
|
|
dialog = InputDialog(msg)
|
|
push_window(dialog)
|
|
event_loop(urwid.main.ui) #HACK
|
|
return dialog.result
|
|
|
|
|
|
def do_delete(book):
|
|
if Confirm("Do you wish to delete %r?" % book):
|
|
lib.delete(book)
|
|
|
|
class BookPageBase(urwid.WidgetWrap):
|
|
def __init__(self):
|
|
self.author = SingleEdit("Author: ")
|
|
self.title = SingleEdit("Title: ")
|
|
self.year = SingleIntEdit("Year: ")
|
|
self.ISBN = urwid.Text("ISBN: ")
|
|
self.description = urwid.Edit("Description: ", multiline=True)
|
|
|
|
buttons = urwid.GridFlow(self._init_buttons(), 13, 2, 1, 'center')
|
|
display = urwid.Pile([self.author, self.title, self.year, self.ISBN, self.description,] +
|
|
self._init_widgets() +
|
|
[urwid.Divider(), buttons])
|
|
urwid.WidgetWrap.__init__(self, display)
|
|
self.refresh()
|
|
|
|
def _init_widgets(self):
|
|
return []
|
|
def _init_buttons(self):
|
|
return []
|
|
def refresh(self, *sender):
|
|
"""update the widgets from the data model"""
|
|
self.author.set_edit_text(self._book.author)
|
|
self.title.set_edit_text(self._book.title)
|
|
self.year.set_edit_text(str(self._book.year))
|
|
self.ISBN.set_text("ISBN: " + self._book.ISBN)
|
|
self.description.set_edit_text(self._book.description)
|
|
|
|
|
|
class BookPage(BookPageBase):
|
|
def __init__(self, book):
|
|
self._book = book
|
|
BookPageBase.__init__(self)
|
|
def _init_widgets(self):
|
|
self.checkout_label = urwid.Text("")
|
|
return [self.checkout_label]
|
|
def _init_buttons(self):
|
|
save = urwid.Button("Save", self.save)
|
|
self.checkout_button = urwid.Button("", self.checkout)
|
|
back = urwid.Button("Back", raise_back)
|
|
remove = urwid.Button("Delete", self.delete)
|
|
return [back, self.checkout_button, save, remove]
|
|
|
|
#all these *senders are to allow these to be used as event handlers or just on their own
|
|
def refresh(self, *sender):
|
|
BookPageBase.refresh(self, *sender)
|
|
if self._book.signout is None:
|
|
self.checkout_label.set_text("Checked In")
|
|
self.checkout_button.set_label("Check Out")
|
|
else:
|
|
self.checkout_label.set_text(self._book.signout._repr_())
|
|
self.checkout_button.set_label("Check In")
|
|
|
|
def save(self, *sender):
|
|
self._book.author = self.author.get_edit_text()
|
|
self._book.title = self.title.get_edit_text()
|
|
yeartmp = self.year.get_edit_text()
|
|
if yeartmp is not None: yeartmp = int(yeartmp)
|
|
self._book.year = yeartmp
|
|
#self._book.ISBN = .... #no... don't do this...
|
|
self._book.description = self.description.get_edit_text()
|
|
lib.save(self._book)
|
|
self.refresh()
|
|
|
|
def checkout(self, *sender):
|
|
username = "nguenthe"
|
|
self._book.sign_out(username)
|
|
self.save()
|
|
|
|
def checkin(self, *sender):
|
|
self._book.sign_in()
|
|
self.save()
|
|
|
|
def delete(self, *sender):
|
|
lib.delete(self._book)
|
|
raise_back()
|