qtutils: add hbox() and vbox() helpers

We'll use these in the dag and elsewhere to simplify things a bit.

Signed-off-by: David Aguilar <davvid@gmail.com>
widgets.standard: add a SpinBox that does not go negative

Signed-off-by: David Aguilar <davvid@gmail.com>
widgets.completion: cache git results

Hook into the model updated signal so that we can avoid needing to call
`git ls-files` everytime the input changes.

We now keep a cached copy the ls-files output around and update it
whenever the `updated()` signal arrives.

Signed-off-by: David Aguilar <davvid@gmail.com>
widgets.completion: simplify completion handling

Simplify the completion code by doing less.

We now do everything in a single KeyReleaseEvent() where we special-case
Tab, Enter et. al  and unconditionally do completion otherwise.

Ensure that the completion popup always shows the first item.  This
makes it so that pressing the down arrow will always highlight the first
visible entry.  The old code would allow the popup's scroll area to
bounce around, which resulted in the visible completions not matching
what is selected when pressing the down arrow.

Remove the mouse events since they complicate things and mess with the
standard interactions.  The callbacks were there to make the completion
popup appear when clicking in the widget.  This was helpful, but it also
made it hard to move the cursor when editing the line.

The moment the user presses a key (e.g. an arrow key) then the
completions will appear so the mouse events can be removed without
losing any functionality.

The end result is simpler code and simpler user interaction.

Signed-off-by: David Aguilar <davvid@gmail.com>
dag: add Refresh action

Add a "Refresh" menu action and bind it to Ctrl+R.
This allows the dag see new commits and branches.

Simplify things by allowing the input to be empty.
Previously we forced the command-line to "$branch --",
but letting it be empty is simpler and more intuitive.

Closes #347

Suggested-by: Matthew Levine @melevine via github.com
Signed-off-by: David Aguilar <davvid@gmail.com>