Merge pull request #29 from OpenMW/master
Add OpenMW commits from end of July
17
.gitignore
vendored
|
@ -10,7 +10,6 @@ prebuilt
|
|||
|
||||
## doxygen
|
||||
Doxygen
|
||||
!docs/cs-manual/Makefile
|
||||
|
||||
## ides/editors
|
||||
*~
|
||||
|
@ -35,17 +34,15 @@ resources
|
|||
|
||||
## binaries
|
||||
/esmtool
|
||||
/mwiniimport
|
||||
/omwlauncher
|
||||
/openmw
|
||||
/opencs
|
||||
/niftest
|
||||
bsatool
|
||||
openmw-cs
|
||||
openmw-essimporter
|
||||
openmw-iniimporter
|
||||
openmw-launcher
|
||||
openmw-wizard
|
||||
/bsatool
|
||||
/openmw-cs
|
||||
/openmw-essimporter
|
||||
/openmw-iniimporter
|
||||
/openmw-launcher
|
||||
/openmw-wizard
|
||||
|
||||
## generated objects
|
||||
apps/openmw/config.hpp
|
||||
|
@ -80,4 +77,4 @@ moc_*.cxx
|
|||
*.so
|
||||
gamecontrollerdb.txt
|
||||
openmw.appdata.xml
|
||||
|
||||
venv/
|
||||
|
|
|
@ -77,6 +77,14 @@ option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
|
|||
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF)
|
||||
option(BUILD_NIFTEST "build nif file tester" OFF)
|
||||
option(BUILD_MYGUI_PLUGIN "build MyGUI plugin for OpenMW resources, to use with MyGUI tools" ON)
|
||||
option(BUILD_DOCS "build documentation." OFF )
|
||||
|
||||
# what is necessary to build documentation
|
||||
IF( BUILD_DOCS )
|
||||
# Builds the documentation.
|
||||
FIND_PACKAGE( Sphinx REQUIRED )
|
||||
FIND_PACKAGE( Doxygen REQUIRED )
|
||||
ENDIF()
|
||||
|
||||
# OS X deployment
|
||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||
|
|
|
@ -86,12 +86,12 @@ opencs_units (view/widget
|
|||
opencs_units (view/render
|
||||
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
|
||||
previewwidget editmode instancemode instanceselectionmode instancemovemode
|
||||
orbitcameramode pathgridmode selectionmode pathgridselectionmode
|
||||
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/render
|
||||
lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
|
||||
cellarrow cellmarker cellborder cameracontroller pathgrid
|
||||
cellarrow cellmarker cellborder pathgrid
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (view/render
|
||||
|
@ -108,11 +108,12 @@ opencs_units_noqt (view/tools
|
|||
)
|
||||
|
||||
opencs_units (view/prefs
|
||||
dialogue pagebase page
|
||||
dialogue pagebase page keybindingpage
|
||||
)
|
||||
|
||||
opencs_units (model/prefs
|
||||
state setting intsetting doublesetting boolsetting enumsetting coloursetting
|
||||
state setting intsetting doublesetting boolsetting enumsetting coloursetting shortcut
|
||||
shortcuteventhandler shortcutmanager shortcutsetting modifiersetting
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/prefs
|
||||
|
|
146
apps/opencs/model/prefs/modifiersetting.cpp
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include "modifiersetting.hpp"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
#include "state.hpp"
|
||||
#include "shortcutmanager.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
ModifierSetting::ModifierSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key,
|
||||
const std::string& label)
|
||||
: Setting(parent, values, mutex, key, label)
|
||||
, mEditorActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::pair<QWidget*, QWidget*> ModifierSetting::makeWidgets(QWidget* parent)
|
||||
{
|
||||
int modifier = 0;
|
||||
State::get().getShortcutManager().getModifier(getKey(), modifier);
|
||||
|
||||
QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(modifier).c_str());
|
||||
|
||||
QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent);
|
||||
QPushButton* widget = new QPushButton(text, parent);
|
||||
|
||||
widget->setCheckable(true);
|
||||
widget->installEventFilter(this);
|
||||
mButton = widget;
|
||||
|
||||
connect(widget, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
|
||||
|
||||
return std::make_pair(label, widget);
|
||||
}
|
||||
|
||||
bool ModifierSetting::eventFilter(QObject* target, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->isAutoRepeat())
|
||||
return true;
|
||||
|
||||
int mod = keyEvent->modifiers();
|
||||
int key = keyEvent->key();
|
||||
|
||||
return handleEvent(target, mod, key);
|
||||
}
|
||||
else if (event->type() == QEvent::MouseButtonPress)
|
||||
{
|
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
int mod = mouseEvent->modifiers();
|
||||
int button = mouseEvent->button();
|
||||
|
||||
return handleEvent(target, mod, button);
|
||||
}
|
||||
else if (event->type() == QEvent::FocusOut)
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModifierSetting::handleEvent(QObject* target, int mod, int value)
|
||||
{
|
||||
// For potential future exceptions
|
||||
const int Blacklist[] =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
const size_t BlacklistSize = sizeof(Blacklist) / sizeof(int);
|
||||
|
||||
if (!mEditorActive)
|
||||
{
|
||||
if (value == Qt::RightButton)
|
||||
{
|
||||
// Clear modifier
|
||||
int modifier = 0;
|
||||
storeValue(modifier);
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle blacklist
|
||||
for (size_t i = 0; i < BlacklistSize; ++i)
|
||||
{
|
||||
if (value == Blacklist[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Update modifier
|
||||
int modifier = value;
|
||||
storeValue(modifier);
|
||||
|
||||
resetState();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModifierSetting::storeValue(int modifier)
|
||||
{
|
||||
State::get().getShortcutManager().setModifier(getKey(), modifier);
|
||||
|
||||
// Convert to string and assign
|
||||
std::string value = State::get().getShortcutManager().convertToString(modifier);
|
||||
|
||||
{
|
||||
QMutexLocker lock(getMutex());
|
||||
getValues().setString(getKey(), getParent()->getKey(), value);
|
||||
}
|
||||
|
||||
getParent()->getState()->update(*this);
|
||||
}
|
||||
|
||||
void ModifierSetting::resetState()
|
||||
{
|
||||
mButton->setChecked(false);
|
||||
mEditorActive = false;
|
||||
|
||||
// Button text
|
||||
int modifier = 0;
|
||||
State::get().getShortcutManager().getModifier(getKey(), modifier);
|
||||
|
||||
QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(modifier).c_str());
|
||||
mButton->setText(text);
|
||||
}
|
||||
|
||||
void ModifierSetting::buttonToggled(bool checked)
|
||||
{
|
||||
if (checked)
|
||||
mButton->setText("Press keys or click here...");
|
||||
|
||||
mEditorActive = checked;
|
||||
}
|
||||
}
|
44
apps/opencs/model/prefs/modifiersetting.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef CSM_PREFS_MODIFIERSETTING_H
|
||||
#define CSM_PREFS_MODIFIERSETTING_H
|
||||
|
||||
#include <QKeySequence>
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
class QEvent;
|
||||
class QPushButton;
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class ModifierSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ModifierSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key,
|
||||
const std::string& label);
|
||||
|
||||
virtual std::pair<QWidget*, QWidget*> makeWidgets(QWidget* parent);
|
||||
|
||||
protected:
|
||||
|
||||
bool eventFilter(QObject* target, QEvent* event);
|
||||
|
||||
private:
|
||||
|
||||
bool handleEvent(QObject* target, int mod, int value);
|
||||
|
||||
void storeValue(int modifier);
|
||||
void resetState();
|
||||
|
||||
QPushButton* mButton;
|
||||
bool mEditorActive;
|
||||
|
||||
private slots:
|
||||
|
||||
void buttonToggled(bool checked);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
214
apps/opencs/model/prefs/shortcut.cpp
Normal file
|
@ -0,0 +1,214 @@
|
|||
#include "shortcut.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <QAction>
|
||||
#include <QWidget>
|
||||
|
||||
#include "state.hpp"
|
||||
#include "shortcutmanager.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
Shortcut::Shortcut(const std::string& name, QWidget* parent)
|
||||
: QObject(parent)
|
||||
, mEnabled(true)
|
||||
, mName(name)
|
||||
, mModName("")
|
||||
, mSecondaryMode(SM_Ignore)
|
||||
, mModifier(0)
|
||||
, mCurrentPos(0)
|
||||
, mLastPos(0)
|
||||
, mActivationStatus(AS_Inactive)
|
||||
, mModifierStatus(false)
|
||||
, mAction(0)
|
||||
{
|
||||
assert (parent);
|
||||
|
||||
State::get().getShortcutManager().addShortcut(this);
|
||||
State::get().getShortcutManager().getSequence(name, mSequence);
|
||||
}
|
||||
|
||||
Shortcut::Shortcut(const std::string& name, const std::string& modName, QWidget* parent)
|
||||
: QObject(parent)
|
||||
, mEnabled(true)
|
||||
, mName(name)
|
||||
, mModName(modName)
|
||||
, mSecondaryMode(SM_Ignore)
|
||||
, mModifier(0)
|
||||
, mCurrentPos(0)
|
||||
, mLastPos(0)
|
||||
, mActivationStatus(AS_Inactive)
|
||||
, mModifierStatus(false)
|
||||
, mAction(0)
|
||||
{
|
||||
assert (parent);
|
||||
|
||||
State::get().getShortcutManager().addShortcut(this);
|
||||
State::get().getShortcutManager().getSequence(name, mSequence);
|
||||
State::get().getShortcutManager().getModifier(modName, mModifier);
|
||||
}
|
||||
|
||||
Shortcut::Shortcut(const std::string& name, const std::string& modName, SecondaryMode secMode, QWidget* parent)
|
||||
: QObject(parent)
|
||||
, mEnabled(true)
|
||||
, mName(name)
|
||||
, mModName(modName)
|
||||
, mSecondaryMode(secMode)
|
||||
, mModifier(0)
|
||||
, mCurrentPos(0)
|
||||
, mLastPos(0)
|
||||
, mActivationStatus(AS_Inactive)
|
||||
, mModifierStatus(false)
|
||||
, mAction(0)
|
||||
{
|
||||
assert (parent);
|
||||
|
||||
State::get().getShortcutManager().addShortcut(this);
|
||||
State::get().getShortcutManager().getSequence(name, mSequence);
|
||||
State::get().getShortcutManager().getModifier(modName, mModifier);
|
||||
}
|
||||
|
||||
Shortcut::~Shortcut()
|
||||
{
|
||||
State::get().getShortcutManager().removeShortcut(this);
|
||||
}
|
||||
|
||||
bool Shortcut::isEnabled() const
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
const std::string& Shortcut::getName() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
const std::string& Shortcut::getModifierName() const
|
||||
{
|
||||
return mModName;
|
||||
}
|
||||
|
||||
Shortcut::SecondaryMode Shortcut::getSecondaryMode() const
|
||||
{
|
||||
return mSecondaryMode;
|
||||
}
|
||||
|
||||
const QKeySequence& Shortcut::getSequence() const
|
||||
{
|
||||
return mSequence;
|
||||
}
|
||||
|
||||
int Shortcut::getModifier() const
|
||||
{
|
||||
return mModifier;
|
||||
}
|
||||
|
||||
int Shortcut::getPosition() const
|
||||
{
|
||||
return mCurrentPos;
|
||||
}
|
||||
|
||||
int Shortcut::getLastPosition() const
|
||||
{
|
||||
return mLastPos;
|
||||
}
|
||||
|
||||
Shortcut::ActivationStatus Shortcut::getActivationStatus() const
|
||||
{
|
||||
return mActivationStatus;
|
||||
}
|
||||
|
||||
bool Shortcut::getModifierStatus() const
|
||||
{
|
||||
return mModifierStatus;
|
||||
}
|
||||
|
||||
void Shortcut::enable(bool state)
|
||||
{
|
||||
mEnabled = state;
|
||||
}
|
||||
|
||||
void Shortcut::setSequence(const QKeySequence& sequence)
|
||||
{
|
||||
mSequence = sequence;
|
||||
mCurrentPos = 0;
|
||||
mLastPos = sequence.count() - 1;
|
||||
|
||||
if (mAction)
|
||||
{
|
||||
mAction->setText(mActionText + "\t" + State::get().getShortcutManager().convertToString(mSequence).data());
|
||||
}
|
||||
}
|
||||
|
||||
void Shortcut::setModifier(int modifier)
|
||||
{
|
||||
mModifier = modifier;
|
||||
}
|
||||
|
||||
void Shortcut::setPosition(int pos)
|
||||
{
|
||||
mCurrentPos = pos;
|
||||
}
|
||||
|
||||
void Shortcut::setActivationStatus(ActivationStatus status)
|
||||
{
|
||||
mActivationStatus = status;
|
||||
}
|
||||
|
||||
void Shortcut::setModifierStatus(bool status)
|
||||
{
|
||||
mModifierStatus = status;
|
||||
}
|
||||
|
||||
void Shortcut::associateAction(QAction* action)
|
||||
{
|
||||
if (mAction)
|
||||
{
|
||||
mAction->setText(mActionText);
|
||||
|
||||
disconnect(this, SIGNAL(activated()), mAction, SLOT(trigger()));
|
||||
disconnect(mAction, SIGNAL(destroyed()), this, SLOT(actionDeleted()));
|
||||
}
|
||||
|
||||
mAction = action;
|
||||
|
||||
if (mAction)
|
||||
{
|
||||
mActionText = mAction->text();
|
||||
mAction->setText(mActionText + "\t" + State::get().getShortcutManager().convertToString(mSequence).data());
|
||||
|
||||
connect(this, SIGNAL(activated()), mAction, SLOT(trigger()));
|
||||
connect(mAction, SIGNAL(destroyed()), this, SLOT(actionDeleted()));
|
||||
}
|
||||
}
|
||||
|
||||
void Shortcut::signalActivated(bool state)
|
||||
{
|
||||
emit activated(state);
|
||||
}
|
||||
|
||||
void Shortcut::signalActivated()
|
||||
{
|
||||
emit activated();
|
||||
}
|
||||
|
||||
void Shortcut::signalSecondary(bool state)
|
||||
{
|
||||
emit secondary(state);
|
||||
}
|
||||
void Shortcut::signalSecondary()
|
||||
{
|
||||
emit secondary();
|
||||
}
|
||||
|
||||
QString Shortcut::toString() const
|
||||
{
|
||||
return QString(State::get().getShortcutManager().convertToString(mSequence, mModifier).data());
|
||||
}
|
||||
|
||||
void Shortcut::actionDeleted()
|
||||
{
|
||||
mAction = 0;
|
||||
}
|
||||
}
|
122
apps/opencs/model/prefs/shortcut.hpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
#ifndef CSM_PREFS_SHORTCUT_H
|
||||
#define CSM_PREFS_SHORTCUT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QKeySequence>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class QAction;
|
||||
class QWidget;
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
/// A class similar in purpose to QShortcut, but with the ability to use mouse buttons
|
||||
class Shortcut : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum ActivationStatus
|
||||
{
|
||||
AS_Regular,
|
||||
AS_Secondary,
|
||||
AS_Inactive
|
||||
};
|
||||
|
||||
enum SecondaryMode
|
||||
{
|
||||
SM_Replace, ///< The secondary signal replaces the regular signal when the modifier is active
|
||||
SM_Detach, ///< The secondary signal is emitted independant of the regular signal, even if not active
|
||||
SM_Ignore ///< The secondary signal will not ever be emitted
|
||||
};
|
||||
|
||||
Shortcut(const std::string& name, QWidget* parent);
|
||||
Shortcut(const std::string& name, const std::string& modName, QWidget* parent);
|
||||
Shortcut(const std::string& name, const std::string& modName, SecondaryMode secMode, QWidget* parent);
|
||||
|
||||
~Shortcut();
|
||||
|
||||
bool isEnabled() const;
|
||||
|
||||
const std::string& getName() const;
|
||||
const std::string& getModifierName() const;
|
||||
|
||||
SecondaryMode getSecondaryMode() const;
|
||||
|
||||
const QKeySequence& getSequence() const;
|
||||
int getModifier() const;
|
||||
|
||||
/// The position in the sequence
|
||||
int getPosition() const;
|
||||
/// The position in the sequence
|
||||
int getLastPosition() const;
|
||||
|
||||
ActivationStatus getActivationStatus() const;
|
||||
bool getModifierStatus() const;
|
||||
|
||||
void enable(bool state);
|
||||
|
||||
void setSequence(const QKeySequence& sequence);
|
||||
void setModifier(int modifier);
|
||||
|
||||
/// The position in the sequence
|
||||
void setPosition(int pos);
|
||||
|
||||
void setActivationStatus(ActivationStatus status);
|
||||
void setModifierStatus(bool status);
|
||||
|
||||
/// Appends the sequence to the QAction text, also keeps it up to date
|
||||
void associateAction(QAction* action);
|
||||
|
||||
// Workaround for Qt4 signals being "protected"
|
||||
void signalActivated(bool state);
|
||||
void signalActivated();
|
||||
|
||||
void signalSecondary(bool state);
|
||||
void signalSecondary();
|
||||
|
||||
QString toString() const;
|
||||
|
||||
private:
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
std::string mName;
|
||||
std::string mModName;
|
||||
SecondaryMode mSecondaryMode;
|
||||
QKeySequence mSequence;
|
||||
int mModifier;
|
||||
|
||||
int mCurrentPos;
|
||||
int mLastPos;
|
||||
|
||||
ActivationStatus mActivationStatus;
|
||||
bool mModifierStatus;
|
||||
|
||||
QAction* mAction;
|
||||
QString mActionText;
|
||||
|
||||
private slots:
|
||||
|
||||
void actionDeleted();
|
||||
|
||||
signals:
|
||||
|
||||
/// Triggered when the shortcut is activated or deactivated; can be determined from \p state
|
||||
void activated(bool state);
|
||||
|
||||
/// Convenience signal.
|
||||
void activated();
|
||||
|
||||
/// Triggered depending on SecondaryMode
|
||||
void secondary(bool state);
|
||||
|
||||
/// Convenience signal.
|
||||
void secondary();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
338
apps/opencs/model/prefs/shortcuteventhandler.cpp
Normal file
|
@ -0,0 +1,338 @@
|
|||
#include "shortcuteventhandler.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include "shortcut.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
ShortcutEventHandler::ShortcutEventHandler(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ShortcutEventHandler::addShortcut(Shortcut* 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)
|
||||
{
|
||||
// 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(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(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(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(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 (ShortcutList::iterator it = shortcutListIt->second.begin(); it != shortcutListIt->second.end(); ++it)
|
||||
{
|
||||
Shortcut* shortcut = *it;
|
||||
|
||||
shortcut->setPosition(0);
|
||||
shortcut->setModifierStatus(false);
|
||||
|
||||
if (shortcut->getActivationStatus() == Shortcut::AS_Regular)
|
||||
{
|
||||
shortcut->setActivationStatus(Shortcut::AS_Inactive);
|
||||
shortcut->signalActivated(false);
|
||||
}
|
||||
else if (shortcut->getActivationStatus() == Shortcut::AS_Secondary)
|
||||
{
|
||||
shortcut->setActivationStatus(Shortcut::AS_Inactive);
|
||||
shortcut->signalSecondary(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event->type() == QEvent::FocusIn)
|
||||
{
|
||||
QWidget* widget = static_cast<QWidget*>(watched);
|
||||
updateParent(widget);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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));
|
||||
updateParent(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;
|
||||
|
||||
while (widget)
|
||||
{
|
||||
ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget);
|
||||
assert(shortcutListIt != mWidgetShortcuts.end());
|
||||
|
||||
// Find potential activations
|
||||
for (ShortcutList::iterator it = shortcutListIt->second.begin(); it != shortcutListIt->second.end(); ++it)
|
||||
{
|
||||
Shortcut* shortcut = *it;
|
||||
|
||||
if (!shortcut->isEnabled())
|
||||
continue;
|
||||
|
||||
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)
|
||||
{
|
||||
if (pos < lastPos && (result == Matches_WithMod || pos > 0))
|
||||
{
|
||||
shortcut->setPosition(pos+1);
|
||||
}
|
||||
else if (pos == lastPos)
|
||||
{
|
||||
potentials.push_back(std::make_pair(result, shortcut));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (!potentials.empty())
|
||||
{
|
||||
std::sort(potentials.begin(), potentials.end(), ShortcutEventHandler::sort);
|
||||
Shortcut* shortcut = potentials.front().second;
|
||||
|
||||
if (shortcut->getModifierStatus() && shortcut->getSecondaryMode() == Shortcut::SM_Replace)
|
||||
{
|
||||
shortcut->setActivationStatus(Shortcut::AS_Secondary);
|
||||
shortcut->signalSecondary(true);
|
||||
shortcut->signalSecondary();
|
||||
}
|
||||
else
|
||||
{
|
||||
shortcut->setActivationStatus(Shortcut::AS_Regular);
|
||||
shortcut->signalActivated(true);
|
||||
shortcut->signalActivated();
|
||||
}
|
||||
|
||||
used = true;
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
bool ShortcutEventHandler::deactivate(QWidget* widget, unsigned int mod, unsigned int button)
|
||||
{
|
||||
const int KeyMask = 0x01FFFFFF;
|
||||
|
||||
bool used = false;
|
||||
|
||||
while (widget)
|
||||
{
|
||||
ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget);
|
||||
assert(shortcutListIt != mWidgetShortcuts.end());
|
||||
|
||||
for (ShortcutList::iterator it = shortcutListIt->second.begin(); it != shortcutListIt->second.end(); ++it)
|
||||
{
|
||||
Shortcut* shortcut = *it;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool ShortcutEventHandler::checkModifier(unsigned int mod, unsigned int button, Shortcut* shortcut, bool activate)
|
||||
{
|
||||
if (!shortcut->isEnabled() || !shortcut->getModifier() || shortcut->getSecondaryMode() == Shortcut::SM_Ignore ||
|
||||
shortcut->getModifierStatus() == activate)
|
||||
return false;
|
||||
|
||||
MatchResult result = match(mod, button, shortcut->getModifier());
|
||||
bool used = false;
|
||||
|
||||
if (result != Matches_Not)
|
||||
{
|
||||
shortcut->setModifierStatus(activate);
|
||||
|
||||
if (shortcut->getSecondaryMode() == Shortcut::SM_Detach)
|
||||
{
|
||||
if (activate)
|
||||
{
|
||||
shortcut->signalSecondary(true);
|
||||
shortcut->signalSecondary();
|
||||
}
|
||||
else
|
||||
{
|
||||
shortcut->signalSecondary(false);
|
||||
}
|
||||
}
|
||||
else if (!activate && shortcut->getActivationStatus() == Shortcut::AS_Secondary)
|
||||
{
|
||||
shortcut->setActivationStatus(Shortcut::AS_Inactive);
|
||||
shortcut->setPosition(0);
|
||||
shortcut->signalSecondary(false);
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
ShortcutEventHandler::MatchResult ShortcutEventHandler::match(unsigned int mod, unsigned int button,
|
||||
unsigned int value)
|
||||
{
|
||||
if ((mod | button) == value)
|
||||
{
|
||||
return Matches_WithMod;
|
||||
}
|
||||
else if (button == value)
|
||||
{
|
||||
return Matches_NoMod;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Matches_Not;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShortcutEventHandler::sort(const std::pair<MatchResult, Shortcut*>& left,
|
||||
const std::pair<MatchResult, Shortcut*>& right)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
69
apps/opencs/model/prefs/shortcuteventhandler.hpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#ifndef CSM_PREFS_SHORTCUT_EVENT_HANDLER_H
|
||||
#define CSM_PREFS_SHORTCUT_EVENT_HANDLER_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QEvent;
|
||||
class QWidget;
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Shortcut;
|
||||
|
||||
/// Users of this class should install it as an event handler
|
||||
class ShortcutEventHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ShortcutEventHandler(QObject* parent);
|
||||
|
||||
void addShortcut(Shortcut* shortcut);
|
||||
void removeShortcut(Shortcut* shortcut);
|
||||
|
||||
protected:
|
||||
|
||||
bool eventFilter(QObject* watched, QEvent* event);
|
||||
|
||||
private:
|
||||
|
||||
typedef std::vector<Shortcut*> ShortcutList;
|
||||
// Child, Parent
|
||||
typedef std::map<QWidget*, QWidget*> WidgetMap;
|
||||
typedef std::map<QWidget*, ShortcutList> ShortcutMap;
|
||||
|
||||
enum MatchResult
|
||||
{
|
||||
Matches_WithMod,
|
||||
Matches_NoMod,
|
||||
Matches_Not
|
||||
};
|
||||
|
||||
void updateParent(QWidget* widget);
|
||||
|
||||
bool activate(QWidget* widget, 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);
|
||||
|
||||
MatchResult match(unsigned int mod, unsigned int button, unsigned int value);
|
||||
|
||||
// Prefers Matches_WithMod and a larger number of buttons
|
||||
static bool sort(const std::pair<MatchResult, Shortcut*>& left,
|
||||
const std::pair<MatchResult, Shortcut*>& right);
|
||||
|
||||
WidgetMap mChildParentRelations;
|
||||
ShortcutMap mWidgetShortcuts;
|
||||
|
||||
private slots:
|
||||
|
||||
void widgetDestroyed();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
791
apps/opencs/model/prefs/shortcutmanager.cpp
Normal file
|
@ -0,0 +1,791 @@
|
|||
#include "shortcutmanager.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QStringList>
|
||||
|
||||
#include "shortcut.hpp"
|
||||
#include "shortcuteventhandler.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
ShortcutManager::ShortcutManager()
|
||||
{
|
||||
createLookupTables();
|
||||
mEventHandler = new ShortcutEventHandler(this);
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(Shortcut* shortcut)
|
||||
{
|
||||
mShortcuts.insert(std::make_pair(shortcut->getName(), shortcut));
|
||||
mShortcuts.insert(std::make_pair(shortcut->getModifierName(), shortcut));
|
||||
mEventHandler->addShortcut(shortcut);
|
||||
}
|
||||
|
||||
void ShortcutManager::removeShortcut(Shortcut* shortcut)
|
||||
{
|
||||
std::pair<ShortcutMap::iterator, ShortcutMap::iterator> range = mShortcuts.equal_range(shortcut->getName());
|
||||
|
||||
for (ShortcutMap::iterator it = range.first; it != range.second;)
|
||||
{
|
||||
if (it->second == shortcut)
|
||||
{
|
||||
mShortcuts.erase(it++);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
mEventHandler->removeShortcut(shortcut);
|
||||
}
|
||||
|
||||
bool ShortcutManager::getSequence(const std::string& name, QKeySequence& sequence) const
|
||||
{
|
||||
SequenceMap::const_iterator item = mSequences.find(name);
|
||||
if (item != mSequences.end())
|
||||
{
|
||||
sequence = item->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShortcutManager::setSequence(const std::string& name, const QKeySequence& sequence)
|
||||
{
|
||||
// Add to map/modify
|
||||
SequenceMap::iterator item = mSequences.find(name);
|
||||
if (item != mSequences.end())
|
||||
{
|
||||
item->second = sequence;
|
||||
}
|
||||
else
|
||||
{
|
||||
mSequences.insert(std::make_pair(name, sequence));
|
||||
}
|
||||
|
||||
// Change active shortcuts
|
||||
std::pair<ShortcutMap::iterator, ShortcutMap::iterator> rangeS = mShortcuts.equal_range(name);
|
||||
|
||||
for (ShortcutMap::iterator it = rangeS.first; it != rangeS.second; ++it)
|
||||
{
|
||||
it->second->setSequence(sequence);
|
||||
}
|
||||
}
|
||||
|
||||
bool ShortcutManager::getModifier(const std::string& name, int& modifier) const
|
||||
{
|
||||
ModifierMap::const_iterator item = mModifiers.find(name);
|
||||
if (item != mModifiers.end())
|
||||
{
|
||||
modifier = item->second;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShortcutManager::setModifier(const std::string& name, int modifier)
|
||||
{
|
||||
// Add to map/modify
|
||||
ModifierMap::iterator item = mModifiers.find(name);
|
||||
if (item != mModifiers.end())
|
||||
{
|
||||
item->second = modifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
mModifiers.insert(std::make_pair(name, modifier));
|
||||
}
|
||||
|
||||
// Change active shortcuts
|
||||
std::pair<ShortcutMap::iterator, ShortcutMap::iterator> rangeS = mShortcuts.equal_range(name);
|
||||
|
||||
for (ShortcutMap::iterator it = rangeS.first; it != rangeS.second; ++it)
|
||||
{
|
||||
it->second->setModifier(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ShortcutManager::convertToString(const QKeySequence& sequence) const
|
||||
{
|
||||
const int MouseKeyMask = 0x01FFFFFF;
|
||||
const int ModMask = 0x7E000000;
|
||||
|
||||
std::string result;
|
||||
|
||||
for (int i = 0; i < (int)sequence.count(); ++i)
|
||||
{
|
||||
int mods = sequence[i] & ModMask;
|
||||
int key = sequence[i] & MouseKeyMask;
|
||||
|
||||
if (key)
|
||||
{
|
||||
NameMap::const_iterator searchResult = mNames.find(key);
|
||||
if (searchResult != mNames.end())
|
||||
{
|
||||
if (mods && i == 0)
|
||||
{
|
||||
if (mods & Qt::ControlModifier)
|
||||
result.append("Ctl+");
|
||||
if (mods & Qt::ShiftModifier)
|
||||
result.append("Shift+");
|
||||
if (mods & Qt::AltModifier)
|
||||
result.append("Alt+");
|
||||
if (mods & Qt::MetaModifier)
|
||||
result.append("Meta+");
|
||||
if (mods & Qt::KeypadModifier)
|
||||
result.append("Keypad+");
|
||||
if (mods & Qt::GroupSwitchModifier)
|
||||
result.append("GroupSwitch+");
|
||||
}
|
||||
else if (i > 0)
|
||||
{
|
||||
result.append("+");
|
||||
}
|
||||
|
||||
result.append(searchResult->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ShortcutManager::convertToString(int modifier) const
|
||||
{
|
||||
NameMap::const_iterator searchResult = mNames.find(modifier);
|
||||
if (searchResult != mNames.end())
|
||||
{
|
||||
return searchResult->second;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ShortcutManager::convertToString(const QKeySequence& sequence, int modifier) const
|
||||
{
|
||||
std::string concat = convertToString(sequence) + ";" + convertToString(modifier);
|
||||
return concat;
|
||||
}
|
||||
|
||||
void ShortcutManager::convertFromString(const std::string& data, QKeySequence& sequence) const
|
||||
{
|
||||
const int MaxKeys = 4; // A limitation of QKeySequence
|
||||
|
||||
size_t end = data.find(";");
|
||||
size_t size = std::min(end, data.size());
|
||||
|
||||
std::string value = data.substr(0, size);
|
||||
size_t start = 0;
|
||||
|
||||
int keyPos = 0;
|
||||
int mods = 0;
|
||||
|
||||
int keys[MaxKeys] = {};
|
||||
|
||||
while (start < value.size())
|
||||
{
|
||||
end = data.find("+", start);
|
||||
end = std::min(end, value.size());
|
||||
|
||||
std::string name = value.substr(start, end - start);
|
||||
|
||||
if (name == "Ctl")
|
||||
{
|
||||
mods |= Qt::ControlModifier;
|
||||
}
|
||||
else if (name == "Shift")
|
||||
{
|
||||
mods |= Qt::ShiftModifier;
|
||||
}
|
||||
else if (name == "Alt")
|
||||
{
|
||||
mods |= Qt::AltModifier;
|
||||
}
|
||||
else if (name == "Meta")
|
||||
{
|
||||
mods |= Qt::MetaModifier;
|
||||
}
|
||||
else if (name == "Keypad")
|
||||
{
|
||||
mods |= Qt::KeypadModifier;
|
||||
}
|
||||
else if (name == "GroupSwitch")
|
||||
{
|
||||
mods |= Qt::GroupSwitchModifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyMap::const_iterator searchResult = mKeys.find(name);
|
||||
if (searchResult != mKeys.end())
|
||||
{
|
||||
keys[keyPos] = mods | searchResult->second;
|
||||
|
||||
mods = 0;
|
||||
keyPos += 1;
|
||||
|
||||
if (keyPos >= MaxKeys)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
sequence = QKeySequence(keys[0], keys[1], keys[2], keys[3]);
|
||||
}
|
||||
|
||||
void ShortcutManager::convertFromString(const std::string& data, int& modifier) const
|
||||
{
|
||||
size_t start = data.find(";") + 1;
|
||||
start = std::min(start, data.size());
|
||||
|
||||
std::string name = data.substr(start);
|
||||
KeyMap::const_iterator searchResult = mKeys.find(name);
|
||||
if (searchResult != mKeys.end())
|
||||
{
|
||||
modifier = searchResult->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
modifier = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutManager::convertFromString(const std::string& data, QKeySequence& sequence, int& modifier) const
|
||||
{
|
||||
convertFromString(data, sequence);
|
||||
convertFromString(data, modifier);
|
||||
}
|
||||
|
||||
void ShortcutManager::createLookupTables()
|
||||
{
|
||||
// Mouse buttons
|
||||
mNames.insert(std::make_pair(Qt::LeftButton, "LMB"));
|
||||
mNames.insert(std::make_pair(Qt::RightButton, "RMB"));
|
||||
mNames.insert(std::make_pair(Qt::MiddleButton, "MMB"));
|
||||
mNames.insert(std::make_pair(Qt::XButton1, "Mouse4"));
|
||||
mNames.insert(std::make_pair(Qt::XButton2, "Mouse5"));
|
||||
|
||||
// Keyboard buttons
|
||||
for (size_t i = 0; QtKeys[i].first != 0; ++i)
|
||||
{
|
||||
mNames.insert(QtKeys[i]);
|
||||
}
|
||||
|
||||
// Generate inverse map
|
||||
for (NameMap::const_iterator it = mNames.begin(); it != mNames.end(); ++it)
|
||||
{
|
||||
mKeys.insert(std::make_pair(it->second, it->first));
|
||||
}
|
||||
}
|
||||
|
||||
QString ShortcutManager::processToolTip(const QString& toolTip) const
|
||||
{
|
||||
const QChar SequenceStart = '{';
|
||||
const QChar SequenceEnd = '}';
|
||||
|
||||
QStringList substrings;
|
||||
|
||||
int prevIndex = 0;
|
||||
int startIndex = toolTip.indexOf(SequenceStart);
|
||||
int endIndex = (startIndex != -1) ? toolTip.indexOf(SequenceEnd, startIndex) : -1;
|
||||
|
||||
// Process every valid shortcut escape sequence
|
||||
while (startIndex != -1 && endIndex != -1)
|
||||
{
|
||||
int count = startIndex - prevIndex;
|
||||
if (count > 0)
|
||||
{
|
||||
substrings.push_back(toolTip.mid(prevIndex, count));
|
||||
}
|
||||
|
||||
// Find sequence name
|
||||
startIndex += 1; // '{' character
|
||||
count = endIndex - startIndex;
|
||||
if (count > 0)
|
||||
{
|
||||
QString settingName = toolTip.mid(startIndex, count);
|
||||
|
||||
QKeySequence sequence;
|
||||
int modifier;
|
||||
|
||||
if (getSequence(settingName.toUtf8().data(), sequence))
|
||||
{
|
||||
QString value = QString::fromUtf8(convertToString(sequence).c_str());
|
||||
substrings.push_back(value);
|
||||
}
|
||||
else if (getModifier(settingName.toUtf8().data(), modifier))
|
||||
{
|
||||
QString value = QString::fromUtf8(convertToString(modifier).c_str());
|
||||
substrings.push_back(value);
|
||||
}
|
||||
|
||||
prevIndex = endIndex + 1; // '}' character
|
||||
}
|
||||
|
||||
startIndex = toolTip.indexOf(SequenceStart, endIndex);
|
||||
endIndex = (startIndex != -1) ? toolTip.indexOf(SequenceEnd, startIndex) : -1;
|
||||
}
|
||||
|
||||
if (prevIndex < toolTip.size())
|
||||
{
|
||||
substrings.push_back(toolTip.mid(prevIndex));
|
||||
}
|
||||
|
||||
return substrings.join("");
|
||||
}
|
||||
|
||||
const std::pair<int, const char*> ShortcutManager::QtKeys[] =
|
||||
{
|
||||
std::make_pair((int)Qt::Key_Space , "Space"),
|
||||
std::make_pair((int)Qt::Key_Exclam , "Exclam"),
|
||||
std::make_pair((int)Qt::Key_QuoteDbl , "QuoteDbl"),
|
||||
std::make_pair((int)Qt::Key_NumberSign , "NumberSign"),
|
||||
std::make_pair((int)Qt::Key_Dollar , "Dollar"),
|
||||
std::make_pair((int)Qt::Key_Percent , "Percent"),
|
||||
std::make_pair((int)Qt::Key_Ampersand , "Ampersand"),
|
||||
std::make_pair((int)Qt::Key_Apostrophe , "Apostrophe"),
|
||||
std::make_pair((int)Qt::Key_ParenLeft , "ParenLeft"),
|
||||
std::make_pair((int)Qt::Key_ParenRight , "ParenRight"),
|
||||
std::make_pair((int)Qt::Key_Asterisk , "Asterisk"),
|
||||
std::make_pair((int)Qt::Key_Plus , "Plus"),
|
||||
std::make_pair((int)Qt::Key_Comma , "Comma"),
|
||||
std::make_pair((int)Qt::Key_Minus , "Minus"),
|
||||
std::make_pair((int)Qt::Key_Period , "Period"),
|
||||
std::make_pair((int)Qt::Key_Slash , "Slash"),
|
||||
std::make_pair((int)Qt::Key_0 , "0"),
|
||||
std::make_pair((int)Qt::Key_1 , "1"),
|
||||
std::make_pair((int)Qt::Key_2 , "2"),
|
||||
std::make_pair((int)Qt::Key_3 , "3"),
|
||||
std::make_pair((int)Qt::Key_4 , "4"),
|
||||
std::make_pair((int)Qt::Key_5 , "5"),
|
||||
std::make_pair((int)Qt::Key_6 , "6"),
|
||||
std::make_pair((int)Qt::Key_7 , "7"),
|
||||
std::make_pair((int)Qt::Key_8 , "8"),
|
||||
std::make_pair((int)Qt::Key_9 , "9"),
|
||||
std::make_pair((int)Qt::Key_Colon , "Colon"),
|
||||
std::make_pair((int)Qt::Key_Semicolon , "Semicolon"),
|
||||
std::make_pair((int)Qt::Key_Less , "Less"),
|
||||
std::make_pair((int)Qt::Key_Equal , "Equal"),
|
||||
std::make_pair((int)Qt::Key_Greater , "Greater"),
|
||||
std::make_pair((int)Qt::Key_Question , "Question"),
|
||||
std::make_pair((int)Qt::Key_At , "At"),
|
||||
std::make_pair((int)Qt::Key_A , "A"),
|
||||
std::make_pair((int)Qt::Key_B , "B"),
|
||||
std::make_pair((int)Qt::Key_C , "C"),
|
||||
std::make_pair((int)Qt::Key_D , "D"),
|
||||
std::make_pair((int)Qt::Key_E , "E"),
|
||||
std::make_pair((int)Qt::Key_F , "F"),
|
||||
std::make_pair((int)Qt::Key_G , "G"),
|
||||
std::make_pair((int)Qt::Key_H , "H"),
|
||||
std::make_pair((int)Qt::Key_I , "I"),
|
||||
std::make_pair((int)Qt::Key_J , "J"),
|
||||
std::make_pair((int)Qt::Key_K , "K"),
|
||||
std::make_pair((int)Qt::Key_L , "L"),
|
||||
std::make_pair((int)Qt::Key_M , "M"),
|
||||
std::make_pair((int)Qt::Key_N , "N"),
|
||||
std::make_pair((int)Qt::Key_O , "O"),
|
||||
std::make_pair((int)Qt::Key_P , "P"),
|
||||
std::make_pair((int)Qt::Key_Q , "Q"),
|
||||
std::make_pair((int)Qt::Key_R , "R"),
|
||||
std::make_pair((int)Qt::Key_S , "S"),
|
||||
std::make_pair((int)Qt::Key_T , "T"),
|
||||
std::make_pair((int)Qt::Key_U , "U"),
|
||||
std::make_pair((int)Qt::Key_V , "V"),
|
||||
std::make_pair((int)Qt::Key_W , "W"),
|
||||
std::make_pair((int)Qt::Key_X , "X"),
|
||||
std::make_pair((int)Qt::Key_Y , "Y"),
|
||||
std::make_pair((int)Qt::Key_Z , "Z"),
|
||||
std::make_pair((int)Qt::Key_BracketLeft , "BracketLeft"),
|
||||
std::make_pair((int)Qt::Key_Backslash , "Backslash"),
|
||||
std::make_pair((int)Qt::Key_BracketRight , "BracketRight"),
|
||||
std::make_pair((int)Qt::Key_AsciiCircum , "AsciiCircum"),
|
||||
std::make_pair((int)Qt::Key_Underscore , "Underscore"),
|
||||
std::make_pair((int)Qt::Key_QuoteLeft , "QuoteLeft"),
|
||||
std::make_pair((int)Qt::Key_BraceLeft , "BraceLeft"),
|
||||
std::make_pair((int)Qt::Key_Bar , "Bar"),
|
||||
std::make_pair((int)Qt::Key_BraceRight , "BraceRight"),
|
||||
std::make_pair((int)Qt::Key_AsciiTilde , "AsciiTilde"),
|
||||
std::make_pair((int)Qt::Key_nobreakspace , "nobreakspace"),
|
||||
std::make_pair((int)Qt::Key_exclamdown , "exclamdown"),
|
||||
std::make_pair((int)Qt::Key_cent , "cent"),
|
||||
std::make_pair((int)Qt::Key_sterling , "sterling"),
|
||||
std::make_pair((int)Qt::Key_currency , "currency"),
|
||||
std::make_pair((int)Qt::Key_yen , "yen"),
|
||||
std::make_pair((int)Qt::Key_brokenbar , "brokenbar"),
|
||||
std::make_pair((int)Qt::Key_section , "section"),
|
||||
std::make_pair((int)Qt::Key_diaeresis , "diaeresis"),
|
||||
std::make_pair((int)Qt::Key_copyright , "copyright"),
|
||||
std::make_pair((int)Qt::Key_ordfeminine , "ordfeminine"),
|
||||
std::make_pair((int)Qt::Key_guillemotleft , "guillemotleft"),
|
||||
std::make_pair((int)Qt::Key_notsign , "notsign"),
|
||||
std::make_pair((int)Qt::Key_hyphen , "hyphen"),
|
||||
std::make_pair((int)Qt::Key_registered , "registered"),
|
||||
std::make_pair((int)Qt::Key_macron , "macron"),
|
||||
std::make_pair((int)Qt::Key_degree , "degree"),
|
||||
std::make_pair((int)Qt::Key_plusminus , "plusminus"),
|
||||
std::make_pair((int)Qt::Key_twosuperior , "twosuperior"),
|
||||
std::make_pair((int)Qt::Key_threesuperior , "threesuperior"),
|
||||
std::make_pair((int)Qt::Key_acute , "acute"),
|
||||
std::make_pair((int)Qt::Key_mu , "mu"),
|
||||
std::make_pair((int)Qt::Key_paragraph , "paragraph"),
|
||||
std::make_pair((int)Qt::Key_periodcentered , "periodcentered"),
|
||||
std::make_pair((int)Qt::Key_cedilla , "cedilla"),
|
||||
std::make_pair((int)Qt::Key_onesuperior , "onesuperior"),
|
||||
std::make_pair((int)Qt::Key_masculine , "masculine"),
|
||||
std::make_pair((int)Qt::Key_guillemotright , "guillemotright"),
|
||||
std::make_pair((int)Qt::Key_onequarter , "onequarter"),
|
||||
std::make_pair((int)Qt::Key_onehalf , "onehalf"),
|
||||
std::make_pair((int)Qt::Key_threequarters , "threequarters"),
|
||||
std::make_pair((int)Qt::Key_questiondown , "questiondown"),
|
||||
std::make_pair((int)Qt::Key_Agrave , "Agrave"),
|
||||
std::make_pair((int)Qt::Key_Aacute , "Aacute"),
|
||||
std::make_pair((int)Qt::Key_Acircumflex , "Acircumflex"),
|
||||
std::make_pair((int)Qt::Key_Atilde , "Atilde"),
|
||||
std::make_pair((int)Qt::Key_Adiaeresis , "Adiaeresis"),
|
||||
std::make_pair((int)Qt::Key_Aring , "Aring"),
|
||||
std::make_pair((int)Qt::Key_AE , "AE"),
|
||||
std::make_pair((int)Qt::Key_Ccedilla , "Ccedilla"),
|
||||
std::make_pair((int)Qt::Key_Egrave , "Egrave"),
|
||||
std::make_pair((int)Qt::Key_Eacute , "Eacute"),
|
||||
std::make_pair((int)Qt::Key_Ecircumflex , "Ecircumflex"),
|
||||
std::make_pair((int)Qt::Key_Ediaeresis , "Ediaeresis"),
|
||||
std::make_pair((int)Qt::Key_Igrave , "Igrave"),
|
||||
std::make_pair((int)Qt::Key_Iacute , "Iacute"),
|
||||
std::make_pair((int)Qt::Key_Icircumflex , "Icircumflex"),
|
||||
std::make_pair((int)Qt::Key_Idiaeresis , "Idiaeresis"),
|
||||
std::make_pair((int)Qt::Key_ETH , "ETH"),
|
||||
std::make_pair((int)Qt::Key_Ntilde , "Ntilde"),
|
||||
std::make_pair((int)Qt::Key_Ograve , "Ograve"),
|
||||
std::make_pair((int)Qt::Key_Oacute , "Oacute"),
|
||||
std::make_pair((int)Qt::Key_Ocircumflex , "Ocircumflex"),
|
||||
std::make_pair((int)Qt::Key_Otilde , "Otilde"),
|
||||
std::make_pair((int)Qt::Key_Odiaeresis , "Odiaeresis"),
|
||||
std::make_pair((int)Qt::Key_multiply , "multiply"),
|
||||
std::make_pair((int)Qt::Key_Ooblique , "Ooblique"),
|
||||
std::make_pair((int)Qt::Key_Ugrave , "Ugrave"),
|
||||
std::make_pair((int)Qt::Key_Uacute , "Uacute"),
|
||||
std::make_pair((int)Qt::Key_Ucircumflex , "Ucircumflex"),
|
||||
std::make_pair((int)Qt::Key_Udiaeresis , "Udiaeresis"),
|
||||
std::make_pair((int)Qt::Key_Yacute , "Yacute"),
|
||||
std::make_pair((int)Qt::Key_THORN , "THORN"),
|
||||
std::make_pair((int)Qt::Key_ssharp , "ssharp"),
|
||||
std::make_pair((int)Qt::Key_division , "division"),
|
||||
std::make_pair((int)Qt::Key_ydiaeresis , "ydiaeresis"),
|
||||
std::make_pair((int)Qt::Key_Escape , "Escape"),
|
||||
std::make_pair((int)Qt::Key_Tab , "Tab"),
|
||||
std::make_pair((int)Qt::Key_Backtab , "Backtab"),
|
||||
std::make_pair((int)Qt::Key_Backspace , "Backspace"),
|
||||
std::make_pair((int)Qt::Key_Return , "Return"),
|
||||
std::make_pair((int)Qt::Key_Enter , "Enter"),
|
||||
std::make_pair((int)Qt::Key_Insert , "Insert"),
|
||||
std::make_pair((int)Qt::Key_Delete , "Delete"),
|
||||
std::make_pair((int)Qt::Key_Pause , "Pause"),
|
||||
std::make_pair((int)Qt::Key_Print , "Print"),
|
||||
std::make_pair((int)Qt::Key_SysReq , "SysReq"),
|
||||
std::make_pair((int)Qt::Key_Clear , "Clear"),
|
||||
std::make_pair((int)Qt::Key_Home , "Home"),
|
||||
std::make_pair((int)Qt::Key_End , "End"),
|
||||
std::make_pair((int)Qt::Key_Left , "Left"),
|
||||
std::make_pair((int)Qt::Key_Up , "Up"),
|
||||
std::make_pair((int)Qt::Key_Right , "Right"),
|
||||
std::make_pair((int)Qt::Key_Down , "Down"),
|
||||
std::make_pair((int)Qt::Key_PageUp , "PageUp"),
|
||||
std::make_pair((int)Qt::Key_PageDown , "PageDown"),
|
||||
std::make_pair((int)Qt::Key_Shift , "Shift"),
|
||||
std::make_pair((int)Qt::Key_Control , "Control"),
|
||||
std::make_pair((int)Qt::Key_Meta , "Meta"),
|
||||
std::make_pair((int)Qt::Key_Alt , "Alt"),
|
||||
std::make_pair((int)Qt::Key_CapsLock , "CapsLock"),
|
||||
std::make_pair((int)Qt::Key_NumLock , "NumLock"),
|
||||
std::make_pair((int)Qt::Key_ScrollLock , "ScrollLock"),
|
||||
std::make_pair((int)Qt::Key_F1 , "F1"),
|
||||
std::make_pair((int)Qt::Key_F2 , "F2"),
|
||||
std::make_pair((int)Qt::Key_F3 , "F3"),
|
||||
std::make_pair((int)Qt::Key_F4 , "F4"),
|
||||
std::make_pair((int)Qt::Key_F5 , "F5"),
|
||||
std::make_pair((int)Qt::Key_F6 , "F6"),
|
||||
std::make_pair((int)Qt::Key_F7 , "F7"),
|
||||
std::make_pair((int)Qt::Key_F8 , "F8"),
|
||||
std::make_pair((int)Qt::Key_F9 , "F9"),
|
||||
std::make_pair((int)Qt::Key_F10 , "F10"),
|
||||
std::make_pair((int)Qt::Key_F11 , "F11"),
|
||||
std::make_pair((int)Qt::Key_F12 , "F12"),
|
||||
std::make_pair((int)Qt::Key_F13 , "F13"),
|
||||
std::make_pair((int)Qt::Key_F14 , "F14"),
|
||||
std::make_pair((int)Qt::Key_F15 , "F15"),
|
||||
std::make_pair((int)Qt::Key_F16 , "F16"),
|
||||
std::make_pair((int)Qt::Key_F17 , "F17"),
|
||||
std::make_pair((int)Qt::Key_F18 , "F18"),
|
||||
std::make_pair((int)Qt::Key_F19 , "F19"),
|
||||
std::make_pair((int)Qt::Key_F20 , "F20"),
|
||||
std::make_pair((int)Qt::Key_F21 , "F21"),
|
||||
std::make_pair((int)Qt::Key_F22 , "F22"),
|
||||
std::make_pair((int)Qt::Key_F23 , "F23"),
|
||||
std::make_pair((int)Qt::Key_F24 , "F24"),
|
||||
std::make_pair((int)Qt::Key_F25 , "F25"),
|
||||
std::make_pair((int)Qt::Key_F26 , "F26"),
|
||||
std::make_pair((int)Qt::Key_F27 , "F27"),
|
||||
std::make_pair((int)Qt::Key_F28 , "F28"),
|
||||
std::make_pair((int)Qt::Key_F29 , "F29"),
|
||||
std::make_pair((int)Qt::Key_F30 , "F30"),
|
||||
std::make_pair((int)Qt::Key_F31 , "F31"),
|
||||
std::make_pair((int)Qt::Key_F32 , "F32"),
|
||||
std::make_pair((int)Qt::Key_F33 , "F33"),
|
||||
std::make_pair((int)Qt::Key_F34 , "F34"),
|
||||
std::make_pair((int)Qt::Key_F35 , "F35"),
|
||||
std::make_pair((int)Qt::Key_Super_L , "Super_L"),
|
||||
std::make_pair((int)Qt::Key_Super_R , "Super_R"),
|
||||
std::make_pair((int)Qt::Key_Menu , "Menu"),
|
||||
std::make_pair((int)Qt::Key_Hyper_L , "Hyper_L"),
|
||||
std::make_pair((int)Qt::Key_Hyper_R , "Hyper_R"),
|
||||
std::make_pair((int)Qt::Key_Help , "Help"),
|
||||
std::make_pair((int)Qt::Key_Direction_L , "Direction_L"),
|
||||
std::make_pair((int)Qt::Key_Direction_R , "Direction_R"),
|
||||
std::make_pair((int)Qt::Key_Back , "Back"),
|
||||
std::make_pair((int)Qt::Key_Forward , "Forward"),
|
||||
std::make_pair((int)Qt::Key_Stop , "Stop"),
|
||||
std::make_pair((int)Qt::Key_Refresh , "Refresh"),
|
||||
std::make_pair((int)Qt::Key_VolumeDown , "VolumeDown"),
|
||||
std::make_pair((int)Qt::Key_VolumeMute , "VolumeMute"),
|
||||
std::make_pair((int)Qt::Key_VolumeUp , "VolumeUp"),
|
||||
std::make_pair((int)Qt::Key_BassBoost , "BassBoost"),
|
||||
std::make_pair((int)Qt::Key_BassUp , "BassUp"),
|
||||
std::make_pair((int)Qt::Key_BassDown , "BassDown"),
|
||||
std::make_pair((int)Qt::Key_TrebleUp , "TrebleUp"),
|
||||
std::make_pair((int)Qt::Key_TrebleDown , "TrebleDown"),
|
||||
std::make_pair((int)Qt::Key_MediaPlay , "MediaPlay"),
|
||||
std::make_pair((int)Qt::Key_MediaStop , "MediaStop"),
|
||||
std::make_pair((int)Qt::Key_MediaPrevious , "MediaPrevious"),
|
||||
std::make_pair((int)Qt::Key_MediaNext , "MediaNext"),
|
||||
std::make_pair((int)Qt::Key_MediaRecord , "MediaRecord"),
|
||||
std::make_pair((int)Qt::Key_MediaPause , "MediaPause"),
|
||||
std::make_pair((int)Qt::Key_MediaTogglePlayPause , "MediaTogglePlayPause"),
|
||||
std::make_pair((int)Qt::Key_HomePage , "HomePage"),
|
||||
std::make_pair((int)Qt::Key_Favorites , "Favorites"),
|
||||
std::make_pair((int)Qt::Key_Search , "Search"),
|
||||
std::make_pair((int)Qt::Key_Standby , "Standby"),
|
||||
std::make_pair((int)Qt::Key_OpenUrl , "OpenUrl"),
|
||||
std::make_pair((int)Qt::Key_LaunchMail , "LaunchMail"),
|
||||
std::make_pair((int)Qt::Key_LaunchMedia , "LaunchMedia"),
|
||||
std::make_pair((int)Qt::Key_Launch0 , "Launch0"),
|
||||
std::make_pair((int)Qt::Key_Launch1 , "Launch1"),
|
||||
std::make_pair((int)Qt::Key_Launch2 , "Launch2"),
|
||||
std::make_pair((int)Qt::Key_Launch3 , "Launch3"),
|
||||
std::make_pair((int)Qt::Key_Launch4 , "Launch4"),
|
||||
std::make_pair((int)Qt::Key_Launch5 , "Launch5"),
|
||||
std::make_pair((int)Qt::Key_Launch6 , "Launch6"),
|
||||
std::make_pair((int)Qt::Key_Launch7 , "Launch7"),
|
||||
std::make_pair((int)Qt::Key_Launch8 , "Launch8"),
|
||||
std::make_pair((int)Qt::Key_Launch9 , "Launch9"),
|
||||
std::make_pair((int)Qt::Key_LaunchA , "LaunchA"),
|
||||
std::make_pair((int)Qt::Key_LaunchB , "LaunchB"),
|
||||
std::make_pair((int)Qt::Key_LaunchC , "LaunchC"),
|
||||
std::make_pair((int)Qt::Key_LaunchD , "LaunchD"),
|
||||
std::make_pair((int)Qt::Key_LaunchE , "LaunchE"),
|
||||
std::make_pair((int)Qt::Key_LaunchF , "LaunchF"),
|
||||
std::make_pair((int)Qt::Key_MonBrightnessUp , "MonBrightnessUp"),
|
||||
std::make_pair((int)Qt::Key_MonBrightnessDown , "MonBrightnessDown"),
|
||||
std::make_pair((int)Qt::Key_KeyboardLightOnOff , "KeyboardLightOnOff"),
|
||||
std::make_pair((int)Qt::Key_KeyboardBrightnessUp , "KeyboardBrightnessUp"),
|
||||
std::make_pair((int)Qt::Key_KeyboardBrightnessDown , "KeyboardBrightnessDown"),
|
||||
std::make_pair((int)Qt::Key_PowerOff , "PowerOff"),
|
||||
std::make_pair((int)Qt::Key_WakeUp , "WakeUp"),
|
||||
std::make_pair((int)Qt::Key_Eject , "Eject"),
|
||||
std::make_pair((int)Qt::Key_ScreenSaver , "ScreenSaver"),
|
||||
std::make_pair((int)Qt::Key_WWW , "WWW"),
|
||||
std::make_pair((int)Qt::Key_Memo , "Memo"),
|
||||
std::make_pair((int)Qt::Key_LightBulb , "LightBulb"),
|
||||
std::make_pair((int)Qt::Key_Shop , "Shop"),
|
||||
std::make_pair((int)Qt::Key_History , "History"),
|
||||
std::make_pair((int)Qt::Key_AddFavorite , "AddFavorite"),
|
||||
std::make_pair((int)Qt::Key_HotLinks , "HotLinks"),
|
||||
std::make_pair((int)Qt::Key_BrightnessAdjust , "BrightnessAdjust"),
|
||||
std::make_pair((int)Qt::Key_Finance , "Finance"),
|
||||
std::make_pair((int)Qt::Key_Community , "Community"),
|
||||
std::make_pair((int)Qt::Key_AudioRewind , "AudioRewind"),
|
||||
std::make_pair((int)Qt::Key_BackForward , "BackForward"),
|
||||
std::make_pair((int)Qt::Key_ApplicationLeft , "ApplicationLeft"),
|
||||
std::make_pair((int)Qt::Key_ApplicationRight , "ApplicationRight"),
|
||||
std::make_pair((int)Qt::Key_Book , "Book"),
|
||||
std::make_pair((int)Qt::Key_CD , "CD"),
|
||||
std::make_pair((int)Qt::Key_Calculator , "Calculator"),
|
||||
std::make_pair((int)Qt::Key_ToDoList , "ToDoList"),
|
||||
std::make_pair((int)Qt::Key_ClearGrab , "ClearGrab"),
|
||||
std::make_pair((int)Qt::Key_Close , "Close"),
|
||||
std::make_pair((int)Qt::Key_Copy , "Copy"),
|
||||
std::make_pair((int)Qt::Key_Cut , "Cut"),
|
||||
std::make_pair((int)Qt::Key_Display , "Display"),
|
||||
std::make_pair((int)Qt::Key_DOS , "DOS"),
|
||||
std::make_pair((int)Qt::Key_Documents , "Documents"),
|
||||
std::make_pair((int)Qt::Key_Excel , "Excel"),
|
||||
std::make_pair((int)Qt::Key_Explorer , "Explorer"),
|
||||
std::make_pair((int)Qt::Key_Game , "Game"),
|
||||
std::make_pair((int)Qt::Key_Go , "Go"),
|
||||
std::make_pair((int)Qt::Key_iTouch , "iTouch"),
|
||||
std::make_pair((int)Qt::Key_LogOff , "LogOff"),
|
||||
std::make_pair((int)Qt::Key_Market , "Market"),
|
||||
std::make_pair((int)Qt::Key_Meeting , "Meeting"),
|
||||
std::make_pair((int)Qt::Key_MenuKB , "MenuKB"),
|
||||
std::make_pair((int)Qt::Key_MenuPB , "MenuPB"),
|
||||
std::make_pair((int)Qt::Key_MySites , "MySites"),
|
||||
std::make_pair((int)Qt::Key_News , "News"),
|
||||
std::make_pair((int)Qt::Key_OfficeHome , "OfficeHome"),
|
||||
std::make_pair((int)Qt::Key_Option , "Option"),
|
||||
std::make_pair((int)Qt::Key_Paste , "Paste"),
|
||||
std::make_pair((int)Qt::Key_Phone , "Phone"),
|
||||
std::make_pair((int)Qt::Key_Calendar , "Calendar"),
|
||||
std::make_pair((int)Qt::Key_Reply , "Reply"),
|
||||
std::make_pair((int)Qt::Key_Reload , "Reload"),
|
||||
std::make_pair((int)Qt::Key_RotateWindows , "RotateWindows"),
|
||||
std::make_pair((int)Qt::Key_RotationPB , "RotationPB"),
|
||||
std::make_pair((int)Qt::Key_RotationKB , "RotationKB"),
|
||||
std::make_pair((int)Qt::Key_Save , "Save"),
|
||||
std::make_pair((int)Qt::Key_Send , "Send"),
|
||||
std::make_pair((int)Qt::Key_Spell , "Spell"),
|
||||
std::make_pair((int)Qt::Key_SplitScreen , "SplitScreen"),
|
||||
std::make_pair((int)Qt::Key_Support , "Support"),
|
||||
std::make_pair((int)Qt::Key_TaskPane , "TaskPane"),
|
||||
std::make_pair((int)Qt::Key_Terminal , "Terminal"),
|
||||
std::make_pair((int)Qt::Key_Tools , "Tools"),
|
||||
std::make_pair((int)Qt::Key_Travel , "Travel"),
|
||||
std::make_pair((int)Qt::Key_Video , "Video"),
|
||||
std::make_pair((int)Qt::Key_Word , "Word"),
|
||||
std::make_pair((int)Qt::Key_Xfer , "Xfer"),
|
||||
std::make_pair((int)Qt::Key_ZoomIn , "ZoomIn"),
|
||||
std::make_pair((int)Qt::Key_ZoomOut , "ZoomOut"),
|
||||
std::make_pair((int)Qt::Key_Away , "Away"),
|
||||
std::make_pair((int)Qt::Key_Messenger , "Messenger"),
|
||||
std::make_pair((int)Qt::Key_WebCam , "WebCam"),
|
||||
std::make_pair((int)Qt::Key_MailForward , "MailForward"),
|
||||
std::make_pair((int)Qt::Key_Pictures , "Pictures"),
|
||||
std::make_pair((int)Qt::Key_Music , "Music"),
|
||||
std::make_pair((int)Qt::Key_Battery , "Battery"),
|
||||
std::make_pair((int)Qt::Key_Bluetooth , "Bluetooth"),
|
||||
std::make_pair((int)Qt::Key_WLAN , "WLAN"),
|
||||
std::make_pair((int)Qt::Key_UWB , "UWB"),
|
||||
std::make_pair((int)Qt::Key_AudioForward , "AudioForward"),
|
||||
std::make_pair((int)Qt::Key_AudioRepeat , "AudioRepeat"),
|
||||
std::make_pair((int)Qt::Key_AudioRandomPlay , "AudioRandomPlay"),
|
||||
std::make_pair((int)Qt::Key_Subtitle , "Subtitle"),
|
||||
std::make_pair((int)Qt::Key_AudioCycleTrack , "AudioCycleTrack"),
|
||||
std::make_pair((int)Qt::Key_Time , "Time"),
|
||||
std::make_pair((int)Qt::Key_Hibernate , "Hibernate"),
|
||||
std::make_pair((int)Qt::Key_View , "View"),
|
||||
std::make_pair((int)Qt::Key_TopMenu , "TopMenu"),
|
||||
std::make_pair((int)Qt::Key_PowerDown , "PowerDown"),
|
||||
std::make_pair((int)Qt::Key_Suspend , "Suspend"),
|
||||
std::make_pair((int)Qt::Key_ContrastAdjust , "ContrastAdjust"),
|
||||
std::make_pair((int)Qt::Key_LaunchG , "LaunchG"),
|
||||
std::make_pair((int)Qt::Key_LaunchH , "LaunchH"),
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,7,0)
|
||||
std::make_pair((int)Qt::Key_TouchpadToggle , "TouchpadToggle"),
|
||||
std::make_pair((int)Qt::Key_TouchpadOn , "TouchpadOn"),
|
||||
std::make_pair((int)Qt::Key_TouchpadOff , "TouchpadOff"),
|
||||
std::make_pair((int)Qt::Key_MicMute , "MicMute"),
|
||||
std::make_pair((int)Qt::Key_Red , "Red"),
|
||||
std::make_pair((int)Qt::Key_Green , "Green"),
|
||||
std::make_pair((int)Qt::Key_Yellow , "Yellow"),
|
||||
std::make_pair((int)Qt::Key_Blue , "Blue"),
|
||||
std::make_pair((int)Qt::Key_ChannelUp , "ChannelUp"),
|
||||
std::make_pair((int)Qt::Key_ChannelDown , "ChannelDown"),
|
||||
std::make_pair((int)Qt::Key_Guide , "Guide"),
|
||||
std::make_pair((int)Qt::Key_Info , "Info"),
|
||||
std::make_pair((int)Qt::Key_Settings , "Settings"),
|
||||
std::make_pair((int)Qt::Key_MicVolumeUp , "MicVolumeUp"),
|
||||
std::make_pair((int)Qt::Key_MicVolumeDown , "MicVolumeDown"),
|
||||
std::make_pair((int)Qt::Key_New , "New"),
|
||||
std::make_pair((int)Qt::Key_Open , "Open"),
|
||||
std::make_pair((int)Qt::Key_Find , "Find"),
|
||||
std::make_pair((int)Qt::Key_Undo , "Undo"),
|
||||
std::make_pair((int)Qt::Key_Redo , "Redo"),
|
||||
#endif
|
||||
std::make_pair((int)Qt::Key_AltGr , "AltGr"),
|
||||
std::make_pair((int)Qt::Key_Multi_key , "Multi_key"),
|
||||
std::make_pair((int)Qt::Key_Kanji , "Kanji"),
|
||||
std::make_pair((int)Qt::Key_Muhenkan , "Muhenkan"),
|
||||
std::make_pair((int)Qt::Key_Henkan , "Henkan"),
|
||||
std::make_pair((int)Qt::Key_Romaji , "Romaji"),
|
||||
std::make_pair((int)Qt::Key_Hiragana , "Hiragana"),
|
||||
std::make_pair((int)Qt::Key_Katakana , "Katakana"),
|
||||
std::make_pair((int)Qt::Key_Hiragana_Katakana , "Hiragana_Katakana"),
|
||||
std::make_pair((int)Qt::Key_Zenkaku , "Zenkaku"),
|
||||
std::make_pair((int)Qt::Key_Hankaku , "Hankaku"),
|
||||
std::make_pair((int)Qt::Key_Zenkaku_Hankaku , "Zenkaku_Hankaku"),
|
||||
std::make_pair((int)Qt::Key_Touroku , "Touroku"),
|
||||
std::make_pair((int)Qt::Key_Massyo , "Massyo"),
|
||||
std::make_pair((int)Qt::Key_Kana_Lock , "Kana_Lock"),
|
||||
std::make_pair((int)Qt::Key_Kana_Shift , "Kana_Shift"),
|
||||
std::make_pair((int)Qt::Key_Eisu_Shift , "Eisu_Shift"),
|
||||
std::make_pair((int)Qt::Key_Eisu_toggle , "Eisu_toggle"),
|
||||
std::make_pair((int)Qt::Key_Hangul , "Hangul"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Start , "Hangul_Start"),
|
||||
std::make_pair((int)Qt::Key_Hangul_End , "Hangul_End"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Hanja , "Hangul_Hanja"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Jamo , "Hangul_Jamo"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Romaja , "Hangul_Romaja"),
|
||||
std::make_pair((int)Qt::Key_Codeinput , "Codeinput"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Jeonja , "Hangul_Jeonja"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Banja , "Hangul_Banja"),
|
||||
std::make_pair((int)Qt::Key_Hangul_PreHanja , "Hangul_PreHanja"),
|
||||
std::make_pair((int)Qt::Key_Hangul_PostHanja , "Hangul_PostHanja"),
|
||||
std::make_pair((int)Qt::Key_SingleCandidate , "SingleCandidate"),
|
||||
std::make_pair((int)Qt::Key_MultipleCandidate , "MultipleCandidate"),
|
||||
std::make_pair((int)Qt::Key_PreviousCandidate , "PreviousCandidate"),
|
||||
std::make_pair((int)Qt::Key_Hangul_Special , "Hangul_Special"),
|
||||
std::make_pair((int)Qt::Key_Mode_switch , "Mode_switch"),
|
||||
std::make_pair((int)Qt::Key_Dead_Grave , "Dead_Grave"),
|
||||
std::make_pair((int)Qt::Key_Dead_Acute , "Dead_Acute"),
|
||||
std::make_pair((int)Qt::Key_Dead_Circumflex , "Dead_Circumflex"),
|
||||
std::make_pair((int)Qt::Key_Dead_Tilde , "Dead_Tilde"),
|
||||
std::make_pair((int)Qt::Key_Dead_Macron , "Dead_Macron"),
|
||||
std::make_pair((int)Qt::Key_Dead_Breve , "Dead_Breve"),
|
||||
std::make_pair((int)Qt::Key_Dead_Abovedot , "Dead_Abovedot"),
|
||||
std::make_pair((int)Qt::Key_Dead_Diaeresis , "Dead_Diaeresis"),
|
||||
std::make_pair((int)Qt::Key_Dead_Abovering , "Dead_Abovering"),
|
||||
std::make_pair((int)Qt::Key_Dead_Doubleacute , "Dead_Doubleacute"),
|
||||
std::make_pair((int)Qt::Key_Dead_Caron , "Dead_Caron"),
|
||||
std::make_pair((int)Qt::Key_Dead_Cedilla , "Dead_Cedilla"),
|
||||
std::make_pair((int)Qt::Key_Dead_Ogonek , "Dead_Ogonek"),
|
||||
std::make_pair((int)Qt::Key_Dead_Iota , "Dead_Iota"),
|
||||
std::make_pair((int)Qt::Key_Dead_Voiced_Sound , "Dead_Voiced_Sound"),
|
||||
std::make_pair((int)Qt::Key_Dead_Semivoiced_Sound , "Dead_Semivoiced_Sound"),
|
||||
std::make_pair((int)Qt::Key_Dead_Belowdot , "Dead_Belowdot"),
|
||||
std::make_pair((int)Qt::Key_Dead_Hook , "Dead_Hook"),
|
||||
std::make_pair((int)Qt::Key_Dead_Horn , "Dead_Horn"),
|
||||
std::make_pair((int)Qt::Key_MediaLast , "MediaLast"),
|
||||
std::make_pair((int)Qt::Key_Select , "Select"),
|
||||
std::make_pair((int)Qt::Key_Yes , "Yes"),
|
||||
std::make_pair((int)Qt::Key_No , "No"),
|
||||
std::make_pair((int)Qt::Key_Cancel , "Cancel"),
|
||||
std::make_pair((int)Qt::Key_Printer , "Printer"),
|
||||
std::make_pair((int)Qt::Key_Execute , "Execute"),
|
||||
std::make_pair((int)Qt::Key_Sleep , "Sleep"),
|
||||
std::make_pair((int)Qt::Key_Play , "Play"),
|
||||
std::make_pair((int)Qt::Key_Zoom , "Zoom"),
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,7,0)
|
||||
std::make_pair((int)Qt::Key_Exit , "Exit"),
|
||||
#endif
|
||||
std::make_pair((int)Qt::Key_Context1 , "Context1"),
|
||||
std::make_pair((int)Qt::Key_Context2 , "Context2"),
|
||||
std::make_pair((int)Qt::Key_Context3 , "Context3"),
|
||||
std::make_pair((int)Qt::Key_Context4 , "Context4"),
|
||||
std::make_pair((int)Qt::Key_Call , "Call"),
|
||||
std::make_pair((int)Qt::Key_Hangup , "Hangup"),
|
||||
std::make_pair((int)Qt::Key_Flip , "Flip"),
|
||||
std::make_pair((int)Qt::Key_ToggleCallHangup , "ToggleCallHangup"),
|
||||
std::make_pair((int)Qt::Key_VoiceDial , "VoiceDial"),
|
||||
std::make_pair((int)Qt::Key_LastNumberRedial , "LastNumberRedial"),
|
||||
std::make_pair((int)Qt::Key_Camera , "Camera"),
|
||||
std::make_pair((int)Qt::Key_CameraFocus , "CameraFocus"),
|
||||
std::make_pair(0 , (const char*) 0)
|
||||
};
|
||||
|
||||
}
|
73
apps/opencs/model/prefs/shortcutmanager.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
#ifndef CSM_PREFS_SHORTCUTMANAGER_H
|
||||
#define CSM_PREFS_SHORTCUTMANAGER_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <QKeySequence>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Shortcut;
|
||||
class ShortcutEventHandler;
|
||||
|
||||
/// Class used to track and update shortcuts/sequences
|
||||
class ShortcutManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ShortcutManager();
|
||||
|
||||
/// The shortcut class will do this automatically
|
||||
void addShortcut(Shortcut* shortcut);
|
||||
|
||||
/// The shortcut class will do this automatically
|
||||
void removeShortcut(Shortcut* shortcut);
|
||||
|
||||
bool getSequence(const std::string& name, QKeySequence& sequence) const;
|
||||
void setSequence(const std::string& name, const QKeySequence& sequence);
|
||||
|
||||
bool getModifier(const std::string& name, int& modifier) const;
|
||||
void setModifier(const std::string& name, int modifier);
|
||||
|
||||
std::string convertToString(const QKeySequence& sequence) const;
|
||||
std::string convertToString(int modifier) const;
|
||||
|
||||
std::string convertToString(const QKeySequence& sequence, int modifier) const;
|
||||
|
||||
void convertFromString(const std::string& data, QKeySequence& sequence) const;
|
||||
void convertFromString(const std::string& data, int& modifier) const;
|
||||
|
||||
void convertFromString(const std::string& data, QKeySequence& sequence, int& modifier) const;
|
||||
|
||||
/// Replaces "{sequence-name}" or "{modifier-name}" with the appropriate text
|
||||
QString processToolTip(const QString& toolTip) const;
|
||||
|
||||
private:
|
||||
|
||||
// Need a multimap in case multiple shortcuts share the same name
|
||||
typedef std::multimap<std::string, Shortcut*> ShortcutMap;
|
||||
typedef std::map<std::string, QKeySequence> SequenceMap;
|
||||
typedef std::map<std::string, int> ModifierMap;
|
||||
typedef std::map<int, std::string> NameMap;
|
||||
typedef std::map<std::string, int> KeyMap;
|
||||
|
||||
ShortcutMap mShortcuts;
|
||||
SequenceMap mSequences;
|
||||
ModifierMap mModifiers;
|
||||
|
||||
NameMap mNames;
|
||||
KeyMap mKeys;
|
||||
|
||||
ShortcutEventHandler* mEventHandler;
|
||||
|
||||
void createLookupTables();
|
||||
|
||||
static const std::pair<int, const char*> QtKeys[];
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
196
apps/opencs/model/prefs/shortcutsetting.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
#include "shortcutsetting.hpp"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
#include "state.hpp"
|
||||
#include "shortcutmanager.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
const int ShortcutSetting::MaxKeys;
|
||||
|
||||
ShortcutSetting::ShortcutSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key,
|
||||
const std::string& label)
|
||||
: Setting(parent, values, mutex, key, label)
|
||||
, mEditorActive(false)
|
||||
, mEditorPos(0)
|
||||
{
|
||||
for (int i = 0; i < MaxKeys; ++i)
|
||||
{
|
||||
mEditorKeys[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<QWidget*, QWidget*> ShortcutSetting::makeWidgets(QWidget* parent)
|
||||
{
|
||||
QKeySequence sequence;
|
||||
State::get().getShortcutManager().getSequence(getKey(), sequence);
|
||||
|
||||
QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(sequence).c_str());
|
||||
|
||||
QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent);
|
||||
QPushButton* widget = new QPushButton(text, parent);
|
||||
|
||||
widget->setCheckable(true);
|
||||
widget->installEventFilter(this);
|
||||
mButton = widget;
|
||||
|
||||
connect(widget, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));
|
||||
|
||||
return std::make_pair(label, widget);
|
||||
}
|
||||
|
||||
bool ShortcutSetting::eventFilter(QObject* target, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->isAutoRepeat())
|
||||
return true;
|
||||
|
||||
int mod = keyEvent->modifiers();
|
||||
int key = keyEvent->key();
|
||||
|
||||
return handleEvent(target, mod, key, true);
|
||||
}
|
||||
else if (event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->isAutoRepeat())
|
||||
return true;
|
||||
|
||||
int mod = keyEvent->modifiers();
|
||||
int key = keyEvent->key();
|
||||
|
||||
return handleEvent(target, mod, key, false);
|
||||
}
|
||||
else if (event->type() == QEvent::MouseButtonPress)
|
||||
{
|
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
int mod = mouseEvent->modifiers();
|
||||
int key = mouseEvent->button();
|
||||
|
||||
return handleEvent(target, mod, key, true);
|
||||
}
|
||||
else if (event->type() == QEvent::MouseButtonRelease)
|
||||
{
|
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
int mod = mouseEvent->modifiers();
|
||||
int key = mouseEvent->button();
|
||||
|
||||
return handleEvent(target, mod, key, false);
|
||||
}
|
||||
else if (event->type() == QEvent::FocusOut)
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShortcutSetting::handleEvent(QObject* target, int mod, int value, bool active)
|
||||
{
|
||||
// Modifiers are handled differently
|
||||
const int Blacklist[] =
|
||||
{
|
||||
Qt::Key_Shift,
|
||||
Qt::Key_Control,
|
||||
Qt::Key_Meta,
|
||||
Qt::Key_Alt,
|
||||
Qt::Key_AltGr
|
||||
};
|
||||
|
||||
const size_t BlacklistSize = sizeof(Blacklist) / sizeof(int);
|
||||
|
||||
if (!mEditorActive)
|
||||
{
|
||||
if (value == Qt::RightButton && !active)
|
||||
{
|
||||
// Clear sequence
|
||||
QKeySequence sequence = QKeySequence(0, 0, 0, 0);
|
||||
storeValue(sequence);
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle blacklist
|
||||
for (size_t i = 0; i < BlacklistSize; ++i)
|
||||
{
|
||||
if (value == Blacklist[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!active || mEditorPos >= MaxKeys)
|
||||
{
|
||||
// Update key
|
||||
QKeySequence sequence = QKeySequence(mEditorKeys[0], mEditorKeys[1], mEditorKeys[2], mEditorKeys[3]);
|
||||
storeValue(sequence);
|
||||
|
||||
resetState();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mEditorPos == 0)
|
||||
{
|
||||
mEditorKeys[0] = mod | value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEditorKeys[mEditorPos] = value;
|
||||
}
|
||||
|
||||
mEditorPos += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShortcutSetting::storeValue(const QKeySequence& sequence)
|
||||
{
|
||||
State::get().getShortcutManager().setSequence(getKey(), sequence);
|
||||
|
||||
// Convert to string and assign
|
||||
std::string value = State::get().getShortcutManager().convertToString(sequence);
|
||||
|
||||
{
|
||||
QMutexLocker lock(getMutex());
|
||||
getValues().setString(getKey(), getParent()->getKey(), value);
|
||||
}
|
||||
|
||||
getParent()->getState()->update(*this);
|
||||
}
|
||||
|
||||
void ShortcutSetting::resetState()
|
||||
{
|
||||
mButton->setChecked(false);
|
||||
mEditorActive = false;
|
||||
mEditorPos = 0;
|
||||
for (int i = 0; i < MaxKeys; ++i)
|
||||
{
|
||||
mEditorKeys[i] = 0;
|
||||
}
|
||||
|
||||
// Button text
|
||||
QKeySequence sequence;
|
||||
State::get().getShortcutManager().getSequence(getKey(), sequence);
|
||||
|
||||
QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(sequence).c_str());
|
||||
mButton->setText(text);
|
||||
}
|
||||
|
||||
void ShortcutSetting::buttonToggled(bool checked)
|
||||
{
|
||||
if (checked)
|
||||
mButton->setText("Press keys or click here...");
|
||||
|
||||
mEditorActive = checked;
|
||||
}
|
||||
}
|
49
apps/opencs/model/prefs/shortcutsetting.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef CSM_PREFS_SHORTCUTSETTING_H
|
||||
#define CSM_PREFS_SHORTCUTSETTING_H
|
||||
|
||||
#include <QKeySequence>
|
||||
|
||||
#include "setting.hpp"
|
||||
|
||||
class QEvent;
|
||||
class QPushButton;
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class ShortcutSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ShortcutSetting(Category* parent, Settings::Manager* values, QMutex* mutex, const std::string& key,
|
||||
const std::string& label);
|
||||
|
||||
virtual std::pair<QWidget*, QWidget*> makeWidgets(QWidget* parent);
|
||||
|
||||
protected:
|
||||
|
||||
bool eventFilter(QObject* target, QEvent* event);
|
||||
|
||||
private:
|
||||
|
||||
bool handleEvent(QObject* target, int mod, int value, bool active);
|
||||
|
||||
void storeValue(const QKeySequence& sequence);
|
||||
void resetState();
|
||||
|
||||
static const int MaxKeys = 4;
|
||||
|
||||
QPushButton* mButton;
|
||||
|
||||
bool mEditorActive;
|
||||
int mEditorPos;
|
||||
int mEditorKeys[MaxKeys];
|
||||
|
||||
private slots:
|
||||
|
||||
void buttonToggled(bool checked);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -9,6 +9,8 @@
|
|||
#include "doublesetting.hpp"
|
||||
#include "boolsetting.hpp"
|
||||
#include "coloursetting.hpp"
|
||||
#include "shortcutsetting.hpp"
|
||||
#include "modifiersetting.hpp"
|
||||
|
||||
CSMPrefs::State *CSMPrefs::State::sThis = 0;
|
||||
|
||||
|
@ -165,16 +167,6 @@ void CSMPrefs::State::declare()
|
|||
"list go to the first/last item");
|
||||
|
||||
declareCategory ("3D Scene Input");
|
||||
EnumValue left ("Left Mouse-Button");
|
||||
EnumValue cLeft ("Ctrl-Left Mouse-Button");
|
||||
EnumValue right ("Right Mouse-Button");
|
||||
EnumValue cRight ("Ctrl-Right Mouse-Button");
|
||||
EnumValue middle ("Middle Mouse-Button");
|
||||
EnumValue cMiddle ("Ctrl-Middle Mouse-Button");
|
||||
EnumValues inputButtons;
|
||||
inputButtons.add (left).add (cLeft).add (right).add (cRight).add (middle).add (cMiddle);
|
||||
declareEnum ("p-navi", "Primary Camera Navigation Button", left).addValues (inputButtons);
|
||||
declareEnum ("s-navi", "Secondary Camera Navigation Button", cLeft).addValues (inputButtons);
|
||||
declareDouble ("p-navi-free-sensitivity", "Free Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0);
|
||||
declareBool ("p-navi-free-invert", "Invert Free Camera Mouse Input", false);
|
||||
declareDouble ("p-navi-orbit-sensitivity", "Orbit Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0);
|
||||
|
@ -186,10 +178,6 @@ void CSMPrefs::State::declare()
|
|||
declareDouble ("navi-free-speed-mult", "Free Camera Speed Multiplier (from Modifier)", 8).setRange(0.001, 1000.0);
|
||||
declareDouble ("navi-orbit-rot-speed", "Orbital Camera Rotational Speed", 3.14 / 4).setRange(0.001, 6.28);
|
||||
declareDouble ("navi-orbit-speed-mult", "Orbital Camera Speed Multiplier (from Modifier)", 4).setRange(0.001, 1000.0);
|
||||
declareEnum ("p-edit", "Primary Editing Button", right).addValues (inputButtons);
|
||||
declareEnum ("s-edit", "Secondary Editing Button", cRight).addValues (inputButtons);
|
||||
declareEnum ("p-select", "Primary Selection Button", middle).addValues (inputButtons);
|
||||
declareEnum ("s-select", "Secondary Selection Button", cMiddle).addValues (inputButtons);
|
||||
declareSeparator();
|
||||
declareBool ("context-select", "Context Sensitive Selection", false);
|
||||
declareDouble ("drag-factor", "Mouse sensitivity during drag operations", 1.0).
|
||||
|
@ -224,6 +212,119 @@ void CSMPrefs::State::declare()
|
|||
addValues (insertOutsideCell);
|
||||
declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert).
|
||||
addValues (insertOutsideVisibleCell);
|
||||
|
||||
declareCategory ("Key Bindings");
|
||||
|
||||
declareSubcategory ("Document");
|
||||
declareShortcut ("document-file-newgame", "New Game", QKeySequence(Qt::ControlModifier | Qt::Key_N));
|
||||
declareShortcut ("document-file-newaddon", "New Addon", QKeySequence());
|
||||
declareShortcut ("document-file-open", "Open", QKeySequence(Qt::ControlModifier | Qt::Key_O));
|
||||
declareShortcut ("document-file-save", "Save", QKeySequence(Qt::ControlModifier | Qt::Key_S));
|
||||
declareShortcut ("document-file-verify", "Verify", QKeySequence());
|
||||
declareShortcut ("document-file-merge", "Merge", QKeySequence());
|
||||
declareShortcut ("document-file-errorlog", "Open Load Error Log", QKeySequence());
|
||||
declareShortcut ("document-file-metadata", "Meta Data", QKeySequence());
|
||||
declareShortcut ("document-file-close", "Close Document", QKeySequence(Qt::ControlModifier | Qt::Key_W));
|
||||
declareShortcut ("document-file-exit", "Exit Application", QKeySequence(Qt::ControlModifier | Qt::Key_Q));
|
||||
declareShortcut ("document-edit-undo", "Undo", QKeySequence(Qt::ControlModifier | Qt::Key_Z));
|
||||
declareShortcut ("document-edit-redo", "Redo", QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Z));
|
||||
declareShortcut ("document-edit-preferences", "Open Preferences", QKeySequence());
|
||||
declareShortcut ("document-edit-search", "Search", QKeySequence(Qt::ControlModifier | Qt::Key_F));
|
||||
declareShortcut ("document-view-newview", "New View", QKeySequence());
|
||||
declareShortcut ("document-view-statusbar", "Toggle Status Bar", QKeySequence());
|
||||
declareShortcut ("document-view-filters", "Open Filter List", QKeySequence());
|
||||
declareShortcut ("document-world-regions", "Open Region List", QKeySequence());
|
||||
declareShortcut ("document-world-cells", "Open Cell List", QKeySequence());
|
||||
declareShortcut ("document-world-referencables", "Open Object List", QKeySequence());
|
||||
declareShortcut ("document-world-references", "Open Instance List", QKeySequence());
|
||||
declareShortcut ("document-world-pathgrid", "Open Pathgrid List", QKeySequence());
|
||||
declareShortcut ("document-world-regionmap", "Open Region Map", QKeySequence());
|
||||
declareShortcut ("document-mechanics-globals", "Open Global List", QKeySequence());
|
||||
declareShortcut ("document-mechanics-gamesettings", "Open Game Settings", QKeySequence());
|
||||
declareShortcut ("document-mechanics-scripts", "Open Script List", QKeySequence());
|
||||
declareShortcut ("document-mechanics-spells", "Open Spell List", QKeySequence());
|
||||
declareShortcut ("document-mechanics-enchantments", "Open Enchantment List", QKeySequence());
|
||||
declareShortcut ("document-mechanics-magiceffects", "Open Magic Effect List", QKeySequence());
|
||||
declareShortcut ("document-mechanics-startscripts", "Open Start Script List", QKeySequence());
|
||||
declareShortcut ("document-character-skills", "Open Skill List", QKeySequence());
|
||||
declareShortcut ("document-character-classes", "Open Class List", QKeySequence());
|
||||
declareShortcut ("document-character-factions", "Open Faction List", QKeySequence());
|
||||
declareShortcut ("document-character-races", "Open Race List", QKeySequence());
|
||||
declareShortcut ("document-character-birthsigns", "Open Birthsign List", QKeySequence());
|
||||
declareShortcut ("document-character-topics", "Open Topic List", QKeySequence());
|
||||
declareShortcut ("document-character-journals", "Open Journal List", QKeySequence());
|
||||
declareShortcut ("document-character-topicinfos", "Open Topic Info List", QKeySequence());
|
||||
declareShortcut ("document-character-journalinfos", "Open Journal Info List", QKeySequence());
|
||||
declareShortcut ("document-character-bodyparts", "Open Body Part List", QKeySequence());
|
||||
declareShortcut ("document-assets-sounds", "Open Sound Asset List", QKeySequence());
|
||||
declareShortcut ("document-assets-soundgens", "Open Sound Generator List", QKeySequence());
|
||||
declareShortcut ("document-assets-meshes", "Open Mesh Asset List", QKeySequence());
|
||||
declareShortcut ("document-assets-icons", "Open Icon Asset List", QKeySequence());
|
||||
declareShortcut ("document-assets-music", "Open Music Asset List", QKeySequence());
|
||||
declareShortcut ("document-assets-soundres", "Open Sound File List", QKeySequence());
|
||||
declareShortcut ("document-assets-textures", "Open Texture Asset List", QKeySequence());
|
||||
declareShortcut ("document-assets-videos", "Open Video Asset List", QKeySequence());
|
||||
declareShortcut ("document-debug-run", "Run Debug", QKeySequence());
|
||||
declareShortcut ("document-debug-shutdown", "Stop Debug", QKeySequence());
|
||||
declareShortcut ("document-debug-runlog", "Open Run Log", QKeySequence());
|
||||
|
||||
declareSubcategory ("Table");
|
||||
declareShortcut ("table-edit", "Edit Record", QKeySequence());
|
||||
declareShortcut ("table-add", "Add Row/Record", QKeySequence(Qt::ShiftModifier | Qt::Key_A));
|
||||
declareShortcut ("table-clone", "Clone Record", QKeySequence(Qt::ShiftModifier | Qt::Key_D));
|
||||
declareShortcut ("table-revert", "Revert Record", QKeySequence());
|
||||
declareShortcut ("table-remove", "Remove Row/Record", QKeySequence(Qt::Key_Delete));
|
||||
declareShortcut ("table-moveup", "Move Record Up", QKeySequence());
|
||||
declareShortcut ("table-movedown", "Move Record Down", QKeySequence());
|
||||
declareShortcut ("table-view", "View Record", QKeySequence());
|
||||
declareShortcut ("table-preview", "Preview Record", QKeySequence());
|
||||
declareShortcut ("table-extendeddelete", "Extended Record Deletion", QKeySequence());
|
||||
declareShortcut ("table-extendedrevert", "Extended Record Revertion", QKeySequence());
|
||||
|
||||
declareSubcategory ("Report Table");
|
||||
declareShortcut ("reporttable-show", "Show Report", QKeySequence());
|
||||
declareShortcut ("reporttable-remove", "Remove Report", QKeySequence(Qt::Key_Delete));
|
||||
declareShortcut ("reporttable-replace", "Replace Report", QKeySequence());
|
||||
declareShortcut ("reporttable-refresh", "Refresh Report", QKeySequence());
|
||||
|
||||
declareSubcategory ("Scene");
|
||||
declareShortcut ("scene-navi-primary", "Camera Rotation From Mouse Movement", QKeySequence(Qt::LeftButton));
|
||||
declareShortcut ("scene-navi-secondary", "Camera Translation From Mouse Movement",
|
||||
QKeySequence(Qt::ControlModifier | (int)Qt::LeftButton));
|
||||
declareShortcut ("scene-edit-primary", "Primary Edit", QKeySequence(Qt::RightButton));
|
||||
declareShortcut ("scene-edit-secondary", "Secondary Edit",
|
||||
QKeySequence(Qt::ControlModifier | (int)Qt::RightButton));
|
||||
declareShortcut ("scene-select-primary", "Primary Select", QKeySequence(Qt::MiddleButton));
|
||||
declareShortcut ("scene-select-secondary", "Secondary Select",
|
||||
QKeySequence(Qt::ControlModifier | (int)Qt::MiddleButton));
|
||||
declareModifier ("scene-speed-modifier", "Speed Modifier", Qt::Key_Shift);
|
||||
declareShortcut ("scene-load-cam-cell", "Load Camera Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_5));
|
||||
declareShortcut ("scene-load-cam-eastcell", "Load East Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_6));
|
||||
declareShortcut ("scene-load-cam-northcell", "Load North Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_8));
|
||||
declareShortcut ("scene-load-cam-westcell", "Load West Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_4));
|
||||
declareShortcut ("scene-load-cam-southcell", "Load South Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_2));
|
||||
declareShortcut ("scene-edit-abort", "Abort", QKeySequence(Qt::Key_Escape));
|
||||
declareShortcut ("scene-focus-toolbar", "Toggle Toolbar Focus", QKeySequence(Qt::Key_T));
|
||||
declareShortcut ("scene-render-stats", "Debug Rendering Stats", QKeySequence(Qt::Key_F3));
|
||||
|
||||
declareSubcategory ("1st/Free Camera");
|
||||
declareShortcut ("free-forward", "Forward", QKeySequence(Qt::Key_W));
|
||||
declareShortcut ("free-backward", "Backward", QKeySequence(Qt::Key_S));
|
||||
declareShortcut ("free-left", "Left", QKeySequence(Qt::Key_A));
|
||||
declareShortcut ("free-right", "Right", QKeySequence(Qt::Key_D));
|
||||
declareShortcut ("free-roll-left", "Roll Left", QKeySequence(Qt::Key_Q));
|
||||
declareShortcut ("free-roll-right", "Roll Right", QKeySequence(Qt::Key_E));
|
||||
declareShortcut ("free-speed-mode", "Toggle Speed Mode", QKeySequence(Qt::Key_F));
|
||||
|
||||
declareSubcategory ("Orbit Camera");
|
||||
declareShortcut ("orbit-up", "Up", QKeySequence(Qt::Key_W));
|
||||
declareShortcut ("orbit-down", "Down", QKeySequence(Qt::Key_S));
|
||||
declareShortcut ("orbit-left", "Left", QKeySequence(Qt::Key_A));
|
||||
declareShortcut ("orbit-right", "Right", QKeySequence(Qt::Key_D));
|
||||
declareShortcut ("orbit-roll-left", "Roll Left", QKeySequence(Qt::Key_Q));
|
||||
declareShortcut ("orbit-roll-right", "Roll Right", QKeySequence(Qt::Key_E));
|
||||
declareShortcut ("orbit-speed-mode", "Toggle Speed Mode", QKeySequence(Qt::Key_F));
|
||||
declareShortcut ("orbit-center-selection", "Center On Selected", QKeySequence(Qt::Key_C));
|
||||
}
|
||||
|
||||
void CSMPrefs::State::declareCategory (const std::string& key)
|
||||
|
@ -340,6 +441,50 @@ CSMPrefs::ColourSetting& CSMPrefs::State::declareColour (const std::string& key,
|
|||
return *setting;
|
||||
}
|
||||
|
||||
CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut (const std::string& key, const std::string& label,
|
||||
const QKeySequence& default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
std::string seqStr = getShortcutManager().convertToString(default_);
|
||||
setDefault (key, seqStr);
|
||||
|
||||
// Setup with actual data
|
||||
QKeySequence sequence;
|
||||
|
||||
getShortcutManager().convertFromString(mSettings.getString(key, mCurrentCategory->second.getKey()), sequence);
|
||||
getShortcutManager().setSequence(key, sequence);
|
||||
|
||||
CSMPrefs::ShortcutSetting *setting = new CSMPrefs::ShortcutSetting (&mCurrentCategory->second, &mSettings, &mMutex,
|
||||
key, label);
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
CSMPrefs::ModifierSetting& CSMPrefs::State::declareModifier(const std::string& key, const std::string& label,
|
||||
int default_)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
std::string modStr = getShortcutManager().convertToString(default_);
|
||||
setDefault (key, modStr);
|
||||
|
||||
// Setup with actual data
|
||||
int modifier;
|
||||
|
||||
getShortcutManager().convertFromString(mSettings.getString(key, mCurrentCategory->second.getKey()), modifier);
|
||||
getShortcutManager().setModifier(key, modifier);
|
||||
|
||||
CSMPrefs::ModifierSetting *setting = new CSMPrefs::ModifierSetting (&mCurrentCategory->second, &mSettings, &mMutex,
|
||||
key, label);
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
|
||||
return *setting;
|
||||
}
|
||||
|
||||
void CSMPrefs::State::declareSeparator()
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
|
@ -351,6 +496,17 @@ void CSMPrefs::State::declareSeparator()
|
|||
mCurrentCategory->second.addSetting (setting);
|
||||
}
|
||||
|
||||
void CSMPrefs::State::declareSubcategory(const std::string& label)
|
||||
{
|
||||
if (mCurrentCategory==mCategories.end())
|
||||
throw std::logic_error ("no category for setting");
|
||||
|
||||
CSMPrefs::Setting *setting =
|
||||
new CSMPrefs::Setting (&mCurrentCategory->second, &mSettings, &mMutex, "", label);
|
||||
|
||||
mCurrentCategory->second.addSetting (setting);
|
||||
}
|
||||
|
||||
void CSMPrefs::State::setDefault (const std::string& key, const std::string& default_)
|
||||
{
|
||||
Settings::CategorySetting fullKey (mCurrentCategory->second.getKey(), key);
|
||||
|
@ -369,10 +525,10 @@ CSMPrefs::State::State (const Files::ConfigurationManager& configurationManager)
|
|||
if (sThis)
|
||||
throw std::logic_error ("An instance of CSMPRefs::State already exists");
|
||||
|
||||
sThis = this;
|
||||
|
||||
load();
|
||||
declare();
|
||||
|
||||
sThis = this;
|
||||
}
|
||||
|
||||
CSMPrefs::State::~State()
|
||||
|
@ -396,6 +552,11 @@ CSMPrefs::State::Iterator CSMPrefs::State::end()
|
|||
return mCategories.end();
|
||||
}
|
||||
|
||||
CSMPrefs::ShortcutManager& CSMPrefs::State::getShortcutManager()
|
||||
{
|
||||
return mShortcutManager;
|
||||
}
|
||||
|
||||
CSMPrefs::Category& CSMPrefs::State::operator[] (const std::string& key)
|
||||
{
|
||||
Iterator iter = mCategories.find (key);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "category.hpp"
|
||||
#include "setting.hpp"
|
||||
#include "enumsetting.hpp"
|
||||
#include "shortcutmanager.hpp"
|
||||
|
||||
class QColor;
|
||||
|
||||
|
@ -25,6 +26,8 @@ namespace CSMPrefs
|
|||
class DoubleSetting;
|
||||
class BoolSetting;
|
||||
class ColourSetting;
|
||||
class ShortcutSetting;
|
||||
class ModifierSetting;
|
||||
|
||||
/// \brief User settings state
|
||||
///
|
||||
|
@ -45,6 +48,7 @@ namespace CSMPrefs
|
|||
|
||||
const std::string mConfigFile;
|
||||
const Files::ConfigurationManager& mConfigurationManager;
|
||||
ShortcutManager mShortcutManager;
|
||||
Settings::Manager mSettings;
|
||||
Collection mCategories;
|
||||
Iterator mCurrentCategory;
|
||||
|
@ -71,8 +75,15 @@ namespace CSMPrefs
|
|||
|
||||
ColourSetting& declareColour (const std::string& key, const std::string& label, QColor default_);
|
||||
|
||||
ShortcutSetting& declareShortcut (const std::string& key, const std::string& label,
|
||||
const QKeySequence& default_);
|
||||
|
||||
ModifierSetting& declareModifier(const std::string& key, const std::string& label, int modifier_);
|
||||
|
||||
void declareSeparator();
|
||||
|
||||
void declareSubcategory(const std::string& label);
|
||||
|
||||
void setDefault (const std::string& key, const std::string& default_);
|
||||
|
||||
public:
|
||||
|
@ -87,6 +98,8 @@ namespace CSMPrefs
|
|||
|
||||
Iterator end();
|
||||
|
||||
ShortcutManager& getShortcutManager();
|
||||
|
||||
Category& operator[](const std::string& key);
|
||||
|
||||
void update (const Setting& setting);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "../../model/doc/document.hpp"
|
||||
#include "../../model/prefs/state.hpp"
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "../../model/world/idtable.hpp"
|
||||
|
||||
|
@ -44,83 +45,98 @@ void CSVDoc::View::closeEvent (QCloseEvent *event)
|
|||
|
||||
void CSVDoc::View::setupFileMenu()
|
||||
{
|
||||
QMenu *file = menuBar()->addMenu (tr ("&File"));
|
||||
QMenu *file = menuBar()->addMenu (tr ("File"));
|
||||
|
||||
QAction *newGame = new QAction (tr ("New Game"), this);
|
||||
connect (newGame, SIGNAL (triggered()), this, SIGNAL (newGameRequest()));
|
||||
setupShortcut("document-file-newgame", newGame);
|
||||
file->addAction (newGame);
|
||||
|
||||
|
||||
QAction *newAddon = new QAction (tr ("New Addon"), this);
|
||||
connect (newAddon, SIGNAL (triggered()), this, SIGNAL (newAddonRequest()));
|
||||
setupShortcut("document-file-newaddon", newAddon);
|
||||
file->addAction (newAddon);
|
||||
|
||||
QAction *open = new QAction (tr ("&Open"), this);
|
||||
QAction *open = new QAction (tr ("Open"), this);
|
||||
connect (open, SIGNAL (triggered()), this, SIGNAL (loadDocumentRequest()));
|
||||
setupShortcut("document-file-open", open);
|
||||
file->addAction (open);
|
||||
|
||||
mSave = new QAction (tr ("&Save"), this);
|
||||
mSave = new QAction (tr ("Save"), this);
|
||||
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
|
||||
setupShortcut("document-file-save", mSave);
|
||||
file->addAction (mSave);
|
||||
|
||||
mVerify = new QAction (tr ("&Verify"), this);
|
||||
mVerify = new QAction (tr ("Verify"), this);
|
||||
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
|
||||
setupShortcut("document-file-verify", mVerify);
|
||||
file->addAction (mVerify);
|
||||
|
||||
mMerge = new QAction (tr ("Merge"), this);
|
||||
connect (mMerge, SIGNAL (triggered()), this, SLOT (merge()));
|
||||
setupShortcut("document-file-merge", mMerge);
|
||||
file->addAction (mMerge);
|
||||
|
||||
QAction *loadErrors = new QAction (tr ("Load Error Log"), this);
|
||||
QAction *loadErrors = new QAction (tr ("Open Load Error Log"), this);
|
||||
connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog()));
|
||||
setupShortcut("document-file-errorlog", loadErrors);
|
||||
file->addAction (loadErrors);
|
||||
|
||||
QAction *meta = new QAction (tr ("Meta Data"), this);
|
||||
connect (meta, SIGNAL (triggered()), this, SLOT (addMetaDataSubView()));
|
||||
setupShortcut("document-file-metadata", meta);
|
||||
file->addAction (meta);
|
||||
|
||||
QAction *close = new QAction (tr ("&Close"), this);
|
||||
QAction *close = new QAction (tr ("Close Document"), this);
|
||||
connect (close, SIGNAL (triggered()), this, SLOT (close()));
|
||||
setupShortcut("document-file-close", close);
|
||||
file->addAction(close);
|
||||
|
||||
QAction *exit = new QAction (tr ("&Exit"), this);
|
||||
QAction *exit = new QAction (tr ("Exit Application"), this);
|
||||
connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
|
||||
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
|
||||
setupShortcut("document-file-exit", exit);
|
||||
|
||||
file->addAction(exit);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupEditMenu()
|
||||
{
|
||||
QMenu *edit = menuBar()->addMenu (tr ("&Edit"));
|
||||
QMenu *edit = menuBar()->addMenu (tr ("Edit"));
|
||||
|
||||
mUndo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo"));
|
||||
mUndo->setShortcuts (QKeySequence::Undo);
|
||||
mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo"));
|
||||
setupShortcut("document-edit-undo", mUndo);
|
||||
edit->addAction (mUndo);
|
||||
|
||||
mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo"));
|
||||
mRedo->setShortcuts (QKeySequence::Redo);
|
||||
mRedo= mDocument->getUndoStack().createRedoAction (this, tr("Redo"));
|
||||
setupShortcut("document-edit-redo", mRedo);
|
||||
edit->addAction (mRedo);
|
||||
|
||||
QAction *userSettings = new QAction (tr ("&Preferences"), this);
|
||||
QAction *userSettings = new QAction (tr ("Preferences"), this);
|
||||
connect (userSettings, SIGNAL (triggered()), this, SIGNAL (editSettingsRequest()));
|
||||
setupShortcut("document-edit-preferences", userSettings);
|
||||
edit->addAction (userSettings);
|
||||
|
||||
QAction *search = new QAction (tr ("Search"), this);
|
||||
connect (search, SIGNAL (triggered()), this, SLOT (addSearchSubView()));
|
||||
setupShortcut("document-edit-search", search);
|
||||
edit->addAction (search);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupViewMenu()
|
||||
{
|
||||
QMenu *view = menuBar()->addMenu (tr ("&View"));
|
||||
QMenu *view = menuBar()->addMenu (tr ("View"));
|
||||
|
||||
QAction *newWindow = new QAction (tr ("&New View"), this);
|
||||
QAction *newWindow = new QAction (tr ("New View"), this);
|
||||
connect (newWindow, SIGNAL (triggered()), this, SLOT (newView()));
|
||||
setupShortcut("document-view-newview", newWindow);
|
||||
view->addAction (newWindow);
|
||||
|
||||
mShowStatusBar = new QAction (tr ("Show Status Bar"), this);
|
||||
mShowStatusBar = new QAction (tr ("Toggle Status Bar"), this);
|
||||
mShowStatusBar->setCheckable (true);
|
||||
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
|
||||
setupShortcut("document-view-statusbar", mShowStatusBar);
|
||||
|
||||
mShowStatusBar->setChecked (CSMPrefs::get()["Windows"]["show-statusbar"].isTrue());
|
||||
|
||||
|
@ -128,70 +144,84 @@ void CSVDoc::View::setupViewMenu()
|
|||
|
||||
QAction *filters = new QAction (tr ("Filters"), this);
|
||||
connect (filters, SIGNAL (triggered()), this, SLOT (addFiltersSubView()));
|
||||
setupShortcut("document-view-filters", filters);
|
||||
view->addAction (filters);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupWorldMenu()
|
||||
{
|
||||
QMenu *world = menuBar()->addMenu (tr ("&World"));
|
||||
QMenu *world = menuBar()->addMenu (tr ("World"));
|
||||
|
||||
QAction *regions = new QAction (tr ("Regions"), this);
|
||||
connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView()));
|
||||
setupShortcut("document-world-regions", regions);
|
||||
world->addAction (regions);
|
||||
|
||||
QAction *cells = new QAction (tr ("Cells"), this);
|
||||
connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView()));
|
||||
setupShortcut("document-world-cells", cells);
|
||||
world->addAction (cells);
|
||||
|
||||
QAction *referenceables = new QAction (tr ("Objects"), this);
|
||||
connect (referenceables, SIGNAL (triggered()), this, SLOT (addReferenceablesSubView()));
|
||||
setupShortcut("document-world-referencables", referenceables);
|
||||
world->addAction (referenceables);
|
||||
|
||||
QAction *references = new QAction (tr ("Instances"), this);
|
||||
connect (references, SIGNAL (triggered()), this, SLOT (addReferencesSubView()));
|
||||
setupShortcut("document-world-references", references);
|
||||
world->addAction (references);
|
||||
|
||||
QAction *grid = new QAction (tr ("Pathgrid"), this);
|
||||
connect (grid, SIGNAL (triggered()), this, SLOT (addPathgridSubView()));
|
||||
setupShortcut("document-world-pathgrid", grid);
|
||||
world->addAction (grid);
|
||||
|
||||
world->addSeparator(); // items that don't represent single record lists follow here
|
||||
|
||||
QAction *regionMap = new QAction (tr ("Region Map"), this);
|
||||
connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView()));
|
||||
setupShortcut("document-world-regionmap", regionMap);
|
||||
world->addAction (regionMap);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupMechanicsMenu()
|
||||
{
|
||||
QMenu *mechanics = menuBar()->addMenu (tr ("&Mechanics"));
|
||||
QMenu *mechanics = menuBar()->addMenu (tr ("Mechanics"));
|
||||
|
||||
QAction *globals = new QAction (tr ("Globals"), this);
|
||||
connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView()));
|
||||
setupShortcut("document-mechanics-globals", globals);
|
||||
mechanics->addAction (globals);
|
||||
|
||||
QAction *gmsts = new QAction (tr ("Game settings"), this);
|
||||
QAction *gmsts = new QAction (tr ("Game Settings"), this);
|
||||
connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
|
||||
setupShortcut("document-mechanics-gamesettings", gmsts);
|
||||
mechanics->addAction (gmsts);
|
||||
|
||||
QAction *scripts = new QAction (tr ("Scripts"), this);
|
||||
connect (scripts, SIGNAL (triggered()), this, SLOT (addScriptsSubView()));
|
||||
setupShortcut("document-mechanics-scripts", scripts);
|
||||
mechanics->addAction (scripts);
|
||||
|
||||
QAction *spells = new QAction (tr ("Spells"), this);
|
||||
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
|
||||
setupShortcut("document-mechanics-spells", spells);
|
||||
mechanics->addAction (spells);
|
||||
|
||||
QAction *enchantments = new QAction (tr ("Enchantments"), this);
|
||||
connect (enchantments, SIGNAL (triggered()), this, SLOT (addEnchantmentsSubView()));
|
||||
setupShortcut("document-mechanics-enchantments", enchantments);
|
||||
mechanics->addAction (enchantments);
|
||||
|
||||
QAction *effects = new QAction (tr ("Magic Effects"), this);
|
||||
connect (effects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView()));
|
||||
setupShortcut("document-mechanics-magiceffects", effects);
|
||||
mechanics->addAction (effects);
|
||||
|
||||
QAction *startScripts = new QAction (tr ("Start Scripts"), this);
|
||||
connect (startScripts, SIGNAL (triggered()), this, SLOT (addStartScriptsSubView()));
|
||||
setupShortcut("document-mechanics-startscripts", startScripts);
|
||||
mechanics->addAction (startScripts);
|
||||
}
|
||||
|
||||
|
@ -201,81 +231,99 @@ void CSVDoc::View::setupCharacterMenu()
|
|||
|
||||
QAction *skills = new QAction (tr ("Skills"), this);
|
||||
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
|
||||
setupShortcut("document-character-skills", skills);
|
||||
characters->addAction (skills);
|
||||
|
||||
QAction *classes = new QAction (tr ("Classes"), this);
|
||||
connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView()));
|
||||
setupShortcut("document-character-classes", classes);
|
||||
characters->addAction (classes);
|
||||
|
||||
QAction *factions = new QAction (tr ("Factions"), this);
|
||||
connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView()));
|
||||
setupShortcut("document-character-factions", factions);
|
||||
characters->addAction (factions);
|
||||
|
||||
QAction *races = new QAction (tr ("Races"), this);
|
||||
connect (races, SIGNAL (triggered()), this, SLOT (addRacesSubView()));
|
||||
setupShortcut("document-character-races", races);
|
||||
characters->addAction (races);
|
||||
|
||||
QAction *birthsigns = new QAction (tr ("Birthsigns"), this);
|
||||
connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView()));
|
||||
setupShortcut("document-character-birthsigns", birthsigns);
|
||||
characters->addAction (birthsigns);
|
||||
|
||||
QAction *topics = new QAction (tr ("Topics"), this);
|
||||
connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView()));
|
||||
setupShortcut("document-character-topics", topics);
|
||||
characters->addAction (topics);
|
||||
|
||||
QAction *journals = new QAction (tr ("Journals"), this);
|
||||
connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView()));
|
||||
setupShortcut("document-character-journals", journals);
|
||||
characters->addAction (journals);
|
||||
|
||||
QAction *topicInfos = new QAction (tr ("Topic Infos"), this);
|
||||
connect (topicInfos, SIGNAL (triggered()), this, SLOT (addTopicInfosSubView()));
|
||||
setupShortcut("document-character-topicinfos", topicInfos);
|
||||
characters->addAction (topicInfos);
|
||||
|
||||
QAction *journalInfos = new QAction (tr ("Journal Infos"), this);
|
||||
connect (journalInfos, SIGNAL (triggered()), this, SLOT (addJournalInfosSubView()));
|
||||
setupShortcut("document-character-journalinfos", journalInfos);
|
||||
characters->addAction (journalInfos);
|
||||
|
||||
QAction *bodyParts = new QAction (tr ("Body Parts"), this);
|
||||
connect (bodyParts, SIGNAL (triggered()), this, SLOT (addBodyPartsSubView()));
|
||||
setupShortcut("document-character-bodyparts", bodyParts);
|
||||
characters->addAction (bodyParts);
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupAssetsMenu()
|
||||
{
|
||||
QMenu *assets = menuBar()->addMenu (tr ("&Assets"));
|
||||
QMenu *assets = menuBar()->addMenu (tr ("Assets"));
|
||||
|
||||
QAction *sounds = new QAction (tr ("Sounds"), this);
|
||||
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
|
||||
setupShortcut("document-assets-sounds", sounds);
|
||||
assets->addAction (sounds);
|
||||
|
||||
QAction *soundGens = new QAction (tr ("Sound Generators"), this);
|
||||
connect (soundGens, SIGNAL (triggered()), this, SLOT (addSoundGensSubView()));
|
||||
setupShortcut("document-assets-soundgens", soundGens);
|
||||
assets->addAction (soundGens);
|
||||
|
||||
assets->addSeparator(); // resources follow here
|
||||
|
||||
QAction *meshes = new QAction (tr ("Meshes"), this);
|
||||
connect (meshes, SIGNAL (triggered()), this, SLOT (addMeshesSubView()));
|
||||
setupShortcut("document-assets-meshes", meshes);
|
||||
assets->addAction (meshes);
|
||||
|
||||
QAction *icons = new QAction (tr ("Icons"), this);
|
||||
connect (icons, SIGNAL (triggered()), this, SLOT (addIconsSubView()));
|
||||
setupShortcut("document-assets-icons", icons);
|
||||
assets->addAction (icons);
|
||||
|
||||
QAction *musics = new QAction (tr ("Music"), this);
|
||||
connect (musics, SIGNAL (triggered()), this, SLOT (addMusicsSubView()));
|
||||
setupShortcut("document-assets-music", musics);
|
||||
assets->addAction (musics);
|
||||
|
||||
QAction *soundsRes = new QAction (tr ("Sound Files"), this);
|
||||
connect (soundsRes, SIGNAL (triggered()), this, SLOT (addSoundsResSubView()));
|
||||
setupShortcut("document-assets-soundres", soundsRes);
|
||||
assets->addAction (soundsRes);
|
||||
|
||||
QAction *textures = new QAction (tr ("Textures"), this);
|
||||
connect (textures, SIGNAL (triggered()), this, SLOT (addTexturesSubView()));
|
||||
setupShortcut("document-assets-textures", textures);
|
||||
assets->addAction (textures);
|
||||
|
||||
QAction *videos = new QAction (tr ("Videos"), this);
|
||||
connect (videos, SIGNAL (triggered()), this, SLOT (addVideosSubView()));
|
||||
setupShortcut("document-assets-videos", videos);
|
||||
assets->addAction (videos);
|
||||
}
|
||||
|
||||
|
@ -299,12 +347,16 @@ void CSVDoc::View::setupDebugMenu()
|
|||
QAction *runDebug = debug->addMenu (mGlobalDebugProfileMenu);
|
||||
runDebug->setText (tr ("Run OpenMW"));
|
||||
|
||||
setupShortcut("document-debug-run", runDebug);
|
||||
|
||||
mStopDebug = new QAction (tr ("Shutdown OpenMW"), this);
|
||||
connect (mStopDebug, SIGNAL (triggered()), this, SLOT (stop()));
|
||||
setupShortcut("document-debug-shutdown", mStopDebug);
|
||||
debug->addAction (mStopDebug);
|
||||
|
||||
QAction *runLog = new QAction (tr ("Run Log"), this);
|
||||
QAction *runLog = new QAction (tr ("Open Run Log"), this);
|
||||
connect (runLog, SIGNAL (triggered()), this, SLOT (addRunLogSubView()));
|
||||
setupShortcut("document-debug-runlog", runLog);
|
||||
debug->addAction (runLog);
|
||||
}
|
||||
|
||||
|
@ -320,6 +372,12 @@ void CSVDoc::View::setupUi()
|
|||
setupDebugMenu();
|
||||
}
|
||||
|
||||
void CSVDoc::View::setupShortcut(const char* name, QAction* action)
|
||||
{
|
||||
CSMPrefs::Shortcut* shortcut = new CSMPrefs::Shortcut(name, this);
|
||||
shortcut->associateAction(action);
|
||||
}
|
||||
|
||||
void CSVDoc::View::updateTitle()
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
|
|
@ -84,6 +84,8 @@ namespace CSVDoc
|
|||
|
||||
void setupUi();
|
||||
|
||||
void setupShortcut(const char* name, QAction* action);
|
||||
|
||||
void updateActions();
|
||||
|
||||
void exitApplication();
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../../model/prefs/state.hpp"
|
||||
|
||||
#include "page.hpp"
|
||||
#include "keybindingpage.hpp"
|
||||
|
||||
void CSVPrefs::Dialogue::buildCategorySelector (QSplitter *main)
|
||||
{
|
||||
|
@ -52,7 +53,9 @@ void CSVPrefs::Dialogue::buildContentArea (QSplitter *main)
|
|||
CSVPrefs::PageBase *CSVPrefs::Dialogue::makePage (const std::string& key)
|
||||
{
|
||||
// special case page code goes here
|
||||
|
||||
if (key == "Key Bindings")
|
||||
return new KeyBindingPage(CSMPrefs::get()[key], mContent);
|
||||
else
|
||||
return new Page (CSMPrefs::get()[key], mContent);
|
||||
}
|
||||
|
||||
|
|
88
apps/opencs/view/prefs/keybindingpage.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include "keybindingpage.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QStackedLayout>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "../../model/prefs/setting.hpp"
|
||||
#include "../../model/prefs/category.hpp"
|
||||
|
||||
namespace CSVPrefs
|
||||
{
|
||||
KeyBindingPage::KeyBindingPage(CSMPrefs::Category& category, QWidget* parent)
|
||||
: PageBase(category, parent)
|
||||
, mStackedLayout(0)
|
||||
, mPageLayout(0)
|
||||
, mPageSelector(0)
|
||||
{
|
||||
// Need one widget for scroll area
|
||||
QWidget* topWidget = new QWidget();
|
||||
QVBoxLayout* topLayout = new QVBoxLayout(topWidget);
|
||||
|
||||
// Allows switching between "pages"
|
||||
QWidget* stackedWidget = new QWidget();
|
||||
mStackedLayout = new QStackedLayout(stackedWidget);
|
||||
|
||||
mPageSelector = new QComboBox();
|
||||
connect(mPageSelector, SIGNAL(currentIndexChanged(int)), mStackedLayout, SLOT(setCurrentIndex(int)));
|
||||
|
||||
topLayout->addWidget(mPageSelector);
|
||||
topLayout->addWidget(stackedWidget);
|
||||
topLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
|
||||
// Add each option
|
||||
for (CSMPrefs::Category::Iterator iter = category.begin(); iter!=category.end(); ++iter)
|
||||
addSetting (*iter);
|
||||
|
||||
setWidgetResizable(true);
|
||||
setWidget(topWidget);
|
||||
}
|
||||
|
||||
void KeyBindingPage::addSetting(CSMPrefs::Setting *setting)
|
||||
{
|
||||
std::pair<QWidget*, QWidget*> widgets = setting->makeWidgets (this);
|
||||
|
||||
if (widgets.first)
|
||||
{
|
||||
// Label, Option widgets
|
||||
assert(mPageLayout);
|
||||
|
||||
int next = mPageLayout->rowCount();
|
||||
mPageLayout->addWidget(widgets.first, next, 0);
|
||||
mPageLayout->addWidget(widgets.second, next, 1);
|
||||
}
|
||||
else if (widgets.second)
|
||||
{
|
||||
// Wide single widget
|
||||
assert(mPageLayout);
|
||||
|
||||
int next = mPageLayout->rowCount();
|
||||
mPageLayout->addWidget(widgets.second, next, 0, 1, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setting->getLabel().empty())
|
||||
{
|
||||
// Insert empty space
|
||||
assert(mPageLayout);
|
||||
|
||||
int next = mPageLayout->rowCount();
|
||||
mPageLayout->addWidget(new QWidget(), next, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create new page
|
||||
QWidget* pageWidget = new QWidget();
|
||||
mPageLayout = new QGridLayout(pageWidget);
|
||||
mPageLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
|
||||
mStackedLayout->addWidget(pageWidget);
|
||||
|
||||
mPageSelector->addItem(QString::fromUtf8(setting->getLabel().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
apps/opencs/view/prefs/keybindingpage.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef CSV_PREFS_KEYBINDINGPAGE_H
|
||||
#define CSV_PREFS_KEYBINDINGPAGE_H
|
||||
|
||||
#include "pagebase.hpp"
|
||||
|
||||
class QComboBox;
|
||||
class QGridLayout;
|
||||
class QStackedLayout;
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Setting;
|
||||
}
|
||||
|
||||
namespace CSVPrefs
|
||||
{
|
||||
class KeyBindingPage : public PageBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
KeyBindingPage(CSMPrefs::Category& category, QWidget* parent);
|
||||
|
||||
void addSetting(CSMPrefs::Setting* setting);
|
||||
|
||||
private:
|
||||
|
||||
QStackedLayout* mStackedLayout;
|
||||
QGridLayout* mPageLayout;
|
||||
QComboBox* mPageSelector;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include <osg/BoundingBox>
|
||||
#include <osg/Camera>
|
||||
|
@ -14,6 +14,10 @@
|
|||
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "scenewidget.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
|
||||
|
@ -27,8 +31,9 @@ namespace CSVRender
|
|||
const osg::Vec3d CameraController::LocalLeft = osg::Vec3d(1, 0, 0);
|
||||
const osg::Vec3d CameraController::LocalForward = osg::Vec3d(0, 0, 1);
|
||||
|
||||
CameraController::CameraController()
|
||||
: mActive(false)
|
||||
CameraController::CameraController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, mActive(false)
|
||||
, mInverted(false)
|
||||
, mCameraSensitivity(1/650.f)
|
||||
, mSecondaryMoveMult(50)
|
||||
|
@ -73,11 +78,19 @@ namespace CSVRender
|
|||
|
||||
void CameraController::setCamera(osg::Camera* camera)
|
||||
{
|
||||
bool wasActive = mActive;
|
||||
|
||||
mCamera = camera;
|
||||
mActive = (mCamera != NULL);
|
||||
|
||||
if (mActive)
|
||||
onActivate();
|
||||
if (mActive != wasActive)
|
||||
{
|
||||
for (std::vector<CSMPrefs::Shortcut*>::iterator it = mShortcuts.begin(); it != mShortcuts.end(); ++it)
|
||||
{
|
||||
CSMPrefs::Shortcut* shortcut = *it;
|
||||
shortcut->enable(mActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CameraController::setCameraSensitivity(double value)
|
||||
|
@ -136,14 +149,23 @@ namespace CSVRender
|
|||
getCamera()->setViewMatrixAsLookAt(eye, center, up);
|
||||
}
|
||||
|
||||
void CameraController::addShortcut(CSMPrefs::Shortcut* shortcut)
|
||||
{
|
||||
mShortcuts.push_back(shortcut);
|
||||
}
|
||||
|
||||
/*
|
||||
Free Camera Controller
|
||||
*/
|
||||
|
||||
FreeCameraController::FreeCameraController()
|
||||
: mLockUpright(false)
|
||||
FreeCameraController::FreeCameraController(QWidget* widget)
|
||||
: CameraController(widget)
|
||||
, mLockUpright(false)
|
||||
, mModified(false)
|
||||
, mNaviPrimary(false)
|
||||
, mNaviSecondary(false)
|
||||
, mFast(false)
|
||||
, mFastAlternate(false)
|
||||
, mLeft(false)
|
||||
, mRight(false)
|
||||
, mForward(false)
|
||||
|
@ -155,6 +177,61 @@ namespace CSVRender
|
|||
, mRotSpeed(osg::PI / 2)
|
||||
, mSpeedMult(8)
|
||||
{
|
||||
CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", widget);
|
||||
naviPrimaryShortcut->enable(false);
|
||||
connect(naviPrimaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviPrimary(bool)));
|
||||
|
||||
addShortcut(naviPrimaryShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", widget);
|
||||
naviSecondaryShortcut->enable(false);
|
||||
connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool)));
|
||||
|
||||
addShortcut(naviSecondaryShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* forwardShortcut = new CSMPrefs::Shortcut("free-forward", "scene-speed-modifier",
|
||||
CSMPrefs::Shortcut::SM_Detach, widget);
|
||||
forwardShortcut->enable(false);
|
||||
connect(forwardShortcut, SIGNAL(activated(bool)), this, SLOT(forward(bool)));
|
||||
connect(forwardShortcut, SIGNAL(secondary(bool)), this, SLOT(alternateFast(bool)));
|
||||
|
||||
addShortcut(forwardShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("free-left", widget);
|
||||
leftShortcut->enable(false);
|
||||
connect(leftShortcut, SIGNAL(activated(bool)), this, SLOT(left(bool)));
|
||||
|
||||
addShortcut(leftShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* backShortcut = new CSMPrefs::Shortcut("free-backward", widget);
|
||||
backShortcut->enable(false);
|
||||
connect(backShortcut, SIGNAL(activated(bool)), this, SLOT(backward(bool)));
|
||||
|
||||
addShortcut(backShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("free-right", widget);
|
||||
rightShortcut->enable(false);
|
||||
connect(rightShortcut, SIGNAL(activated(bool)), this, SLOT(right(bool)));
|
||||
|
||||
addShortcut(rightShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("free-roll-left", widget);
|
||||
rollLeftShortcut->enable(false);
|
||||
connect(rollLeftShortcut, SIGNAL(activated(bool)), this, SLOT(rollLeft(bool)));
|
||||
|
||||
addShortcut(rollLeftShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("free-roll-right", widget);
|
||||
rollRightShortcut->enable(false);
|
||||
connect(rollRightShortcut, SIGNAL(activated(bool)), this, SLOT(rollRight(bool)));
|
||||
|
||||
addShortcut(rollRightShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("free-speed-mode", widget);
|
||||
speedModeShortcut->enable(false);
|
||||
connect(speedModeShortcut, SIGNAL(activated()), this, SLOT(swapSpeedMode()));
|
||||
|
||||
addShortcut(speedModeShortcut);
|
||||
}
|
||||
|
||||
double FreeCameraController::getLinearSpeed() const
|
||||
|
@ -199,59 +276,18 @@ namespace CSVRender
|
|||
mLockUpright = false;
|
||||
}
|
||||
|
||||
bool FreeCameraController::handleKeyEvent(QKeyEvent* event, bool pressed)
|
||||
void FreeCameraController::handleMouseMoveEvent(int x, int y)
|
||||
{
|
||||
if (!isActive())
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (event->key() == Qt::Key_Q)
|
||||
{
|
||||
mRollLeft = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_E)
|
||||
{
|
||||
mRollRight = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_A)
|
||||
{
|
||||
mLeft = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_D)
|
||||
{
|
||||
mRight = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_W)
|
||||
{
|
||||
mForward = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_S)
|
||||
{
|
||||
mBackward = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_Shift)
|
||||
{
|
||||
mFast = pressed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FreeCameraController::handleMouseMoveEvent(std::string mode, int x, int y)
|
||||
{
|
||||
if (!isActive())
|
||||
return false;
|
||||
|
||||
if (mode == "p-navi")
|
||||
if (mNaviPrimary)
|
||||
{
|
||||
double scalar = getCameraSensitivity() * (getInverted() ? -1.0 : 1.0);
|
||||
yaw(x * scalar);
|
||||
pitch(y * scalar);
|
||||
}
|
||||
else if (mode == "s-navi")
|
||||
else if (mNaviSecondary)
|
||||
{
|
||||
osg::Vec3d movement;
|
||||
movement += LocalLeft * -x * getSecondaryMovementMultiplier();
|
||||
|
@ -259,16 +295,14 @@ namespace CSVRender
|
|||
|
||||
translate(movement);
|
||||
}
|
||||
else if (mode == "t-navi")
|
||||
{
|
||||
translate(LocalForward * x * (mFast ? getWheelMovementMultiplier() : 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
void FreeCameraController::handleMouseScrollEvent(int x)
|
||||
{
|
||||
if (!isActive())
|
||||
return;
|
||||
|
||||
translate(LocalForward * x * ((mFast ^ mFastAlternate) ? getWheelMovementMultiplier() : 1));
|
||||
}
|
||||
|
||||
void FreeCameraController::update(double dt)
|
||||
|
@ -279,7 +313,7 @@ namespace CSVRender
|
|||
double linDist = mLinSpeed * dt;
|
||||
double rotDist = mRotSpeed * dt;
|
||||
|
||||
if (mFast)
|
||||
if (mFast ^ mFastAlternate)
|
||||
linDist *= mSpeedMult;
|
||||
|
||||
if (mLeft)
|
||||
|
@ -308,17 +342,6 @@ namespace CSVRender
|
|||
getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix());
|
||||
}
|
||||
|
||||
void FreeCameraController::resetInput()
|
||||
{
|
||||
mFast = false;
|
||||
mLeft = false;
|
||||
mRight = false;
|
||||
mForward = false;
|
||||
mBackward = false;
|
||||
mRollLeft = false;
|
||||
mRollRight = false;
|
||||
}
|
||||
|
||||
void FreeCameraController::yaw(double value)
|
||||
{
|
||||
getCamera()->getViewMatrix() *= osg::Matrixd::rotate(value, LocalUp);
|
||||
|
@ -368,13 +391,67 @@ namespace CSVRender
|
|||
getCamera()->setViewMatrixAsLookAt(eye, center, mUp);
|
||||
}
|
||||
|
||||
void FreeCameraController::naviPrimary(bool active)
|
||||
{
|
||||
mNaviPrimary = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::naviSecondary(bool active)
|
||||
{
|
||||
mNaviSecondary = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::forward(bool active)
|
||||
{
|
||||
mForward = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::left(bool active)
|
||||
{
|
||||
mLeft = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::backward(bool active)
|
||||
{
|
||||
mBackward = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::right(bool active)
|
||||
{
|
||||
mRight = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::rollLeft(bool active)
|
||||
{
|
||||
mRollLeft = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::rollRight(bool active)
|
||||
{
|
||||
mRollRight = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::alternateFast(bool active)
|
||||
{
|
||||
mFastAlternate = active;
|
||||
}
|
||||
|
||||
void FreeCameraController::swapSpeedMode()
|
||||
{
|
||||
mFast = !mFast;
|
||||
}
|
||||
|
||||
/*
|
||||
Orbit Camera Controller
|
||||
*/
|
||||
|
||||
OrbitCameraController::OrbitCameraController()
|
||||
: mInitialized(false)
|
||||
OrbitCameraController::OrbitCameraController(QWidget* widget)
|
||||
: CameraController(widget)
|
||||
, mInitialized(false)
|
||||
, mNaviPrimary(false)
|
||||
, mNaviSecondary(false)
|
||||
, mFast(false)
|
||||
, mFastAlternate(false)
|
||||
, mLeft(false)
|
||||
, mRight(false)
|
||||
, mUp(false)
|
||||
|
@ -387,6 +464,61 @@ namespace CSVRender
|
|||
, mOrbitSpeed(osg::PI / 4)
|
||||
, mOrbitSpeedMult(4)
|
||||
{
|
||||
CSMPrefs::Shortcut* naviPrimaryShortcut = new CSMPrefs::Shortcut("scene-navi-primary", widget);
|
||||
naviPrimaryShortcut->enable(false);
|
||||
connect(naviPrimaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviPrimary(bool)));
|
||||
|
||||
addShortcut(naviPrimaryShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* naviSecondaryShortcut = new CSMPrefs::Shortcut("scene-navi-secondary", widget);
|
||||
naviSecondaryShortcut->enable(false);
|
||||
connect(naviSecondaryShortcut, SIGNAL(activated(bool)), this, SLOT(naviSecondary(bool)));
|
||||
|
||||
addShortcut(naviSecondaryShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* upShortcut = new CSMPrefs::Shortcut("orbit-up", "scene-speed-modifier",
|
||||
CSMPrefs::Shortcut::SM_Detach, widget);
|
||||
upShortcut->enable(false);
|
||||
connect(upShortcut, SIGNAL(activated(bool)), this, SLOT(up(bool)));
|
||||
connect(upShortcut, SIGNAL(secondary(bool)), this, SLOT(alternateFast(bool)));
|
||||
|
||||
addShortcut(upShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* leftShortcut = new CSMPrefs::Shortcut("orbit-left", widget);
|
||||
leftShortcut->enable(false);
|
||||
connect(leftShortcut, SIGNAL(activated(bool)), this, SLOT(left(bool)));
|
||||
|
||||
addShortcut(leftShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* downShortcut = new CSMPrefs::Shortcut("orbit-down", widget);
|
||||
downShortcut->enable(false);
|
||||
connect(downShortcut, SIGNAL(activated(bool)), this, SLOT(down(bool)));
|
||||
|
||||
addShortcut(downShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* rightShortcut = new CSMPrefs::Shortcut("orbit-right", widget);
|
||||
rightShortcut->enable(false);
|
||||
connect(rightShortcut, SIGNAL(activated(bool)), this, SLOT(right(bool)));
|
||||
|
||||
addShortcut(rightShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* rollLeftShortcut = new CSMPrefs::Shortcut("orbit-roll-left", widget);
|
||||
rollLeftShortcut->enable(false);
|
||||
connect(rollLeftShortcut, SIGNAL(activated(bool)), this, SLOT(rollLeft(bool)));
|
||||
|
||||
addShortcut(rollLeftShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* rollRightShortcut = new CSMPrefs::Shortcut("orbit-roll-right", widget);
|
||||
rollRightShortcut->enable(false);
|
||||
connect(rollRightShortcut, SIGNAL(activated(bool)), this, SLOT(rollRight(bool)));
|
||||
|
||||
addShortcut(rollRightShortcut);
|
||||
|
||||
CSMPrefs::Shortcut* speedModeShortcut = new CSMPrefs::Shortcut("orbit-speed-mode", widget);
|
||||
speedModeShortcut->enable(false);
|
||||
connect(speedModeShortcut, SIGNAL(activated()), this, SLOT(swapSpeedMode()));
|
||||
|
||||
addShortcut(speedModeShortcut);
|
||||
}
|
||||
|
||||
osg::Vec3d OrbitCameraController::getCenter() const
|
||||
|
@ -437,65 +569,21 @@ namespace CSVRender
|
|||
mPickingMask = value;
|
||||
}
|
||||
|
||||
bool OrbitCameraController::handleKeyEvent(QKeyEvent* event, bool pressed)
|
||||
void OrbitCameraController::handleMouseMoveEvent(int x, int y)
|
||||
{
|
||||
if (!isActive())
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (!mInitialized)
|
||||
initialize();
|
||||
|
||||
if (event->key() == Qt::Key_Q)
|
||||
{
|
||||
mRollLeft = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_E)
|
||||
{
|
||||
mRollRight = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_A)
|
||||
{
|
||||
mLeft = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_D)
|
||||
{
|
||||
mRight = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_W)
|
||||
{
|
||||
mUp = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_S)
|
||||
{
|
||||
mDown = pressed;
|
||||
}
|
||||
else if (event->key() == Qt::Key_Shift)
|
||||
{
|
||||
mFast = pressed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OrbitCameraController::handleMouseMoveEvent(std::string mode, int x, int y)
|
||||
{
|
||||
if (!isActive())
|
||||
return false;
|
||||
|
||||
if (!mInitialized)
|
||||
initialize();
|
||||
|
||||
if (mode == "p-navi")
|
||||
if (mNaviPrimary)
|
||||
{
|
||||
double scalar = getCameraSensitivity() * (getInverted() ? -1.0 : 1.0);
|
||||
rotateHorizontal(x * scalar);
|
||||
rotateVertical(-y * scalar);
|
||||
}
|
||||
else if (mode == "s-navi")
|
||||
else if (mNaviSecondary)
|
||||
{
|
||||
osg::Vec3d movement;
|
||||
movement += LocalLeft * x * getSecondaryMovementMultiplier();
|
||||
|
@ -503,16 +591,14 @@ namespace CSVRender
|
|||
|
||||
translate(movement);
|
||||
}
|
||||
else if (mode == "t-navi")
|
||||
{
|
||||
zoom(-x * (mFast ? getWheelMovementMultiplier() : 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
void OrbitCameraController::handleMouseScrollEvent(int x)
|
||||
{
|
||||
if (!isActive())
|
||||
return;
|
||||
|
||||
zoom(-x * ((mFast ^ mFastAlternate) ? getWheelMovementMultiplier() : 1));
|
||||
}
|
||||
|
||||
void OrbitCameraController::update(double dt)
|
||||
|
@ -525,7 +611,7 @@ namespace CSVRender
|
|||
|
||||
double rotDist = mOrbitSpeed * dt;
|
||||
|
||||
if (mFast)
|
||||
if (mFast ^ mFastAlternate)
|
||||
rotDist *= mOrbitSpeedMult;
|
||||
|
||||
if (mLeft)
|
||||
|
@ -546,17 +632,6 @@ namespace CSVRender
|
|||
getCamera()->getViewMatrix().orthoNormal(getCamera()->getViewMatrix());
|
||||
}
|
||||
|
||||
void OrbitCameraController::resetInput()
|
||||
{
|
||||
mFast = false;
|
||||
mLeft = false;
|
||||
mRight =false;
|
||||
mUp = false;
|
||||
mDown = false;
|
||||
mRollLeft = false;
|
||||
mRollRight = false;
|
||||
}
|
||||
|
||||
void OrbitCameraController::onActivate()
|
||||
{
|
||||
mInitialized = false;
|
||||
|
@ -647,4 +722,55 @@ namespace CSVRender
|
|||
|
||||
getCamera()->setViewMatrixAsLookAt(mCenter + offset, mCenter, up);
|
||||
}
|
||||
|
||||
void OrbitCameraController::naviPrimary(bool active)
|
||||
{
|
||||
mNaviPrimary = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::naviSecondary(bool active)
|
||||
{
|
||||
mNaviSecondary = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::up(bool active)
|
||||
{
|
||||
mUp = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::left(bool active)
|
||||
{
|
||||
mLeft = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::down(bool active)
|
||||
{
|
||||
mDown = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::right(bool active)
|
||||
{
|
||||
mRight = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::rollLeft(bool active)
|
||||
{
|
||||
if (isActive())
|
||||
mRollLeft = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::rollRight(bool active)
|
||||
{
|
||||
mRollRight = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::alternateFast(bool active)
|
||||
{
|
||||
mFastAlternate = active;
|
||||
}
|
||||
|
||||
void OrbitCameraController::swapSpeedMode()
|
||||
{
|
||||
mFast = !mFast;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,32 @@
|
|||
#define OPENCS_VIEW_CAMERACONTROLLER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
class QKeyEvent;
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Camera;
|
||||
class Group;
|
||||
}
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Shortcut;
|
||||
}
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
class CameraController
|
||||
class SceneWidget;
|
||||
|
||||
class CameraController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static const osg::Vec3d WorldUp;
|
||||
|
@ -26,7 +36,7 @@ namespace CSVRender
|
|||
static const osg::Vec3d LocalLeft;
|
||||
static const osg::Vec3d LocalForward;
|
||||
|
||||
CameraController();
|
||||
CameraController(QObject* parent);
|
||||
virtual ~CameraController();
|
||||
|
||||
bool isActive() const;
|
||||
|
@ -46,17 +56,17 @@ namespace CSVRender
|
|||
// moves the camera to an intelligent position
|
||||
void setup(osg::Group* root, unsigned int mask, const osg::Vec3d& up);
|
||||
|
||||
virtual bool handleKeyEvent(QKeyEvent* event, bool pressed) = 0;
|
||||
virtual bool handleMouseMoveEvent(std::string mode, int x, int y) = 0;
|
||||
virtual void handleMouseMoveEvent(int x, int y) = 0;
|
||||
virtual void handleMouseScrollEvent(int x) = 0;
|
||||
|
||||
virtual void update(double dt) = 0;
|
||||
|
||||
virtual void resetInput() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void onActivate(){}
|
||||
|
||||
void addShortcut(CSMPrefs::Shortcut* shortcut);
|
||||
|
||||
private:
|
||||
|
||||
bool mActive, mInverted;
|
||||
|
@ -65,13 +75,17 @@ namespace CSVRender
|
|||
double mWheelMoveMult;
|
||||
|
||||
osg::Camera* mCamera;
|
||||
|
||||
std::vector<CSMPrefs::Shortcut*> mShortcuts;
|
||||
};
|
||||
|
||||
class FreeCameraController : public CameraController
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
FreeCameraController();
|
||||
FreeCameraController(QWidget* parent);
|
||||
|
||||
double getLinearSpeed() const;
|
||||
double getRotationalSpeed() const;
|
||||
|
@ -84,13 +98,11 @@ namespace CSVRender
|
|||
void fixUpAxis(const osg::Vec3d& up);
|
||||
void unfixUpAxis();
|
||||
|
||||
bool handleKeyEvent(QKeyEvent* event, bool pressed);
|
||||
bool handleMouseMoveEvent(std::string mode, int x, int y);
|
||||
void handleMouseMoveEvent(int x, int y);
|
||||
void handleMouseScrollEvent(int x);
|
||||
|
||||
void update(double dt);
|
||||
|
||||
void resetInput();
|
||||
|
||||
private:
|
||||
|
||||
void yaw(double value);
|
||||
|
@ -101,19 +113,36 @@ namespace CSVRender
|
|||
void stabilize();
|
||||
|
||||
bool mLockUpright, mModified;
|
||||
bool mFast, mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight;
|
||||
bool mNaviPrimary, mNaviSecondary;
|
||||
bool mFast, mFastAlternate;
|
||||
bool mLeft, mRight, mForward, mBackward, mRollLeft, mRollRight;
|
||||
osg::Vec3d mUp;
|
||||
|
||||
double mLinSpeed;
|
||||
double mRotSpeed;
|
||||
double mSpeedMult;
|
||||
|
||||
private slots:
|
||||
|
||||
void naviPrimary(bool active);
|
||||
void naviSecondary(bool active);
|
||||
void forward(bool active);
|
||||
void left(bool active);
|
||||
void backward(bool active);
|
||||
void right(bool active);
|
||||
void rollLeft(bool active);
|
||||
void rollRight(bool active);
|
||||
void alternateFast(bool active);
|
||||
void swapSpeedMode();
|
||||
};
|
||||
|
||||
class OrbitCameraController : public CameraController
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
OrbitCameraController();
|
||||
OrbitCameraController(QWidget* parent);
|
||||
|
||||
osg::Vec3d getCenter() const;
|
||||
double getOrbitSpeed() const;
|
||||
|
@ -125,13 +154,11 @@ namespace CSVRender
|
|||
void setOrbitSpeedMultiplier(double value);
|
||||
void setPickingMask(unsigned int value);
|
||||
|
||||
bool handleKeyEvent(QKeyEvent* event, bool pressed);
|
||||
bool handleMouseMoveEvent(std::string mode, int x, int y);
|
||||
void handleMouseMoveEvent(int x, int y);
|
||||
void handleMouseScrollEvent(int x);
|
||||
|
||||
void update(double dt);
|
||||
|
||||
void resetInput();
|
||||
|
||||
private:
|
||||
|
||||
void onActivate();
|
||||
|
@ -145,13 +172,28 @@ namespace CSVRender
|
|||
void zoom(double value);
|
||||
|
||||
bool mInitialized;
|
||||
bool mFast, mLeft, mRight, mUp, mDown, mRollLeft, mRollRight;
|
||||
bool mNaviPrimary, mNaviSecondary;
|
||||
bool mFast, mFastAlternate;
|
||||
bool mLeft, mRight, mUp, mDown, mRollLeft, mRollRight;
|
||||
unsigned int mPickingMask;
|
||||
osg::Vec3d mCenter;
|
||||
double mDistance;
|
||||
|
||||
double mOrbitSpeed;
|
||||
double mOrbitSpeedMult;
|
||||
|
||||
private slots:
|
||||
|
||||
void naviPrimary(bool active);
|
||||
void naviSecondary(bool active);
|
||||
void up(bool active);
|
||||
void left(bool active);
|
||||
void down(bool active);
|
||||
void right(bool active);
|
||||
void rollLeft(bool active);
|
||||
void rollRight(bool active);
|
||||
void alternateFast(bool active);
|
||||
void swapSpeedMode();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include <osg/Geometry>
|
||||
#include <osg/PrimitiveSet>
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
#include "../../model/prefs/shortcutmanager.hpp"
|
||||
|
||||
#include "mask.hpp"
|
||||
|
||||
CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow)
|
||||
|
@ -35,14 +38,19 @@ QString CSVRender::CellArrowTag::getToolTip (bool hideBasics) const
|
|||
text +=
|
||||
"<p>"
|
||||
"Modify which cells are shown"
|
||||
"<ul><li>Primary-Edit: Add cell in given direction</li>"
|
||||
"<li>Secondary-Edit: Add cell and remove old cell</li>"
|
||||
"<li>Shift Primary-Edit: Add cells in given direction</li>"
|
||||
"<li>Shift Secondary-Edit: Add cells and remove old cells</li>"
|
||||
"<ul><li>{scene-edit-primary}: Add cell in given direction</li>"
|
||||
"<li>{scene-edit-secondary}: Add cell and remove old cell</li>"
|
||||
"<li>{scene-select-primary}: Add cells in given direction</li>"
|
||||
"<li>{scene-select-secondary}: Add cells and remove old cells</li>"
|
||||
"<li>{scene-load-cam-cell}: Load cell where camera is located</li>"
|
||||
"<li>{scene-load-cam-eastcell}: Load cell to east</li>"
|
||||
"<li>{scene-load-cam-northcell}: Load cell to north</li>"
|
||||
"<li>{scene-load-cam-westcell}: Load cell to west</li>"
|
||||
"<li>{scene-load-cam-southcell}: Load cell to south</li>"
|
||||
"</ul>";
|
||||
}
|
||||
|
||||
return text;
|
||||
return CSMPrefs::State::get().getShortcutManager().processToolTip(text);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,14 +42,14 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
|||
mSubMode->addButton (new InstanceMoveMode (this), "move");
|
||||
mSubMode->addButton (":placeholder", "rotate",
|
||||
"Rotate selected instances"
|
||||
"<ul><li>Use primary edit to rotate instances freely</li>"
|
||||
"<li>Use secondary edit to rotate instances within the grid</li>"
|
||||
"<ul><li>Use {scene-edit-primary} to rotate instances freely</li>"
|
||||
"<li>Use {scene-edit-secondary} to rotate instances within the grid</li>"
|
||||
"</ul>"
|
||||
"<font color=Red>Not implemented yet</font color>");
|
||||
mSubMode->addButton (":placeholder", "scale",
|
||||
"Scale selected instances"
|
||||
"<ul><li>Use primary edit to scale instances freely</li>"
|
||||
"<li>Use secondary edit to scale instances along the grid</li>"
|
||||
"<ul><li>Use {scene-edit-primary} to scale instances freely</li>"
|
||||
"<li>Use {scene-edit-secondary} to scale instances along the grid</li>"
|
||||
"</ul>"
|
||||
"<font color=Red>Not implemented yet</font color>");
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
CSVRender::InstanceMoveMode::InstanceMoveMode (QWidget *parent)
|
||||
: ModeButton (QIcon (QPixmap (":placeholder")),
|
||||
"Move selected instances"
|
||||
"<ul><li>Use primary edit to move instances around freely</li>"
|
||||
"<li>Use secondary edit to move instances around within the grid</li>"
|
||||
"<ul><li>Use {scene-edit-primary} to move instances around freely</li>"
|
||||
"<li>Use {scene-edit-secondary} to move instances around within the grid</li>"
|
||||
"</ul>"
|
||||
"<font color=Red>Grid move not implemented yet</font color>",
|
||||
parent)
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include <QMenu>
|
||||
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
#include "../../model/prefs/shortcuteventhandler.hpp"
|
||||
|
||||
#include "worldspacewidget.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
|
@ -11,13 +14,29 @@ namespace CSVRender
|
|||
: ModeButton(icon, tooltip, parent)
|
||||
, mWorldspaceWidget(worldspaceWidget)
|
||||
, mCenterOnSelection(0)
|
||||
{
|
||||
mCenterShortcut.reset(new CSMPrefs::Shortcut("orbit-center-selection", worldspaceWidget));
|
||||
mCenterShortcut->enable(false);
|
||||
connect(mCenterShortcut.get(), SIGNAL(activated()), this, SLOT(centerSelection()));
|
||||
}
|
||||
|
||||
OrbitCameraMode::~OrbitCameraMode()
|
||||
{
|
||||
}
|
||||
|
||||
void OrbitCameraMode::activate(CSVWidget::SceneToolbar* toolbar)
|
||||
{
|
||||
mCenterOnSelection = new QAction("Center on selected object", this);
|
||||
mCenterShortcut->associateAction(mCenterOnSelection);
|
||||
connect(mCenterOnSelection, SIGNAL(triggered()), this, SLOT(centerSelection()));
|
||||
|
||||
mCenterShortcut->enable(true);
|
||||
}
|
||||
|
||||
void OrbitCameraMode::deactivate(CSVWidget::SceneToolbar* toolbar)
|
||||
{
|
||||
mCenterShortcut->associateAction(0);
|
||||
mCenterShortcut->enable(false);
|
||||
}
|
||||
|
||||
bool OrbitCameraMode::createContextMenu(QMenu* menu)
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
#ifndef CSV_RENDER_ORBITCAMERAPICKMODE_H
|
||||
#define CSV_RENDER_ORBITCAMERAPICKMODE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../widget/modebutton.hpp"
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Shortcut;
|
||||
}
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
class WorldspaceWidget;
|
||||
|
@ -15,14 +22,17 @@ namespace CSVRender
|
|||
|
||||
OrbitCameraMode(WorldspaceWidget* worldspaceWidget, const QIcon& icon, const QString& tooltip = "",
|
||||
QWidget* parent = 0);
|
||||
~OrbitCameraMode();
|
||||
|
||||
virtual void activate(CSVWidget::SceneToolbar* toolbar);
|
||||
virtual void deactivate(CSVWidget::SceneToolbar* toolbar);
|
||||
virtual bool createContextMenu(QMenu* menu);
|
||||
|
||||
private:
|
||||
|
||||
WorldspaceWidget* mWorldspaceWidget;
|
||||
QAction* mCenterOnSelection;
|
||||
std::auto_ptr<CSMPrefs::Shortcut> mCenterShortcut;
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <components/esm/loadland.hpp>
|
||||
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
|
||||
|
@ -142,15 +144,11 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
|
|||
"terrain-move");
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResult& hit, const std::string& button,
|
||||
bool shift)
|
||||
void CSVRender::PagedWorldspaceWidget::handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type)
|
||||
{
|
||||
if (hit.tag && hit.tag->getMask()==Mask_CellArrow)
|
||||
{
|
||||
if (button=="p-edit" || button=="s-edit")
|
||||
{
|
||||
if (CellArrowTag *cellArrowTag =
|
||||
dynamic_cast<CSVRender::CellArrowTag *> (hit.tag.get()))
|
||||
if (CellArrowTag *cellArrowTag = dynamic_cast<CSVRender::CellArrowTag *> (hit.tag.get()))
|
||||
{
|
||||
CellArrow *arrow = cellArrowTag->getCellArrow();
|
||||
|
||||
|
@ -171,16 +169,17 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResu
|
|||
|
||||
bool modified = false;
|
||||
|
||||
if (shift)
|
||||
if (type == InteractionType_PrimarySelect)
|
||||
{
|
||||
if (button=="p-edit")
|
||||
addCellSelection (x, y);
|
||||
else
|
||||
moveCellSelection (x, y);
|
||||
|
||||
modified = true;
|
||||
}
|
||||
else
|
||||
else if (type == InteractionType_SecondarySelect)
|
||||
{
|
||||
moveCellSelection (x, y);
|
||||
modified = true;
|
||||
}
|
||||
else // Primary/SecondaryEdit
|
||||
{
|
||||
CSMWorld::CellCoordinates newCoordinates = coordinates.move (x, y);
|
||||
|
||||
|
@ -191,7 +190,7 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResu
|
|||
modified = true;
|
||||
}
|
||||
|
||||
if (button=="s-edit")
|
||||
if (type == InteractionType_SecondaryEdit)
|
||||
{
|
||||
if (mCells.find (coordinates)!=mCells.end())
|
||||
{
|
||||
|
@ -208,9 +207,8 @@ void CSVRender::PagedWorldspaceWidget::handleMouseClick (const WorldspaceHitResu
|
|||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WorldspaceWidget::handleMouseClick (hit, button, shift);
|
||||
WorldspaceWidget::handleInteractionPress (hit, type);
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
|
||||
|
@ -437,6 +435,27 @@ void CSVRender::PagedWorldspaceWidget::moveCellSelection (int x, int y)
|
|||
mSelection = newSelection;
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::addCellToSceneFromCamera (int offsetX, int offsetY)
|
||||
{
|
||||
const int CellSize = 8192;
|
||||
|
||||
osg::Vec3f eye, center, up;
|
||||
getCamera()->getViewMatrixAsLookAt(eye, center, up);
|
||||
|
||||
int cellX = (int)std::floor(center.x() / CellSize) + offsetX;
|
||||
int cellY = (int)std::floor(center.y() / CellSize) + offsetY;
|
||||
|
||||
CSMWorld::CellCoordinates cellCoordinates(cellX, cellY);
|
||||
|
||||
if (!mSelection.has(cellCoordinates))
|
||||
{
|
||||
addCellToScene(cellCoordinates);
|
||||
mSelection.add(cellCoordinates);
|
||||
|
||||
adjustCells();
|
||||
}
|
||||
}
|
||||
|
||||
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
|
||||
: WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"),
|
||||
mControlElements(NULL), mDisplayCellCoord(true)
|
||||
|
@ -450,6 +469,22 @@ CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc
|
|||
this, SLOT (cellRemoved (const QModelIndex&, int, int)));
|
||||
connect (cells, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||
this, SLOT (cellAdded (const QModelIndex&, int, int)));
|
||||
|
||||
// Shortcuts
|
||||
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
||||
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
||||
|
||||
CSMPrefs::Shortcut* loadCameraEastCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-eastcell", this);
|
||||
connect(loadCameraEastCellShortcut, SIGNAL(activated()), this, SLOT(loadEastCell()));
|
||||
|
||||
CSMPrefs::Shortcut* loadCameraNorthCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-northcell", this);
|
||||
connect(loadCameraNorthCellShortcut, SIGNAL(activated()), this, SLOT(loadNorthCell()));
|
||||
|
||||
CSMPrefs::Shortcut* loadCameraWestCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-westcell", this);
|
||||
connect(loadCameraWestCellShortcut, SIGNAL(activated()), this, SLOT(loadWestCell()));
|
||||
|
||||
CSMPrefs::Shortcut* loadCameraSouthCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-southcell", this);
|
||||
connect(loadCameraSouthCellShortcut, SIGNAL(activated()), this, SLOT(loadSouthCell()));
|
||||
}
|
||||
|
||||
CSVRender::PagedWorldspaceWidget::~PagedWorldspaceWidget()
|
||||
|
@ -722,3 +757,28 @@ void CSVRender::PagedWorldspaceWidget::cellAdded (const QModelIndex& index, int
|
|||
if (adjustCells())
|
||||
flagAsModified();
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::loadCameraCell()
|
||||
{
|
||||
addCellToSceneFromCamera(0, 0);
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::loadEastCell()
|
||||
{
|
||||
addCellToSceneFromCamera(1, 0);
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::loadNorthCell()
|
||||
{
|
||||
addCellToSceneFromCamera(0, 1);
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::loadWestCell()
|
||||
{
|
||||
addCellToSceneFromCamera(-1, 0);
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::loadSouthCell()
|
||||
{
|
||||
addCellToSceneFromCamera(0, -1);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ namespace CSVRender
|
|||
/// \note Does not update the view or any cell marker
|
||||
void moveCellSelection (int x, int y);
|
||||
|
||||
void addCellToSceneFromCamera (int offsetX, int offsetY);
|
||||
|
||||
public:
|
||||
|
||||
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
|
||||
|
@ -138,7 +140,7 @@ namespace CSVRender
|
|||
|
||||
virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool);
|
||||
|
||||
virtual void handleMouseClick (const WorldspaceHitResult& hit, const std::string& button, bool shift);
|
||||
virtual void handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type);
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -152,6 +154,16 @@ namespace CSVRender
|
|||
|
||||
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
||||
|
||||
void loadCameraCell();
|
||||
|
||||
void loadEastCell();
|
||||
|
||||
void loadNorthCell();
|
||||
|
||||
void loadWestCell();
|
||||
|
||||
void loadSouthCell();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,10 @@ namespace CSVRender
|
|||
{
|
||||
return QString(
|
||||
"Pathgrid editing"
|
||||
"<ul><li>Primary edit: Add node to scene</li>"
|
||||
"<li>Secondary edit: Connect selected nodes to node</li>"
|
||||
"<li>Primary drag: Move selected nodes</li>"
|
||||
"<li>Secondary drag: Connect one node to another</li>"
|
||||
"<ul><li>Press {scene-edit-primary} to add a node to the cursor location</li>"
|
||||
"<li>Press {scene-edit-secondary} to connect the selected nodes to the node beneath the cursor</li>"
|
||||
"<li>Press {scene-edit-primary} and drag to move selected nodes</li>"
|
||||
"<li>Press {scene-edit-secondary} and drag to connect one node to another</li>"
|
||||
"</ul><p>Note: Only a single cell's pathgrid may be edited at a time");
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,16 @@ namespace CSVRender
|
|||
toolbar->addTool(mSelectionMode);
|
||||
}
|
||||
|
||||
void PathgridMode::deactivate(CSVWidget::SceneToolbar* toolbar)
|
||||
{
|
||||
if (mSelectionMode)
|
||||
{
|
||||
toolbar->removeTool (mSelectionMode);
|
||||
delete mSelectionMode;
|
||||
mSelectionMode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PathgridMode::primaryEditPressed(const WorldspaceHitResult& hitResult)
|
||||
{
|
||||
if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue() &&
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace CSVRender
|
|||
|
||||
virtual void activate(CSVWidget::SceneToolbar* toolbar);
|
||||
|
||||
virtual void deactivate(CSVWidget::SceneToolbar* toolbar);
|
||||
|
||||
virtual void primaryEditPressed(const WorldspaceHitResult& hit);
|
||||
|
||||
virtual void secondaryEditPressed(const WorldspaceHitResult& hit);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <QEvent>
|
||||
#include <QResizeEvent>
|
||||
#include <QTimer>
|
||||
#include <QShortcut>
|
||||
#include <QLayout>
|
||||
|
||||
#include <extern/osgQt/GraphicsWindowQt>
|
||||
|
@ -19,6 +18,8 @@
|
|||
#include "../widget/scenetoolmode.hpp"
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
#include "../../model/prefs/shortcuteventhandler.hpp"
|
||||
|
||||
#include "lighting.hpp"
|
||||
#include "mask.hpp"
|
||||
|
@ -75,7 +76,7 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
|
|||
|
||||
mView->setSceneData(mRootNode);
|
||||
|
||||
// Press S to reveal profiling stats
|
||||
// Add ability to signal osg to show its statistics for debugging purposes
|
||||
mView->addEventHandler(new osgViewer::StatsHandler);
|
||||
|
||||
mView->getCamera()->setCullMask(~(Mask_UpdateVisitor));
|
||||
|
@ -105,6 +106,15 @@ osg::Camera *RenderWidget::getCamera()
|
|||
return mView->getCamera();
|
||||
}
|
||||
|
||||
void RenderWidget::toggleRenderStats()
|
||||
{
|
||||
osgViewer::GraphicsWindow* window =
|
||||
static_cast<osgViewer::GraphicsWindow*>(mView->getCamera()->getGraphicsContext());
|
||||
|
||||
window->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_S);
|
||||
window->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_S);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
|
@ -158,13 +168,13 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
|
|||
, mHasDefaultAmbient(false)
|
||||
, mPrevMouseX(0)
|
||||
, mPrevMouseY(0)
|
||||
, mFreeCamControl(new FreeCameraController())
|
||||
, mOrbitCamControl(new OrbitCameraController())
|
||||
, mCurrentCamControl(mFreeCamControl.get())
|
||||
, mCamPositionSet(false)
|
||||
{
|
||||
mFreeCamControl = new FreeCameraController(this);
|
||||
mOrbitCamControl = new OrbitCameraController(this);
|
||||
mCurrentCamControl = mFreeCamControl;
|
||||
|
||||
mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain);
|
||||
selectNavigationMode("free");
|
||||
|
||||
// we handle lighting manually
|
||||
mView->setLightingMode(osgViewer::View::NO_LIGHT);
|
||||
|
@ -175,11 +185,7 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
|
|||
|
||||
// Recieve mouse move event even if mouse button is not pressed
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
/// \todo make shortcut configurable
|
||||
QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut);
|
||||
connect (focusToolbar, SIGNAL (activated()), this, SIGNAL (focusToolbarRequest()));
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
|
||||
connect (&CSMPrefs::State::get(), SIGNAL (settingChanged (const CSMPrefs::Setting *)),
|
||||
this, SLOT (settingChanged (const CSMPrefs::Setting *)));
|
||||
|
@ -192,6 +198,13 @@ SceneWidget::SceneWidget(boost::shared_ptr<Resource::ResourceSystem> resourceSys
|
|||
}
|
||||
|
||||
connect (&CompositeViewer::get(), SIGNAL (simulationUpdated(double)), this, SLOT (update(double)));
|
||||
|
||||
// Shortcuts
|
||||
CSMPrefs::Shortcut* focusToolbarShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this);
|
||||
connect(focusToolbarShortcut, SIGNAL(activated()), this, SIGNAL(focusToolbarRequest()));
|
||||
|
||||
CSMPrefs::Shortcut* renderStatsShortcut = new CSMPrefs::Shortcut("scene-render-stats", this);
|
||||
connect(renderStatsShortcut, SIGNAL(activated()), this, SLOT(toggleRenderStats()));
|
||||
}
|
||||
|
||||
SceneWidget::~SceneWidget()
|
||||
|
@ -271,45 +284,17 @@ void SceneWidget::setDefaultAmbient (const osg::Vec4f& colour)
|
|||
setAmbient(mLighting->getAmbientColour(&mDefaultAmbient));
|
||||
}
|
||||
|
||||
void SceneWidget::mousePressEvent (QMouseEvent *event)
|
||||
{
|
||||
mMouseMode = mapButton(event);
|
||||
|
||||
mPrevMouseX = event->x();
|
||||
mPrevMouseY = event->y();
|
||||
}
|
||||
|
||||
void SceneWidget::mouseReleaseEvent (QMouseEvent *event)
|
||||
{
|
||||
mMouseMode = "";
|
||||
}
|
||||
|
||||
void SceneWidget::mouseMoveEvent (QMouseEvent *event)
|
||||
{
|
||||
mCurrentCamControl->handleMouseMoveEvent(mMouseMode, event->x() - mPrevMouseX, event->y() - mPrevMouseY);
|
||||
mCurrentCamControl->handleMouseMoveEvent(event->x() - mPrevMouseX, event->y() - mPrevMouseY);
|
||||
|
||||
mPrevMouseX = event->x();
|
||||
mPrevMouseY = event->y();
|
||||
}
|
||||
|
||||
void SceneWidget::focusOutEvent (QFocusEvent *event)
|
||||
{
|
||||
mCurrentCamControl->resetInput();
|
||||
}
|
||||
|
||||
void SceneWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
mCurrentCamControl->handleMouseMoveEvent("t-navi", event->delta(), 0);
|
||||
}
|
||||
|
||||
void SceneWidget::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
mCurrentCamControl->handleKeyEvent(event, true);
|
||||
}
|
||||
|
||||
void SceneWidget::keyReleaseEvent (QKeyEvent *event)
|
||||
{
|
||||
mCurrentCamControl->handleKeyEvent(event, false);
|
||||
mCurrentCamControl->handleMouseScrollEvent(event->delta());
|
||||
}
|
||||
|
||||
void SceneWidget::update(double dt)
|
||||
|
@ -373,10 +358,6 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting)
|
|||
{
|
||||
mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble());
|
||||
}
|
||||
else
|
||||
{
|
||||
storeMappingSetting(setting);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneWidget::selectNavigationMode (const std::string& mode)
|
||||
|
@ -384,73 +365,23 @@ void SceneWidget::selectNavigationMode (const std::string& mode)
|
|||
if (mode=="1st")
|
||||
{
|
||||
mCurrentCamControl->setCamera(NULL);
|
||||
mCurrentCamControl = mFreeCamControl.get();
|
||||
mCurrentCamControl->setCamera(getCamera());
|
||||
mCurrentCamControl = mFreeCamControl;
|
||||
mFreeCamControl->setCamera(getCamera());
|
||||
mFreeCamControl->fixUpAxis(CameraController::WorldUp);
|
||||
}
|
||||
else if (mode=="free")
|
||||
{
|
||||
mCurrentCamControl->setCamera(NULL);
|
||||
mCurrentCamControl = mFreeCamControl.get();
|
||||
mCurrentCamControl->setCamera(getCamera());
|
||||
mCurrentCamControl = mFreeCamControl;
|
||||
mFreeCamControl->setCamera(getCamera());
|
||||
mFreeCamControl->unfixUpAxis();
|
||||
}
|
||||
else if (mode=="orbit")
|
||||
{
|
||||
mCurrentCamControl->setCamera(NULL);
|
||||
mCurrentCamControl = mOrbitCamControl.get();
|
||||
mCurrentCamControl->setCamera(getCamera());
|
||||
mCurrentCamControl = mOrbitCamControl;
|
||||
mOrbitCamControl->setCamera(getCamera());
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneWidget::storeMappingSetting (const CSMPrefs::Setting *setting)
|
||||
{
|
||||
if (setting->getParent()->getKey()!="3D Scene Input")
|
||||
return false;
|
||||
|
||||
static const char * const sMappingSettings[] =
|
||||
{
|
||||
"p-navi", "s-navi",
|
||||
0
|
||||
};
|
||||
|
||||
for (int i=0; sMappingSettings[i]; ++i)
|
||||
if (setting->getKey()==sMappingSettings[i])
|
||||
{
|
||||
QString value = QString::fromUtf8 (setting->toString().c_str());
|
||||
|
||||
Qt::MouseButton button = Qt::NoButton;
|
||||
|
||||
if (value.endsWith ("Left Mouse-Button"))
|
||||
button = Qt::LeftButton;
|
||||
else if (value.endsWith ("Right Mouse-Button"))
|
||||
button = Qt::RightButton;
|
||||
else if (value.endsWith ("Middle Mouse-Button"))
|
||||
button = Qt::MiddleButton;
|
||||
else
|
||||
return false;
|
||||
|
||||
bool ctrl = value.startsWith ("Ctrl-");
|
||||
|
||||
mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string SceneWidget::mapButton (QMouseEvent *event)
|
||||
{
|
||||
std::pair<Qt::MouseButton, bool> phyiscal (
|
||||
event->button(), event->modifiers() & Qt::ControlModifier);
|
||||
|
||||
std::map<std::pair<Qt::MouseButton, bool>, std::string>::const_iterator iter =
|
||||
mButtonMapping.find (phyiscal);
|
||||
|
||||
if (iter!=mButtonMapping.end())
|
||||
return iter->second;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,14 +7,15 @@
|
|||
#include <QWidget>
|
||||
#include <QTimer>
|
||||
|
||||
#include <osgViewer/View>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "lightingday.hpp"
|
||||
#include "lightingnight.hpp"
|
||||
#include "lightingbright.hpp"
|
||||
|
||||
#include <osgViewer/View>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
@ -53,6 +54,7 @@ namespace CSVRender
|
|||
RenderWidget(QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||
virtual ~RenderWidget();
|
||||
|
||||
/// Initiates a request to redraw the view
|
||||
void flagAsModified();
|
||||
|
||||
void setVisibilityMask(int mask);
|
||||
|
@ -62,13 +64,16 @@ namespace CSVRender
|
|||
protected:
|
||||
|
||||
osg::ref_ptr<osgViewer::View> mView;
|
||||
|
||||
osg::Group* mRootNode;
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
|
||||
QTimer mTimer;
|
||||
|
||||
protected slots:
|
||||
|
||||
void toggleRenderStats();
|
||||
};
|
||||
|
||||
// Extension of RenderWidget to support lighting mode selection & toolbar
|
||||
/// Extension of RenderWidget to support lighting mode selection & toolbar
|
||||
class SceneWidget : public RenderWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -90,18 +95,8 @@ namespace CSVRender
|
|||
|
||||
void setAmbient(const osg::Vec4f& ambient);
|
||||
|
||||
virtual void mousePressEvent (QMouseEvent *event);
|
||||
virtual void mouseReleaseEvent (QMouseEvent *event);
|
||||
virtual void mouseMoveEvent (QMouseEvent *event);
|
||||
virtual void wheelEvent (QWheelEvent *event);
|
||||
virtual void keyPressEvent (QKeyEvent *event);
|
||||
virtual void keyReleaseEvent (QKeyEvent *event);
|
||||
virtual void focusOutEvent (QFocusEvent *event);
|
||||
|
||||
/// \return Is \a key a button mapping setting? (ignored otherwise)
|
||||
virtual bool storeMappingSetting (const CSMPrefs::Setting *setting);
|
||||
|
||||
std::string mapButton (QMouseEvent *event);
|
||||
|
||||
boost::shared_ptr<Resource::ResourceSystem> mResourceSystem;
|
||||
|
||||
|
@ -114,12 +109,10 @@ namespace CSVRender
|
|||
LightingBright mLightingBright;
|
||||
|
||||
int mPrevMouseX, mPrevMouseY;
|
||||
std::string mMouseMode;
|
||||
std::auto_ptr<FreeCameraController> mFreeCamControl;
|
||||
std::auto_ptr<OrbitCameraController> mOrbitCamControl;
|
||||
CameraController* mCurrentCamControl;
|
||||
|
||||
std::map<std::pair<Qt::MouseButton, bool>, std::string> mButtonMapping;
|
||||
FreeCameraController* mFreeCamControl;
|
||||
OrbitCameraController* mOrbitCamControl;
|
||||
CameraController* mCurrentCamControl;
|
||||
|
||||
private:
|
||||
bool mCamPositionSet;
|
||||
|
|
|
@ -15,22 +15,28 @@ namespace CSVRender
|
|||
{
|
||||
addButton(":placeholder", "cube-centre",
|
||||
"Centred cube"
|
||||
"<ul><li>Drag with primary (make instances the selection) or secondary (invert selection state) select button from the centre of the selection cube outwards</li>"
|
||||
"<ul><li>Drag with {scene-select-primary} (make instances the selection) or {scene-select-secondary} "
|
||||
"(invert selection state) from the centre of the selection cube outwards</li>"
|
||||
"<li>The selection cube is aligned to the word space axis</li>"
|
||||
"<li>If context selection mode is enabled, a drag with primary/secondary edit not starting on an instance will have the same effect</li>"
|
||||
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
||||
"starting on an instance will have the same effect</li>"
|
||||
"</ul>"
|
||||
"<font color=Red>Not implemented yet</font color>");
|
||||
addButton(":placeholder", "cube-corner",
|
||||
"Cube corner to corner"
|
||||
"<ul><li>Drag with primary (make instances the selection) or secondary (invert selection state) select button from one corner of the selection cube to the opposite corner</li>"
|
||||
"<ul><li>Drag with {scene-select-primary} (make instances the selection) or {scene-select-secondary} "
|
||||
"(invert selection state) from one corner of the selection cube to the opposite corner</li>"
|
||||
"<li>The selection cube is aligned to the word space axis</li>"
|
||||
"<li>If context selection mode is enabled, a drag with primary/secondary edit not starting on an instance will have the same effect</li>"
|
||||
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
||||
"starting on an instance will have the same effect</li>"
|
||||
"</ul>"
|
||||
"<font color=Red>Not implemented yet</font color>");
|
||||
addButton(":placeholder", "sphere",
|
||||
"Centred sphere"
|
||||
"<ul><li>Drag with primary (make instances the selection) or secondary (invert selection state) select button from the centre of the selection sphere outwards</li>"
|
||||
"<li>If context selection mode is enabled, a drag with primary/secondary edit not starting on an instance will have the same effect</li>"
|
||||
"<ul><li>Drag with {scene-select-primary} (make instances the selection) or {scene-select-secondary} "
|
||||
"(invert selection state) from the centre of the selection sphere outwards</li>"
|
||||
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
||||
"starting on an instance will have the same effect</li>"
|
||||
"</ul>"
|
||||
"<font color=Red>Not implemented yet</font color>");
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "../../model/world/universalid.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
#include "../../model/prefs/shortcuteventhandler.hpp"
|
||||
#include "../../model/prefs/state.hpp"
|
||||
|
||||
#include "../render/orbitcameramode.hpp"
|
||||
|
@ -31,10 +33,24 @@
|
|||
#include "cameracontroller.hpp"
|
||||
|
||||
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
|
||||
: SceneWidget (document.getData().getResourceSystem(), parent, 0, false), mSceneElements(0), mRun(0), mDocument(document),
|
||||
mInteractionMask (0), mEditMode (0), mLocked (false), mDragging (false), mDragX(0), mDragY(0), mDragFactor(0),
|
||||
mDragWheelFactor(0), mDragShiftFactor(0),
|
||||
mToolTipPos (-1, -1), mShowToolTips(false), mToolTipDelay(0)
|
||||
: SceneWidget (document.getData().getResourceSystem(), parent, 0, false)
|
||||
, mSceneElements(0)
|
||||
, mRun(0)
|
||||
, mDocument(document)
|
||||
, mInteractionMask (0)
|
||||
, mEditMode (0)
|
||||
, mLocked (false)
|
||||
, mDragMode(InteractionType_None)
|
||||
, mDragging (false)
|
||||
, mDragX(0)
|
||||
, mDragY(0)
|
||||
, mSpeedMode(false)
|
||||
, mDragFactor(0)
|
||||
, mDragWheelFactor(0)
|
||||
, mDragShiftFactor(0)
|
||||
, mToolTipPos (-1, -1)
|
||||
, mShowToolTips(false)
|
||||
, mToolTipDelay(0)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
|
||||
|
@ -80,6 +96,24 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg
|
|||
|
||||
CSMPrefs::get()["3D Scene Input"].update();
|
||||
CSMPrefs::get()["Tooltips"].update();
|
||||
|
||||
// Shortcuts
|
||||
CSMPrefs::Shortcut* primaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-primary", "scene-speed-modifier",
|
||||
CSMPrefs::Shortcut::SM_Detach, this);
|
||||
connect(primaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(primaryEdit(bool)));
|
||||
connect(primaryEditShortcut, SIGNAL(secondary(bool)), this, SLOT(speedMode(bool)));
|
||||
|
||||
CSMPrefs::Shortcut* secondaryEditShortcut = new CSMPrefs::Shortcut("scene-edit-secondary", this);
|
||||
connect(secondaryEditShortcut, SIGNAL(activated(bool)), this, SLOT(secondaryEdit(bool)));
|
||||
|
||||
CSMPrefs::Shortcut* primarySelectShortcut = new CSMPrefs::Shortcut("scene-select-primary", this);
|
||||
connect(primarySelectShortcut, SIGNAL(activated(bool)), this, SLOT(primarySelect(bool)));
|
||||
|
||||
CSMPrefs::Shortcut* secondarySelectShortcut = new CSMPrefs::Shortcut("scene-select-secondary", this);
|
||||
connect(secondarySelectShortcut, SIGNAL(activated(bool)), this, SLOT(secondarySelect(bool)));
|
||||
|
||||
CSMPrefs::Shortcut* abortShortcut = new CSMPrefs::Shortcut("scene-edit-abort", this);
|
||||
connect(abortShortcut, SIGNAL(activated()), this, SLOT(abortDrag()));
|
||||
}
|
||||
|
||||
CSVRender::WorldspaceWidget::~WorldspaceWidget ()
|
||||
|
@ -132,30 +166,32 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
|
|||
/// \todo consider user-defined button-mapping
|
||||
tool->addButton (":scenetoolbar/1st-person", "1st",
|
||||
"First Person"
|
||||
"<ul><li>Mouse-Look while holding the left button</li>"
|
||||
"<li>WASD movement keys</li>"
|
||||
"<ul><li>Camera is held upright</li>"
|
||||
"<li>Mouse-Look while holding {scene-navi-primary}</li>"
|
||||
"<li>Movement keys: {free-forward}(forward), {free-left}(left), {free-backward}(back), {free-right}(right)</li>"
|
||||
"<li>Strafing (also vertically) by holding {scene-navi-secondary}</li>"
|
||||
"<li>Mouse wheel moves the camera forward/backward</li>"
|
||||
"<li>Strafing (also vertically) by holding the left mouse button and control</li>"
|
||||
"<li>Camera is held upright</li>"
|
||||
"<li>Hold shift to speed up movement</li>"
|
||||
"<li>Hold {scene-speed-modifier} to speed up movement</li>"
|
||||
"</ul>");
|
||||
tool->addButton (":scenetoolbar/free-camera", "free",
|
||||
"Free Camera"
|
||||
"<ul><li>Mouse-Look while holding the left button</li>"
|
||||
"<li>Strafing (also vertically) via WASD or by holding the left mouse button and control</li>"
|
||||
"<ul><li>Mouse-Look while holding {scene-navi-primary}</li>"
|
||||
"<li>Movement keys: {free-forward}(forward), {free-left}(left), {free-backward}(back), {free-right}(right)</li>"
|
||||
"<li>Roll camera with {free-roll-left} and {free-roll-right} keys</li>"
|
||||
"<li>Strafing (also vertically) by holding {scene-navi-secondary}</li>"
|
||||
"<li>Mouse wheel moves the camera forward/backward</li>"
|
||||
"<li>Roll camera with Q and E keys</li>"
|
||||
"<li>Hold shift to speed up movement</li>"
|
||||
"<li>Hold {free-forward:mod} to speed up movement</li>"
|
||||
"</ul>");
|
||||
tool->addButton(
|
||||
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>"
|
||||
"<li>Rotate around the centre point via {orbit-up}, {orbit-left}, {orbit-down}, {orbit-right} or by moving "
|
||||
"the mouse while holding {scene-navi-primary}</li>"
|
||||
"<li>Roll camera with {orbit-roll-left} and {orbit-roll-right} keys</li>"
|
||||
"<li>Strafing (also vertically) by holding {scene-navi-secondary} (includes relocation of the centre point)</li>"
|
||||
"<li>Mouse wheel moves camera away or towards centre point but can not pass through it</li>"
|
||||
"<li>Roll camera with Q and E keys</li>"
|
||||
"<li>Strafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)</li>"
|
||||
"<li>Hold shift to speed up movement</li>"
|
||||
"<li>Hold {scene-speed-modifier} to speed up movement</li>"
|
||||
"</ul>", tool),
|
||||
"orbit");
|
||||
|
||||
|
@ -409,7 +445,7 @@ void CSVRender::WorldspaceWidget::abortDrag()
|
|||
|
||||
editMode.dragAborted();
|
||||
mDragging = false;
|
||||
mDragMode.clear();
|
||||
mDragMode = InteractionType_None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,45 +489,6 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
bool CSVRender::WorldspaceWidget::storeMappingSetting (const CSMPrefs::Setting *setting)
|
||||
{
|
||||
static const char * const sMappingSettings[] =
|
||||
{
|
||||
"p-edit", "s-edit",
|
||||
"p-select", "s-select",
|
||||
0
|
||||
};
|
||||
|
||||
if (setting->getParent()->getKey()=="3D Scene Input")
|
||||
{
|
||||
for (int i=0; sMappingSettings[i]; ++i)
|
||||
{
|
||||
if (setting->getKey()==sMappingSettings[i])
|
||||
{
|
||||
QString value = QString::fromUtf8 (setting->toString().c_str());
|
||||
|
||||
Qt::MouseButton button = Qt::NoButton;
|
||||
|
||||
if (value.endsWith ("Left Mouse-Button"))
|
||||
button = Qt::LeftButton;
|
||||
else if (value.endsWith ("Right Mouse-Button"))
|
||||
button = Qt::RightButton;
|
||||
else if (value.endsWith ("Middle Mouse-Button"))
|
||||
button = Qt::MiddleButton;
|
||||
else
|
||||
return false;
|
||||
|
||||
bool ctrl = value.startsWith ("Ctrl-");
|
||||
|
||||
mButtonMapping[std::make_pair (button, ctrl)] = sMappingSettings[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SceneWidget::storeMappingSetting(setting);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
|
||||
{
|
||||
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||
|
@ -567,7 +564,7 @@ void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id)
|
|||
{
|
||||
dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()).setEditLock (mLocked);
|
||||
mDragging = false;
|
||||
mDragMode.clear();
|
||||
mDragMode = InteractionType_None;
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::showToolTip()
|
||||
|
@ -608,24 +605,24 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
|
|||
|
||||
double factor = mDragFactor;
|
||||
|
||||
if (event->modifiers() & Qt::ShiftModifier)
|
||||
if (mSpeedMode)
|
||||
factor *= mDragShiftFactor;
|
||||
|
||||
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
|
||||
|
||||
editMode.drag (event->pos(), diffX, diffY, factor);
|
||||
}
|
||||
else if (mDragMode=="p-edit" || mDragMode=="s-edit" || mDragMode=="p-select" || mDragMode=="s-select")
|
||||
else if (mDragMode != InteractionType_None)
|
||||
{
|
||||
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
|
||||
|
||||
if (mDragMode=="p-edit")
|
||||
if (mDragMode == InteractionType_PrimaryEdit)
|
||||
mDragging = editMode.primaryEditStartDrag (event->pos());
|
||||
else if (mDragMode=="s-edit")
|
||||
else if (mDragMode == InteractionType_SecondaryEdit)
|
||||
mDragging = editMode.secondaryEditStartDrag (event->pos());
|
||||
else if (mDragMode=="p-select")
|
||||
else if (mDragMode == InteractionType_PrimarySelect)
|
||||
mDragging = editMode.primarySelectStartDrag (event->pos());
|
||||
else if (mDragMode=="s-select")
|
||||
else if (mDragMode == InteractionType_SecondarySelect)
|
||||
mDragging = editMode.secondarySelectStartDrag (event->pos());
|
||||
|
||||
if (mDragging)
|
||||
|
@ -656,53 +653,13 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event)
|
||||
{
|
||||
std::string button = mapButton (event);
|
||||
|
||||
if (button=="p-edit" || button=="s-edit" ||
|
||||
button=="p-select" || button=="s-select")
|
||||
{
|
||||
if (!mDragging)
|
||||
mDragMode = button;
|
||||
}
|
||||
else
|
||||
SceneWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event)
|
||||
{
|
||||
std::string button = mapButton (event);
|
||||
mDragMode.clear();
|
||||
|
||||
if (button=="p-edit" || button=="s-edit" ||
|
||||
button=="p-select" || button=="s-select")
|
||||
{
|
||||
if (mDragging)
|
||||
{
|
||||
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
|
||||
|
||||
editMode.dragCompleted(event->pos());
|
||||
mDragging = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldspaceHitResult hit = mousePick(event->pos(), getInteractionMask());
|
||||
|
||||
handleMouseClick (hit, button, event->modifiers() & Qt::ShiftModifier);
|
||||
}
|
||||
}
|
||||
else
|
||||
SceneWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event)
|
||||
{
|
||||
if (mDragging)
|
||||
{
|
||||
double factor = mDragWheelFactor;
|
||||
|
||||
if (event->modifiers() & Qt::ShiftModifier)
|
||||
if (mSpeedMode)
|
||||
factor *= mDragShiftFactor;
|
||||
|
||||
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
|
||||
|
@ -713,27 +670,17 @@ void CSVRender::WorldspaceWidget::wheelEvent (QWheelEvent *event)
|
|||
SceneWidget::wheelEvent(event);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
if(event->key() == Qt::Key_Escape)
|
||||
{
|
||||
abortDrag();
|
||||
}
|
||||
else
|
||||
SceneWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::handleMouseClick (const WorldspaceHitResult& hit, const std::string& button, bool shift)
|
||||
void CSVRender::WorldspaceWidget::handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type)
|
||||
{
|
||||
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
|
||||
|
||||
if (button=="p-edit")
|
||||
if (type == InteractionType_PrimaryEdit)
|
||||
editMode.primaryEditPressed (hit);
|
||||
else if (button=="s-edit")
|
||||
else if (type == InteractionType_SecondaryEdit)
|
||||
editMode.secondaryEditPressed (hit);
|
||||
else if (button=="p-select")
|
||||
else if (type == InteractionType_PrimarySelect)
|
||||
editMode.primarySelectPressed (hit);
|
||||
else if (button=="s-select")
|
||||
else if (type == InteractionType_SecondarySelect)
|
||||
editMode.secondarySelectPressed (hit);
|
||||
}
|
||||
|
||||
|
@ -741,3 +688,53 @@ CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode()
|
|||
{
|
||||
return dynamic_cast<CSVRender::EditMode *> (mEditMode->getCurrent());
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::primaryEdit(bool activate)
|
||||
{
|
||||
handleInteraction(InteractionType_PrimaryEdit, activate);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::secondaryEdit(bool activate)
|
||||
{
|
||||
handleInteraction(InteractionType_SecondaryEdit, activate);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::primarySelect(bool activate)
|
||||
{
|
||||
handleInteraction(InteractionType_PrimarySelect, activate);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::secondarySelect(bool activate)
|
||||
{
|
||||
handleInteraction(InteractionType_SecondarySelect, activate);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::speedMode(bool activate)
|
||||
{
|
||||
mSpeedMode = activate;
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::handleInteraction(InteractionType type, bool activate)
|
||||
{
|
||||
if (activate)
|
||||
{
|
||||
if (!mDragging)
|
||||
mDragMode = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDragMode = InteractionType_None;
|
||||
|
||||
if (mDragging)
|
||||
{
|
||||
EditMode* editMode = getEditMode();
|
||||
editMode->dragCompleted(mapFromGlobal(QCursor::pos()));
|
||||
mDragging = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldspaceHitResult hit = mousePick(mapFromGlobal(QCursor::pos()), getInteractionMask());
|
||||
handleInteractionPress(hit, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,10 +55,11 @@ namespace CSVRender
|
|||
unsigned int mInteractionMask;
|
||||
CSVWidget::SceneToolMode *mEditMode;
|
||||
bool mLocked;
|
||||
std::string mDragMode;
|
||||
int mDragMode;
|
||||
bool mDragging;
|
||||
int mDragX;
|
||||
int mDragY;
|
||||
bool mSpeedMode;
|
||||
double mDragFactor;
|
||||
double mDragWheelFactor;
|
||||
double mDragShiftFactor;
|
||||
|
@ -85,6 +86,15 @@ namespace CSVRender
|
|||
ignored //either mixed cells, or not cells
|
||||
};
|
||||
|
||||
enum InteractionType
|
||||
{
|
||||
InteractionType_PrimaryEdit,
|
||||
InteractionType_PrimarySelect,
|
||||
InteractionType_SecondaryEdit,
|
||||
InteractionType_SecondarySelect,
|
||||
InteractionType_None
|
||||
};
|
||||
|
||||
WorldspaceWidget (CSMDoc::Document& document, QWidget *parent = 0);
|
||||
~WorldspaceWidget ();
|
||||
|
||||
|
@ -171,12 +181,6 @@ namespace CSVRender
|
|||
/// Erase all overrides and restore the visual representation to its true state.
|
||||
virtual void reset (unsigned int elementMask) = 0;
|
||||
|
||||
/// \note Drags will be automatically aborted when the aborting is triggered
|
||||
/// (either explicitly or implicitly) from within this class. This function only
|
||||
/// needs to be called, when the drag abort is triggered externally (e.g. from
|
||||
/// an edit mode).
|
||||
void abortDrag();
|
||||
|
||||
protected:
|
||||
|
||||
/// Visual elements in a scene
|
||||
|
@ -197,21 +201,16 @@ namespace CSVRender
|
|||
virtual void updateOverlay();
|
||||
|
||||
virtual void mouseMoveEvent (QMouseEvent *event);
|
||||
virtual void mousePressEvent (QMouseEvent *event);
|
||||
virtual void mouseReleaseEvent (QMouseEvent *event);
|
||||
virtual void wheelEvent (QWheelEvent *event);
|
||||
virtual void keyPressEvent (QKeyEvent *event);
|
||||
|
||||
virtual void handleMouseClick (const WorldspaceHitResult& hit, const std::string& button,
|
||||
bool shift);
|
||||
|
||||
/// \return Is \a key a button mapping setting? (ignored otherwise)
|
||||
virtual bool storeMappingSetting (const CSMPrefs::Setting *setting);
|
||||
virtual void handleInteractionPress (const WorldspaceHitResult& hit, InteractionType type);
|
||||
|
||||
virtual void settingChanged (const CSMPrefs::Setting *setting);
|
||||
|
||||
EditMode *getEditMode();
|
||||
|
||||
bool getSpeedMode();
|
||||
|
||||
private:
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
|
@ -222,6 +221,16 @@ namespace CSVRender
|
|||
|
||||
virtual std::string getStartupInstruction() = 0;
|
||||
|
||||
void handleInteraction(InteractionType type, bool activate);
|
||||
|
||||
public slots:
|
||||
|
||||
/// \note Drags will be automatically aborted when the aborting is triggered
|
||||
/// (either explicitly or implicitly) from within this class. This function only
|
||||
/// needs to be called, when the drag abort is triggered externally (e.g. from
|
||||
/// an edit mode).
|
||||
void abortDrag();
|
||||
|
||||
private slots:
|
||||
|
||||
virtual void referenceableDataChanged (const QModelIndex& topLeft,
|
||||
|
@ -255,6 +264,16 @@ namespace CSVRender
|
|||
|
||||
void showToolTip();
|
||||
|
||||
void primaryEdit(bool activate);
|
||||
|
||||
void secondaryEdit(bool activate);
|
||||
|
||||
void primarySelect(bool activate);
|
||||
|
||||
void secondarySelect(bool activate);
|
||||
|
||||
void speedMode(bool activate);
|
||||
|
||||
protected slots:
|
||||
|
||||
void elementSelectionChanged();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "../../model/tools/reportmodel.hpp"
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "../../view/world/idtypedelegate.hpp"
|
||||
|
||||
|
@ -171,14 +172,20 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document,
|
|||
mShowAction = new QAction (tr ("Show"), this);
|
||||
connect (mShowAction, SIGNAL (triggered()), this, SLOT (showSelection()));
|
||||
addAction (mShowAction);
|
||||
CSMPrefs::Shortcut* showShortcut = new CSMPrefs::Shortcut("reporttable-show", this);
|
||||
showShortcut->associateAction(mShowAction);
|
||||
|
||||
mRemoveAction = new QAction (tr ("Remove from list"), this);
|
||||
connect (mRemoveAction, SIGNAL (triggered()), this, SLOT (removeSelection()));
|
||||
addAction (mRemoveAction);
|
||||
CSMPrefs::Shortcut* removeShortcut = new CSMPrefs::Shortcut("reporttable-remove", this);
|
||||
removeShortcut->associateAction(mRemoveAction);
|
||||
|
||||
mReplaceAction = new QAction (tr ("Replace"), this);
|
||||
connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest()));
|
||||
addAction (mReplaceAction);
|
||||
CSMPrefs::Shortcut* replaceShortcut = new CSMPrefs::Shortcut("reporttable-replace", this);
|
||||
replaceShortcut->associateAction(mReplaceAction);
|
||||
|
||||
if (mRefreshState)
|
||||
{
|
||||
|
@ -186,6 +193,8 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document,
|
|||
mRefreshAction->setEnabled (!(mDocument.getState() & mRefreshState));
|
||||
connect (mRefreshAction, SIGNAL (triggered()), this, SIGNAL (refreshRequest()));
|
||||
addAction (mRefreshAction);
|
||||
CSMPrefs::Shortcut* refreshShortcut = new CSMPrefs::Shortcut("reporttable-refresh", this);
|
||||
refreshShortcut->associateAction(mRefreshAction);
|
||||
}
|
||||
|
||||
mDoubleClickActions.insert (std::make_pair (Qt::NoModifier, Action_Edit));
|
||||
|
|
|
@ -3,9 +3,17 @@
|
|||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
#include "../../model/prefs/shortcutmanager.hpp"
|
||||
|
||||
void CSVWidget::PushButton::processShortcuts()
|
||||
{
|
||||
mProcessedToolTip = CSMPrefs::State::get().getShortcutManager().processToolTip(mToolTip);
|
||||
}
|
||||
|
||||
void CSVWidget::PushButton::setExtendedToolTip()
|
||||
{
|
||||
QString tooltip = mToolTip;
|
||||
QString tooltip = mProcessedToolTip;
|
||||
|
||||
if (tooltip.isEmpty())
|
||||
tooltip = "(Tool tip not implemented yet)";
|
||||
|
@ -77,13 +85,18 @@ CSVWidget::PushButton::PushButton (const QIcon& icon, Type type, const QString&
|
|||
connect (this, SIGNAL (toggled (bool)), this, SLOT (checkedStateChanged (bool)));
|
||||
}
|
||||
setCheckable (type==Type_Mode || type==Type_Toggle);
|
||||
processShortcuts();
|
||||
setExtendedToolTip();
|
||||
|
||||
connect (&CSMPrefs::State::get(), SIGNAL (settingChanged (const CSMPrefs::Setting *)),
|
||||
this, SLOT (settingChanged (const CSMPrefs::Setting *)));
|
||||
}
|
||||
|
||||
CSVWidget::PushButton::PushButton (Type type, const QString& tooltip, QWidget *parent)
|
||||
: QPushButton (parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
|
||||
{
|
||||
setCheckable (type==Type_Mode || type==Type_Toggle);
|
||||
processShortcuts();
|
||||
setExtendedToolTip();
|
||||
}
|
||||
|
||||
|
@ -94,7 +107,7 @@ bool CSVWidget::PushButton::hasKeepOpen() const
|
|||
|
||||
QString CSVWidget::PushButton::getBaseToolTip() const
|
||||
{
|
||||
return mToolTip;
|
||||
return mProcessedToolTip;
|
||||
}
|
||||
|
||||
CSVWidget::PushButton::Type CSVWidget::PushButton::getType() const
|
||||
|
@ -106,3 +119,12 @@ void CSVWidget::PushButton::checkedStateChanged (bool checked)
|
|||
{
|
||||
setExtendedToolTip();
|
||||
}
|
||||
|
||||
void CSVWidget::PushButton::settingChanged (const CSMPrefs::Setting *setting)
|
||||
{
|
||||
if (setting->getParent()->getKey() == "Key Bindings")
|
||||
{
|
||||
processShortcuts();
|
||||
setExtendedToolTip();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
#include <QPushButton>
|
||||
|
||||
namespace CSMPrefs
|
||||
{
|
||||
class Setting;
|
||||
}
|
||||
|
||||
namespace CSVWidget
|
||||
{
|
||||
class PushButton : public QPushButton
|
||||
|
@ -24,9 +29,11 @@ namespace CSVWidget
|
|||
bool mKeepOpen;
|
||||
Type mType;
|
||||
QString mToolTip;
|
||||
QString mProcessedToolTip;
|
||||
|
||||
private:
|
||||
|
||||
void processShortcuts();
|
||||
void setExtendedToolTip();
|
||||
|
||||
protected:
|
||||
|
@ -57,6 +64,7 @@ namespace CSVWidget
|
|||
private slots:
|
||||
|
||||
void checkedStateChanged (bool checked);
|
||||
void settingChanged (const CSMPrefs::Setting *setting);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include "scenetoolbar.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QShortcut>
|
||||
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "scenetool.hpp"
|
||||
|
||||
|
@ -25,9 +26,8 @@ CSVWidget::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent)
|
|||
|
||||
setLayout (mLayout);
|
||||
|
||||
/// \todo make shortcut configurable
|
||||
QShortcut *focusScene = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut);
|
||||
connect (focusScene, SIGNAL (activated()), this, SIGNAL (focusSceneRequest()));
|
||||
CSMPrefs::Shortcut* focusSceneShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this);
|
||||
connect(focusSceneShortcut, SIGNAL(activated()), this, SIGNAL(focusSceneRequest()));
|
||||
}
|
||||
|
||||
void CSVWidget::SceneToolbar::addTool (SceneTool *tool, SceneTool *insertPoint)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QSignalMapper>
|
||||
#include <QMenu>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QEvent>
|
||||
|
||||
#include "scenetoolbar.hpp"
|
||||
#include "modebutton.hpp"
|
||||
|
@ -133,6 +134,16 @@ void CSVWidget::SceneToolMode::setButton (const std::string& id)
|
|||
}
|
||||
}
|
||||
|
||||
bool CSVWidget::SceneToolMode::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip)
|
||||
{
|
||||
adjustToolTip(mCurrent);
|
||||
}
|
||||
|
||||
return SceneTool::event(event);
|
||||
}
|
||||
|
||||
void CSVWidget::SceneToolMode::selected()
|
||||
{
|
||||
std::map<ModeButton *, std::string>::iterator iter =
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
class QHBoxLayout;
|
||||
class QMenu;
|
||||
class QEvent;
|
||||
|
||||
namespace CSVWidget
|
||||
{
|
||||
|
@ -43,6 +44,10 @@ namespace CSVWidget
|
|||
|
||||
void setButton (std::map<ModeButton *, std::string>::iterator iter);
|
||||
|
||||
protected:
|
||||
|
||||
bool event(QEvent* event);
|
||||
|
||||
public:
|
||||
|
||||
SceneToolMode (SceneToolbar *parent, const QString& toolTip);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <QMenu>
|
||||
#include <QDebug>
|
||||
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "../../model/world/nestedtableproxymodel.hpp"
|
||||
#include "../../model/world/universalid.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
@ -60,14 +62,16 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
|
|||
if (!fixedRows)
|
||||
{
|
||||
mAddNewRowAction = new QAction (tr ("Add new row"), this);
|
||||
|
||||
connect(mAddNewRowAction, SIGNAL(triggered()),
|
||||
this, SLOT(addNewRowActionTriggered()));
|
||||
CSMPrefs::Shortcut* addRowShortcut = new CSMPrefs::Shortcut("table-add", this);
|
||||
addRowShortcut->associateAction(mAddNewRowAction);
|
||||
|
||||
mRemoveRowAction = new QAction (tr ("Remove rows"), this);
|
||||
|
||||
connect(mRemoveRowAction, SIGNAL(triggered()),
|
||||
this, SLOT(removeRowActionTriggered()));
|
||||
CSMPrefs::Shortcut* removeRowShortcut = new CSMPrefs::Shortcut("table-remove", this);
|
||||
removeRowShortcut->associateAction(mRemoveRowAction);
|
||||
}
|
||||
|
||||
mEditIdAction = new TableEditIdAction(*this, this);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../../model/world/commanddispatcher.hpp"
|
||||
|
||||
#include "../../model/prefs/state.hpp"
|
||||
#include "../../model/prefs/shortcut.hpp"
|
||||
|
||||
#include "tableeditidaction.hpp"
|
||||
#include "util.hpp"
|
||||
|
@ -283,49 +284,72 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||
mEditAction = new QAction (tr ("Edit Record"), this);
|
||||
connect (mEditAction, SIGNAL (triggered()), this, SLOT (editRecord()));
|
||||
addAction (mEditAction);
|
||||
CSMPrefs::Shortcut* editShortcut = new CSMPrefs::Shortcut("table-edit", this);
|
||||
editShortcut->associateAction(mEditAction);
|
||||
|
||||
if (createAndDelete)
|
||||
{
|
||||
mCreateAction = new QAction (tr ("Add Record"), this);
|
||||
connect (mCreateAction, SIGNAL (triggered()), this, SIGNAL (createRequest()));
|
||||
addAction (mCreateAction);
|
||||
CSMPrefs::Shortcut* createShortcut = new CSMPrefs::Shortcut("table-add", this);
|
||||
createShortcut->associateAction(mCreateAction);
|
||||
|
||||
mCloneAction = new QAction (tr ("Clone Record"), this);
|
||||
connect(mCloneAction, SIGNAL (triggered()), this, SLOT (cloneRecord()));
|
||||
addAction(mCloneAction);
|
||||
CSMPrefs::Shortcut* cloneShortcut = new CSMPrefs::Shortcut("table-clone", this);
|
||||
cloneShortcut->associateAction(mCloneAction);
|
||||
}
|
||||
|
||||
mRevertAction = new QAction (tr ("Revert Record"), this);
|
||||
connect (mRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeRevert()));
|
||||
addAction (mRevertAction);
|
||||
CSMPrefs::Shortcut* revertShortcut = new CSMPrefs::Shortcut("table-revert", this);
|
||||
revertShortcut->associateAction(mRevertAction);
|
||||
|
||||
mDeleteAction = new QAction (tr ("Delete Record"), this);
|
||||
connect (mDeleteAction, SIGNAL (triggered()), mDispatcher, SLOT (executeDelete()));
|
||||
addAction (mDeleteAction);
|
||||
CSMPrefs::Shortcut* deleteShortcut = new CSMPrefs::Shortcut("table-remove", this);
|
||||
deleteShortcut->associateAction(mDeleteAction);
|
||||
|
||||
|
||||
mMoveUpAction = new QAction (tr ("Move Up"), this);
|
||||
connect (mMoveUpAction, SIGNAL (triggered()), this, SLOT (moveUpRecord()));
|
||||
addAction (mMoveUpAction);
|
||||
CSMPrefs::Shortcut* moveUpShortcut = new CSMPrefs::Shortcut("table-moveup", this);
|
||||
moveUpShortcut->associateAction(mMoveUpAction);
|
||||
|
||||
mMoveDownAction = new QAction (tr ("Move Down"), this);
|
||||
connect (mMoveDownAction, SIGNAL (triggered()), this, SLOT (moveDownRecord()));
|
||||
addAction (mMoveDownAction);
|
||||
CSMPrefs::Shortcut* moveDownShortcut = new CSMPrefs::Shortcut("table-movedown", this);
|
||||
moveDownShortcut->associateAction(mMoveDownAction);
|
||||
|
||||
mViewAction = new QAction (tr ("View"), this);
|
||||
connect (mViewAction, SIGNAL (triggered()), this, SLOT (viewRecord()));
|
||||
addAction (mViewAction);
|
||||
CSMPrefs::Shortcut* viewShortcut = new CSMPrefs::Shortcut("table-view", this);
|
||||
viewShortcut->associateAction(mViewAction);
|
||||
|
||||
mPreviewAction = new QAction (tr ("Preview"), this);
|
||||
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
|
||||
addAction (mPreviewAction);
|
||||
CSMPrefs::Shortcut* previewShortcut = new CSMPrefs::Shortcut("table-preview", this);
|
||||
previewShortcut->associateAction(mPreviewAction);
|
||||
|
||||
mExtendedDeleteAction = new QAction (tr ("Extended Delete Record"), this);
|
||||
connect (mExtendedDeleteAction, SIGNAL (triggered()), this, SLOT (executeExtendedDelete()));
|
||||
addAction (mExtendedDeleteAction);
|
||||
CSMPrefs::Shortcut* extendedDeleteShortcut = new CSMPrefs::Shortcut("table-extendeddelete", this);
|
||||
extendedDeleteShortcut->associateAction(mExtendedDeleteAction);
|
||||
|
||||
mExtendedRevertAction = new QAction (tr ("Extended Revert Record"), this);
|
||||
connect (mExtendedRevertAction, SIGNAL (triggered()), this, SLOT (executeExtendedRevert()));
|
||||
addAction (mExtendedRevertAction);
|
||||
CSMPrefs::Shortcut* extendedRevertShortcut = new CSMPrefs::Shortcut("table-extendedrevert", this);
|
||||
extendedRevertShortcut->associateAction(mExtendedRevertAction);
|
||||
|
||||
mEditIdAction = new TableEditIdAction (*this, this);
|
||||
connect (mEditIdAction, SIGNAL (triggered()), this, SLOT (editCell()));
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <components/version/version.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/files/escape.hpp>
|
||||
#include <components/fallback/validate.hpp>
|
||||
|
||||
#include <SDL_messagebox.h>
|
||||
|
@ -76,7 +77,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
desc.add_options()
|
||||
("help", "print help message")
|
||||
("version", "print version information and quit")
|
||||
("data", bpo::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")
|
||||
("data", bpo::value<Files::EscapePathContainer>()->default_value(Files::EscapePathContainer(), "data")
|
||||
->multitoken()->composing(), "set data directories (later directories have higher priority)")
|
||||
|
||||
("data-local", bpo::value<Files::EscapeHashString>()->default_value(""),
|
||||
|
@ -193,7 +194,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
// directory settings
|
||||
engine.enableFSStrict(variables["fs-strict"].as<bool>());
|
||||
|
||||
Files::PathContainer dataDirs(variables["data"].as<Files::PathContainer>());
|
||||
Files::PathContainer dataDirs(Files::EscapePath::toPathContainer(variables["data"].as<Files::EscapePathContainer>()));
|
||||
|
||||
std::string local(variables["data-local"].as<Files::EscapeHashString>().toStdString());
|
||||
if (!local.empty())
|
||||
|
|
|
@ -395,7 +395,9 @@ namespace MWGui
|
|||
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
|
||||
if (info.enchant != "")
|
||||
{
|
||||
enchant = store.get<ESM::Enchantment>().find(info.enchant);
|
||||
enchant = store.get<ESM::Enchantment>().search(info.enchant);
|
||||
if (enchant)
|
||||
{
|
||||
if (enchant->mData.mType == ESM::Enchantment::CastOnce)
|
||||
text += "\n#{sItemCastOnce}";
|
||||
else if (enchant->mData.mType == ESM::Enchantment::WhenStrikes)
|
||||
|
@ -405,6 +407,7 @@ namespace MWGui
|
|||
else if (enchant->mData.mType == ESM::Enchantment::ConstantEffect)
|
||||
text += "\n#{sItemCastConstant}";
|
||||
}
|
||||
}
|
||||
|
||||
// this the maximum width of the tooltip before it starts word-wrapping
|
||||
setCoord(0, 0, 300, 300);
|
||||
|
@ -472,9 +475,8 @@ namespace MWGui
|
|||
totalSize.width = std::max(totalSize.width, coord.width);
|
||||
}
|
||||
|
||||
if (info.enchant != "")
|
||||
if (enchant)
|
||||
{
|
||||
assert(enchant);
|
||||
MyGUI::Widget* enchantArea = mDynamicToolTipBox->createWidget<MyGUI::Widget>("",
|
||||
MyGUI::IntCoord(padding.left, totalSize.height, 300-padding.left, 300-totalSize.height),
|
||||
MyGUI::Align::Stretch);
|
||||
|
|
|
@ -1143,10 +1143,18 @@ namespace MWRender
|
|||
std::string enchantmentName = item.getClass().getEnchantment(item);
|
||||
if (enchantmentName.empty())
|
||||
return result;
|
||||
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(enchantmentName);
|
||||
|
||||
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().search(enchantmentName);
|
||||
if (!enchantment)
|
||||
return result;
|
||||
|
||||
assert (enchantment->mEffects.mList.size());
|
||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
||||
|
||||
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().search(
|
||||
enchantment->mEffects.mList.front().mEffectID);
|
||||
if (!magicEffect)
|
||||
return result;
|
||||
|
||||
result.x() = magicEffect->mData.mRed / 255.f;
|
||||
result.y() = magicEffect->mData.mGreen / 255.f;
|
||||
result.z() = magicEffect->mData.mBlue / 255.f;
|
||||
|
|
|
@ -29,6 +29,18 @@ namespace MWWorld
|
|||
mList.push_back(item);
|
||||
return mList.back();
|
||||
}
|
||||
|
||||
/// Remove all references with the given refNum from this list.
|
||||
void remove (const ESM::RefNum &refNum)
|
||||
{
|
||||
for (typename List::iterator it = mList.begin(); it != mList.end();)
|
||||
{
|
||||
if (*it == refNum)
|
||||
mList.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -524,8 +524,10 @@ namespace MWWorld
|
|||
// List moved references, from separately tracked list.
|
||||
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it)
|
||||
{
|
||||
const ESM::CellRef &ref = *it;
|
||||
const ESM::CellRef &ref = it->first;
|
||||
bool deleted = it->second;
|
||||
|
||||
if (!deleted)
|
||||
mIds.push_back(Misc::StringUtils::lowerCase(ref.mRefID));
|
||||
}
|
||||
|
||||
|
@ -541,6 +543,8 @@ namespace MWWorld
|
|||
if (mCell->mContextList.empty())
|
||||
return; // this is a dynamically generated cell -> skipping.
|
||||
|
||||
std::map<ESM::RefNum, std::string> refNumToID; // used to detect refID modifications
|
||||
|
||||
// Load references from all plugins that do something with this cell.
|
||||
for (size_t i = 0; i < mCell->mContextList.size(); i++)
|
||||
{
|
||||
|
@ -564,7 +568,7 @@ namespace MWWorld
|
|||
continue;
|
||||
}
|
||||
|
||||
loadRef (ref, deleted);
|
||||
loadRef (ref, deleted, refNumToID);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
@ -576,9 +580,10 @@ namespace MWWorld
|
|||
// Load moved references, from separately tracked list.
|
||||
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it)
|
||||
{
|
||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(it->first);
|
||||
bool deleted = it->second;
|
||||
|
||||
loadRef (ref, false);
|
||||
loadRef (ref, deleted, refNumToID);
|
||||
}
|
||||
|
||||
updateMergedRefs();
|
||||
|
@ -609,12 +614,47 @@ namespace MWWorld
|
|||
return Ptr();
|
||||
}
|
||||
|
||||
void CellStore::loadRef (ESM::CellRef& ref, bool deleted)
|
||||
void CellStore::loadRef (ESM::CellRef& ref, bool deleted, std::map<ESM::RefNum, std::string>& refNumToID)
|
||||
{
|
||||
Misc::StringUtils::lowerCaseInPlace (ref.mRefID);
|
||||
|
||||
const MWWorld::ESMStore& store = mStore;
|
||||
|
||||
std::map<ESM::RefNum, std::string>::iterator it = refNumToID.find(ref.mRefNum);
|
||||
if (it != refNumToID.end())
|
||||
{
|
||||
if (it->second != ref.mRefID)
|
||||
{
|
||||
// refID was modified, make sure we don't end up with duplicated refs
|
||||
switch (store.find(it->second))
|
||||
{
|
||||
case ESM::REC_ACTI: mActivators.remove(ref.mRefNum); break;
|
||||
case ESM::REC_ALCH: mPotions.remove(ref.mRefNum); break;
|
||||
case ESM::REC_APPA: mAppas.remove(ref.mRefNum); break;
|
||||
case ESM::REC_ARMO: mArmors.remove(ref.mRefNum); break;
|
||||
case ESM::REC_BOOK: mBooks.remove(ref.mRefNum); break;
|
||||
case ESM::REC_CLOT: mClothes.remove(ref.mRefNum); break;
|
||||
case ESM::REC_CONT: mContainers.remove(ref.mRefNum); break;
|
||||
case ESM::REC_CREA: mCreatures.remove(ref.mRefNum); break;
|
||||
case ESM::REC_DOOR: mDoors.remove(ref.mRefNum); break;
|
||||
case ESM::REC_INGR: mIngreds.remove(ref.mRefNum); break;
|
||||
case ESM::REC_LEVC: mCreatureLists.remove(ref.mRefNum); break;
|
||||
case ESM::REC_LEVI: mItemLists.remove(ref.mRefNum); break;
|
||||
case ESM::REC_LIGH: mLights.remove(ref.mRefNum); break;
|
||||
case ESM::REC_LOCK: mLockpicks.remove(ref.mRefNum); break;
|
||||
case ESM::REC_MISC: mMiscItems.remove(ref.mRefNum); break;
|
||||
case ESM::REC_NPC_: mNpcs.remove(ref.mRefNum); break;
|
||||
case ESM::REC_PROB: mProbes.remove(ref.mRefNum); break;
|
||||
case ESM::REC_REPA: mRepairs.remove(ref.mRefNum); break;
|
||||
case ESM::REC_STAT: mStatics.remove(ref.mRefNum); break;
|
||||
case ESM::REC_WEAP: mWeapons.remove(ref.mRefNum); break;
|
||||
case ESM::REC_BODY: mBodyParts.remove(ref.mRefNum); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (store.find (ref.mRefID))
|
||||
{
|
||||
case ESM::REC_ACTI: mActivators.load(ref, deleted, store); break;
|
||||
|
@ -639,12 +679,15 @@ namespace MWWorld
|
|||
case ESM::REC_WEAP: mWeapons.load(ref, deleted, store); break;
|
||||
case ESM::REC_BODY: mBodyParts.load(ref, deleted, store); break;
|
||||
|
||||
case 0: std::cerr << "Cell reference '" + ref.mRefID + "' not found!\n"; break;
|
||||
case 0: std::cerr << "Cell reference '" + ref.mRefID + "' not found!\n"; return;
|
||||
|
||||
default:
|
||||
std::cerr
|
||||
<< "WARNING: Ignoring reference '" << ref.mRefID << "' of unhandled type\n";
|
||||
return;
|
||||
}
|
||||
|
||||
refNumToID[ref.mRefNum] = ref.mRefID;
|
||||
}
|
||||
|
||||
void CellStore::loadState (const ESM::CellState& state)
|
||||
|
|
|
@ -385,7 +385,7 @@ namespace MWWorld
|
|||
|
||||
void loadRefs();
|
||||
|
||||
void loadRef (ESM::CellRef& ref, bool deleted);
|
||||
void loadRef (ESM::CellRef& ref, bool deleted, std::map<ESM::RefNum, std::string>& refNumToID);
|
||||
///< Make case-adjustments to \a ref and insert it into the respective container.
|
||||
///
|
||||
/// Invalid \a ref objects are silently dropped.
|
||||
|
|
|
@ -513,19 +513,16 @@ namespace MWWorld
|
|||
bool deleted = false;
|
||||
cell->getNextRef(esm, ref, deleted);
|
||||
|
||||
if (!deleted)
|
||||
{
|
||||
// Add data required to make reference appear in the correct cell.
|
||||
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
|
||||
cell->mMovedRefs.push_back(cMRef);
|
||||
|
||||
// But there may be duplicates here!
|
||||
ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefNum);
|
||||
ESM::CellRefTracker::iterator iter = std::find_if(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ESM::CellRefTrackerPredicate(ref.mRefNum));
|
||||
if (iter == cellAlt->mLeasedRefs.end())
|
||||
cellAlt->mLeasedRefs.push_back(ref);
|
||||
cellAlt->mLeasedRefs.push_back(std::make_pair(ref, deleted));
|
||||
else
|
||||
*iter = ref;
|
||||
}
|
||||
*iter = std::make_pair(ref, deleted);
|
||||
}
|
||||
}
|
||||
const ESM::Cell *Store<ESM::Cell>::search(const std::string &id) const
|
||||
|
@ -678,14 +675,17 @@ namespace MWWorld
|
|||
for (ESM::MovedCellRefTracker::const_iterator it = cell.mMovedRefs.begin(); it != cell.mMovedRefs.end(); ++it) {
|
||||
// remove reference from current leased ref tracker and add it to new cell
|
||||
ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefNum);
|
||||
if (itold != oldcell->mMovedRefs.end()) {
|
||||
ESM::MovedCellRef target0 = *itold;
|
||||
ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
|
||||
ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefNum);
|
||||
if (itold != oldcell->mMovedRefs.end())
|
||||
{
|
||||
if (it->mTarget[0] != itold->mTarget[0] || it->mTarget[1] != itold->mTarget[1])
|
||||
{
|
||||
ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(itold->mTarget[0], itold->mTarget[1]));
|
||||
ESM::CellRefTracker::iterator it_lease = std::find_if(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), ESM::CellRefTrackerPredicate(it->mRefNum));
|
||||
if (it_lease != wipecell->mLeasedRefs.end())
|
||||
wipecell->mLeasedRefs.erase(it_lease);
|
||||
else
|
||||
std::cerr << "can't find " << it->mRefNum.mIndex << " " << it->mRefNum.mContentFile << " in leasedRefs " << std::endl;
|
||||
}
|
||||
*itold = *it;
|
||||
}
|
||||
else
|
||||
|
|
145
cmake/FindSphinx.cmake
Normal file
|
@ -0,0 +1,145 @@
|
|||
# - This module looks for Sphinx
|
||||
# Find the Sphinx documentation generator
|
||||
#
|
||||
# This modules defines
|
||||
# SPHINX_EXECUTABLE
|
||||
# SPHINX_FOUND
|
||||
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
PATHS
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
/opt/local/bin
|
||||
DOC "Sphinx documentation generator"
|
||||
)
|
||||
|
||||
if( NOT SPHINX_EXECUTABLE )
|
||||
set(_Python_VERSIONS
|
||||
2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0 1.6 1.5
|
||||
)
|
||||
|
||||
foreach( _version ${_Python_VERSIONS} )
|
||||
set( _sphinx_NAMES sphinx-build-${_version} )
|
||||
|
||||
find_program( SPHINX_EXECUTABLE
|
||||
NAMES ${_sphinx_NAMES}
|
||||
PATHS
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
/opt/loca/bin
|
||||
DOC "Sphinx documentation generator"
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_standard_args(Sphinx DEFAULT_MSG
|
||||
SPHINX_EXECUTABLE
|
||||
)
|
||||
|
||||
|
||||
option( SPHINX_HTML_OUTPUT "Build a single HTML with the whole content." ON )
|
||||
option( SPHINX_DIRHTML_OUTPUT "Build HTML pages, but with a single directory per document." OFF )
|
||||
option( SPHINX_HTMLHELP_OUTPUT "Build HTML pages with additional information for building a documentation collection in htmlhelp." OFF )
|
||||
option( SPHINX_QTHELP_OUTPUT "Build HTML pages with additional information for building a documentation collection in qthelp." OFF )
|
||||
option( SPHINX_DEVHELP_OUTPUT "Build HTML pages with additional information for building a documentation collection in devhelp." OFF )
|
||||
option( SPHINX_EPUB_OUTPUT "Build HTML pages with additional information for building a documentation collection in epub." OFF )
|
||||
option( SPHINX_LATEX_OUTPUT "Build LaTeX sources that can be compiled to a PDF document using pdflatex." OFF )
|
||||
option( SPHINX_MAN_OUTPUT "Build manual pages in groff format for UNIX systems." OFF )
|
||||
option( SPHINX_TEXT_OUTPUT "Build plain text files." OFF )
|
||||
|
||||
|
||||
mark_as_advanced(
|
||||
SPHINX_EXECUTABLE
|
||||
SPHINX_HTML_OUTPUT
|
||||
SPHINX_DIRHTML_OUTPUT
|
||||
SPHINX_HTMLHELP_OUTPUT
|
||||
SPHINX_QTHELP_OUTPUT
|
||||
SPHINX_DEVHELP_OUTPUT
|
||||
SPHINX_EPUB_OUTPUT
|
||||
SPHINX_LATEX_OUTPUT
|
||||
SPHINX_MAN_OUTPUT
|
||||
SPHINX_TEXT_OUTPUT
|
||||
)
|
||||
|
||||
function( Sphinx_add_target target_name builder conf source destination )
|
||||
add_custom_target( ${target_name} ALL
|
||||
COMMAND ${SPHINX_EXECUTABLE} -b ${builder}
|
||||
-c ${conf}
|
||||
${source}
|
||||
${destination}
|
||||
COMMENT "Generating sphinx documentation: ${builder}"
|
||||
)
|
||||
|
||||
set_property(
|
||||
DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
${destination}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Target dependencies can be optionally listed at the end.
|
||||
function( Sphinx_add_targets target_base_name conf source base_destination )
|
||||
|
||||
set( _dependencies )
|
||||
|
||||
foreach( arg IN LISTS ARGN )
|
||||
set( _dependencies ${_dependencies} ${arg} )
|
||||
endforeach()
|
||||
|
||||
if( ${SPHINX_HTML_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_html html ${conf} ${source} ${base_destination}/html )
|
||||
|
||||
add_dependencies( ${target_base_name}_html ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_DIRHTML_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_dirhtml dirhtml ${conf} ${source} ${base_destination}/dirhtml )
|
||||
|
||||
add_dependencies( ${target_base_name}_dirhtml ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_QTHELP_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_qthelp qthelp ${conf} ${source} ${base_destination}/qthelp )
|
||||
|
||||
add_dependencies( ${target_base_name}_qthelp ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_DEVHELP_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_devhelp devhelp ${conf} ${source} ${base_destination}/devhelp )
|
||||
|
||||
add_dependencies( ${target_base_name}_devhelp ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_EPUB_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_epub epub ${conf} ${source} ${base_destination}/epub )
|
||||
|
||||
add_dependencies( ${target_base_name}_epub ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_LATEX_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_latex latex ${conf} ${source} ${base_destination}/latex )
|
||||
|
||||
add_dependencies( ${target_base_name}_latex ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_MAN_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_man man ${conf} ${source} ${base_destination}/man )
|
||||
|
||||
add_dependencies( ${target_base_name}_man ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${SPHINX_TEXT_OUTPUT} )
|
||||
Sphinx_add_target( ${target_base_name}_text text ${conf} ${source} ${base_destination}/text )
|
||||
|
||||
add_dependencies( ${target_base_name}_text ${_dependencies} )
|
||||
endif()
|
||||
|
||||
if( ${BUILD_TESTING} )
|
||||
sphinx_add_target( ${target_base_name}_linkcheck linkcheck ${conf} ${source} ${base_destination}/linkcheck )
|
||||
|
||||
add_dependencies( ${target_base_name}_linkcheck ${_dependencies} )
|
||||
endif()
|
||||
endfunction()
|
|
@ -95,7 +95,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
add_definitions(-DGLOBAL_CONFIG_PATH="${GLOBAL_CONFIG_PATH}")
|
||||
ENDIF()
|
||||
add_component_dir (files
|
||||
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager
|
||||
linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager escape
|
||||
lowlevelfile constrainedfilestream memorystream
|
||||
)
|
||||
|
||||
|
|
|
@ -43,7 +43,15 @@ bool operator==(const MovedCellRef& ref, const RefNum& refNum);
|
|||
bool operator==(const CellRef& ref, const RefNum& refNum);
|
||||
|
||||
typedef std::list<MovedCellRef> MovedCellRefTracker;
|
||||
typedef std::list<CellRef> CellRefTracker;
|
||||
typedef std::list<std::pair<CellRef, bool> > CellRefTracker;
|
||||
|
||||
struct CellRefTrackerPredicate
|
||||
{
|
||||
RefNum mRefNum;
|
||||
|
||||
CellRefTrackerPredicate(const RefNum& refNum) : mRefNum(refNum) {}
|
||||
bool operator() (const std::pair<CellRef, bool>& refdelPair) { return refdelPair.first == mRefNum; }
|
||||
};
|
||||
|
||||
/* Cells hold data about objects, creatures, statics (rocks, walls,
|
||||
buildings) and landscape (for exterior cells). Cells frequently
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/files/escape.hpp>
|
||||
|
||||
// Parses and validates a fallback map from boost program_options.
|
||||
// Note: for boost to pick up the validate function, you need to pull in the namespace e.g.
|
||||
|
@ -47,25 +47,4 @@ namespace Fallback
|
|||
}
|
||||
}
|
||||
|
||||
namespace Files {
|
||||
void validate(boost::any &v, const std::vector<std::string> &tokens, Files::EscapeHashString * eHS, int a)
|
||||
{
|
||||
boost::program_options::validators::check_first_occurrence(v);
|
||||
|
||||
if (v.empty())
|
||||
v = boost::any(EscapeHashString(boost::program_options::validators::get_single_string(tokens)));
|
||||
}
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &tokens, EscapeStringVector *, int)
|
||||
{
|
||||
if (v.empty())
|
||||
v = boost::any(EscapeStringVector());
|
||||
|
||||
EscapeStringVector * eSV = boost::any_cast<EscapeStringVector>(&v);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
|
||||
eSV->mVector.push_back(EscapeHashString(*it));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
#include <algorithm>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <components/files/escape.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/algorithm/string/erase.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
|
@ -164,152 +167,6 @@ bool ConfigurationManager::loadConfig(const boost::filesystem::path& path,
|
|||
return false;
|
||||
}
|
||||
|
||||
const int escape_hash_filter::sEscape = '@';
|
||||
const int escape_hash_filter::sEscapeIdentifier = 'a';
|
||||
const int escape_hash_filter::sHashIdentifier = 'h';
|
||||
|
||||
escape_hash_filter::escape_hash_filter() : mNext(), mSeenNonWhitespace(false), mFinishLine(false)
|
||||
{
|
||||
}
|
||||
|
||||
escape_hash_filter::~escape_hash_filter()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Source>
|
||||
int escape_hash_filter::get(Source & src)
|
||||
{
|
||||
if (mNext.empty())
|
||||
{
|
||||
int character = boost::iostreams::get(src);
|
||||
bool record = true;
|
||||
if (character == boost::iostreams::WOULD_BLOCK)
|
||||
{
|
||||
mNext.push(character);
|
||||
record = false;
|
||||
}
|
||||
else if (character == EOF)
|
||||
{
|
||||
mSeenNonWhitespace = false;
|
||||
mFinishLine = false;
|
||||
mNext.push(character);
|
||||
}
|
||||
else if (character == '\n')
|
||||
{
|
||||
mSeenNonWhitespace = false;
|
||||
mFinishLine = false;
|
||||
mNext.push(character);
|
||||
}
|
||||
else if (mFinishLine)
|
||||
{
|
||||
mNext.push(character);
|
||||
}
|
||||
else if (character == '#')
|
||||
{
|
||||
if (mSeenNonWhitespace)
|
||||
{
|
||||
mNext.push(sEscape);
|
||||
mNext.push(sHashIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's fine being interpreted by Boost as a comment, and so is anything afterwards
|
||||
mNext.push(character);
|
||||
mFinishLine = true;
|
||||
}
|
||||
}
|
||||
else if (mPrevious == sEscape)
|
||||
{
|
||||
mNext.push(sEscape);
|
||||
mNext.push(sEscapeIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
mNext.push(character);
|
||||
}
|
||||
if (!mSeenNonWhitespace && !isspace(character))
|
||||
mSeenNonWhitespace = true;
|
||||
if (record)
|
||||
mPrevious = character;
|
||||
}
|
||||
int retval = mNext.front();
|
||||
mNext.pop();
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string EscapeHashString::processString(const std::string & str)
|
||||
{
|
||||
std::string temp = boost::replace_all_copy<std::string>(str, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sHashIdentifier, "#");
|
||||
boost::replace_all(temp, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sEscapeIdentifier, std::string((char) escape_hash_filter::sEscape, 1));
|
||||
return temp;
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString() : mData()
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const std::string & str) : mData(EscapeHashString::processString(str))
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const std::string & str, size_t pos, size_t len) : mData(EscapeHashString::processString(str), pos, len)
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const char * s) : mData(EscapeHashString::processString(std::string(s)))
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const char * s, size_t n) : mData(EscapeHashString::processString(std::string(s)), 0, n)
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(size_t n, char c) : mData(n, c)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
EscapeHashString::EscapeHashString(InputIterator first, InputIterator last) : mData(EscapeHashString::processString(std::string(first, last)))
|
||||
{
|
||||
}
|
||||
|
||||
std::string EscapeHashString::toStdString() const
|
||||
{
|
||||
return std::string(mData);
|
||||
}
|
||||
|
||||
std::istream & operator>> (std::istream & is, EscapeHashString & eHS)
|
||||
{
|
||||
std::string temp;
|
||||
is >> temp;
|
||||
eHS = EscapeHashString(temp);
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS)
|
||||
{
|
||||
os << eHS.mData;
|
||||
return os;
|
||||
}
|
||||
|
||||
EscapeStringVector::EscapeStringVector() : mVector()
|
||||
{
|
||||
}
|
||||
|
||||
EscapeStringVector::~EscapeStringVector()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::string> EscapeStringVector::toStdStringVector() const
|
||||
{
|
||||
std::vector<std::string> temp = std::vector<std::string>();
|
||||
for (std::vector<EscapeHashString>::const_iterator it = mVector.begin(); it != mVector.end(); ++it)
|
||||
{
|
||||
temp.push_back(it->toStdString());
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
const boost::filesystem::path& ConfigurationManager::getGlobalPath() const
|
||||
{
|
||||
return mFixedPath.getGlobalConfigPath();
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
#define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
|
||||
#include <components/files/fixedpath.hpp>
|
||||
#include <components/files/collections.hpp>
|
||||
|
@ -64,66 +62,6 @@ struct ConfigurationManager
|
|||
|
||||
bool mSilent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \struct escape_hash_filter
|
||||
*/
|
||||
struct escape_hash_filter : public boost::iostreams::input_filter
|
||||
{
|
||||
static const int sEscape;
|
||||
static const int sHashIdentifier;
|
||||
static const int sEscapeIdentifier;
|
||||
|
||||
escape_hash_filter();
|
||||
virtual ~escape_hash_filter();
|
||||
|
||||
template <typename Source> int get(Source & src);
|
||||
|
||||
private:
|
||||
std::queue<int> mNext;
|
||||
int mPrevious;
|
||||
|
||||
bool mSeenNonWhitespace;
|
||||
bool mFinishLine;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class EscapeHashString
|
||||
*/
|
||||
class EscapeHashString
|
||||
{
|
||||
private:
|
||||
std::string mData;
|
||||
public:
|
||||
static std::string processString(const std::string & str);
|
||||
|
||||
EscapeHashString();
|
||||
EscapeHashString(const std::string & str);
|
||||
EscapeHashString(const std::string & str, size_t pos, size_t len = std::string::npos);
|
||||
EscapeHashString(const char * s);
|
||||
EscapeHashString(const char * s, size_t n);
|
||||
EscapeHashString(size_t n, char c);
|
||||
template <class InputIterator>
|
||||
EscapeHashString(InputIterator first, InputIterator last);
|
||||
|
||||
std::string toStdString() const;
|
||||
|
||||
friend std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS);
|
||||
};
|
||||
|
||||
std::istream & operator>> (std::istream & is, EscapeHashString & eHS);
|
||||
|
||||
struct EscapeStringVector
|
||||
{
|
||||
std::vector<Files::EscapeHashString> mVector;
|
||||
|
||||
EscapeStringVector();
|
||||
virtual ~EscapeStringVector();
|
||||
|
||||
std::vector<std::string> toStdStringVector() const;
|
||||
};
|
||||
|
||||
} /* namespace Cfg */
|
||||
|
||||
#endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */
|
||||
|
|
140
components/files/escape.cpp
Normal file
|
@ -0,0 +1,140 @@
|
|||
#include "escape.hpp"
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
namespace Files
|
||||
{
|
||||
const int escape_hash_filter::sEscape = '@';
|
||||
const int escape_hash_filter::sEscapeIdentifier = 'a';
|
||||
const int escape_hash_filter::sHashIdentifier = 'h';
|
||||
|
||||
escape_hash_filter::escape_hash_filter() : mNext(), mSeenNonWhitespace(false), mFinishLine(false)
|
||||
{
|
||||
}
|
||||
|
||||
escape_hash_filter::~escape_hash_filter()
|
||||
{
|
||||
}
|
||||
|
||||
unescape_hash_filter::unescape_hash_filter() : expectingIdentifier(false)
|
||||
{
|
||||
}
|
||||
|
||||
unescape_hash_filter::~unescape_hash_filter()
|
||||
{
|
||||
}
|
||||
|
||||
std::string EscapeHashString::processString(const std::string & str)
|
||||
{
|
||||
std::string temp = boost::replace_all_copy<std::string>(str, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sHashIdentifier, "#");
|
||||
boost::replace_all(temp, std::string() + (char)escape_hash_filter::sEscape + (char)escape_hash_filter::sEscapeIdentifier, std::string((char)escape_hash_filter::sEscape, 1));
|
||||
return temp;
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString() : mData()
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const std::string & str) : mData(EscapeHashString::processString(str))
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const std::string & str, size_t pos, size_t len) : mData(EscapeHashString::processString(str), pos, len)
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const char * s) : mData(EscapeHashString::processString(std::string(s)))
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(const char * s, size_t n) : mData(EscapeHashString::processString(std::string(s)), 0, n)
|
||||
{
|
||||
}
|
||||
|
||||
EscapeHashString::EscapeHashString(size_t n, char c) : mData(n, c)
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
EscapeHashString::EscapeHashString(InputIterator first, InputIterator last) : mData(EscapeHashString::processString(std::string(first, last)))
|
||||
{
|
||||
}
|
||||
|
||||
std::string EscapeHashString::toStdString() const
|
||||
{
|
||||
return std::string(mData);
|
||||
}
|
||||
|
||||
std::istream & operator>> (std::istream & is, EscapeHashString & eHS)
|
||||
{
|
||||
std::string temp;
|
||||
is >> temp;
|
||||
eHS = EscapeHashString(temp);
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS)
|
||||
{
|
||||
os << eHS.mData;
|
||||
return os;
|
||||
}
|
||||
|
||||
EscapeStringVector::EscapeStringVector() : mVector()
|
||||
{
|
||||
}
|
||||
|
||||
EscapeStringVector::~EscapeStringVector()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::string> EscapeStringVector::toStdStringVector() const
|
||||
{
|
||||
std::vector<std::string> temp = std::vector<std::string>();
|
||||
for (std::vector<EscapeHashString>::const_iterator it = mVector.begin(); it != mVector.end(); ++it)
|
||||
{
|
||||
temp.push_back(it->toStdString());
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
// boost program options validation
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &tokens, Files::EscapeHashString * eHS, int a)
|
||||
{
|
||||
boost::program_options::validators::check_first_occurrence(v);
|
||||
|
||||
if (v.empty())
|
||||
v = boost::any(EscapeHashString(boost::program_options::validators::get_single_string(tokens)));
|
||||
}
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &tokens, EscapeStringVector *, int)
|
||||
{
|
||||
if (v.empty())
|
||||
v = boost::any(EscapeStringVector());
|
||||
|
||||
EscapeStringVector * eSV = boost::any_cast<EscapeStringVector>(&v);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
|
||||
eSV->mVector.push_back(EscapeHashString(*it));
|
||||
}
|
||||
|
||||
PathContainer EscapePath::toPathContainer(const EscapePathContainer & escapePathContainer)
|
||||
{
|
||||
PathContainer temp;
|
||||
for (EscapePathContainer::const_iterator it = escapePathContainer.begin(); it != escapePathContainer.end(); ++it)
|
||||
temp.push_back(it->mPath);
|
||||
return temp;
|
||||
}
|
||||
|
||||
std::istream & operator>> (std::istream & istream, EscapePath & escapePath)
|
||||
{
|
||||
boost::iostreams::filtering_istream filteredStream;
|
||||
filteredStream.push(unescape_hash_filter());
|
||||
filteredStream.push(istream);
|
||||
|
||||
filteredStream >> escapePath.mPath;
|
||||
|
||||
return istream;
|
||||
}
|
||||
}
|
196
components/files/escape.hpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
#ifndef COMPONENTS_FILES_ESCAPE_HPP
|
||||
#define COMPONENTS_FILES_ESCAPE_HPP
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <components/files/multidircollection.hpp>
|
||||
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
/**
|
||||
* \namespace Files
|
||||
*/
|
||||
namespace Files
|
||||
{
|
||||
/**
|
||||
* \struct escape_hash_filter
|
||||
*/
|
||||
struct escape_hash_filter : public boost::iostreams::input_filter
|
||||
{
|
||||
static const int sEscape;
|
||||
static const int sHashIdentifier;
|
||||
static const int sEscapeIdentifier;
|
||||
|
||||
escape_hash_filter();
|
||||
virtual ~escape_hash_filter();
|
||||
|
||||
template <typename Source> int get(Source & src);
|
||||
|
||||
private:
|
||||
std::queue<int> mNext;
|
||||
int mPrevious;
|
||||
|
||||
bool mSeenNonWhitespace;
|
||||
bool mFinishLine;
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
int escape_hash_filter::get(Source & src)
|
||||
{
|
||||
if (mNext.empty())
|
||||
{
|
||||
int character = boost::iostreams::get(src);
|
||||
bool record = true;
|
||||
if (character == boost::iostreams::WOULD_BLOCK)
|
||||
{
|
||||
mNext.push(character);
|
||||
record = false;
|
||||
}
|
||||
else if (character == EOF)
|
||||
{
|
||||
mSeenNonWhitespace = false;
|
||||
mFinishLine = false;
|
||||
mNext.push(character);
|
||||
}
|
||||
else if (character == '\n')
|
||||
{
|
||||
mSeenNonWhitespace = false;
|
||||
mFinishLine = false;
|
||||
mNext.push(character);
|
||||
}
|
||||
else if (mFinishLine)
|
||||
{
|
||||
mNext.push(character);
|
||||
}
|
||||
else if (character == '#')
|
||||
{
|
||||
if (mSeenNonWhitespace)
|
||||
{
|
||||
mNext.push(sEscape);
|
||||
mNext.push(sHashIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's fine being interpreted by Boost as a comment, and so is anything afterwards
|
||||
mNext.push(character);
|
||||
mFinishLine = true;
|
||||
}
|
||||
}
|
||||
else if (mPrevious == sEscape)
|
||||
{
|
||||
mNext.push(sEscape);
|
||||
mNext.push(sEscapeIdentifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
mNext.push(character);
|
||||
}
|
||||
if (!mSeenNonWhitespace && !isspace(character))
|
||||
mSeenNonWhitespace = true;
|
||||
if (record)
|
||||
mPrevious = character;
|
||||
}
|
||||
int retval = mNext.front();
|
||||
mNext.pop();
|
||||
return retval;
|
||||
}
|
||||
|
||||
struct unescape_hash_filter : public boost::iostreams::input_filter
|
||||
{
|
||||
unescape_hash_filter();
|
||||
virtual ~unescape_hash_filter();
|
||||
|
||||
template <typename Source> int get(Source & src);
|
||||
|
||||
private:
|
||||
bool expectingIdentifier;
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
int unescape_hash_filter::get(Source & src)
|
||||
{
|
||||
int character;
|
||||
if (!expectingIdentifier)
|
||||
character = boost::iostreams::get(src);
|
||||
else
|
||||
{
|
||||
character = escape_hash_filter::sEscape;
|
||||
expectingIdentifier = false;
|
||||
}
|
||||
if (character == escape_hash_filter::sEscape)
|
||||
{
|
||||
int nextChar = boost::iostreams::get(src);
|
||||
int intended;
|
||||
if (nextChar == escape_hash_filter::sEscapeIdentifier)
|
||||
intended = escape_hash_filter::sEscape;
|
||||
else if (nextChar == escape_hash_filter::sHashIdentifier)
|
||||
intended = '#';
|
||||
else if (nextChar == boost::iostreams::WOULD_BLOCK)
|
||||
{
|
||||
expectingIdentifier = true;
|
||||
intended = nextChar;
|
||||
}
|
||||
else
|
||||
intended = '?';
|
||||
return intended;
|
||||
}
|
||||
else
|
||||
return character;
|
||||
}
|
||||
|
||||
/**
|
||||
* \class EscapeHashString
|
||||
*/
|
||||
class EscapeHashString
|
||||
{
|
||||
private:
|
||||
std::string mData;
|
||||
public:
|
||||
static std::string processString(const std::string & str);
|
||||
|
||||
EscapeHashString();
|
||||
EscapeHashString(const std::string & str);
|
||||
EscapeHashString(const std::string & str, size_t pos, size_t len = std::string::npos);
|
||||
EscapeHashString(const char * s);
|
||||
EscapeHashString(const char * s, size_t n);
|
||||
EscapeHashString(size_t n, char c);
|
||||
template <class InputIterator>
|
||||
EscapeHashString(InputIterator first, InputIterator last);
|
||||
|
||||
std::string toStdString() const;
|
||||
|
||||
friend std::ostream & operator<< (std::ostream & os, const EscapeHashString & eHS);
|
||||
};
|
||||
|
||||
std::istream & operator>> (std::istream & is, EscapeHashString & eHS);
|
||||
|
||||
struct EscapeStringVector
|
||||
{
|
||||
std::vector<Files::EscapeHashString> mVector;
|
||||
|
||||
EscapeStringVector();
|
||||
virtual ~EscapeStringVector();
|
||||
|
||||
std::vector<std::string> toStdStringVector() const;
|
||||
};
|
||||
|
||||
//boost program options validation
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &tokens, Files::EscapeHashString * eHS, int a);
|
||||
|
||||
void validate(boost::any &v, const std::vector<std::string> &tokens, EscapeStringVector *, int);
|
||||
|
||||
struct EscapePath
|
||||
{
|
||||
boost::filesystem::path mPath;
|
||||
|
||||
static PathContainer toPathContainer(const std::vector<EscapePath> & escapePathContainer);
|
||||
};
|
||||
|
||||
typedef std::vector<EscapePath> EscapePathContainer;
|
||||
|
||||
std::istream & operator>> (std::istream & istream, EscapePath & escapePath);
|
||||
} /* namespace Files */
|
||||
#endif /* COMPONENTS_FILES_ESCAPE_HPP */
|
|
@ -1,216 +0,0 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " applehelp to make an Apple Help Book"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
.PHONY: html
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
.PHONY: dirhtml
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
.PHONY: singlehtml
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
.PHONY: pickle
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
.PHONY: json
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
.PHONY: htmlhelp
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
.PHONY: qthelp
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OpenMWCSManual.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OpenMWCSManual.qhc"
|
||||
|
||||
.PHONY: applehelp
|
||||
applehelp:
|
||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||
@echo
|
||||
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||
"~/Library/Documentation/Help or install it in your application" \
|
||||
"bundle."
|
||||
|
||||
.PHONY: devhelp
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/OpenMWCSManual"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OpenMWCSManual"
|
||||
@echo "# devhelp"
|
||||
|
||||
.PHONY: epub
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
.PHONY: latex
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
.PHONY: latexpdf
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
.PHONY: latexpdfja
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
.PHONY: text
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
.PHONY: man
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
.PHONY: texinfo
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
.PHONY: info
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
.PHONY: gettext
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
.PHONY: changes
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
.PHONY: linkcheck
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
.PHONY: doctest
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||
@echo "Testing of coverage in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/coverage/python.txt."
|
||||
|
||||
.PHONY: xml
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
.PHONY: pseudoxml
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
|
@ -1,263 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% source
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
echo. coverage to run coverage check of the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
REM Check if sphinx-build is available and fallback to Python version if any
|
||||
%SPHINXBUILD% 1>NUL 2>NUL
|
||||
if errorlevel 9009 goto sphinx_python
|
||||
goto sphinx_ok
|
||||
|
||||
:sphinx_python
|
||||
|
||||
set SPHINXBUILD=python -m sphinx.__init__
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:sphinx_ok
|
||||
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\OpenMWCSManual.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\OpenMWCSManual.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "coverage" (
|
||||
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of coverage in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/coverage/python.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
3
docs/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
breathe
|
||||
parse_cmake
|
||||
sphinx
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# OpenMW CS Manual documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Feb 5 21:28:27 2016.
|
||||
# OpenMW documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed May 14 15:16:35 2014.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
|
@ -18,7 +18,8 @@ import os
|
|||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
project_root = os.path.abspath('../../')
|
||||
sys.path.insert(0, project_root)
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
|
@ -29,14 +30,27 @@ import os
|
|||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.viewcode',
|
||||
'breathe',
|
||||
]
|
||||
|
||||
# Where breathe can find the source files
|
||||
breathe_projects_source = {
|
||||
"openmw": (project_root+"/apps/openmw", ["engine.hpp",
|
||||
"mwbase/dialoguemanager.hpp", "mwbase/environment.hpp",
|
||||
"mwbase/inputmanager.hpp", "mwbase/journal.hpp", "mwbase/mechanicsmanager.hpp",
|
||||
"mwbase/scriptmanager.hpp", "mwbase/soundmanager.hpp", "mwbase/statemanager.hpp",
|
||||
"mwbase/windowmanager.hpp", "mwbase/world.hpp"])
|
||||
}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
# source_suffix = ['.rst', '.md']
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
|
@ -46,25 +60,25 @@ source_suffix = '.rst'
|
|||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'OpenMW CS Manual'
|
||||
copyright = u'2016, The OpenMW Project'
|
||||
author = u'HiPhish'
|
||||
project = u'OpenMW'
|
||||
copyright = u'2016, OpenMW Team'
|
||||
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'0.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'0.0'
|
||||
|
||||
from parse_cmake import parsing
|
||||
cmake_raw = open(project_root+'/CMakeLists.txt', 'r').read()
|
||||
cmake_data = parsing.parse(cmake_raw)
|
||||
release = version = int(cmake_data[24][1][1].contents), int(cmake_data[25][1][1].contents), int(cmake_data[26][1][1].contents)
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
#language = cpp
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
|
@ -100,15 +114,13 @@ pygments_style = 'sphinx'
|
|||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
primary_domain = 'c'
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'alabaster'
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
@ -137,7 +149,9 @@ html_theme = 'alabaster'
|
|||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = ['_static',
|
||||
'openmw-cs/_static'
|
||||
]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
|
@ -185,22 +199,9 @@ html_static_path = ['_static']
|
|||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Language to be used for generating the HTML full-text search index.
|
||||
# Sphinx supports the following languages:
|
||||
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
|
||||
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
|
||||
#html_search_language = 'en'
|
||||
|
||||
# A dictionary with options for the search language support, empty by default.
|
||||
# Now only 'ja' uses this config value
|
||||
#html_search_options = {'type': 'default'}
|
||||
|
||||
# The name of a javascript file (relative to the configuration directory) that
|
||||
# implements a search results scorer. If empty, the default will be used.
|
||||
#html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'OpenMWCSManualdoc'
|
||||
htmlhelp_basename = 'OpenMWdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
|
@ -213,17 +214,14 @@ latex_elements = {
|
|||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'OpenMWCSManual.tex', u'OpenMW CS Manual Documentation',
|
||||
u'HiPhish', 'manual'),
|
||||
('index', 'OpenMW.tex', u'OpenMW Documentation',
|
||||
u'Bret Curtis', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
@ -252,8 +250,8 @@ latex_documents = [
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'openmwcsmanual', u'OpenMW CS Manual Documentation',
|
||||
[author], 1)
|
||||
('index', 'openmw', u'OpenMW Documentation',
|
||||
[u'Bret Curtis'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
|
@ -266,8 +264,8 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'OpenMWCSManual', u'OpenMW CS Manual Documentation',
|
||||
author, 'OpenMWCSManual', 'One line description of project.',
|
||||
('index', 'OpenMW', u'OpenMW Documentation',
|
||||
u'Bret Curtis', 'OpenMW', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
@ -282,77 +280,3 @@ texinfo_documents = [
|
|||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# -- Options for Epub output ----------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
epub_author = author
|
||||
epub_publisher = author
|
||||
epub_copyright = copyright
|
||||
|
||||
# The basename for the epub file. It defaults to the project name.
|
||||
#epub_basename = project
|
||||
|
||||
# The HTML theme for the epub output. Since the default themes are not
|
||||
# optimized for small screen space, using the same theme for HTML and epub
|
||||
# output is usually not wise. This defaults to 'epub', a theme designed to save
|
||||
# visual space.
|
||||
#epub_theme = 'epub'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or 'en' if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
|
||||
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
|
||||
#epub_guide = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files that should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
# Choose between 'default' and 'includehidden'.
|
||||
#epub_tocscope = 'default'
|
||||
|
||||
# Fix unsupported image types using the Pillow.
|
||||
#epub_fix_images = False
|
||||
|
||||
# Scale large images.
|
||||
#epub_max_image_width = 0
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#epub_show_urls = 'inline'
|
||||
|
||||
# If false, no index is generated.
|
||||
#epub_use_index = True
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'https://docs.python.org/': None}
|
20
docs/source/index.rst
Normal file
|
@ -0,0 +1,20 @@
|
|||
|
||||
Welcome to OpenMW's documentation!
|
||||
=====================================
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
openmw/index
|
||||
openmw-cs/index
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 187 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 90 KiB |
|
@ -1,8 +1,3 @@
|
|||
.. OpenMW CS Manual documentation master file, created by
|
||||
sphinx-quickstart on Fri Feb 5 21:28:27 2016.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
#####################
|
||||
OpenMW CS user manual
|
||||
#####################
|
|
@ -24,7 +24,7 @@ We will start by launching OpenMW CS, the location of the program depends on
|
|||
your operating system. You will be presented with a dialogue with three
|
||||
options: create a new game, create a new addon, edit a content file.
|
||||
|
||||
.. figure:: ./_static/images/chapter-1/opening-dialogue.png
|
||||
.. figure:: _static/images/chapter-1/opening-dialogue.png
|
||||
:alt: Opening dialogue with three option and setting button (the wrench)
|
||||
|
||||
The first option is for creating an entirely new game, that's not what we want.
|
||||
|
@ -37,7 +37,7 @@ optionally a number of other addons we want to depend on. The name of the
|
|||
project is arbitrary, it will be used to identify the addon later in the OpenMW
|
||||
launcher.
|
||||
|
||||
.. figure:: ./_static/images/chapter-1/new-project.png
|
||||
.. figure:: _static/images/chapter-1/new-project.png
|
||||
:alt: Creation dialogue for a new project, pick content modules and name
|
||||
|
||||
Choose Morrowind as your content file and enter `Ring of Night Vision` as the
|
||||
|
@ -47,7 +47,7 @@ to, but for this mod the base game is enough.
|
|||
Once the addon has been created you will be presented with a table. If you see
|
||||
a blank window rather than a table choose *World* → *Objects* from the menu.
|
||||
|
||||
.. figure:: ./_static/images/chapter-1/objects.png
|
||||
.. figure:: _static/images/chapter-1/objects.png
|
||||
:alt: The table showing all objet records in the game.
|
||||
|
||||
Let's talk about the interface for a second. Every window in OpenMW CS has
|
||||
|
@ -83,7 +83,7 @@ We need to enter an *ID* (short for *identifier*) and pick the type. The
|
|||
identifier is a unique name by which the ring can later be identified; I have
|
||||
chosen `ring_night_vision`. For the type choose *Clothing*.
|
||||
|
||||
.. figure:: ./_static/images/chapter-1/add-record.png
|
||||
.. figure:: _static/images/chapter-1/add-record.png
|
||||
:alt: Enter the ID and type of the new ring
|
||||
|
||||
The table should jump right to our newly created record, if not read further
|
||||
|
@ -101,7 +101,7 @@ instead of using the context menu; the default is double-clicking while
|
|||
holding down the shift key.
|
||||
|
||||
|
||||
.. figure:: ./_static/images/chapter-1/edit-record.png
|
||||
.. figure:: _static/images/chapter-1/edit-record.png
|
||||
:alt: Edit the properties of the record in a separate panel
|
||||
|
||||
You can set the name, weight and coin value as you like, I chose `Ring of Night
|
17
docs/source/openmw/index.rst
Normal file
|
@ -0,0 +1,17 @@
|
|||
###########################
|
||||
OpenMW Source Documentation
|
||||
###########################
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
mwbase
|
||||
|
||||
.. autodoxygenfile:: engine.hpp
|
||||
:project: openmw
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
34
docs/source/openmw/mwbase.rst
Normal file
|
@ -0,0 +1,34 @@
|
|||
########
|
||||
./mwbase
|
||||
########
|
||||
|
||||
.. autodoxygenfile:: mwbase/dialoguemanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/environment.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/inputmanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/journal.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/mechanicsmanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/scriptmanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/soundmanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/statemanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/windowmanager.hpp
|
||||
:project: openmw
|
||||
|
||||
.. autodoxygenfile:: mwbase/world.hpp
|
||||
:project: openmw
|
||||
|