Redesigned shortcut handler to be capable of dealing with child and

parent widgets. This should be the final design change. Also, some
various bug fixes.
pull/990/head
Aesylwinn 9 years ago
parent acdb636935
commit f251c3867d

@ -1,15 +1,15 @@
#include "shortcut.hpp"
#include <QKeyEvent>
#include <QMouseEvent>
#include <QShortcut>
#include <cassert>
#include <QWidget>
#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);

@ -7,9 +7,7 @@
#include <QObject>
#include <QString>
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();

@ -1,7 +1,7 @@
#include "shortcuteventhandler.hpp"
#include <algorithm>
#include <iostream>
#include <cassert>
#include <QEvent>
#include <QKeyEvent>
@ -19,54 +19,88 @@ namespace CSMPrefs
void ShortcutEventHandler::addShortcut(Shortcut* shortcut)
{
mShortcuts.push_back(shortcut);
// Enforced by shortcut class
QWidget* widget = static_cast<QWidget*>(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<QWidget*>(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<QWidget*>(watched);
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(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<QWidget*>(watched);
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(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<QWidget*>(watched);
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(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<QWidget*>(watched);
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(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<QWidget*>(watched);
ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget);
// Deactivate in case events are missed
for (std::vector<Shortcut*>::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<QWidget*>(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<std::pair<MatchResult, Shortcut*> > potentials;
bool used = false;
// Find potential activations
for (std::vector<Shortcut*>::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<Shortcut*>::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<MatchResult, Shortcut*>& left,
const std::pair<MatchResult, Shortcut*>& 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<QWidget*>(sender());
mWidgetShortcuts.erase(widget);
mChildParentRelations.erase(widget);
}
}

@ -1,6 +1,7 @@
#ifndef CSM_PREFS_SHORTCUT_EVENT_HANDLER_H
#define CSM_PREFS_SHORTCUT_EVENT_HANDLER_H
#include <map>
#include <vector>
#include <QObject>
@ -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<Shortcut*> ShortcutList;
// Child, Parent
typedef std::map<QWidget*, QWidget*> WidgetMap;
typedef std::map<QWidget*, ShortcutList> 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<MatchResult, Shortcut*>& left,
const std::pair<MatchResult, Shortcut*>& right);
std::vector<Shortcut*> mShortcuts;
WidgetMap mChildParentRelations;
ShortcutMap mWidgetShortcuts;
private slots:
void widgetDestroyed();
};
}

@ -3,17 +3,25 @@
#include <sstream>
#include <iostream>
#include <QApplication>
#include <QMetaEnum>
#include <QRegExp>
#include <QStringList>
#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

@ -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<QKeySequence, int> 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;
};
}

@ -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));

@ -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);

@ -2,7 +2,7 @@
#include <cmath>
#include <QKeyEvent>
#include <QWidget>
#include <osg/BoundingBox>
#include <osg/Camera>
@ -15,7 +15,6 @@
#include <osgUtil/LineSegmentIntersector>
#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<CSMPrefs::Shortcut*> shortcuts = findChildren<CSMPrefs::Shortcut*>();
for (QList<CSMPrefs::Shortcut*>::iterator it = shortcuts.begin(); it != shortcuts.end(); ++it)
for (std::vector<CSMPrefs::Shortcut*>::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it)
{
(*it)->enable(true);
}
}
else
{
QList<CSMPrefs::Shortcut*> shortcuts = findChildren<CSMPrefs::Shortcut*>();
for (QList<CSMPrefs::Shortcut*>::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

@ -2,14 +2,13 @@
#define OPENCS_VIEW_CAMERACONTROLLER_H
#include <string>
#include <vector>
#include <QObject>
#include <osg/ref_ptr>
#include <osg/Vec3d>
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<CSMPrefs::Shortcut*> 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;

@ -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)

@ -1,12 +1,13 @@
#ifndef CSV_RENDER_ORBITCAMERAPICKMODE_H
#define CSV_RENDER_ORBITCAMERAPICKMODE_H
#include <memory>
#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<CSMPrefs::Shortcut> mCenterShortcut;
private slots:

@ -171,11 +171,8 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> 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<Resource::ResourceSystem> 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());
}

@ -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;

@ -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 (
"<li>Hold shift to speed up movement</li>"
"</ul>");
tool->addButton(
new CSVRender::OrbitCameraMode(this, mShortcutHandler, QIcon(":scenetoolbar/orbiting-camera"),
new CSVRender::OrbitCameraMode(this, QIcon(":scenetoolbar/orbiting-camera"),
"Orbiting Camera"
"<ul><li>Always facing the centre point</li>"
"<li>Rotate around the centre point via WASD or by moving the mouse while holding the left button</li>"

@ -15,7 +15,6 @@
namespace CSMPrefs
{
class Setting;
class Shortcut;
}
namespace CSMWorld

Loading…
Cancel
Save