I have attached what I have so far.  What is the right way to pass
keypresses between two arbitrary widgets in my program?  The "size"
parameter seems to throw a wrench in the works.

Cheers,
Drew

On Thu, Mar 11, 2010 at 1:10 PM, Andrew Wagner <[email protected]> wrote:
> Thanks for the thorough reply Dominic!
>
> On Thu, Mar 11, 2010 at 1:03 AM, Dominic LoBue <[email protected]> wrote:
>> Drew,
>>
>> Not to rain on your parade or anything, but there really isn't much of
>> a need for an application like that in *nix. In a GUI-based OS like
>> windows, sure, it'd be really handy. But in linux, an application like
>> that is rendered superfluous by grep. If you know the note's
>> title/filename you want has a specific word in it, but don't remember
>> the whole title: ls | grep -i word. If you want to find a note that
>> contains a word that isn't in its title: grep -i word *.
>
> Notational Velocity is actually the main tool I use to catalog the
> common usage idioms for commands like grep :)   Also, there are no
> secrets between me and my notational velocity database.  It has
> passwords, website bookmarks, many of my contacts, my romantic
> history...  The database needs to be encrypted and blazingly fast, as
> measured in keystrokes.
>
> nv(Enter)wor (not specific enough... I'll narrow it down)
> d word2 (oh, there it is... Let's add some new info...)
> (down, down, down)   (to select the note from the narrowed list)
> (tab)    (to switch keyboard focus to the note editing pane)
>
> cd ~/notes
> ls | grep -i word (Enter) (nothing... maybe it's in the note body, not
> the filename...)
> grep -i word * (Enter) (too much maybe I need to narrow it down more...)
> (up) (for command history)
> (backspace, backspace) word2 * (Enter) (oh, there it is...  but I want
> to see the actual note.... not just the lines grep filtered out)
> less (cut and paste the note filename from somewhere in the above
> history, if it showed up...)
> and so on...
>
> I'm sure there are better UNIX flavored workflows than the above, so
> this is admittedly a strawman, but you get the idea.  When most of the
> UNIX tools were designed, computers were barely fast enough to display
> the text as you typed, let alone fast enough to search a database and
> re-render the screen with the results in the time it takes you to hit
> the next letter of the word you're typing.
>
>> That said, It is hard to suggest what widgets you should use when we
>> have no idea what the application looks like. From the description of
>> how the app works on notational.net though, the way I see the widgets
>> being structured is with the top-most widget being a Frame. Frames
>> have a body and can either have a header or a footer widget (or both).
>> The header would be an Edit widget, and it would have focus to begin
>> with. You'd use some key combination to change focus, like tab or
>> ctrl+t.
>>
>> You'd need two different widgets for the body: one for auto-complete
>> suggestions, and one for editing. The editing widget would obviously
>> be an Edit you initialize with multiline=True. The autocomplete would
>> be a ListBox around a ListWalker of some sort. In the ListWalker would
>> be a list with Text widgets representing the autocomplete choices.
>>
>> --
>> Dominic LoBue
>
> Notational Velocity has three panes.  As far as keyboard focus is
> concerned, the first two are logically grouped together.  (The two
> modes are selecting/searching/creating notes and editing them).  As
> visual layout is concerned, the last two panes are logically grouped
> together.  (You want the divider between the two panes to stay in a
> reasonable place as you resize the window)
>
> That said, this mismatch between the keyboard logic and the widget
> hierarchy is probably not that big a deal; in truth most of the logic
> in the program is already inside the ListBox and Edit classes
> (Thanks!).
>
> At the moment I'm thinking something like Pile(Edit, ListBox, Edit),
> everything subclassed for keyboard handling.  The listbox would not be
> selectable and the top Edit would send keyboard events that affect the
> list focus (up and down keys) to the ListBox.  Modifications to the
> text in the first Edit would trigger (through a signal) updates to the
> content of the ListBox and the note window.
>
> Cheers,
> Drew
>
#!/usr/bin/python
# This is an urwid port of the Notational Velocity note taking program.
# Andrew Wagner 2010
import urwid

database = {'fruit':'apples\noranges\npears\npeaches\raspberries\strawberries',
            'animals':'pythons\nbears\njellyfish\ndolphins\nelephants',
            'Sustainable Means of Transportation':'bicycling\n\
            \nwalking\n\
            taking the train',
            "A few of Drew's favorite things":'python programming language\n\
            bicycling\nstrawberries\nnotational velocity\n'}

palette = [('search', 'white', 'black', '', 'black', 'g62'),
    ('list focus', 'black', 'dark cyan', '', 'black', '#8af'),
    ('list nofocus', 'black', 'dark gray', '', 'black', 'g78'),
    ('edit', 'black', 'white')]

verboseMode = True

# An Edit box for the filter
class NV_Edit1(urwid.Edit):        
    def keypress(self, size, key):
        # Filter out Up and down arrows and send them to the ListBox.
        if key in ['up','down','pageup','pagedown']:
            listBox.keypress(size, key) # <------------ BORK!!! listBox not happy with size!
        else:
            super(NV_Edit1, self).keypress(size, key)
if verboseMode:
    promptString = "Enter your search term here:"
else:
    promptString = ""
searchWidget = NV_Edit1(promptString, wrap='clip', multiline=False)


# A list walker for the filtered entries...
class NV_SimpleListWalker(urwid.SimpleListWalker):
    def selectable(self):
        return False
if verboseMode:
    promptString = "This area will contain filtered note titles \
                   once you start typing."
else:
    promptString = ""
listWidget = NV_SimpleListWalker([urwid.Text(promptString),
                                  urwid.Text('This is a second initial entry')])

# An Edit for the body of the note...
# No need to subclass yet, but to be futureproof...
NV_Edit2 = urwid.Edit
if verboseMode:
    promptString = "This is where you view and edit notes:"
else:
    promptString = ""
editWidget = NV_Edit2(promptString, wrap='space', multiline=True,
                      allow_tab=True, edit_pos=0)

# A Pile to handle global keyboard focus...
class NV_Pile(urwid.Pile):
    def __init__(self, widget_list, focus_item=None):
        super(NV_Pile, self).__init__(widget_list, focus_item=None)
    def keypress(self, size, key):
        if key in ['ctrl q']:
            raise urwid.ExitMainLoop()
        if self.get_focus() == self.widget_list[0]:
            if key.lower() in ['tab']:
                self.set_focus(2)
            else:
                return super(NV_Pile, self).keypress(size, key)
        elif self.get_focus() == self.widget_list[2]:
            if key.lower() in ['shift tab']:
                self.set_focus(0)
            else:
                return super(NV_Pile, self).keypress(size, key)

# Add some formatting and padding widgets.
temp1 = searchWidget
temp1 = urwid.AttrMap(temp1, 'search')

temp2 = listWidget
temp2 = urwid.ListBox(temp2)
listBox = temp2
temp2 = urwid.AttrMap(temp2, 'list nofocus', 'list focus')

temp3 = editWidget
temp3 = urwid.AttrMap(temp3, 'edit')
temp3 = urwid.Filler(temp3)

# Glue everything together
pile = NV_Pile([('flow', temp1),
    ('weight',1,temp2),
    ('weight',2,temp3)])

def do_pass(input=None):
    pass

loop = urwid.MainLoop(pile, palette, unhandled_input=do_pass)
loop.screen.set_terminal_properties(colors=256)
loop.run()

_______________________________________________
Urwid mailing list
[email protected]
http://lists.excess.org/mailman/listinfo/urwid

Reply via email to