pyceo-broken/ceo/urwid/library.py

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()