Cleaned files, started to follow naming convention
This commit is contained in:
parent
b6ce427f06
commit
45dafba38a
23
TODO
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:
|
||||
|
|
|
@ -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…
Reference in New Issue