diff --git a/apps/opencs/model/prefs/shortcut.cpp b/apps/opencs/model/prefs/shortcut.cpp index 247dadf99..c0682fed3 100644 --- a/apps/opencs/model/prefs/shortcut.cpp +++ b/apps/opencs/model/prefs/shortcut.cpp @@ -1,15 +1,15 @@ #include "shortcut.hpp" -#include -#include -#include +#include + +#include #include "state.hpp" #include "shortcutmanager.hpp" namespace CSMPrefs { - Shortcut::Shortcut(const std::string& name, QObject* parent) + Shortcut::Shortcut(const std::string& name, QWidget* parent) : QObject(parent) , mEnabled(true) , mName(name) @@ -20,13 +20,15 @@ namespace CSMPrefs , mActivationStatus(AS_Inactive) , mModifierStatus(false) { + assert (parent); + State::get().getShortcutManager().addShortcut(this); ShortcutManager::SequenceData data = State::get().getShortcutManager().getSequence(name); setSequence(data.first); setModifier(data.second); } - Shortcut::Shortcut(const std::string& name, SecondaryMode secMode, QObject* parent) + Shortcut::Shortcut(const std::string& name, SecondaryMode secMode, QWidget* parent) : QObject(parent) , mEnabled(true) , mName(name) @@ -37,6 +39,8 @@ namespace CSMPrefs , mActivationStatus(AS_Inactive) , mModifierStatus(false) { + assert (parent); + State::get().getShortcutManager().addShortcut(this); ShortcutManager::SequenceData data = State::get().getShortcutManager().getSequence(name); setSequence(data.first); diff --git a/apps/opencs/model/prefs/shortcut.hpp b/apps/opencs/model/prefs/shortcut.hpp index af3a20c06..2df47f382 100644 --- a/apps/opencs/model/prefs/shortcut.hpp +++ b/apps/opencs/model/prefs/shortcut.hpp @@ -7,9 +7,7 @@ #include #include -class QKeyEvent; -class QMouseEvent; -class QShortcut; +class QWidget; namespace CSMPrefs { @@ -34,8 +32,8 @@ namespace CSMPrefs SM_Ignore ///< The secondary signal will not ever be emitted }; - Shortcut(const std::string& name, QObject* parent); - Shortcut(const std::string& name, SecondaryMode secMode, QObject* parent); + Shortcut(const std::string& name, QWidget* parent); + Shortcut(const std::string& name, SecondaryMode secMode, QWidget* parent); ~Shortcut(); diff --git a/apps/opencs/model/prefs/shortcuteventhandler.cpp b/apps/opencs/model/prefs/shortcuteventhandler.cpp index c04f9e310..341881367 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.cpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.cpp @@ -1,7 +1,7 @@ #include "shortcuteventhandler.hpp" #include -#include +#include #include #include @@ -19,54 +19,88 @@ namespace CSMPrefs void ShortcutEventHandler::addShortcut(Shortcut* shortcut) { - mShortcuts.push_back(shortcut); + // Enforced by shortcut class + QWidget* widget = static_cast(shortcut->parent()); + + // Check if widget setup is needed + ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget); + if (shortcutListIt == mWidgetShortcuts.end()) + { + // Create list + shortcutListIt = mWidgetShortcuts.insert(std::make_pair(widget, ShortcutList())).first; + + // Check if widget has a parent with shortcuts, unfortunately it is not typically set yet + updateParent(widget); + + // Intercept widget events + widget->installEventFilter(this); + connect(widget, SIGNAL(destroyed()), this, SLOT(widgetDestroyed())); + } + + // Add to list + shortcutListIt->second.push_back(shortcut); } void ShortcutEventHandler::removeShortcut(Shortcut* shortcut) { - std::remove(mShortcuts.begin(), mShortcuts.end(), shortcut); + // Enforced by shortcut class + QWidget* widget = static_cast(shortcut->parent()); + + ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget); + if (shortcutListIt != mWidgetShortcuts.end()) + { + std::remove(shortcutListIt->second.begin(), shortcutListIt->second.end(), shortcut); + } } bool ShortcutEventHandler::eventFilter(QObject* watched, QEvent* event) { + // Process event if (event->type() == QEvent::KeyPress) { + QWidget* widget = static_cast(watched); QKeyEvent* keyEvent = static_cast(event); unsigned int mod = (unsigned int) keyEvent->modifiers(); unsigned int key = (unsigned int) keyEvent->key(); if (!keyEvent->isAutoRepeat()) - return activate(mod, key); + return activate(widget, mod, key); } else if (event->type() == QEvent::KeyRelease) { + QWidget* widget = static_cast(watched); QKeyEvent* keyEvent = static_cast(event); unsigned int mod = (unsigned int) keyEvent->modifiers(); unsigned int key = (unsigned int) keyEvent->key(); if (!keyEvent->isAutoRepeat()) - return deactivate(mod, key); + return deactivate(widget, mod, key); } else if (event->type() == QEvent::MouseButtonPress) { + QWidget* widget = static_cast(watched); QMouseEvent* mouseEvent = static_cast(event); unsigned int mod = (unsigned int) mouseEvent->modifiers(); unsigned int button = (unsigned int) mouseEvent->button(); - return activate(mod, button); + return activate(widget, mod, button); } else if (event->type() == QEvent::MouseButtonRelease) { + QWidget* widget = static_cast(watched); QMouseEvent* mouseEvent = static_cast(event); unsigned int mod = (unsigned int) mouseEvent->modifiers(); unsigned int button = (unsigned int) mouseEvent->button(); - return deactivate(mod, button); + return deactivate(widget, mod, button); } else if (event->type() == QEvent::FocusOut) { + QWidget* widget = static_cast(watched); + ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget); + // Deactivate in case events are missed - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) + for (ShortcutList::iterator it = shortcutListIt->second.begin(); it != shortcutListIt->second.end(); ++it) { Shortcut* shortcut = *it; @@ -85,41 +119,76 @@ namespace CSMPrefs } } } + else if (event->type() == QEvent::FocusIn) + { + QWidget* widget = static_cast(watched); + updateParent(widget); + } return false; } - bool ShortcutEventHandler::activate(unsigned int mod, unsigned int button) + void ShortcutEventHandler::updateParent(QWidget* widget) + { + QWidget* parent = widget->parentWidget(); + while (parent) + { + ShortcutMap::iterator parentIt = mWidgetShortcuts.find(parent); + if (parentIt != mWidgetShortcuts.end()) + { + mChildParentRelations.insert(std::make_pair(widget, parent)); + break; + } + + // Check next + parent = parent->parentWidget(); + } + } + + bool ShortcutEventHandler::activate(QWidget* widget, unsigned int mod, unsigned int button) { std::vector > potentials; bool used = false; - // Find potential activations - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) + while (widget) { - Shortcut* shortcut = *it; + ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget); + assert(shortcutListIt != mWidgetShortcuts.end()); - if (!shortcut->isEnabled()) - continue; + // Find potential activations + for (ShortcutList::iterator it = shortcutListIt->second.begin(); it != shortcutListIt->second.end(); ++it) + { + Shortcut* shortcut = *it; - int pos = shortcut->getPosition(); - int lastPos = shortcut->getLastPosition(); - MatchResult result = match(mod, button, shortcut->getSequence()[pos]); + if (!shortcut->isEnabled()) + continue; - if (result == Matches_WithMod || result == Matches_NoMod) - { - if (pos < lastPos && (result == Matches_WithMod || pos > 0)) - { - shortcut->setPosition(pos+1); - } - else if (pos == lastPos) + if (checkModifier(mod, button, shortcut, true)) + used = true; + + if (shortcut->getActivationStatus() != Shortcut::AS_Inactive) + continue; + + int pos = shortcut->getPosition(); + int lastPos = shortcut->getLastPosition(); + MatchResult result = match(mod, button, shortcut->getSequence()[pos]); + + if (result == Matches_WithMod || result == Matches_NoMod) { - potentials.push_back(std::make_pair(result, shortcut)); + if (pos < lastPos && (result == Matches_WithMod || pos > 0)) + { + shortcut->setPosition(pos+1); + } + else if (pos == lastPos) + { + potentials.push_back(std::make_pair(result, shortcut)); + } } } - if (checkModifier(mod, button, shortcut, true)) - used = true; + // Move on to parent + WidgetMap::iterator widgetIt = mChildParentRelations.find(widget); + widget = (widgetIt != mChildParentRelations.end()) ? widgetIt->second : 0; } // Only activate the best match; in exact conflicts, this will favor the first shortcut added. @@ -147,39 +216,49 @@ namespace CSMPrefs return used; } - bool ShortcutEventHandler::deactivate(unsigned int mod, unsigned int button) + bool ShortcutEventHandler::deactivate(QWidget* widget, unsigned int mod, unsigned int button) { const int KeyMask = 0x01FFFFFF; bool used = false; - for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) + while (widget) { - Shortcut* shortcut = *it; + ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget); + assert(shortcutListIt != mWidgetShortcuts.end()); - if (checkModifier(mod, button, shortcut, false)) - used = true; - - int pos = shortcut->getPosition(); - MatchResult result = match(0, button, shortcut->getSequence()[pos] & KeyMask); - - if (result != Matches_Not) + for (ShortcutList::iterator it = shortcutListIt->second.begin(); it != shortcutListIt->second.end(); ++it) { - shortcut->setPosition(0); + Shortcut* shortcut = *it; - if (shortcut->getActivationStatus() == Shortcut::AS_Regular) - { - shortcut->setActivationStatus(Shortcut::AS_Inactive); - shortcut->signalActivated(false); + if (checkModifier(mod, button, shortcut, false)) used = true; - } - else if (shortcut->getActivationStatus() == Shortcut::AS_Secondary) + + int pos = shortcut->getPosition(); + MatchResult result = match(0, button, shortcut->getSequence()[pos] & KeyMask); + + if (result != Matches_Not) { - shortcut->setActivationStatus(Shortcut::AS_Inactive); - shortcut->signalSecondary(false); - used = true; + shortcut->setPosition(0); + + if (shortcut->getActivationStatus() == Shortcut::AS_Regular) + { + shortcut->setActivationStatus(Shortcut::AS_Inactive); + shortcut->signalActivated(false); + used = true; + } + else if (shortcut->getActivationStatus() == Shortcut::AS_Secondary) + { + shortcut->setActivationStatus(Shortcut::AS_Inactive); + shortcut->signalSecondary(false); + used = true; + } } } + + // Move on to parent + WidgetMap::iterator widgetIt = mChildParentRelations.find(widget); + widget = (widgetIt != mChildParentRelations.end()) ? widgetIt->second : 0; } return used; @@ -187,7 +266,8 @@ namespace CSMPrefs bool ShortcutEventHandler::checkModifier(unsigned int mod, unsigned int button, Shortcut* shortcut, bool activate) { - if (!shortcut->isEnabled() || !shortcut->getModifier() || shortcut->getSecondaryMode() == Shortcut::SM_Ignore) + if (!shortcut->isEnabled() || !shortcut->getModifier() || shortcut->getSecondaryMode() == Shortcut::SM_Ignore || + shortcut->getModifierStatus() == activate) return false; MatchResult result = match(mod, button, shortcut->getModifier()); @@ -208,8 +288,6 @@ namespace CSMPrefs { shortcut->signalSecondary(false); } - - used = true; } else if (!activate && shortcut->getActivationStatus() == Shortcut::AS_Secondary) { @@ -243,9 +321,17 @@ namespace CSMPrefs bool ShortcutEventHandler::sort(const std::pair& left, const std::pair& right) { - if (left.first == Matches_WithMod && left.first != right.first) + if (left.first == Matches_WithMod && right.first == Matches_NoMod) return true; else return left.second->getPosition() >= right.second->getPosition(); } + + void ShortcutEventHandler::widgetDestroyed() + { + QWidget* widget = static_cast(sender()); + + mWidgetShortcuts.erase(widget); + mChildParentRelations.erase(widget); + } } diff --git a/apps/opencs/model/prefs/shortcuteventhandler.hpp b/apps/opencs/model/prefs/shortcuteventhandler.hpp index d6a0d16ec..6a7ba2522 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.hpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.hpp @@ -1,6 +1,7 @@ #ifndef CSM_PREFS_SHORTCUT_EVENT_HANDLER_H #define CSM_PREFS_SHORTCUT_EVENT_HANDLER_H +#include #include #include @@ -19,7 +20,7 @@ namespace CSMPrefs public: - ShortcutEventHandler(QObject* parent=0); + ShortcutEventHandler(QObject* parent); void addShortcut(Shortcut* shortcut); void removeShortcut(Shortcut* shortcut); @@ -30,6 +31,11 @@ namespace CSMPrefs private: + typedef std::vector ShortcutList; + // Child, Parent + typedef std::map WidgetMap; + typedef std::map ShortcutMap; + enum MatchResult { Matches_WithMod, @@ -37,9 +43,11 @@ namespace CSMPrefs Matches_Not }; - bool activate(unsigned int mod, unsigned int button); + void updateParent(QWidget* widget); + + bool activate(QWidget* widget, unsigned int mod, unsigned int button); - bool deactivate(unsigned int mod, unsigned int button); + bool deactivate(QWidget* widget, unsigned int mod, unsigned int button); bool checkModifier(unsigned int mod, unsigned int button, Shortcut* shortcut, bool activate); @@ -49,7 +57,12 @@ namespace CSMPrefs static bool sort(const std::pair& left, const std::pair& right); - std::vector mShortcuts; + WidgetMap mChildParentRelations; + ShortcutMap mWidgetShortcuts; + + private slots: + + void widgetDestroyed(); }; } diff --git a/apps/opencs/model/prefs/shortcutmanager.cpp b/apps/opencs/model/prefs/shortcutmanager.cpp index f8e9ccb8a..300c2b61a 100644 --- a/apps/opencs/model/prefs/shortcutmanager.cpp +++ b/apps/opencs/model/prefs/shortcutmanager.cpp @@ -3,17 +3,25 @@ #include #include +#include #include #include #include #include "shortcut.hpp" +#include "shortcuteventhandler.hpp" namespace CSMPrefs { + ShortcutManager::ShortcutManager() + { + mEventHandler = new ShortcutEventHandler(this); + } + void ShortcutManager::addShortcut(Shortcut* shortcut) { mShortcuts.insert(std::make_pair(shortcut->getName(), shortcut)); + mEventHandler->addShortcut(shortcut); } void ShortcutManager::removeShortcut(Shortcut* shortcut) @@ -31,6 +39,8 @@ namespace CSMPrefs ++it; } } + + mEventHandler->removeShortcut(shortcut); } ShortcutManager::SequenceData ShortcutManager::getSequence(const std::string& name) const diff --git a/apps/opencs/model/prefs/shortcutmanager.hpp b/apps/opencs/model/prefs/shortcutmanager.hpp index 60cdefe36..fe813341c 100644 --- a/apps/opencs/model/prefs/shortcutmanager.hpp +++ b/apps/opencs/model/prefs/shortcutmanager.hpp @@ -9,6 +9,7 @@ namespace CSMPrefs { class Shortcut; + class ShortcutEventHandler; /// Class used to track and update shortcuts/sequences class ShortcutManager : public QObject @@ -20,6 +21,9 @@ namespace CSMPrefs /// Key Sequence, Modifier (for secondary signal) typedef std::pair SequenceData; + + ShortcutManager(); + /// The shortcut class will do this automatically void addShortcut(Shortcut* shortcut); @@ -40,6 +44,8 @@ namespace CSMPrefs ShortcutMap mShortcuts; SequenceMap mSequences; + + ShortcutEventHandler* mEventHandler; }; } diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index cfb06f21a..75e15c08c 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -229,6 +229,10 @@ void CSMPrefs::State::declare() addValues (insertOutsideVisibleCell); declareCategory ("Key Bindings"); + + declareShortcut ("document-save", "Save", QKeySequence(Qt::ControlModifier | Qt::Key_S)); + + declareSeparator (); declareShortcut ("free-forward", "Free camera forward", QKeySequence(Qt::Key_W), Qt::Key_Shift); declareShortcut ("free-backward", "Free camera backward", QKeySequence(Qt::Key_S)); declareShortcut ("free-left", "Free camera left", QKeySequence(Qt::Key_A)); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 6f14e5a4d..bc4230dfd 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -16,6 +16,7 @@ #include "../../model/doc/document.hpp" #include "../../model/prefs/state.hpp" +#include "../../model/prefs/shortcut.hpp" #include "../../model/world/idtable.hpp" @@ -62,6 +63,9 @@ void CSVDoc::View::setupFileMenu() connect (mSave, SIGNAL (triggered()), this, SLOT (save())); file->addAction (mSave); + CSMPrefs::Shortcut* saveShortcut = new CSMPrefs::Shortcut("document-save", this); + connect (saveShortcut, SIGNAL(activated()), this, SLOT(save())); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); file->addAction (mVerify); diff --git a/apps/opencs/view/render/cameracontroller.cpp b/apps/opencs/view/render/cameracontroller.cpp index df71a9b88..6df7c0478 100644 --- a/apps/opencs/view/render/cameracontroller.cpp +++ b/apps/opencs/view/render/cameracontroller.cpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include @@ -15,7 +15,6 @@ #include #include "../../model/prefs/shortcut.hpp" -#include "../../model/prefs/shortcuteventhandler.hpp" #include "scenewidget.hpp" @@ -79,27 +78,17 @@ namespace CSVRender void CameraController::setCamera(osg::Camera* camera) { + bool wasActive = mActive; + mCamera = camera; mActive = (mCamera != NULL); - if (mActive) + if (mActive != wasActive) { - onActivate(); - - QList shortcuts = findChildren(); - - for (QList::iterator it = shortcuts.begin(); it != shortcuts.end(); ++it) + for (std::vector::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it) { - (*it)->enable(true); - } - } - else - { - QList shortcuts = findChildren(); - - for (QList::iterator it = shortcuts.begin(); it != shortcuts.end(); ++it) - { - (*it)->enable(false); + CSMPrefs::Shortcut* shortcut = *it; + shortcut->enable(mActive); } } } @@ -160,14 +149,21 @@ namespace CSVRender getCamera()->setViewMatrixAsLookAt(eye, center, up); } + void CameraController::addShortcut(CSMPrefs::Shortcut* shortcut) + { + mShortcuts.push_back(shortcut); + } + /* Free Camera Controller */ - FreeCameraController::FreeCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent) - : CameraController(parent) + FreeCameraController::FreeCameraController(QWidget* widget) + : CameraController(widget) , mLockUpright(false) , mModified(false) + , mNaviPrimary(false) + , mNaviSecondary(false) , mFast(false) , mFastAlternate(false) , mLeft(false) @@ -181,52 +177,61 @@ namespace CSVRender , mRotSpeed(osg::PI / 2) , mSpeedMult(8) { - CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", this); + CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", widget); naviPrimaryShortcut->enable(false); - handler->addShortcut(naviPrimaryShortcut); connect(naviPrimaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviPrimary(bool))); - CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", this); + addShortcut(naviPrimaryShortcut); + + CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", widget); naviSecondaryShortcut->enable(false); - handler->addShortcut(naviSecondaryShortcut); connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool))); + addShortcut(naviSecondaryShortcut); + CSMPrefs::Shortcut* forwardShortcut = new CSMPrefs::Shortcut("free-forward", CSMPrefs::Shortcut::SM_Detach, - this); + widget); forwardShortcut->enable(false); - handler->addShortcut(forwardShortcut); connect(forwardShortcut, SIGNAL(activated(bool)), this, SLOT(forward(bool))); connect(forwardShortcut, SIGNAL(secondary(bool)), this, SLOT(alternateFast(bool))); - CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("free-left", this); + addShortcut(forwardShortcut); + + CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("free-left", widget); leftShortcut->enable(false); - handler->addShortcut(leftShortcut); connect(leftShortcut, SIGNAL(activated(bool)), this, SLOT(left(bool))); - CSMPrefs::Shortcut* backShortcut = new CSMPrefs::Shortcut("free-backward", this); + addShortcut(leftShortcut); + + CSMPrefs::Shortcut* backShortcut = new CSMPrefs::Shortcut("free-backward", widget); backShortcut->enable(false); - handler->addShortcut(backShortcut); connect(backShortcut, SIGNAL(activated(bool)), this, SLOT(backward(bool))); - CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("free-right", this); + addShortcut(backShortcut); + + CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("free-right", widget); rightShortcut->enable(false); - handler->addShortcut(rightShortcut); connect(rightShortcut, SIGNAL(activated(bool)), this, SLOT(right(bool))); - CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("free-roll-left", this); + addShortcut(rightShortcut); + + CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("free-roll-left", widget); rollLeftShortcut->enable(false); - handler->addShortcut(rollLeftShortcut); connect(rollLeftShortcut, SIGNAL(activated(bool)), this, SLOT(rollLeft(bool))); - CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("free-roll-right", this); + addShortcut(rollLeftShortcut); + + CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("free-roll-right", widget); rollRightShortcut->enable(false); - handler->addShortcut(rollRightShortcut); connect(rollRightShortcut, SIGNAL(activated(bool)), this, SLOT(rollRight(bool))); - CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("free-speed-mode", this); + addShortcut(rollRightShortcut); + + CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("free-speed-mode", widget); speedModeShortcut->enable(false); - handler->addShortcut(speedModeShortcut); connect(speedModeShortcut, SIGNAL(activated()), this, SLOT(swapSpeedMode())); + + addShortcut(speedModeShortcut); } double FreeCameraController::getLinearSpeed() const @@ -440,9 +445,11 @@ namespace CSVRender Orbit Camera Controller */ - OrbitCameraController::OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent) - : CameraController(parent) + OrbitCameraController::OrbitCameraController(QWidget* widget) + : CameraController(widget) , mInitialized(false) + , mNaviPrimary(false) + , mNaviSecondary(false) , mFast(false) , mFastAlternate(false) , mLeft(false) @@ -457,51 +464,60 @@ namespace CSVRender , mOrbitSpeed(osg::PI / 4) , mOrbitSpeedMult(4) { - CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", this); + CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", widget); naviPrimaryShortcut->enable(false); - handler->addShortcut(naviPrimaryShortcut); connect(naviPrimaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviPrimary(bool))); - CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", this); + addShortcut(naviPrimaryShortcut); + + CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", widget); naviSecondaryShortcut->enable(false); - handler->addShortcut(naviSecondaryShortcut); connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool))); - CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", CSMPrefs::Shortcut::SM_Detach, this); + addShortcut(naviSecondaryShortcut); + + CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", CSMPrefs::Shortcut::SM_Detach, widget); upShortcut->enable(false); - handler->addShortcut(upShortcut); connect(upShortcut, SIGNAL(activated(bool)), this, SLOT(up(bool))); connect(upShortcut, SIGNAL(secondary(bool)), this, SLOT(alternateFast(bool))); - CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("orbit-left", this); + addShortcut(upShortcut); + + CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("orbit-left", widget); leftShortcut->enable(false); - handler->addShortcut(leftShortcut); connect(leftShortcut, SIGNAL(activated(bool)), this, SLOT(left(bool))); - CSMPrefs::Shortcut* downShortcut = new CSMPrefs::Shortcut("orbit-down", this); + addShortcut(leftShortcut); + + CSMPrefs::Shortcut* downShortcut = new CSMPrefs::Shortcut("orbit-down", widget); downShortcut->enable(false); - handler->addShortcut(downShortcut); connect(downShortcut, SIGNAL(activated(bool)), this, SLOT(down(bool))); - CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("orbit-right", this); + addShortcut(downShortcut); + + CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("orbit-right", widget); rightShortcut->enable(false); - handler->addShortcut(rightShortcut); connect(rightShortcut, SIGNAL(activated(bool)), this, SLOT(right(bool))); - CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("orbit-roll-left", this); + addShortcut(rightShortcut); + + CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("orbit-roll-left", widget); rollLeftShortcut->enable(false); - handler->addShortcut(rollLeftShortcut); connect(rollLeftShortcut, SIGNAL(activated(bool)), this, SLOT(rollLeft(bool))); - CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("orbit-roll-right", this); + addShortcut(rollLeftShortcut); + + CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("orbit-roll-right", widget); rollRightShortcut->enable(false); - handler->addShortcut(rollRightShortcut); connect(rollRightShortcut, SIGNAL(activated(bool)), this, SLOT(rollRight(bool))); - CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("orbit-speed-mode", this); + addShortcut(rollRightShortcut); + + CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("orbit-speed-mode", widget); speedModeShortcut->enable(false); - handler->addShortcut(speedModeShortcut); connect(speedModeShortcut, SIGNAL(activated()), this, SLOT(swapSpeedMode())); + + addShortcut(speedModeShortcut); } osg::Vec3d OrbitCameraController::getCenter() const diff --git a/apps/opencs/view/render/cameracontroller.hpp b/apps/opencs/view/render/cameracontroller.hpp index 45ccfc14e..97af85790 100644 --- a/apps/opencs/view/render/cameracontroller.hpp +++ b/apps/opencs/view/render/cameracontroller.hpp @@ -2,14 +2,13 @@ #define OPENCS_VIEW_CAMERACONTROLLER_H #include +#include #include #include #include -class QKeyEvent; - namespace osg { class Camera; @@ -18,7 +17,7 @@ namespace osg namespace CSMPrefs { - class ShortcutEventHandler; + class Shortcut; } namespace CSVRender @@ -66,6 +65,8 @@ namespace CSVRender virtual void onActivate(){} + void addShortcut(CSMPrefs::Shortcut* shortcut); + private: bool mActive, mInverted; @@ -74,6 +75,8 @@ namespace CSVRender double mWheelMoveMult; osg::Camera* mCamera; + + std::vector mShortcuts; }; class FreeCameraController : public CameraController @@ -82,7 +85,7 @@ namespace CSVRender public: - FreeCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent=0); + FreeCameraController(QWidget* parent); double getLinearSpeed() const; double getRotationalSpeed() const; @@ -139,7 +142,7 @@ namespace CSVRender public: - OrbitCameraController(CSMPrefs::ShortcutEventHandler* handler, QObject* parent=0); + OrbitCameraController(QWidget* parent); osg::Vec3d getCenter() const; double getOrbitSpeed() const; diff --git a/apps/opencs/view/render/orbitcameramode.cpp b/apps/opencs/view/render/orbitcameramode.cpp index 6c4fb1f1e..286bab3e4 100644 --- a/apps/opencs/view/render/orbitcameramode.cpp +++ b/apps/opencs/view/render/orbitcameramode.cpp @@ -9,22 +9,19 @@ namespace CSVRender { - OrbitCameraMode::OrbitCameraMode(WorldspaceWidget* worldspaceWidget, CSMPrefs::ShortcutEventHandler* handler, - const QIcon& icon, const QString& tooltip, QWidget* parent) + OrbitCameraMode::OrbitCameraMode(WorldspaceWidget* worldspaceWidget, const QIcon& icon, const QString& tooltip, + QWidget* parent) : ModeButton(icon, tooltip, parent) , mWorldspaceWidget(worldspaceWidget) - , mShortcutHandler(handler) , mCenterOnSelection(0) { - mCenterShortcut = new CSMPrefs::Shortcut("orbit-center-selection", this); + mCenterShortcut.reset(new CSMPrefs::Shortcut("orbit-center-selection", worldspaceWidget)); mCenterShortcut->enable(false); - mShortcutHandler->addShortcut(mCenterShortcut); - connect(mCenterShortcut, SIGNAL(activated()), this, SLOT(centerSelection())); + connect(mCenterShortcut.get(), SIGNAL(activated()), this, SLOT(centerSelection())); } OrbitCameraMode::~OrbitCameraMode() { - mShortcutHandler->removeShortcut(mCenterShortcut); } void OrbitCameraMode::activate(CSVWidget::SceneToolbar* toolbar) diff --git a/apps/opencs/view/render/orbitcameramode.hpp b/apps/opencs/view/render/orbitcameramode.hpp index 990999b22..4f72de957 100644 --- a/apps/opencs/view/render/orbitcameramode.hpp +++ b/apps/opencs/view/render/orbitcameramode.hpp @@ -1,12 +1,13 @@ #ifndef CSV_RENDER_ORBITCAMERAPICKMODE_H #define CSV_RENDER_ORBITCAMERAPICKMODE_H +#include + #include "../widget/modebutton.hpp" namespace CSMPrefs { class Shortcut; - class ShortcutEventHandler; } namespace CSVRender @@ -19,8 +20,8 @@ namespace CSVRender public: - OrbitCameraMode(WorldspaceWidget* worldspaceWidget, CSMPrefs::ShortcutEventHandler* shortcutHandler, - const QIcon& icon, const QString& tooltip = "", QWidget* parent = 0); + OrbitCameraMode(WorldspaceWidget* worldspaceWidget, const QIcon& icon, const QString& tooltip = "", + QWidget* parent = 0); ~OrbitCameraMode(); virtual void activate(CSVWidget::SceneToolbar* toolbar); @@ -30,9 +31,8 @@ namespace CSVRender private: WorldspaceWidget* mWorldspaceWidget; - CSMPrefs::ShortcutEventHandler* mShortcutHandler; QAction* mCenterOnSelection; - CSMPrefs::Shortcut* mCenterShortcut; + std::auto_ptr mCenterShortcut; private slots: diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index c32427863..65c7a89f4 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -171,11 +171,8 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys , mPrevMouseY(0) , mCamPositionSet(false) { - mShortcutHandler = new CSMPrefs::ShortcutEventHandler(this); - installEventFilter(mShortcutHandler); - - mFreeCamControl = new FreeCameraController(mShortcutHandler, this); - mOrbitCamControl = new OrbitCameraController(mShortcutHandler, this); + mFreeCamControl = new FreeCameraController(this); + mOrbitCamControl = new OrbitCameraController(this); mCurrentCamControl = mFreeCamControl; mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain); @@ -205,18 +202,14 @@ SceneWidget::SceneWidget(boost::shared_ptr resourceSys // Shortcuts CSMPrefs::Shortcut* focusToolbarShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this); - mShortcutHandler->addShortcut(focusToolbarShortcut); connect(focusToolbarShortcut, SIGNAL(activated()), this, SIGNAL(focusToolbarRequest())); CSMPrefs::Shortcut* renderStatsShortcut = new CSMPrefs::Shortcut("scene-render-stats", this); - mShortcutHandler->addShortcut(renderStatsShortcut); connect(renderStatsShortcut, SIGNAL(activated()), this, SLOT(toggleRenderStats())); } SceneWidget::~SceneWidget() { - removeEventFilter(mShortcutHandler); - // Since we're holding on to the scene templates past the existance of this graphics context, we'll need to manually release the created objects mResourceSystem->getSceneManager()->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState()); } diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index fbe5bc13e..723d93c00 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -37,8 +37,6 @@ namespace CSVWidget namespace CSMPrefs { class Setting; - class Shortcut; - class ShortcutEventHandler; } namespace CSVRender @@ -116,8 +114,6 @@ namespace CSVRender OrbitCameraController* mOrbitCamControl; CameraController* mCurrentCamControl; - CSMPrefs::ShortcutEventHandler *mShortcutHandler; - private: bool mCamPositionSet; diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index ab6a525d9..fa2a755f2 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -98,23 +98,18 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg // Shortcuts CSMPrefs::Shortcut* primaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-primary", this); - mShortcutHandler->addShortcut(primaryEditShortcut); connect(primaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(primaryEdit(bool))); CSMPrefs::Shortcut* secondaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-secondary", this); - mShortcutHandler->addShortcut(secondaryEditShortcut); connect(secondaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(secondaryEdit(bool))); CSMPrefs::Shortcut* primarySelectShortcut = new CSMPrefs::Shortcut("scene-select-primary", this); - mShortcutHandler->addShortcut(primarySelectShortcut); connect(primarySelectShortcut, SIGNAL(activated(bool)), this, SLOT(primarySelect(bool))); CSMPrefs::Shortcut* secondarySelectShortcut = new CSMPrefs::Shortcut("scene-select-secondary", this); - mShortcutHandler->addShortcut(secondarySelectShortcut); connect(secondarySelectShortcut, SIGNAL(activated(bool)), this, SLOT(secondarySelect(bool))); CSMPrefs::Shortcut* abortShortcut = new CSMPrefs::Shortcut("scene-edit-abort", this); - mShortcutHandler->addShortcut(abortShortcut); connect(abortShortcut, SIGNAL(activated()), this, SLOT(abortDrag())); } @@ -184,7 +179,7 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( "
  • Hold shift to speed up movement
  • " ""); tool->addButton( - new CSVRender::OrbitCameraMode(this, mShortcutHandler, QIcon(":scenetoolbar/orbiting-camera"), + new CSVRender::OrbitCameraMode(this, QIcon(":scenetoolbar/orbiting-camera"), "Orbiting Camera" "
    • Always facing the centre point
    • " "
    • Rotate around the centre point via WASD or by moving the mouse while holding the left button
    • " diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 8a8ce1c6f..f3c31f896 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -15,7 +15,6 @@ namespace CSMPrefs { class Setting; - class Shortcut; } namespace CSMWorld