@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -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)
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -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
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
@ -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()
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||||||
|
breathe
|
||||||
|
parse_cmake
|
||||||
|
sphinx
|
@ -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
|
OpenMW CS user manual
|
||||||
#####################
|
#####################
|
@ -0,0 +1,17 @@
|
|||||||
|
###########################
|
||||||
|
OpenMW Source Documentation
|
||||||
|
###########################
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
mwbase
|
||||||
|
|
||||||
|
.. autodoxygenfile:: engine.hpp
|
||||||
|
:project: openmw
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
@ -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
|
||||||
|
|