I have already submitted a patch to improve the jog/shuttle part of the code to get a bigger range of speeds.

I have spend a little thinking and coding to improve the button part too. Here is my design:

I use the existing JogShuttle object, that embeds a thread, that takes care of the device reading and low-level events emitting, and makes sure we get JOG_STOP, deal with the wrapping counter for the jog, and returns the button ID as events.
I then have a JogShuttleAction object that receives these events, and based on the configuration, will actually convert these low-level events in an action event, either a transport command or an action. It also defines the entire set of actions that are possible to be mapped to the jogshuttle, including their localized names, which I can then use in the configuration dialog.
Finally, the mainwindow.cpp contains the code that
 - creates the JogShuttle, the JogShuttleAction with the config, links them and starts them,
 - receives the actions from that device through the slotShuttleAction, and has a proper implementation for each of the supported actions. There is no mapping neede dhere anymore, as it-s happening in the JogShuttleAction.

I wanted to have the low-level / action split, because I'd like to have the low-level events during configuration time when we encounter a new device. I have a plan to have a JogShuttleConfig object, that knows how to read some pre-defined configuration for a set of devices we know and can test for.
For a little while, I was pondering about the cost of having one more level of events in the chain, but froma user-interface, I guess it-s not much to worry about.

If you think this is reasonable, I am happy to provide another patch that implements this, part I (the new mapping intermediary object) as well as part II later (the updated config dialog).