Finished changing over to new form.py
This commit is contained in:
parent
a7c29c5df0
commit
18058ac98c
|
@ -1,7 +1,7 @@
|
||||||
import sys
|
import sys
|
||||||
import curses
|
import curses
|
||||||
import db_layer as db
|
import db_layer as db
|
||||||
from gui import BookForm,CategoryForm
|
from form import BookForm,CategoryForm
|
||||||
|
|
||||||
class browserWindow:
|
class browserWindow:
|
||||||
hl=0
|
hl=0
|
||||||
|
|
400
form.py
400
form.py
|
@ -1,202 +1,285 @@
|
||||||
import curses
|
import curses
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
class formWindow:
|
|
||||||
|
class TextEntry:
|
||||||
|
|
||||||
|
"""A part of a window that handles text entry.
|
||||||
|
Properties:
|
||||||
|
value holds the string that was entered
|
||||||
|
|
||||||
|
Public Methods:
|
||||||
|
set_geom(row,column,width) Sets the geometry in the window
|
||||||
|
set_value(string) Set the value and redraw
|
||||||
|
gain_focus() Gives it focus, moving cursor and changing the drawing
|
||||||
|
lose_focus() Takes focus, moving cursor to start, changing drawing
|
||||||
|
handle_input(ch) Pass this the ncurses key, and it manages input
|
||||||
|
redraw() Redraw the text entry (should never need to do this
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Public
|
||||||
|
value = "" # Use the set_value function to set, but retrieve with value
|
||||||
|
|
||||||
|
# Should be Private
|
||||||
|
cursor = 0
|
||||||
|
start = 0
|
||||||
|
focus = False
|
||||||
|
x = 0
|
||||||
|
y = 0
|
||||||
|
width = 10
|
||||||
|
|
||||||
|
# Public methods
|
||||||
|
def __init__(self, parent_window, value=""):
|
||||||
|
self.w = parent_window
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def set_geom(self,y,x,width):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
def set_value(self,v):
|
||||||
|
self.value=v
|
||||||
|
self.cursor=len(v)
|
||||||
|
self.redraw()
|
||||||
|
|
||||||
|
def gain_focus(self):
|
||||||
|
#sys.stderr.write('I have focus!\n')
|
||||||
|
self.focus = True
|
||||||
|
self._mv_cursor(+len(self.value))
|
||||||
|
self.start = max(0,self.cursor-self.width)
|
||||||
|
self.redraw()
|
||||||
|
|
||||||
|
def lose_focus(self):
|
||||||
|
self.focus = False
|
||||||
|
self.cursor = 0
|
||||||
|
self.start = 0
|
||||||
|
self.redraw()
|
||||||
|
|
||||||
|
def handle_input(self,ch):
|
||||||
|
if ch==curses.KEY_LEFT:
|
||||||
|
self._mv_cursor(-1)
|
||||||
|
elif ch==curses.KEY_HOME:
|
||||||
|
self._set_cursor(0)
|
||||||
|
elif ch==curses.KEY_RIGHT:
|
||||||
|
self._mv_cursor(+1)
|
||||||
|
elif ch==curses.KEY_END:
|
||||||
|
self._set_cursor(len(self.value))
|
||||||
|
elif ch>=32 and ch<=126:
|
||||||
|
self._insert(curses.keyname(ch).decode('utf-8'))
|
||||||
|
elif ch==curses.KEY_BACKSPACE:
|
||||||
|
self._backspace()
|
||||||
|
elif ch==curses.KEY_DC:
|
||||||
|
self._delete()
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Private functions
|
||||||
|
def _mv_cursor(self,delta):
|
||||||
|
self._set_cursor(self.cursor + delta)
|
||||||
|
|
||||||
|
def _set_cursor(self, new_c):
|
||||||
|
self.cursor = max(0, min(len(self.value), new_c))
|
||||||
|
self.start = max(0,self.cursor-self.width+1)
|
||||||
|
self.redraw()
|
||||||
|
# Place the drawn cursor in the correct spot
|
||||||
|
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._mv_cursor(+1)
|
||||||
|
|
||||||
|
def _backspace(self):
|
||||||
|
if self.cursor>0:
|
||||||
|
c = self.cursor
|
||||||
|
self.value=self.value[:c-1] + self.value[c:]
|
||||||
|
self._mv_cursor(-1)
|
||||||
|
|
||||||
|
def _delete(self):
|
||||||
|
c = self.cursor
|
||||||
|
self.value = self.value[:c] + self.value[c+1:]
|
||||||
|
self._mv_cursor(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FormWindow:
|
||||||
|
|
||||||
|
"""General class for a Form Window.
|
||||||
|
|
||||||
|
To use, make the window for it, call the constructor, then call event_loop.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Private variables
|
||||||
mx = my = 0
|
mx = my = 0
|
||||||
hl = 0
|
hl = 0
|
||||||
bt = -1
|
bt = -1
|
||||||
cursor = 0
|
|
||||||
textStart = 0
|
|
||||||
left = 0
|
left = 0
|
||||||
top = 2
|
top = 2
|
||||||
row = 2
|
row = 2
|
||||||
caption = "Form"
|
caption = "Form"
|
||||||
blabel = "Done"
|
blabel = "Done"
|
||||||
labels = ["label1"]
|
labels = ["label1"]
|
||||||
entries = []
|
|
||||||
|
|
||||||
commands = [('pU', 'top'),('pD', 'bottom'),('Es', 'cancel')]
|
commands = [('pU', 'top'),('pD', 'bottom'),('Es', 'cancel')]
|
||||||
|
|
||||||
|
|
||||||
|
# Public functions
|
||||||
|
def __init__(self,window,helpbar,book={}):
|
||||||
|
self.w = window
|
||||||
|
self.w.resize(len(self.labels)+6,50)
|
||||||
|
self.hb = helpbar
|
||||||
|
self._make_entries()
|
||||||
|
self._update_geometry()
|
||||||
|
self._set_entries(book)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.w.erase()
|
self.w.erase()
|
||||||
self.w.refresh()
|
self.w.refresh()
|
||||||
|
|
||||||
def __init__(self,window,helpbar,book={}):
|
def event_loop(self):
|
||||||
self.w = window
|
|
||||||
self.w.resize(len(self.labels)+6,50)
|
|
||||||
self.hb = helpbar
|
|
||||||
self.updateEntries(book)
|
|
||||||
self.updateGeometry()
|
|
||||||
|
|
||||||
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
|
|
||||||
self.width = self.mx-self.left-2
|
|
||||||
self.top = 2
|
|
||||||
# next, the buttons
|
|
||||||
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):
|
|
||||||
self.entries=[]
|
|
||||||
for l in self.labels:
|
|
||||||
if l.lower() in book:
|
|
||||||
self.entries.append(str(book[l.lower()]))
|
|
||||||
else:
|
|
||||||
self.entries.append("")
|
|
||||||
|
|
||||||
def refresh(self):
|
|
||||||
self.hb.commands = self.commands
|
|
||||||
self.hb.refresh()
|
|
||||||
self.updateGeometry()
|
|
||||||
self.w.box()
|
|
||||||
self.w.addstr(0,(self.mx-len(self.caption))//2,self.caption)
|
|
||||||
r=self.top
|
|
||||||
for l in self.labels:
|
|
||||||
c = self.left-len(l)-2
|
|
||||||
self.w.addstr(r,c,l+":")
|
|
||||||
self.drawRow(r-self.top)
|
|
||||||
r+=1
|
|
||||||
self.w.addstr(r+1,self.bcol[0], "<cancel> <"+self.blabel+">")
|
|
||||||
self.w.refresh()
|
|
||||||
|
|
||||||
def drawRow(self,row):
|
|
||||||
r = self.top + row
|
|
||||||
self.w.addnstr(r,self.left, self.entries[row]+" "*self.width, self.width)
|
|
||||||
|
|
||||||
def highlight(self):
|
|
||||||
if self.bt == -1:
|
|
||||||
self.w.chgat(self.row, self.left, self.width, curses.A_UNDERLINE)
|
|
||||||
self.mvCursor(0)
|
|
||||||
curses.curs_set(1)
|
|
||||||
else:
|
|
||||||
self.w.chgat(self.row, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
|
|
||||||
curses.curs_set(0)
|
|
||||||
|
|
||||||
def unHighlight(self):
|
|
||||||
self.w.chgat(self.row,1,self.mx-2,curses.A_NORMAL)
|
|
||||||
|
|
||||||
def mvHighlight(self,delta):
|
|
||||||
self.unHighlight()
|
|
||||||
new = self.hl+delta
|
|
||||||
new = max(new,0)
|
|
||||||
new = min(new,len(self.labels)) # the extra is for the buttons
|
|
||||||
self.hl = new
|
|
||||||
self.row = self.hl + self.top
|
|
||||||
if new == len(self.labels):
|
|
||||||
self.bt =1
|
|
||||||
self.bt = min(self.bt,1)
|
|
||||||
self.row+=1
|
|
||||||
else:
|
|
||||||
self.mvCursor(+len(self.entries[self.hl]))
|
|
||||||
self.bt=-1
|
|
||||||
self.highlight()
|
|
||||||
|
|
||||||
def mvCursor(self,delta):
|
|
||||||
n = self.cursor + delta
|
|
||||||
n = max(n,0)
|
|
||||||
n = min(n,len(self.entries[self.hl]))
|
|
||||||
self.cursor = n
|
|
||||||
col = self.left + self.cursor - self.textStart
|
|
||||||
if col >= self.left and col < self.left+self.width:
|
|
||||||
self.w.move(self.row,col)
|
|
||||||
|
|
||||||
def insert(self,ch):
|
|
||||||
c = self.cursor
|
|
||||||
#sys.stderr.write(str(type(ch)))
|
|
||||||
self.entries[self.hl]=self.entries[self.hl][:c] +ch.decode('utf-8')+ self.entries[self.hl][c:]
|
|
||||||
self.drawRow(self.hl)
|
|
||||||
self.mvCursor(+1)
|
|
||||||
self.highlight()
|
|
||||||
|
|
||||||
def backspace(self):
|
|
||||||
if self.cursor>0:
|
|
||||||
self.entries[self.hl]=self.entries[self.hl][:self.cursor-1] + self.entries[self.hl][self.cursor:]
|
|
||||||
self.drawRow(self.hl)
|
|
||||||
self.mvCursor(-1)
|
|
||||||
self.highlight()
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
c = self.cursor
|
|
||||||
self.entries[self.hl]=self.entries[self.hl][:c] + self.entries[self.hl][c+1:]
|
|
||||||
self.drawRow(self.hl)
|
|
||||||
self.highlight()
|
|
||||||
|
|
||||||
def returnValues(self):
|
|
||||||
book = {}
|
|
||||||
for k,v in zip(self.labels, self.entries):
|
|
||||||
if v!="" and k.lower()!="publish date":
|
|
||||||
book[k.lower()]=v
|
|
||||||
return book
|
|
||||||
|
|
||||||
def eventLoop(self):
|
|
||||||
self.w.keypad(1)
|
self.w.keypad(1)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
self.mvCursor(+len(self.entries[self.hl]))
|
self.hl=0;
|
||||||
self.highlight()
|
self.entries[self.hl].gain_focus()
|
||||||
|
|
||||||
ch = self.w.getch()
|
ch = self.w.getch()
|
||||||
while ch != 27:
|
while ch != 27:
|
||||||
self.handleInput(ch)
|
#sys.stderr.write(curses.keyname(ch).decode('utf-8'))
|
||||||
|
self.handle_input(ch)
|
||||||
if ch==10 or ch==curses.KEY_ENTER:
|
if ch==10 or ch==curses.KEY_ENTER:
|
||||||
if self.bt==0:
|
if self.bt==0:
|
||||||
return {}
|
return {}
|
||||||
elif self.bt==1:
|
elif self.bt==1:
|
||||||
return self.returnValues()
|
return self.return_values()
|
||||||
self.mvHighlight(+1)
|
else:
|
||||||
|
self._mv_focus(+1)
|
||||||
self.w.refresh()
|
self.w.refresh()
|
||||||
ch = self.w.getch()
|
ch = self.w.getch()
|
||||||
curses.curs_set(0)
|
curses.curs_set(0)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def _make_entries(self):
|
||||||
|
self.entries = []
|
||||||
|
for e in range(len(self.labels)):
|
||||||
|
self.entries.append(TextEntry(self.w))
|
||||||
|
|
||||||
def handleInput(self,ch):
|
def _update_geometry(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].set_geom(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 _set_entries(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._update_geometry()
|
||||||
|
self.redraw()
|
||||||
|
|
||||||
|
def _highlight_button(self):
|
||||||
|
self.w.chgat(self.brow, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
|
||||||
|
curses.curs_set(0)
|
||||||
|
|
||||||
|
def _unhighlight_button(self):
|
||||||
|
self.w.chgat(self.brow,1,self.mx-2,curses.A_NORMAL)
|
||||||
|
|
||||||
|
def _mv_focus(self,delta):
|
||||||
|
if self.bt==-1:
|
||||||
|
self.entries[self.hl].lose_focus()
|
||||||
|
else:
|
||||||
|
self._unhighlight_button()
|
||||||
|
new = self.hl+delta
|
||||||
|
new = max(0, min(len(self.labels), new)) # the extra is for the buttons
|
||||||
|
self.hl = new
|
||||||
|
if new == len(self.labels):
|
||||||
|
self.bt = 1
|
||||||
|
self.bt = min(self.bt,1)
|
||||||
|
self._highlight_button()
|
||||||
|
else:
|
||||||
|
self.bt=-1
|
||||||
|
self.entries[self.hl].gain_focus()
|
||||||
|
|
||||||
|
|
||||||
|
def _return_values(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 handle_input(self,ch):
|
||||||
if ch==curses.KEY_UP:
|
if ch==curses.KEY_UP:
|
||||||
self.mvHighlight(-1)
|
self._mv_focus(-1)
|
||||||
elif ch==curses.KEY_PPAGE:
|
elif ch==curses.KEY_PPAGE:
|
||||||
self.mvHighlight(-len(self.labels))
|
self._mv_focus(-len(self.labels))
|
||||||
elif ch==curses.KEY_DOWN:
|
elif ch==curses.KEY_DOWN:
|
||||||
self.mvHighlight(+1)
|
self._mv_focus(+1)
|
||||||
elif ch==curses.KEY_NPAGE:
|
elif ch==curses.KEY_NPAGE:
|
||||||
self.mvHighlight(+len(self.labels))
|
self._mv_focus(+len(self.labels))
|
||||||
|
|
||||||
elif ch==curses.KEY_LEFT:
|
elif ch==curses.KEY_LEFT:
|
||||||
if self.bt==-1:
|
if self.bt==-1:
|
||||||
self.mvCursor(-1)
|
self.entries[self.hl].handle_input(ch)
|
||||||
else:
|
else:
|
||||||
self.unHighlight()
|
self._unhighlight_button()
|
||||||
self.bt=0
|
self.bt=0
|
||||||
self.highlight()
|
self._highlight_button()
|
||||||
elif ch==curses.KEY_HOME:
|
elif ch==curses.KEY_HOME:
|
||||||
if self.bt==-1:
|
if self.bt==-1:
|
||||||
self.mvCursor(-len(self.entries[self.hl]))
|
self._mv_cursor(-len(self.entries[self.hl]))
|
||||||
elif ch==curses.KEY_RIGHT:
|
elif ch==curses.KEY_RIGHT:
|
||||||
if self.bt==-1:
|
if self.bt==-1:
|
||||||
self.mvCursor(+1)
|
self.entries[self.hl].handle_input(ch)
|
||||||
else:
|
else:
|
||||||
self.unHighlight()
|
self._unhighlight_button()
|
||||||
self.bt=1
|
self.bt=1
|
||||||
self.highlight()
|
self._highlight_button()
|
||||||
elif ch==curses.KEY_END:
|
else:
|
||||||
if self.bt==-1:
|
if self.bt==-1:
|
||||||
self.mvCursor(+len(self.entries[self.hl]))
|
self.entries[self.hl].handle_input(ch)
|
||||||
|
|
||||||
elif ch>=32 and ch<=126:
|
|
||||||
if self.bt==-1:
|
|
||||||
self.insert(curses.keyname(ch))
|
|
||||||
elif ch==curses.KEY_BACKSPACE:
|
|
||||||
if self.bt==-1:
|
|
||||||
self.backspace()
|
|
||||||
elif ch==curses.KEY_DC:
|
|
||||||
if self.bt==-1:
|
|
||||||
self.delete()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class bookForm(formWindow):
|
class BookForm(FormWindow):
|
||||||
caption = "Add a Book"
|
caption = "Add a Book"
|
||||||
blabel = "Add"
|
blabel = "Add"
|
||||||
labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
|
labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
|
||||||
|
@ -212,30 +295,31 @@ class bookForm(formWindow):
|
||||||
def lookup_lccn(self,lccn):
|
def lookup_lccn(self,lccn):
|
||||||
return {'lccn':lccn}
|
return {'lccn':lccn}
|
||||||
|
|
||||||
def returnBook(self):
|
def return_book(self):
|
||||||
return self.returnValues()
|
return self.return_values()
|
||||||
|
|
||||||
def handleInput(self,ch):
|
def handle_input(self,ch):
|
||||||
if ch==10 or ch==curses.KEY_ENTER:
|
if ch==10 or ch==curses.KEY_ENTER:
|
||||||
if self.hl==0: # lookup by isbn
|
if self.hl==0: # lookup by isbn
|
||||||
book = self.lookup_isbn(self.entries[0])
|
book = self.lookup_isbn(self.entries[0].value)
|
||||||
if book != {}:
|
if book != {}:
|
||||||
self.updateEntries(book)
|
#sys.stderr.write('updating entries\n')
|
||||||
|
self._set_entries(book)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
self.mvHighlight(+7)
|
self._mv_focus(+7)
|
||||||
if self.hl==1: # lookup by lccn
|
if self.hl==1: # lookup by lccn
|
||||||
book = self.lookup_lccn(self.entries[1])
|
book = self.lookup_lccn(self.entries[1].value)
|
||||||
if book != {}:
|
if book != {}:
|
||||||
self.updateEntries(book)
|
self._set_entries(book)
|
||||||
self.refresh()
|
self.refresh()
|
||||||
self.mvHighlight(+6)
|
self._mv_focus(+6)
|
||||||
else:
|
else:
|
||||||
formWindow.handleInput(self,ch)
|
FormWindow.handle_input(self,ch)
|
||||||
|
|
||||||
class categoryForm(formWindow):
|
class CategoryForm(FormWindow):
|
||||||
caption = "Add a Category"
|
caption = "Add a Category"
|
||||||
blabel = "Add"
|
blabel = "Add"
|
||||||
labels = ["Category"]
|
labels = ["Category"]
|
||||||
|
|
||||||
def returnValues(self):
|
def return_values(self):
|
||||||
return self.entries
|
return self.entries
|
||||||
|
|
324
gui.py
324
gui.py
|
@ -1,324 +0,0 @@
|
||||||
import curses
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
class TextEntry:
|
|
||||||
|
|
||||||
"""A part of a window that handles text entry.
|
|
||||||
Properties:
|
|
||||||
value holds the string that was entered
|
|
||||||
|
|
||||||
Public Methods:
|
|
||||||
set_geom(row,column,width) Sets the geometry in the window
|
|
||||||
set_value(string) Set the value and redraw
|
|
||||||
gain_focus() Gives it focus, moving cursor and changing the drawing
|
|
||||||
lose_focus() Takes focus, moving cursor to start, changing drawing
|
|
||||||
handle_input(ch) Pass this the ncurses key, and it manages input
|
|
||||||
redraw() Redraw the text entry (should never need to do this
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Public
|
|
||||||
value = "" # Use the set_value function to set, but retrieve with value
|
|
||||||
|
|
||||||
# Should be Private
|
|
||||||
cursor = 0
|
|
||||||
start = 0
|
|
||||||
focus = False
|
|
||||||
x = 0
|
|
||||||
y = 0
|
|
||||||
width = 10
|
|
||||||
|
|
||||||
def __init__(self, parent_window, value=""):
|
|
||||||
self.w = parent_window
|
|
||||||
self.value = value
|
|
||||||
|
|
||||||
def set_geom(self,y,x,width):
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.width = width
|
|
||||||
|
|
||||||
def set_value(self,v):
|
|
||||||
self.value=v
|
|
||||||
self.cursor=len(v)
|
|
||||||
self.redraw()
|
|
||||||
|
|
||||||
def gain_focus(self):
|
|
||||||
#sys.stderr.write('I have focus!\n')
|
|
||||||
self.focus = True
|
|
||||||
self._mv_cursor(+len(self.value))
|
|
||||||
self.start = max(0,self.cursor-self.width)
|
|
||||||
self.redraw()
|
|
||||||
|
|
||||||
def lose_focus(self):
|
|
||||||
self.focus = False
|
|
||||||
self.cursor = 0
|
|
||||||
self.start = 0
|
|
||||||
self.redraw()
|
|
||||||
|
|
||||||
def handle_input(self,ch):
|
|
||||||
if ch==curses.KEY_LEFT:
|
|
||||||
self._mv_cursor(-1)
|
|
||||||
elif ch==curses.KEY_HOME:
|
|
||||||
self._set_cursor(0)
|
|
||||||
elif ch==curses.KEY_RIGHT:
|
|
||||||
self._mv_cursor(+1)
|
|
||||||
elif ch==curses.KEY_END:
|
|
||||||
self._set_cursor(len(self.value))
|
|
||||||
elif ch>=32 and ch<=126:
|
|
||||||
self._insert(curses.keyname(ch).decode('utf-8'))
|
|
||||||
elif ch==curses.KEY_BACKSPACE:
|
|
||||||
self._backspace()
|
|
||||||
elif ch==curses.KEY_DC:
|
|
||||||
self._delete()
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
# Private functions
|
|
||||||
def _mv_cursor(self,delta):
|
|
||||||
self._set_cursor(self.cursor + delta)
|
|
||||||
|
|
||||||
def _set_cursor(self, new_c):
|
|
||||||
self.cursor = max(0, min(len(self.value), new_c))
|
|
||||||
self.start = max(0,self.cursor-self.width+1)
|
|
||||||
self.redraw()
|
|
||||||
# Place the drawn cursor in the correct spot
|
|
||||||
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._mv_cursor(+1)
|
|
||||||
|
|
||||||
def _backspace(self):
|
|
||||||
if self.cursor>0:
|
|
||||||
c = self.cursor
|
|
||||||
self.value=self.value[:c-1] + self.value[c:]
|
|
||||||
self._mv_cursor(-1)
|
|
||||||
|
|
||||||
def _delete(self):
|
|
||||||
c = self.cursor
|
|
||||||
self.value = self.value[:c] + self.value[c+1:]
|
|
||||||
self._mv_cursor(0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FormWindow:
|
|
||||||
|
|
||||||
"""General class for a Form Window.
|
|
||||||
|
|
||||||
To use, make the window for it, call the constructor, then call event_loop.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Private variables
|
|
||||||
mx = my = 0
|
|
||||||
hl = 0
|
|
||||||
bt = -1
|
|
||||||
left = 0
|
|
||||||
top = 2
|
|
||||||
row = 2
|
|
||||||
caption = "Form"
|
|
||||||
blabel = "Done"
|
|
||||||
labels = ["label1"]
|
|
||||||
|
|
||||||
commands = [('pU', 'top'),('pD', 'bottom'),('Es', 'cancel')]
|
|
||||||
|
|
||||||
|
|
||||||
# Public functions
|
|
||||||
def __init__(self,window,helpbar,book={}):
|
|
||||||
self.w = window
|
|
||||||
self.w.resize(len(self.labels)+6,50)
|
|
||||||
self.hb = helpbar
|
|
||||||
self._make_entries()
|
|
||||||
self._update_geometry()
|
|
||||||
self._set_entries(book)
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self.w.erase()
|
|
||||||
self.w.refresh()
|
|
||||||
|
|
||||||
def event_loop(self):
|
|
||||||
self.w.keypad(1)
|
|
||||||
self.refresh()
|
|
||||||
self.hl=0;
|
|
||||||
self.entries[self.hl].gain_focus()
|
|
||||||
|
|
||||||
ch = self.w.getch()
|
|
||||||
while ch != 27:
|
|
||||||
#sys.stderr.write(curses.keyname(ch).decode('utf-8'))
|
|
||||||
self.handle_input(ch)
|
|
||||||
if ch==10 or ch==curses.KEY_ENTER:
|
|
||||||
if self.bt==0:
|
|
||||||
return {}
|
|
||||||
elif self.bt==1:
|
|
||||||
return self.return_values()
|
|
||||||
else:
|
|
||||||
self._mv_focus(+1)
|
|
||||||
self.w.refresh()
|
|
||||||
ch = self.w.getch()
|
|
||||||
curses.curs_set(0)
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def _make_entries(self):
|
|
||||||
self.entries = []
|
|
||||||
for e in range(len(self.labels)):
|
|
||||||
self.entries.append(TextEntry(self.w))
|
|
||||||
|
|
||||||
def _update_geometry(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].set_geom(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 _set_entries(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._update_geometry()
|
|
||||||
self.redraw()
|
|
||||||
|
|
||||||
def _highlight_button(self):
|
|
||||||
self.w.chgat(self.brow, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
|
|
||||||
curses.curs_set(0)
|
|
||||||
|
|
||||||
def _unhighlight_button(self):
|
|
||||||
self.w.chgat(self.brow,1,self.mx-2,curses.A_NORMAL)
|
|
||||||
|
|
||||||
def _mv_focus(self,delta):
|
|
||||||
if self.bt==-1:
|
|
||||||
self.entries[self.hl].lose_focus()
|
|
||||||
else:
|
|
||||||
self._unhighlight_button()
|
|
||||||
new = self.hl+delta
|
|
||||||
new = max(0, min(len(self.labels), new)) # the extra is for the buttons
|
|
||||||
self.hl = new
|
|
||||||
if new == len(self.labels):
|
|
||||||
self.bt = 1
|
|
||||||
self.bt = min(self.bt,1)
|
|
||||||
self._highlight_button()
|
|
||||||
else:
|
|
||||||
self.bt=-1
|
|
||||||
self.entries[self.hl].gain_focus()
|
|
||||||
|
|
||||||
|
|
||||||
def _return_values(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 handle_input(self,ch):
|
|
||||||
if ch==curses.KEY_UP:
|
|
||||||
self._mv_focus(-1)
|
|
||||||
elif ch==curses.KEY_PPAGE:
|
|
||||||
self._mv_focus(-len(self.labels))
|
|
||||||
elif ch==curses.KEY_DOWN:
|
|
||||||
self._mv_focus(+1)
|
|
||||||
elif ch==curses.KEY_NPAGE:
|
|
||||||
self._mv_focus(+len(self.labels))
|
|
||||||
elif ch==curses.KEY_LEFT:
|
|
||||||
if self.bt==-1:
|
|
||||||
self.entries[self.hl].handle_input(ch)
|
|
||||||
else:
|
|
||||||
self._unhighlight_button()
|
|
||||||
self.bt=0
|
|
||||||
self._highlight_button()
|
|
||||||
elif ch==curses.KEY_HOME:
|
|
||||||
if self.bt==-1:
|
|
||||||
self._mv_cursor(-len(self.entries[self.hl]))
|
|
||||||
elif ch==curses.KEY_RIGHT:
|
|
||||||
if self.bt==-1:
|
|
||||||
self.entries[self.hl].handle_input(ch)
|
|
||||||
else:
|
|
||||||
self._unhighlight_button()
|
|
||||||
self.bt=1
|
|
||||||
self._highlight_button()
|
|
||||||
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 return_book(self):
|
|
||||||
return self.return_values()
|
|
||||||
|
|
||||||
def handle_input(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._set_entries(book)
|
|
||||||
self.refresh()
|
|
||||||
self._mv_focus(+7)
|
|
||||||
if self.hl==1: # lookup by lccn
|
|
||||||
book = self.lookup_lccn(self.entries[1].value)
|
|
||||||
if book != {}:
|
|
||||||
self._set_entries(book)
|
|
||||||
self.refresh()
|
|
||||||
self._mv_focus(+6)
|
|
||||||
else:
|
|
||||||
FormWindow.handle_input(self,ch)
|
|
||||||
|
|
||||||
class CategoryForm(FormWindow):
|
|
||||||
caption = "Add a Category"
|
|
||||||
blabel = "Add"
|
|
||||||
labels = ["Category"]
|
|
||||||
|
|
||||||
def return_values(self):
|
|
||||||
return self.entries
|
|
|
@ -3,7 +3,7 @@
|
||||||
import curses
|
import curses
|
||||||
import db_layer as db
|
import db_layer as db
|
||||||
import browser
|
import browser
|
||||||
import gui as form
|
import form
|
||||||
import help_bar as helpBar
|
import help_bar as helpBar
|
||||||
|
|
||||||
import book_data
|
import book_data
|
||||||
|
|
Loading…
Reference in New Issue