Commit 36de7593 authored by Dirk Wilden's avatar Dirk Wilden

added changeable keyBindings

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@4269 383ad7c9-94d9-4d36-a494-682f7c89f535
parent b42b4ca4
......@@ -466,175 +466,6 @@ CoreWidget::showToolbox( bool _state ) {
}
}
//-----------------------------------------------------------------------------
/** Handles keypress events or passes them to plugins
*/
void
CoreWidget::keyPressEvent(QKeyEvent* _e)
{
if (_e->modifiers() == Qt::ControlModifier ) {
switch (_e->key())
{
case Qt::Key_F :
toggleFullscreen();
return;
case Qt::Key_L :
toggleLogger();
return;
case Qt::Key_T :
toggleToolbox();
return;
// Send remaining events to plugins
default:
mapKeyPressEvent(_e);
return;
}
}
switch (_e->key())
{
case Qt::Key_Escape:
for ( uint i = 0 ; i < examiner_widgets_.size(); ++i)
examiner_widgets_[i]->actionMode(examiner_widgets_[i]->lastActionMode());
// Send remaining events to plugins
default:
mapKeyPressEvent(_e);
break;
}
}
//-----------------------------------------------------------------------------
/** Handle Key Release Events */
void
CoreWidget::keyReleaseEvent(QKeyEvent* _e) {
mapKeyReleaseEvent(_e);
}
//-----------------------------------------------------------------------------
/** Map Key Press Events to Plugins */
void
CoreWidget::mapKeyPressEvent(QKeyEvent* _e){
//find the first plugin which wants to handle that key
for (uint i=0; i < plugins_.size(); i++)
for (int k=0; k < plugins_[i].keys.count(); k++)
if ( plugins_[i].keys[k].key == _e->key()
&& plugins_[i].keys[k].modifiers == _e->modifiers() ){
KeyInterface* keyPlugin = qobject_cast< KeyInterface * >(plugins_[i].plugin);
if (keyPlugin){
// if ( checkSlot( plugins_[i].plugin , "slotKeyEvent(QKeyEvent*)" ) )
keyPlugin->slotKeyEvent(_e);
}
//only inform further plugins if this is a multiUse key
if (!plugins_[i].keys[k].multiUse)
return;
}
}
//-----------------------------------------------------------------------------
/** Map Key Release Events to Plugins */
void
CoreWidget::mapKeyReleaseEvent(QKeyEvent* _e){
if (_e->isAutoRepeat()) return; //consider only "real" release events
//find the first plugin which wants to handle that key
for (uint i=0; i < plugins_.size(); i++)
for (int k=0; k < plugins_[i].keys.count(); k++)
if ( plugins_[i].keys[k].key == _e->key()
&& plugins_[i].keys[k].modifiers == _e->modifiers() ){
KeyInterface* keyPlugin = qobject_cast< KeyInterface * >(plugins_[i].plugin);
if (keyPlugin){
// if ( checkSlot( plugins_[i].plugin , "slotKeyReleaseEvent(QKeyEvent*)" ) )
keyPlugin->slotKeyReleaseEvent(_e);
}
//only inform further plugins if this is a multiUse key
if (!plugins_[i].keys[k].multiUse)
return;
}
}
//-----------------------------------------------------------------------------
/** Register a key to a plugin */
void
CoreWidget::slotRegisterKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description, bool _multiUse){
//first check if the key is already registered by the coreWidget
bool found = false;
bool multi = false;
for (uint i=0; i < coreKeys_.size(); i++)
if (coreKeys_[i].key == _key && coreKeys_[i].modifiers == _modifiers){
found = true;
multi = coreKeys_[i].multiUse;
break;
}
//then check if the key is already registered by a different plugin
if (!found)
for (uint i=0; i < plugins_.size(); i++)
for (int k=0; k < plugins_[i].keys.count(); k++)
if (plugins_[i].keys[k].key == _key
&& plugins_[i].keys[k].modifiers == _modifiers){
found = true;
multi = plugins_[i].keys[k].multiUse;
break;
}
if (found)
emit log(LOGERR, "Key already registered elsewhere.");
//check if its a key for the core
if (sender() == this){
KeyBinding kb;
kb.key = _key;
kb.modifiers = _modifiers;
kb.description = _description;
kb.multiUse = multi || _multiUse;
if (multi && !_multiUse)
log(LOGWARN, "Key registered as multiUse key.");
coreKeys_.push_back( kb );
return;
}
//find plugin
PluginInfo* pluginInfo = 0;
for (uint i=0; i < plugins_.size(); i++)
if (plugins_[i].plugin == sender())
pluginInfo = &plugins_[i];
if (pluginInfo == 0){
emit log(LOGERR, "Unable to register key. Plugin not found!");
return;
}
KeyBinding kb;
kb.key = _key;
kb.modifiers = _modifiers;
kb.description = _description;
kb.multiUse = multi || _multiUse;
if (multi && !_multiUse)
log(LOGWARN, "Key registered as multiUse key.");
pluginInfo->keys.append( kb );
}
//=============================================================================
void
......@@ -680,9 +511,11 @@ void CoreWidget::showOptionsWidget() {
return;
if ( optionsWidget_ == 0 ) {
optionsWidget_ = new OptionsWidget(plugins_, coreKeys_, 0);
optionsWidget_ = new OptionsWidget(plugins_, coreKeys_, invKeys_, 0);
connect(optionsWidget_,SIGNAL(applyOptions()),this,SIGNAL(applyOptions()));
connect(optionsWidget_,SIGNAL(saveOptions()),this,SIGNAL(saveOptions()));
connect(optionsWidget_,SIGNAL(addKeyMapping(int,Qt::KeyboardModifiers,QObject*,int)),
this, SLOT(slotAddKeyMapping(int,Qt::KeyboardModifiers,QObject*,int)));
}
//show the optionsWidget centered
......
......@@ -166,16 +166,38 @@ public:
void PluginKeyReleaseEvent(QKeyEvent* );
/// internal signal to register CoreWidget keys
void registerKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description, bool _multiUse = false);
void registerKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description,
bool _multiUse = false);
private:
void mapKeyPressEvent(QKeyEvent* _e);
void mapKeyReleaseEvent(QKeyEvent* _e);
///typedefs
typedef std::multimap< std::pair< int, Qt::KeyboardModifiers > , std::pair< QObject*, int > > KeyMap;
typedef std::multimap< std::pair< QObject*, int >, std::pair< int, Qt::KeyboardModifiers > > InverseKeyMap;
typedef std::pair< KeyMap::iterator, KeyMap::iterator > KeyRange;
/// Handle core key events
void coreKeyPressEvent (QKeyEvent* _e);
void coreKeyReleaseEvent(QKeyEvent* _e);
KeyBinding getKeyBinding(QObject* _plugin, int _keyIndex );
///vector of keys registered to the core
std::vector<KeyBinding> coreKeys_;
///mapping of all keys to registered keys and the corresponding plugins
KeyMap keys_;
///mapping of all registered keys and the corresponding plugins to currently assigned keys
InverseKeyMap invKeys_;
private slots:
void slotRegisterKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description, bool _multiUse = false);
void slotRegisterKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description,
bool _multiUse = false);
public slots:
void slotAddKeyMapping(int _key, Qt::KeyboardModifiers _modifiers, QObject* _plugin, int _keyBindingID);
/** @} */
......
......@@ -111,7 +111,7 @@ void CoreWidget::setupMenuBar()
//Load object
QAction* AC_Load = new QAction(tr("&Load Object"), this);
AC_Load->setShortcut (Qt::CTRL + Qt::Key_O);
// AC_Load->setShortcut (Qt::CTRL + Qt::Key_O);
AC_Load->setStatusTip(tr("Load an object"));
AC_Load->setWhatsThis("Load a new object");
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"document-open.png");
......@@ -133,7 +133,7 @@ void CoreWidget::setupMenuBar()
//Save object
QAction* AC_Save = new QAction(tr("&Save Object"), this);
AC_Save->setShortcut (Qt::CTRL + Qt::Key_S);
// AC_Save->setShortcut (Qt::CTRL + Qt::Key_S);
AC_Save->setStatusTip(tr("Save currently selected objects"));
AC_Save->setWhatsThis("Saves all currently selected objects");
icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"document-save.png");
......
#include "CoreWidget.hh"
#include <OpenFlipper/BasePlugin/KeyInterface.hh>
#include <OpenFlipper/BasePlugin/BaseInterface.hh>
//-----------------------------------------------------------------------------
KeyBinding CoreWidget::getKeyBinding(QObject* _plugin, int _keyIndex ){
if (_plugin == 0)
return coreKeys_[_keyIndex];
for (uint i=0; i < plugins_.size(); i++){
if (plugins_[i].plugin == _plugin)
return plugins_[i].keys[_keyIndex];
}
std::cerr << "ERROR: could not get KeyBinding\n";
return KeyBinding();
}
/// passes keyPressEvents to either the Core or a Plugin depending on who has registered the key
void CoreWidget::keyPressEvent(QKeyEvent* _e)
{
std::pair< int,Qt::KeyboardModifiers > key = std::make_pair(_e->key(), _e->modifiers() );
//iterate over all assigned keys
KeyRange range = keys_.equal_range(key);
KeyMap::iterator it;
for (it=range.first; it != range.second; ++it){
QObject* plugin = (*it).second.first;
KeyBinding binding = getKeyBinding( plugin, (*it).second.second );
//check if its a core Key
if (plugin == 0){
QKeyEvent* mappedEvent = new QKeyEvent(_e->type(),binding.key, binding.modifiers,
_e->text(), _e->isAutoRepeat(), _e->count() );
coreKeyPressEvent(mappedEvent);
delete mappedEvent;
//if the key is multiUse also check other assigned keys
if (binding.multiUse)
continue;
else
return;
}
//it's a plugin key
KeyInterface* keyPlugin = qobject_cast< KeyInterface * >(plugin);
if (keyPlugin){
QKeyEvent* mappedEvent = new QKeyEvent(_e->type(),binding.key, binding.modifiers,
_e->text(), _e->isAutoRepeat(), _e->count() );
keyPlugin->slotKeyEvent(mappedEvent);
}
//if its not a multiUse key we are ready
if (!binding.multiUse)
return;
}
}
//-----------------------------------------------------------------------------
/// passes keyReleaseEvents to either the Core or a Plugin depending on who has registered the key
void CoreWidget::keyReleaseEvent(QKeyEvent* _e) {
if (_e->isAutoRepeat()) return; //consider only "real" release events
std::pair< int,Qt::KeyboardModifiers > key = std::make_pair(_e->key(), _e->modifiers() );
//iterate over all assigned keys
KeyRange range = keys_.equal_range(key);
KeyMap::iterator it;
for (it=range.first; it != range.second; ++it){
QObject* plugin = (*it).second.first;
KeyBinding binding = getKeyBinding( plugin, (*it).second.second );
//check if its a core Key
if (plugin == 0){
QKeyEvent* mappedEvent = new QKeyEvent(_e->type(),binding.key, binding.modifiers,
_e->text(), _e->isAutoRepeat(), _e->count() );
coreKeyReleaseEvent(mappedEvent);
delete mappedEvent;
//if the key is multiUse also check other assigned keys
if (binding.multiUse)
continue;
else
return;
}
//it's a plugin key
KeyInterface* keyPlugin = qobject_cast< KeyInterface * >(plugin);
if (keyPlugin){
QKeyEvent* mappedEvent = new QKeyEvent(_e->type(),binding.key, binding.modifiers,
_e->text(), _e->isAutoRepeat(), _e->count() );
keyPlugin->slotKeyEvent(mappedEvent);
}
//if its not a multiUse key we are ready
if (!binding.multiUse)
return;
}
}
//-----------------------------------------------------------------------------
/// Register a key to the core or a plugin
void CoreWidget::slotRegisterKey(int _key, Qt::KeyboardModifiers _modifiers, QString _description, bool _multiUse){
//first check if the key is already registered by the coreWidget
bool found = false;
bool multi = false;
for (uint i=0; i < coreKeys_.size(); i++)
if (coreKeys_[i].key == _key && coreKeys_[i].modifiers == _modifiers){
found = true;
multi = coreKeys_[i].multiUse;
break;
}
//then check if the key is already registered by a different plugin
if (!found)
for (uint i=0; i < plugins_.size(); i++)
for (int k=0; k < plugins_[i].keys.count(); k++)
if (plugins_[i].keys[k].key == _key
&& plugins_[i].keys[k].modifiers == _modifiers){
found = true;
multi = plugins_[i].keys[k].multiUse;
break;
}
if (found)
emit log(LOGERR, "Key already registered elsewhere.");
//check if its a key for the core
if (sender() == this){
KeyBinding kb;
kb.key = _key;
kb.modifiers = _modifiers;
kb.description = _description;
kb.multiUse = multi || _multiUse;
if (multi && !_multiUse)
log(LOGWARN, "Key registered as multiUse key.");
coreKeys_.push_back( kb );
keys_.insert( std::make_pair( std::make_pair(_key, _modifiers) , std::make_pair ((QObject*)0, coreKeys_.size()-1 ) )) ;
invKeys_.insert( std::make_pair( std::make_pair ((QObject*)0, coreKeys_.size()-1 ) , std::make_pair(_key, _modifiers) ) );
return;
}
//find plugin
PluginInfo* pluginInfo = 0;
for (uint i=0; i < plugins_.size(); i++)
if (plugins_[i].plugin == sender())
pluginInfo = &plugins_[i];
if (pluginInfo == 0){
emit log(LOGERR, "Unable to register key. Plugin not found!");
return;
}
KeyBinding kb;
kb.key = _key;
kb.modifiers = _modifiers;
kb.description = _description;
kb.multiUse = multi || _multiUse;
if (multi && !_multiUse)
log(LOGWARN, "Key registered as multiUse key.");
pluginInfo->keys.append( kb );
keys_.insert( std::make_pair( std::make_pair(_key, _modifiers) , std::make_pair(pluginInfo->plugin, pluginInfo->keys.size()-1) ) );
invKeys_.insert( std::make_pair( std::make_pair(pluginInfo->plugin, pluginInfo->keys.size()-1) , std::make_pair(_key, _modifiers) ) );
}
/// add a new keyMapping (keyBindingID is the id of the keyBinding in the pluginInfo of _plugin :)
void CoreWidget::slotAddKeyMapping(int _key, Qt::KeyboardModifiers _modifiers, QObject* _plugin, int _keyBindingID){
std::pair< int,Qt::KeyboardModifiers > keyCombi = std::make_pair(_key, _modifiers );
std::pair< int,Qt::KeyboardModifiers > oldCombi;
std::pair< QObject*, int > oldTarget;
bool replace = false;
//and check if the key is already assigned without multiUse
KeyMap::iterator it;
for (it=keys_.begin(); it != keys_.end(); ++it){
int key = (*it).first.first;
Qt::KeyboardModifiers modifiers = (*it).first.second;
QObject* plugin = (*it).second.first;
int bindingID = (*it).second.second;
KeyBinding binding = getKeyBinding(plugin, bindingID);
//check if its the keyBinding we want to map/replace
if (plugin == _plugin && bindingID == _keyBindingID){
replace = true;
oldCombi = (*it).first;
oldTarget = (*it).second;
continue;
}
//check if the mapping is conflicting with other mappings
if (_key == key && _modifiers == modifiers ){
if (!binding.multiUse){
if (plugin == 0)
emit log(LOGERR, "Could not add key mapping. Key already assigned to the core.");
else{
BaseInterface* basePlugin = qobject_cast< BaseInterface * >(plugin);
if (basePlugin)
emit log(LOGERR, "Could not add key mapping. Key already assigned to " + basePlugin->name() );
else
emit log(LOGERR, "Could not add key mapping. Key already assigned to an unknown plugin.");
}
return;
}
}
}
KeyBinding keyBinding = getKeyBinding(_plugin, _keyBindingID);
//check if new binding doesn't allow multiUse but other assignments for the key exist
if (!keyBinding.multiUse)
if ( (replace && keys_.count(keyCombi) > 1) || (!replace && keys_.count(keyCombi) > 0) ){
emit log(LOGERR, "Could not add (single usage) key mapping. Key already assigned.");
return;
}
//now we can add the mapping
keys_.insert ( std::make_pair( keyCombi , std::make_pair(_plugin, _keyBindingID) ));
invKeys_.insert( std::make_pair( std::make_pair(_plugin, _keyBindingID), keyCombi ));
if (replace){
keys_.erase(oldCombi);
invKeys_.erase(oldTarget);
}
}
/// if a keyPressEvent belongs to the core this functions is called
void CoreWidget::coreKeyPressEvent (QKeyEvent* _e){
if (_e->modifiers() == Qt::ControlModifier ) {
switch (_e->key())
{
case Qt::Key_F :
toggleFullscreen();
return;
case Qt::Key_L :
toggleLogger();
return;
case Qt::Key_T :
toggleToolbox();
return;
case Qt::Key_O :
loadMenu();
case Qt::Key_S :
saveMenu();
default:
return;
}
}
switch (_e->key())
{
case Qt::Key_Escape:
for ( uint i = 0 ; i < examiner_widgets_.size(); ++i)
examiner_widgets_[i]->actionMode(examiner_widgets_[i]->lastActionMode());
// Send remaining events to plugins
default:
return;
}
}
/// if a keyReleaseEvent belongs to the core this functions is called
void CoreWidget::coreKeyReleaseEvent(QKeyEvent* /*_e*/){
}
#include "ShortcutButton.hh"
#include <iostream>
///Constructor
ShortcutButton::ShortcutButton(QWidget* _parent) : QPushButton(_parent)
{
key_ = -1;
setCheckable(true);
}
///set the current shortcut
void ShortcutButton::setCurrentShortcut(int _key, Qt::KeyboardModifiers _modifiers)
{
key_ = _key;
modifiers_ = _modifiers;
showCurrentShortcut();
}
///get current key
int ShortcutButton::key()
{
return key_;
}
///get current modifiers
Qt::KeyboardModifiers ShortcutButton::modifiers()
{
return modifiers_;
}
///key press
void ShortcutButton::keyPressEvent(QKeyEvent* event)
{
if (firstPress_){
oldKey_ = key_;
oldModifiers_ = modifiers_;
}
firstPress_ = false;
key_ = event->key();
modifiers_ = event->modifiers();
}
///key release
void ShortcutButton::keyReleaseEvent(QKeyEvent* /*event*/)
{
showCurrentShortcut();
emit keyChanged();
}
///show the current shortcut
void ShortcutButton::showCurrentShortcut()
{
firstPress_ = true;
QString keyString;
if (key_ == Qt::Key_AltGr || key_ == Qt::Key_Alt || key_ == Qt::Key_Control || key_ == Qt::Key_Shift || key_ == Qt::Key_Meta){
keyString = QKeySequence( modifiers_ ).toString();
keyString = keyString.left(keyString.size()-1);
}else
keyString = QKeySequence( key_ + modifiers_ ).toString();
setText(keyString);
}
void ShortcutButton::focusInEvent(QFocusEvent* event){
setChecked(true);
setText("");
QPushButton::focusInEvent(event);
}
void ShortcutButton::focusOutEvent(QFocusEvent* event){
set