Cleaned files, started to follow naming convention

jessie
John Ladan 9 years ago
parent b6ce427f06
commit 45dafba38a
  1. 23
      TODO
  2. 0
      book_data.py
  3. 2
      browser.py
  4. 0
      db_layer.py
  5. 292
      gui.py
  6. 0
      help_bar.py
  7. 6
      librarian.py
  8. 0
      ncurses_tools/cursestest.py
  9. 0
      ncurses_tools/echokey.py

23
TODO

@ -2,15 +2,32 @@ _List of Desired Features_
Categories work based on selection, not just highlight
- i.e. assign categories to multiple books at once
Support UTF-8 for everything
- this may involve extra logic if books don't have the same categories beforehand
Search ignores Case
Regex Search
Choose shown columns in browser
Support for multiple copies
Text entry supports longer string
- implementation started in gui.py
Home and End navigate to top and bottom of catalogue respectively.
_Code Quality Improvements_
Document all functions
Conform to python naming conventions and code style
Make db_layer use a helper function to handle most of the database queries
_Implemented Features_
Sort by column in browser
_Bugs_
Error when entering bad ISBN e.g. 02010798X (instead of 020107981X)
- seems to be an intermittant error, likely related to polling openLibrary
When the top element shown is highlighted in the browser window, and pgUp is pressed (causing a scrollup), the bottom border of the window turns into 'qqqqqqqq'.
- does not happen when up_arrow is pressed.
_Implemented Features_
Sort by column in browser
Support UTF-8 for everything

@ -1,6 +1,6 @@
import sys
import curses
import dbLayer as db
import db_layer as db
from form import bookForm,categoryForm
class browserWindow:

292
gui.py

@ -0,0 +1,292 @@
import curses
import sys
class textEntry:
cursor = 0
start = 0
focus = False
x = 0
y = 0
width = 10
value = ""
def __init__(self, parent_window, value=""):
self.w = parent_window
self.value = value
def setGeom(self,y,x,width):
self.x = x
self.y = y
self.width = width
def redraw(self):
self.w.addnstr(self.y,self.x, self.value[self.start:]+" "*self.width, self.width)
if self.focus:
self.w.chgat(self.y, self.x, self.width, curses.A_UNDERLINE)
curses.curs_set(1)
def gainFocus(self):
sys.stderr.write('I have focus!\n')
self.focus = True
self.mvCursor(+len(self.value))
self.start = max(0,self.cursor-self.width)
self.redraw()
def loseFocus(self):
self.focus = False
self.cursor = 0
self.start = 0
self.redraw()
def mvCursor(self,delta):
n = self.cursor + delta
# make sure new position is legal
n = max(n,0)
n = min(n,len(self.value))
self.cursor = n
self.start = max(0,self.cursor-self.width+1)
self.redraw()
col = self.x + self.cursor - self.start
self.w.move(self.y,col)
def insert(self,ch):
c = self.cursor
self.value = self.value[:c] +ch+ self.value[c:]
self.mvCursor(+1)
def backspace(self):
if self.cursor>0:
c = self.cursor
self.value=self.value[:c-1] + self.value[c:]
self.mvCursor(-1)
def delete(self):
c = self.cursor
self.value = self.value[:c] + self.value[c+1:]
self.mvCursor(0)
def handle_input(self,ch):
if ch==curses.KEY_LEFT:
self.mvCursor(-1)
elif ch==curses.KEY_HOME:
self.mvCursor(-len(self.value))
elif ch==curses.KEY_RIGHT:
self.mvCursor(+1)
elif ch==curses.KEY_END:
self.mvCursor(+len(self.value))
elif ch>=32 and ch<=126:
self.insert(curses.keyname(ch))
elif ch==curses.KEY_BACKSPACE:
self.backspace()
elif ch==curses.KEY_DC:
self.delete()
class formWindow:
mx = my = 0
hl = 0
bt = -1
left = 0
top = 2
row = 2
caption = "Form"
blabel = "Done"
labels = ["label1"]
entries=[]
commands = [('pU', 'top'),('pD', 'bottom'),('Es', 'cancel')]
def clear(self):
self.w.erase()
self.w.refresh()
def __init__(self,window,helpbar,book={}):
self.w = window
self.w.resize(len(self.labels)+6,50)
self.hb = helpbar
self.makeEntries()
self.updateGeometry()
self.updateEntries(book)
def makeEntries(self):
for e in range(len(self.labels)):
self.entries.append(textEntry(self.w))
def updateGeometry(self):
(self.my, self.mx) = self.w.getmaxyx()
self.left=0
for l in self.labels:
self.left = max(len(l),self.left)
self.left += 4
width = self.mx-self.left-2
self.top = 2
for r in range(len(self.entries)):
self.entries[r].setGeom(r+self.top, self.left, width)
# next, the buttons
self.brow = self.top+len(self.labels)+1
self.bcol = [self.mx-len(self.blabel)-14, self.mx-len(self.blabel)-4]
self.bwidth = [8,len(self.blabel)+2]
def updateEntries(self,book):
e = 0
for l in self.labels:
sys.stderr.write('updating label: '+l+'\n')
if l.lower() in book:
sys.stderr.write(' '+l+' found\n')
self.entries[e].value = str(book[l.lower()])
else:
sys.stderr.write(' '+l+' notfound\n')
self.entries[e].value = ""
e += 1
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 = self.left-len(l)-2
self.w.addstr(r+self.top,c,l+":")
self.entries[r].redraw()
r+=1
self.w.addstr(self.brow,self.bcol[0], "<cancel> <"+self.blabel+">")
self.w.refresh()
def refresh(self):
self.hb.commands = self.commands
self.hb.refresh()
self.updateGeometry()
self.redraw()
def highlightButton(self):
self.w.chgat(self.brow, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
curses.curs_set(0)
def unHighlightButton(self):
self.w.chgat(self.brow,1,self.mx-2,curses.A_NORMAL)
def mvFocus(self,delta):
if self.bt==-1:
self.entries[self.hl].loseFocus()
else:
self.unHighlightButton()
new = self.hl+delta
new = max(new,0)
new = min(new,len(self.labels)) # the extra is for the buttons
self.hl = new
if new == len(self.labels):
self.bt = 1
self.bt = min(self.bt,1)
self.highlightButton()
else:
self.bt=-1
self.entries[self.hl].gainFocus()
def returnValues(self):
book = {}
for k,e in zip(self.labels, self.entries):
if v!="" and k.lower()!="publish date":
book[k.lower()]=e.value
return book
def eventLoop(self):
self.w.keypad(1)
self.refresh()
self.hl=0;
self.entries[self.hl].gainFocus()
ch = self.w.getch()
while ch != 27:
self.handleInput(ch)
if ch==10 or ch==curses.KEY_ENTER:
if self.bt==0:
return {}
elif self.bt==1:
return self.returnValues()
else:
self.mvFocus(+1)
self.w.refresh()
ch = self.w.getch()
curses.curs_set(0)
return {}
def handleInput(self,ch):
if ch==curses.KEY_UP:
self.mvFocus(-1)
elif ch==curses.KEY_PPAGE:
self.mvFocus(-len(self.labels))
elif ch==curses.KEY_DOWN:
self.mvFocus(+1)
elif ch==curses.KEY_NPAGE:
self.mvFocus(+len(self.labels))
elif ch==curses.KEY_LEFT:
if self.bt==-1:
self.entries[self.hl].handle_input(ch)
else:
self.unHighlightButton()
self.bt=0
self.highlightButton()
elif ch==curses.KEY_HOME:
if self.bt==-1:
self.mvCursor(-len(self.entries[self.hl]))
elif ch==curses.KEY_RIGHT:
if self.bt==-1:
self.entries[self.hl].handle_input(ch)
else:
self.unHighlightButton()
self.bt=1
self.highlightButton()
else:
if self.bt==-1:
self.entries[self.hl].handle_input(ch)
class bookForm(formWindow):
caption = "Add a Book"
blabel = "Add"
labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
"Publisher", "Publish Date", "Publish Year", "Publish Month", "Publish location",
"Pages", "Pagination", "Weight"]
# redefineable functions lookup is called when 'enter' is pressed on ISBN
# and returns the looked-up book. Default returns nothing
def lookup_isbn(self,isbn):
return {'isbn':isbn}
def lookup_lccn(self,lccn):
return {'lccn':lccn}
def returnBook(self):
return self.returnValues()
def handleInput(self,ch):
if ch==10 or ch==curses.KEY_ENTER:
if self.hl==0: # lookup by isbn
book = self.lookup_isbn(self.entries[0].value)
if book != {}:
sys.stderr.write('updating entries\n')
self.updateEntries(book)
self.refresh()
self.mvFocus(+7)
if self.hl==1: # lookup by lccn
book = self.lookup_lccn(self.entries[1].value)
if book != {}:
self.updateEntries(book)
self.refresh()
self.mvFocus(+6)
else:
formWindow.handleInput(self,ch)
class categoryForm(formWindow):
caption = "Add a Category"
blabel = "Add"
labels = ["Category"]
def returnValues(self):
return self.entries

@ -1,12 +1,12 @@
#!/usr/bin/env python3
import curses
import dbLayer as db
import db_layer as db
import browser
import form as form
import helpBar
import help_bar as helpBar
import bookData
import book_data
stdscr=0

Loading…
Cancel
Save