Added keyboard shortcuts for move up, move down and delete.
This fixes issue #1430.
This commit is contained in:
parent
bdf2bba1bb
commit
d235b8faa6
4 changed files with 222 additions and 3 deletions
|
@ -53,6 +53,20 @@ using namespace LiveSupport::GLiveSupport;
|
||||||
|
|
||||||
/* ================================================ local constants & macros */
|
/* ================================================ local constants & macros */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The modifier keys we check against in onKeyPressed().
|
||||||
|
* The following modifiers are omitted, hence ignored:
|
||||||
|
* GDK_LOCK_MASK (caps lock),
|
||||||
|
* GDK_MOD2_MASK (don't know what; always on on my computer),
|
||||||
|
* GDK_MOD3_MASK (don't know what; always off on my computer),
|
||||||
|
* GDK_BUTTONX_MASK (mouse buttons, X = 1..5).
|
||||||
|
*/
|
||||||
|
static const guint MODIFIERS_CHECKED = GDK_SHIFT_MASK
|
||||||
|
| GDK_CONTROL_MASK
|
||||||
|
| GDK_MOD1_MASK // Alt
|
||||||
|
| GDK_MOD4_MASK // Windows key
|
||||||
|
| GDK_MOD5_MASK; // Alt-gr
|
||||||
|
|
||||||
|
|
||||||
/* =============================================== local function prototypes */
|
/* =============================================== local function prototypes */
|
||||||
|
|
||||||
|
@ -106,6 +120,10 @@ LiveModeWindow :: LiveModeWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
|
||||||
&LiveModeWindow::onEntryClicked));
|
&LiveModeWindow::onEntryClicked));
|
||||||
treeView->signal_row_activated().connect(sigc::mem_fun(*this,
|
treeView->signal_row_activated().connect(sigc::mem_fun(*this,
|
||||||
&LiveModeWindow::onDoubleClick));
|
&LiveModeWindow::onDoubleClick));
|
||||||
|
|
||||||
|
// register the signal handler for keyboard key presses
|
||||||
|
treeView->signal_key_press_event().connect(sigc::mem_fun(*this,
|
||||||
|
&LiveModeWindow::onKeyPressed));
|
||||||
|
|
||||||
// Add the TreeView, inside a ScrolledWindow, with the button underneath:
|
// Add the TreeView, inside a ScrolledWindow, with the button underneath:
|
||||||
scrolledWindow.add(*treeView);
|
scrolledWindow.add(*treeView);
|
||||||
|
@ -284,7 +302,7 @@ LiveModeWindow :: onOutputPlay(void) throw ()
|
||||||
* Event handler for an entry being clicked in the list.
|
* Event handler for an entry being clicked in the list.
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
LiveModeWindow :: onEntryClicked (GdkEventButton * event) throw ()
|
LiveModeWindow :: onEntryClicked(GdkEventButton * event) throw ()
|
||||||
{
|
{
|
||||||
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
||||||
Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
|
Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
|
||||||
|
@ -323,3 +341,39 @@ LiveModeWindow :: onDoubleClick(const Gtk::TreeModel::Path & path,
|
||||||
onOutputPlay();
|
onOutputPlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Event handler for a key pressed.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
bool
|
||||||
|
LiveModeWindow :: onKeyPressed(GdkEventKey * event) throw ()
|
||||||
|
{
|
||||||
|
if (event->type == GDK_KEY_PRESS) {
|
||||||
|
Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
|
||||||
|
treeView->get_selection();
|
||||||
|
Gtk::TreeModel::iterator iter = refSelection->get_selected();
|
||||||
|
|
||||||
|
if (iter) {
|
||||||
|
if ((event->keyval == GDK_Up
|
||||||
|
|| event->keyval == GDK_KP_Up)
|
||||||
|
&& (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) {
|
||||||
|
treeView->onUpMenuOption();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if ((event->keyval == GDK_Down
|
||||||
|
|| event->keyval == GDK_KP_Down)
|
||||||
|
&& (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) {
|
||||||
|
treeView->onDownMenuOption();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (event->keyval == GDK_Delete
|
||||||
|
|| event->keyval == GDK_KP_Delete) {
|
||||||
|
treeView->onRemoveMenuOption();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ class LiveModeWindow : public WhiteWindow, public LocalizedObject
|
||||||
* @param event the button event recieved
|
* @param event the button event recieved
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
onEntryClicked(GdkEventButton * event) throw ();
|
onEntryClicked(GdkEventButton * event) throw ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal handler for the user double-clicking, or pressing Enter
|
* Signal handler for the user double-clicking, or pressing Enter
|
||||||
|
@ -177,6 +177,28 @@ class LiveModeWindow : public WhiteWindow, public LocalizedObject
|
||||||
const Gtk::TreeViewColumn * column)
|
const Gtk::TreeViewColumn * column)
|
||||||
throw ();
|
throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal handler for a key pressed at one of the entries.
|
||||||
|
* The keys handled are:
|
||||||
|
* <ul>
|
||||||
|
* <li>Alt-Up : move item up</li>
|
||||||
|
* <li>Alt-Down : move item down</li>
|
||||||
|
* <li>Delete : remove item</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Technical note: the symbolic key names are found in
|
||||||
|
* <code>/usr/include/gtk-2.0/gdk/gdkkeysyms.h</code>,
|
||||||
|
* and the symbolic modifier names are found in
|
||||||
|
* <code>/usr/include/gtk-2.0/gdk/gdktypes.h</code>.
|
||||||
|
*
|
||||||
|
* TODO: make keys customizable from a config file?
|
||||||
|
*
|
||||||
|
* @param event the button event recieved
|
||||||
|
* @return true if the key press was fully handled, false if not
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
onKeyPressed(GdkEventKey * event) throw ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal handler for the "rows reordered" event.
|
* Signal handler for the "rows reordered" event.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -53,6 +53,20 @@ using namespace LiveSupport::GLiveSupport;
|
||||||
|
|
||||||
/* ================================================ local constants & macros */
|
/* ================================================ local constants & macros */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The modifier keys we check against in onKeyPressed().
|
||||||
|
* The following modifiers are omitted, hence ignored:
|
||||||
|
* GDK_LOCK_MASK (caps lock),
|
||||||
|
* GDK_MOD2_MASK (don't know what; always on on my computer),
|
||||||
|
* GDK_MOD3_MASK (don't know what; always off on my computer),
|
||||||
|
* GDK_BUTTONX_MASK (mouse buttons, X = 1..5).
|
||||||
|
*/
|
||||||
|
static const guint MODIFIERS_CHECKED = GDK_SHIFT_MASK
|
||||||
|
| GDK_CONTROL_MASK
|
||||||
|
| GDK_MOD1_MASK // Alt
|
||||||
|
| GDK_MOD4_MASK // Windows key
|
||||||
|
| GDK_MOD5_MASK; // Alt-gr
|
||||||
|
|
||||||
|
|
||||||
/* =============================================== local function prototypes */
|
/* =============================================== local function prototypes */
|
||||||
|
|
||||||
|
@ -122,6 +136,10 @@ ScratchpadWindow :: ScratchpadWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
|
||||||
treeView->signal_row_activated().connect(sigc::mem_fun(*this,
|
treeView->signal_row_activated().connect(sigc::mem_fun(*this,
|
||||||
&ScratchpadWindow::onDoubleClick));
|
&ScratchpadWindow::onDoubleClick));
|
||||||
|
|
||||||
|
// register the signal handler for keyboard key presses
|
||||||
|
treeView->signal_key_press_event().connect(sigc::mem_fun(*this,
|
||||||
|
&ScratchpadWindow::onKeyPressed));
|
||||||
|
|
||||||
// Add the TreeView, inside a ScrolledWindow, with the button underneath:
|
// Add the TreeView, inside a ScrolledWindow, with the button underneath:
|
||||||
scrolledWindow.add(*treeView);
|
scrolledWindow.add(*treeView);
|
||||||
|
|
||||||
|
@ -388,13 +406,37 @@ ScratchpadWindow :: onEntryClicked (GdkEventButton * event) throw ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Select the row which contains the playable specified.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
ScratchpadWindow :: selectRow(Ptr<Playable>::Ref playable) throw ()
|
||||||
|
{
|
||||||
|
Gtk::TreeModel::const_iterator iter;
|
||||||
|
|
||||||
|
for (iter = treeModel->children().begin();
|
||||||
|
iter != treeModel->children().end(); ++iter) {
|
||||||
|
|
||||||
|
Gtk::TreeRow row = *iter;
|
||||||
|
Ptr<Playable>::Ref currentPlayable = row[modelColumns.playableColumn];
|
||||||
|
|
||||||
|
if (*playable->getId() == *currentPlayable->getId()) {
|
||||||
|
Glib::RefPtr<Gtk::TreeView::Selection>
|
||||||
|
selection = treeView->get_selection();
|
||||||
|
selection->select(iter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* Event handler for the Up menu item selected from the entry context menu
|
* Event handler for the Up menu item selected from the entry context menu
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
ScratchpadWindow :: onUpItem(void) throw ()
|
ScratchpadWindow :: onUpItem(void) throw ()
|
||||||
{
|
{
|
||||||
Ptr<Playable>::Ref playable = currentRow[modelColumns.playableColumn];
|
Ptr<Playable>::Ref playable = currentRow[modelColumns.playableColumn];
|
||||||
|
|
||||||
Ptr<GLiveSupport::PlayableList>::Ref scratchpadContents;
|
Ptr<GLiveSupport::PlayableList>::Ref scratchpadContents;
|
||||||
GLiveSupport::PlayableList::iterator it;
|
GLiveSupport::PlayableList::iterator it;
|
||||||
|
@ -421,6 +463,8 @@ ScratchpadWindow :: onUpItem(void) throw ()
|
||||||
|
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectRow(playable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -460,6 +504,8 @@ ScratchpadWindow :: onDownItem(void) throw ()
|
||||||
|
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectRow(playable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -590,3 +636,58 @@ ScratchpadWindow :: onDoubleClick(const Gtk::TreeModel::Path & path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Event handler for a key pressed.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
bool
|
||||||
|
ScratchpadWindow :: onKeyPressed(GdkEventKey * event) throw ()
|
||||||
|
{
|
||||||
|
if (event->type == GDK_KEY_PRESS) {
|
||||||
|
if ((event->keyval == GDK_Up
|
||||||
|
|| event->keyval == GDK_KP_Up)
|
||||||
|
&& (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) {
|
||||||
|
if (isSelectionSingle()) {
|
||||||
|
onUpItem();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ((event->keyval == GDK_Down
|
||||||
|
|| event->keyval == GDK_KP_Down)
|
||||||
|
&& (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) {
|
||||||
|
if (isSelectionSingle()) {
|
||||||
|
onDownItem();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (event->keyval == GDK_Delete
|
||||||
|
|| event->keyval == GDK_KP_Delete) {
|
||||||
|
onRemoveItemButtonClicked();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Check whether exactly one row is selected.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
bool
|
||||||
|
ScratchpadWindow :: isSelectionSingle(void) throw ()
|
||||||
|
{
|
||||||
|
Glib::RefPtr<Gtk::TreeView::Selection>
|
||||||
|
selection = treeView->get_selection();
|
||||||
|
std::vector<Gtk::TreePath>
|
||||||
|
selectedRows = selection->get_selected_rows();
|
||||||
|
|
||||||
|
if (selectedRows.size() == 1) {
|
||||||
|
Gtk::TreeIter iter = treeModel->get_iter(selectedRows.at(0));
|
||||||
|
currentRow = *iter;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,26 @@ class ScratchpadWindow : public WhiteWindow,
|
||||||
public LocalizedObject
|
public LocalizedObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Check whether exactly one row is selected, and if so, set
|
||||||
|
* the currentRow variable to point to it.
|
||||||
|
*
|
||||||
|
* This is an auxilliary function used by onKeyPressed().
|
||||||
|
*
|
||||||
|
* @return true if a single row is selected, false if not.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
isSelectionSingle(void) throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the (first) row which contains the playable specified.
|
||||||
|
* If no such row is found, then it does nothing.
|
||||||
|
*
|
||||||
|
* @param playable the playable to be selected.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
selectRow(Ptr<Playable>::Ref playable) throw ();
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -234,6 +254,28 @@ class ScratchpadWindow : public WhiteWindow,
|
||||||
const Gtk::TreeViewColumn * column)
|
const Gtk::TreeViewColumn * column)
|
||||||
throw ();
|
throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal handler for a key pressed at one of the entries.
|
||||||
|
* The keys handled are:
|
||||||
|
* <ul>
|
||||||
|
* <li>Alt-Up : move item up</li>
|
||||||
|
* <li>Alt-Down : move item down</li>
|
||||||
|
* <li>Delete : remove item</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Technical note: the symbolic key names are found in
|
||||||
|
* <code>/usr/include/gtk-2.0/gdk/gdkkeysyms.h</code>,
|
||||||
|
* and the symbolic modifier names are found in
|
||||||
|
* <code>/usr/include/gtk-2.0/gdk/gdktypes.h</code>.
|
||||||
|
*
|
||||||
|
* TODO: make keys customizable from a config file?
|
||||||
|
*
|
||||||
|
* @param event the button event recieved
|
||||||
|
* @return true if the key press was fully handled, false if not
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
onKeyPressed(GdkEventKey * event) throw ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal handler for the "up" menu item selected from
|
* Signal handler for the "up" menu item selected from
|
||||||
* the entry context menu.
|
* the entry context menu.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue